Generated on Fri Oct 19 11:24:52 2018 for Gecode by doxygen 1.6.3

mult.hpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *     Vincent Barichard <Vincent.Barichard@univ-angers.fr>
00006  *
00007  *  Copyright:
00008  *     Christian Schulte, 2004
00009  *     Vincent Barichard, 2012
00010  *
00011  *  This file is part of Gecode, the generic constraint
00012  *  development environment:
00013  *     http://www.gecode.org
00014  *
00015  *  Permission is hereby granted, free of charge, to any person obtaining
00016  *  a copy of this software and associated documentation files (the
00017  *  "Software"), to deal in the Software without restriction, including
00018  *  without limitation the rights to use, copy, modify, merge, publish,
00019  *  distribute, sublicense, and/or sell copies of the Software, and to
00020  *  permit persons to whom the Software is furnished to do so, subject to
00021  *  the following conditions:
00022  *
00023  *  The above copyright notice and this permission notice shall be
00024  *  included in all copies or substantial portions of the Software.
00025  *
00026  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00027  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00028  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00029  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00030  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00031  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00032  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00033  *
00034  */
00035 
00036 namespace Gecode { namespace Float { namespace Arithmetic {
00037 
00039   template<class View>
00040   forceinline bool
00041   pos(const View& x) {
00042     return x.min() >= 0.0;
00043   }
00045   template<class View>
00046   forceinline bool
00047   neg(const View& x) {
00048     return x.max() <= 0.0;
00049   }
00051   template<class View>
00052   forceinline bool
00053   any(const View& x) {
00054     return (x.min() <= 0.0) && (x.max() >= 0.0);
00055   }
00056 
00057   /*
00058    * Propagator for x * y = x
00059    *
00060    */
00061 
00062   template<class View>
00063   forceinline
00064   MultZeroOne<View>::MultZeroOne(Home home, View x0, View x1)
00065     : BinaryPropagator<View,PC_FLOAT_BND>(home,x0,x1) {}
00066 
00067   template<class View>
00068   forceinline ExecStatus
00069   MultZeroOne<View>::post(Home home, View x0, View x1) {
00070     switch (rtest_eq(x0,0.0)) {
00071     case RT_FALSE:
00072       GECODE_ME_CHECK(x1.eq(home,1.0));
00073       break;
00074     case RT_TRUE:
00075       break;
00076     case RT_MAYBE:
00077       switch (rtest_eq(x1,1.0)) {
00078       case RT_FALSE:
00079         GECODE_ME_CHECK(x0.eq(home,0.0));
00080         break;
00081       case RT_TRUE:
00082         break;
00083       case RT_MAYBE:
00084         (void) new (home) MultZeroOne<View>(home,x0,x1);
00085         break;
00086       default: GECODE_NEVER;
00087       }
00088       break;
00089     default: GECODE_NEVER;
00090     }
00091     return ES_OK;
00092   }
00093 
00094   template<class View>
00095   forceinline
00096   MultZeroOne<View>::MultZeroOne(Space& home, MultZeroOne<View>& p)
00097     : BinaryPropagator<View,PC_FLOAT_BND>(home,p) {}
00098 
00099   template<class View>
00100   Actor*
00101   MultZeroOne<View>::copy(Space& home) {
00102     return new (home) MultZeroOne<View>(home,*this);
00103   }
00104 
00105   template<class View>
00106   ExecStatus
00107   MultZeroOne<View>::propagate(Space& home, const ModEventDelta&) {
00108     switch (rtest_eq(x0,0.0)) {
00109     case RT_FALSE:
00110       GECODE_ME_CHECK(x1.eq(home,1.0));
00111       break;
00112     case RT_TRUE:
00113       break;
00114     case RT_MAYBE:
00115       switch (rtest_eq(x1,1.0)) {
00116       case RT_FALSE:
00117         GECODE_ME_CHECK(x0.eq(home,0.0));
00118         break;
00119       case RT_TRUE:
00120         break;
00121       case RT_MAYBE:
00122         return ES_FIX;
00123       default: GECODE_NEVER;
00124       }
00125       break;
00126     default: GECODE_NEVER;
00127     }
00128     return home.ES_SUBSUMED(*this);
00129   }
00130 
00131 
00132   /*
00133    * Positive bounds consistent multiplication
00134    *
00135    */
00136   template<class VA, class VB, class VC>
00137   forceinline
00138   MultPlus<VA,VB,VC>::MultPlus(Home home, VA x0, VB x1, VC x2)
00139     : MixTernaryPropagator<VA,PC_FLOAT_BND,VB,PC_FLOAT_BND,VC,PC_FLOAT_BND>
00140   (home,x0,x1,x2) {}
00141 
00142   template<class VA, class VB, class VC>
00143   forceinline
00144   MultPlus<VA,VB,VC>::MultPlus(Space& home, MultPlus<VA,VB,VC>& p)
00145     : MixTernaryPropagator<VA,PC_FLOAT_BND,VB,PC_FLOAT_BND,VC,PC_FLOAT_BND>
00146   (home,p) {}
00147 
00148   template<class VA, class VB, class VC>
00149   Actor*
00150   MultPlus<VA,VB,VC>::copy(Space& home) {
00151     return new (home) MultPlus<VA,VB,VC>(home,*this);
00152   }
00153 
00154   template<class VA, class VB, class VC>
00155   ExecStatus
00156   MultPlus<VA,VB,VC>::propagate(Space& home, const ModEventDelta&) {
00157     if (x1.min() != 0.0)
00158       GECODE_ME_CHECK(x0.eq(home,x2.val() / x1.val()));
00159     if (x0.min() != 0.0)
00160       GECODE_ME_CHECK(x1.eq(home,x2.val() / x0.val()));
00161     GECODE_ME_CHECK(x2.eq(home,x0.val() * x1.val()));
00162     if (x0.assigned() && x1.assigned() && x2.assigned())
00163       return home.ES_SUBSUMED(*this);
00164     return ES_NOFIX;
00165   }
00166 
00167   template<class VA, class VB, class VC>
00168   forceinline ExecStatus
00169   MultPlus<VA,VB,VC>::post(Home home, VA x0, VB x1, VC x2) {
00170     GECODE_ME_CHECK(x0.gq(home,0.0));
00171     GECODE_ME_CHECK(x1.gq(home,0.0));
00172     Rounding r;
00173     GECODE_ME_CHECK(x2.gq(home,r.mul_down(x0.min(),x1.min())));
00174     (void) new (home) MultPlus<VA,VB,VC>(home,x0,x1,x2);
00175     return ES_OK;
00176   }
00177 
00178 
00179   /*
00180    * Bounds consistent multiplication
00181    *
00182    */
00183   template<class View>
00184   forceinline
00185   Mult<View>::Mult(Home home, View x0, View x1, View x2)
00186     : TernaryPropagator<View,PC_FLOAT_BND>(home,x0,x1,x2) {}
00187 
00188   template<class View>
00189   forceinline
00190   Mult<View>::Mult(Space& home, Mult<View>& p)
00191     : TernaryPropagator<View,PC_FLOAT_BND>(home,p) {}
00192 
00193   template<class View>
00194   Actor*
00195   Mult<View>::copy(Space& home) {
00196     return new (home) Mult<View>(home,*this);
00197   }
00198 
00199   template<class View>
00200   ExecStatus
00201   Mult<View>::propagate(Space& home, const ModEventDelta&) {
00202     Rounding r;
00203     if (pos(x0)) {
00204       if (pos(x1) || pos(x2)) goto rewrite_ppp;
00205       if (neg(x1) || neg(x2)) goto rewrite_pnn;
00206       goto prop_pxx;
00207     }
00208     if (neg(x0)) {
00209       if (neg(x1) || pos(x2)) goto rewrite_nnp;
00210       if (pos(x1) || neg(x2)) goto rewrite_npn;
00211       goto prop_nxx;
00212     }
00213     if (pos(x1)) {
00214       if (pos(x2)) goto rewrite_ppp;
00215       if (neg(x2)) goto rewrite_npn;
00216       goto prop_xpx;
00217     }
00218     if (neg(x1)) {
00219       if (pos(x2)) goto rewrite_nnp;
00220       if (neg(x2)) goto rewrite_pnn;
00221       goto prop_xnx;
00222     }
00223 
00224     assert(any(x0) && any(x1));
00225     GECODE_ME_CHECK(x2.lq(home,std::max(r.mul_up(x0.max(),x1.max()),
00226                                         r.mul_up(x0.min(),x1.min()))));
00227     GECODE_ME_CHECK(x2.gq(home,std::min(r.mul_down(x0.min(),x1.max()),
00228                                         r.mul_down(x0.max(),x1.min()))));
00229 
00230     if (pos(x2)) {
00231       if (r.div_up(x2.min(),x1.min()) < x0.min())
00232         GECODE_ME_CHECK(x0.gq(home,0));
00233       if (r.div_up(x2.min(),x0.min()) < x1.min())
00234         GECODE_ME_CHECK(x1.gq(home,0));
00235     }
00236     if (neg(x2)) {
00237       if (r.div_up(x2.max(),x1.max()) < x0.min())
00238         GECODE_ME_CHECK(x0.gq(home,0));
00239       if (r.div_up(x2.max(),x0.max()) < x1.min())
00240         GECODE_ME_CHECK(x1.gq(home,0));
00241     }
00242 
00243     if (x0.assigned()) {
00244       assert((x0.val() == 0.0) && (x2.val() == 0.0));
00245       return home.ES_SUBSUMED(*this);
00246     }
00247 
00248     if (x1.assigned()) {
00249       assert((x1.val() == 0.0) && (x2.val() == 0.0));
00250       return home.ES_SUBSUMED(*this);
00251     }
00252 
00253     return ES_NOFIX;
00254 
00255   prop_xpx:
00256     std::swap(x0,x1);
00257   prop_pxx:
00258     assert(pos(x0) && any(x1) && any(x2));
00259 
00260     GECODE_ME_CHECK(x2.lq(home,r.mul_up(x0.max(),x1.max())));
00261     GECODE_ME_CHECK(x2.gq(home,r.mul_down(x0.max(),x1.min())));
00262 
00263     if (pos(x2)) goto rewrite_ppp;
00264     if (neg(x2)) goto rewrite_pnn;
00265 
00266     GECODE_ME_CHECK(x1.lq(home,r.div_up(x2.max(),x0.min())));
00267     GECODE_ME_CHECK(x1.gq(home,r.div_down(x2.min(),x0.min())));
00268 
00269     if (x0.assigned() && x1.assigned()) {
00270       GECODE_ME_CHECK(x2.eq(home,x0.val()*x1.val()));
00271       return home.ES_SUBSUMED(*this);
00272     }
00273 
00274     return ES_NOFIX;
00275 
00276   prop_xnx:
00277     std::swap(x0,x1);
00278   prop_nxx:
00279     assert(neg(x0) && any(x1) && any(x2));
00280 
00281     GECODE_ME_CHECK(x2.lq(home,r.mul_up(x0.min(),x1.min())));
00282     GECODE_ME_CHECK(x2.gq(home,r.mul_down(x0.min(),x1.max())));
00283 
00284     if (pos(x2)) goto rewrite_nnp;
00285     if (neg(x2)) goto rewrite_npn;
00286 
00287     if (x0.max() != 0.0) {
00288       GECODE_ME_CHECK(x1.lq(home,r.div_up(x2.min(),x0.max())));
00289       GECODE_ME_CHECK(x1.gq(home,r.div_down(x2.max(),x0.max())));
00290     }
00291 
00292     if (x0.assigned() && x1.assigned()) {
00293       GECODE_ME_CHECK(x2.eq(home,x0.val()*x1.val()));
00294       return home.ES_SUBSUMED(*this);
00295     }
00296 
00297     return ES_NOFIX;
00298 
00299   rewrite_ppp:
00300     GECODE_REWRITE(*this,(MultPlus<FloatView,FloatView,FloatView>
00301                          ::post(home(*this),x0,x1,x2)));
00302   rewrite_nnp:
00303     GECODE_REWRITE(*this,(MultPlus<MinusView,MinusView,FloatView>
00304                          ::post(home(*this),MinusView(x0),MinusView(x1),x2)));
00305   rewrite_pnn:
00306     std::swap(x0,x1);
00307   rewrite_npn:
00308     GECODE_REWRITE(*this,(MultPlus<MinusView,FloatView,MinusView>
00309                          ::post(home(*this),MinusView(x0),x1,MinusView(x2))));
00310   }
00311 
00312   template<class View>
00313   ExecStatus
00314   Mult<View>::post(Home home, View x0, View x1, View x2) {
00315     if (x0 == x1)
00316       return Sqr<View>::post(home,x0,x2);
00317     if (x0 == x2)
00318       return MultZeroOne<View>::post(home,x0,x1);
00319     if (x1 == x2)
00320       return MultZeroOne<View>::post(home,x1,x0);
00321     if (pos(x0)) {
00322       if (pos(x1) || pos(x2)) goto post_ppp;
00323       if (neg(x1) || neg(x2)) goto post_pnn;
00324     } else if (neg(x0)) {
00325       if (neg(x1) || pos(x2)) goto post_nnp;
00326       if (pos(x1) || neg(x2)) goto post_npn;
00327     } else if (pos(x1)) {
00328       if (pos(x2)) goto post_ppp;
00329       if (neg(x2)) goto post_npn;
00330     } else if (neg(x1)) {
00331       if (pos(x2)) goto post_nnp;
00332       if (neg(x2)) goto post_pnn;
00333     }
00334     {
00335       GECODE_ME_CHECK(x2.eq(home,x0.val()*x1.val()));
00336       (void) new (home) Mult<View>(home,x0,x1,x2);
00337     }
00338     return ES_OK;
00339 
00340   post_ppp:
00341     return MultPlus<FloatView,FloatView,FloatView>::post(home,x0,x1,x2);
00342   post_nnp:
00343     return MultPlus<MinusView,MinusView,FloatView>::post(home,
00344       MinusView(x0),MinusView(x1),x2);
00345   post_pnn:
00346     std::swap(x0,x1);
00347   post_npn:
00348     return MultPlus<MinusView,FloatView,MinusView>::post(home,
00349       MinusView(x0),x1,MinusView(x2));
00350   }
00351 
00352 
00353 }}}
00354 
00355 // STATISTICS: float-prop
00356