00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 namespace Gecode { namespace Float { namespace Arithmetic {
00041
00043 template<class View>
00044 forceinline bool
00045 pos(const View& x) {
00046 return x.min() >= 0.0;
00047 }
00049 template<class View>
00050 forceinline bool
00051 neg(const View& x) {
00052 return x.max() <= 0.0;
00053 }
00055 template<class View>
00056 forceinline bool
00057 any(const View& x) {
00058 return (x.min() <= 0.0) && (x.max() >= 0.0);
00059 }
00060
00061
00062
00063
00064
00065
00066 template<class View>
00067 forceinline
00068 MultZeroOne<View>::MultZeroOne(Home home, View x0, View x1)
00069 : BinaryPropagator<View,PC_FLOAT_BND>(home,x0,x1) {}
00070
00071 template<class View>
00072 forceinline ExecStatus
00073 MultZeroOne<View>::post(Home home, View x0, View x1) {
00074 switch (rtest_eq(x0,0.0)) {
00075 case RT_FALSE:
00076 GECODE_ME_CHECK(x1.eq(home,1.0));
00077 break;
00078 case RT_TRUE:
00079 break;
00080 case RT_MAYBE:
00081 switch (rtest_eq(x1,1.0)) {
00082 case RT_FALSE:
00083 GECODE_ME_CHECK(x0.eq(home,0.0));
00084 break;
00085 case RT_TRUE:
00086 break;
00087 case RT_MAYBE:
00088 (void) new (home) MultZeroOne<View>(home,x0,x1);
00089 break;
00090 default: GECODE_NEVER;
00091 }
00092 break;
00093 default: GECODE_NEVER;
00094 }
00095 return ES_OK;
00096 }
00097
00098 template<class View>
00099 forceinline
00100 MultZeroOne<View>::MultZeroOne(Space& home, bool share,
00101 MultZeroOne<View>& p)
00102 : BinaryPropagator<View,PC_FLOAT_BND>(home,share,p) {}
00103
00104 template<class View>
00105 Actor*
00106 MultZeroOne<View>::copy(Space& home, bool share) {
00107 return new (home) MultZeroOne<View>(home,share,*this);
00108 }
00109
00110 template<class View>
00111 ExecStatus
00112 MultZeroOne<View>::propagate(Space& home, const ModEventDelta&) {
00113 switch (rtest_eq(x0,0.0)) {
00114 case RT_FALSE:
00115 GECODE_ME_CHECK(x1.eq(home,1.0));
00116 break;
00117 case RT_TRUE:
00118 break;
00119 case RT_MAYBE:
00120 switch (rtest_eq(x1,1.0)) {
00121 case RT_FALSE:
00122 GECODE_ME_CHECK(x0.eq(home,0.0));
00123 break;
00124 case RT_TRUE:
00125 break;
00126 case RT_MAYBE:
00127 return ES_FIX;
00128 default: GECODE_NEVER;
00129 }
00130 break;
00131 default: GECODE_NEVER;
00132 }
00133 return home.ES_SUBSUMED(*this);
00134 }
00135
00136
00137
00138
00139
00140
00141 template<class VA, class VB, class VC>
00142 forceinline
00143 MultPlus<VA,VB,VC>::MultPlus(Home home, VA x0, VB x1, VC x2)
00144 : MixTernaryPropagator<VA,PC_FLOAT_BND,VB,PC_FLOAT_BND,VC,PC_FLOAT_BND>
00145 (home,x0,x1,x2) {}
00146
00147 template<class VA, class VB, class VC>
00148 forceinline
00149 MultPlus<VA,VB,VC>::MultPlus(Space& home, bool share,
00150 MultPlus<VA,VB,VC>& p)
00151 : MixTernaryPropagator<VA,PC_FLOAT_BND,VB,PC_FLOAT_BND,VC,PC_FLOAT_BND>
00152 (home,share,p) {}
00153
00154 template<class VA, class VB, class VC>
00155 Actor*
00156 MultPlus<VA,VB,VC>::copy(Space& home, bool share) {
00157 return new (home) MultPlus<VA,VB,VC>(home,share,*this);
00158 }
00159
00160 template<class VA, class VB, class VC>
00161 ExecStatus
00162 MultPlus<VA,VB,VC>::propagate(Space& home, const ModEventDelta&) {
00163 if (x1.min() != 0.0)
00164 GECODE_ME_CHECK(x0.eq(home,x2.val() / x1.val()));
00165 if (x0.min() != 0.0)
00166 GECODE_ME_CHECK(x1.eq(home,x2.val() / x0.val()));
00167 GECODE_ME_CHECK(x2.eq(home,x0.val() * x1.val()));
00168 if (x0.assigned() && x1.assigned() && x2.assigned())
00169 return home.ES_SUBSUMED(*this);
00170 return ES_NOFIX;
00171 }
00172
00173 template<class VA, class VB, class VC>
00174 forceinline ExecStatus
00175 MultPlus<VA,VB,VC>::post(Home home, VA x0, VB x1, VC x2) {
00176 GECODE_ME_CHECK(x0.gq(home,0.0));
00177 GECODE_ME_CHECK(x1.gq(home,0.0));
00178 Rounding r;
00179 GECODE_ME_CHECK(x2.gq(home,r.mul_down(x0.min(),x1.min())));
00180 (void) new (home) MultPlus<VA,VB,VC>(home,x0,x1,x2);
00181 return ES_OK;
00182 }
00183
00184
00185
00186
00187
00188
00189 template<class View>
00190 forceinline
00191 Mult<View>::Mult(Home home, View x0, View x1, View x2)
00192 : TernaryPropagator<View,PC_FLOAT_BND>(home,x0,x1,x2) {}
00193
00194 template<class View>
00195 forceinline
00196 Mult<View>::Mult(Space& home, bool share, Mult<View>& p)
00197 : TernaryPropagator<View,PC_FLOAT_BND>(home,share,p) {}
00198
00199 template<class View>
00200 Actor*
00201 Mult<View>::copy(Space& home, bool share) {
00202 return new (home) Mult<View>(home,share,*this);
00203 }
00204
00205 template<class View>
00206 ExecStatus
00207 Mult<View>::propagate(Space& home, const ModEventDelta&) {
00208 Rounding r;
00209 if (pos(x0)) {
00210 if (pos(x1) || pos(x2)) goto rewrite_ppp;
00211 if (neg(x1) || neg(x2)) goto rewrite_pnn;
00212 goto prop_pxx;
00213 }
00214 if (neg(x0)) {
00215 if (neg(x1) || pos(x2)) goto rewrite_nnp;
00216 if (pos(x1) || neg(x2)) goto rewrite_npn;
00217 goto prop_nxx;
00218 }
00219 if (pos(x1)) {
00220 if (pos(x2)) goto rewrite_ppp;
00221 if (neg(x2)) goto rewrite_npn;
00222 goto prop_xpx;
00223 }
00224 if (neg(x1)) {
00225 if (pos(x2)) goto rewrite_nnp;
00226 if (neg(x2)) goto rewrite_pnn;
00227 goto prop_xnx;
00228 }
00229
00230 assert(any(x0) && any(x1));
00231 GECODE_ME_CHECK(x2.lq(home,std::max(r.mul_up(x0.max(),x1.max()),
00232 r.mul_up(x0.min(),x1.min()))));
00233 GECODE_ME_CHECK(x2.gq(home,std::min(r.mul_down(x0.min(),x1.max()),
00234 r.mul_down(x0.max(),x1.min()))));
00235
00236 if (pos(x2)) {
00237 if (r.div_up(x2.min(),x1.min()) < x0.min())
00238 GECODE_ME_CHECK(x0.gq(home,0));
00239 if (r.div_up(x2.min(),x0.min()) < x1.min())
00240 GECODE_ME_CHECK(x1.gq(home,0));
00241 }
00242 if (neg(x2)) {
00243 if (r.div_up(x2.max(),x1.max()) < x0.min())
00244 GECODE_ME_CHECK(x0.gq(home,0));
00245 if (r.div_up(x2.max(),x0.max()) < x1.min())
00246 GECODE_ME_CHECK(x1.gq(home,0));
00247 }
00248
00249 if (x0.assigned()) {
00250 assert((x0.val() == 0.0) && (x2.val() == 0.0));
00251 return home.ES_SUBSUMED(*this);
00252 }
00253
00254 if (x1.assigned()) {
00255 assert((x1.val() == 0.0) && (x2.val() == 0.0));
00256 return home.ES_SUBSUMED(*this);
00257 }
00258
00259 return ES_NOFIX;
00260
00261 prop_xpx:
00262 std::swap(x0,x1);
00263 prop_pxx:
00264 assert(pos(x0) && any(x1) && any(x2));
00265
00266 GECODE_ME_CHECK(x2.lq(home,r.mul_up(x0.max(),x1.max())));
00267 GECODE_ME_CHECK(x2.gq(home,r.mul_down(x0.max(),x1.min())));
00268
00269 if (pos(x2)) goto rewrite_ppp;
00270 if (neg(x2)) goto rewrite_pnn;
00271
00272 GECODE_ME_CHECK(x1.lq(home,r.div_up(x2.max(),x0.min())));
00273 GECODE_ME_CHECK(x1.gq(home,r.div_down(x2.min(),x0.min())));
00274
00275 if (x0.assigned() && x1.assigned()) {
00276 GECODE_ME_CHECK(x2.eq(home,x0.val()*x1.val()));
00277 return home.ES_SUBSUMED(*this);
00278 }
00279
00280 return ES_NOFIX;
00281
00282 prop_xnx:
00283 std::swap(x0,x1);
00284 prop_nxx:
00285 assert(neg(x0) && any(x1) && any(x2));
00286
00287 GECODE_ME_CHECK(x2.lq(home,r.mul_up(x0.min(),x1.min())));
00288 GECODE_ME_CHECK(x2.gq(home,r.mul_down(x0.min(),x1.max())));
00289
00290 if (pos(x2)) goto rewrite_nnp;
00291 if (neg(x2)) goto rewrite_npn;
00292
00293 if (x0.max() != 0.0) {
00294 GECODE_ME_CHECK(x1.lq(home,r.div_up(x2.min(),x0.max())));
00295 GECODE_ME_CHECK(x1.gq(home,r.div_down(x2.max(),x0.max())));
00296 }
00297
00298 if (x0.assigned() && x1.assigned()) {
00299 GECODE_ME_CHECK(x2.eq(home,x0.val()*x1.val()));
00300 return home.ES_SUBSUMED(*this);
00301 }
00302
00303 return ES_NOFIX;
00304
00305 rewrite_ppp:
00306 GECODE_REWRITE(*this,(MultPlus<FloatView,FloatView,FloatView>
00307 ::post(home(*this),x0,x1,x2)));
00308 rewrite_nnp:
00309 GECODE_REWRITE(*this,(MultPlus<MinusView,MinusView,FloatView>
00310 ::post(home(*this),MinusView(x0),MinusView(x1),x2)));
00311 rewrite_pnn:
00312 std::swap(x0,x1);
00313 rewrite_npn:
00314 GECODE_REWRITE(*this,(MultPlus<MinusView,FloatView,MinusView>
00315 ::post(home(*this),MinusView(x0),x1,MinusView(x2))));
00316 }
00317
00318 template<class View>
00319 ExecStatus
00320 Mult<View>::post(Home home, View x0, View x1, View x2) {
00321 if (same(x0,x1))
00322 return Sqr<View>::post(home,x0,x2);
00323 if (same(x0,x2))
00324 return MultZeroOne<View>::post(home,x0,x1);
00325 if (same(x1,x2))
00326 return MultZeroOne<View>::post(home,x1,x0);
00327 if (pos(x0)) {
00328 if (pos(x1) || pos(x2)) goto post_ppp;
00329 if (neg(x1) || neg(x2)) goto post_pnn;
00330 } else if (neg(x0)) {
00331 if (neg(x1) || pos(x2)) goto post_nnp;
00332 if (pos(x1) || neg(x2)) goto post_npn;
00333 } else if (pos(x1)) {
00334 if (pos(x2)) goto post_ppp;
00335 if (neg(x2)) goto post_npn;
00336 } else if (neg(x1)) {
00337 if (pos(x2)) goto post_nnp;
00338 if (neg(x2)) goto post_pnn;
00339 }
00340 {
00341 GECODE_ME_CHECK(x2.eq(home,x0.val()*x1.val()));
00342 (void) new (home) Mult<View>(home,x0,x1,x2);
00343 }
00344 return ES_OK;
00345
00346 post_ppp:
00347 return MultPlus<FloatView,FloatView,FloatView>::post(home,x0,x1,x2);
00348 post_nnp:
00349 return MultPlus<MinusView,MinusView,FloatView>::post(home,
00350 MinusView(x0),MinusView(x1),x2);
00351 post_pnn:
00352 std::swap(x0,x1);
00353 post_npn:
00354 return MultPlus<MinusView,FloatView,MinusView>::post(home,
00355 MinusView(x0),x1,MinusView(x2));
00356 }
00357
00358
00359 }}}
00360
00361
00362