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 #include <cmath>
00039 #include <climits>
00040
00041 #include <gecode/int/support-values.hh>
00042
00043 namespace Gecode { namespace Int { namespace Arithmetic {
00044
00045
00046
00047
00048
00049
00051 template<class Val>
00052 Val m(int x, int y);
00053
00055 template<class Val>
00056 Val m(int x, double y);
00057
00058 template<>
00059 forceinline double
00060 m(int x, int y) {
00061 return static_cast<double>(x)*static_cast<double>(y);
00062 }
00063
00064 template<>
00065 forceinline double
00066 m(int x, double y) {
00067 return static_cast<double>(x)*y;
00068 }
00069
00070 template<>
00071 forceinline int
00072 m(int x, int y) {
00073 return x*y;
00074 }
00075
00077 template<class Val>
00078 int c_d_p(int x, Val y);
00080 template<class Val>
00081 int f_d_p(int x, Val y);
00082
00083 template <>
00084 forceinline int
00085 c_d_p<int>(int x, int y) {
00086 assert((x >= 0) && (y >= 0));
00087 return (x+y-1)/y;
00088 }
00089 template <>
00090 forceinline int
00091 c_d_p<double>(int x, double y) {
00092 assert((x >= 0) && (y >= 0));
00093 return static_cast<int>(ceil(static_cast<double>(x) / y));
00094 }
00095 template <>
00096 forceinline int
00097 f_d_p<int>(int x, int y) {
00098 assert((x >= 0) && (y >= 0));
00099 return x/y;
00100 }
00101 template <>
00102 forceinline int
00103 f_d_p<double>(int x, double y) {
00104 assert((x >= 0) && (y >= 0));
00105 return static_cast<int>(floor(static_cast<double>(x) / y));
00106 }
00107
00108
00110 forceinline int
00111 f_d(int x, int y) {
00112 return static_cast<int>(floor(static_cast<double>(x) /
00113 static_cast<double>(y)));
00114 }
00115
00117 forceinline int
00118 c_d(int x, int y) {
00119 return static_cast<int>(ceil(static_cast<double>(x) /
00120 static_cast<double>(y)));
00121 }
00122
00124 template <class View>
00125 forceinline bool
00126 pos(const View& x) {
00127 return x.min() > 0;
00128 }
00130 template <class View>
00131 forceinline bool
00132 neg(const View& x) {
00133 return x.max() < 0;
00134 }
00136 template <class View>
00137 forceinline bool
00138 any(const View& x) {
00139 return (x.min() <= 0) && (x.max() >= 0);
00140 }
00141
00142
00143
00144
00145
00146
00147
00148 template <class View, PropCond pc>
00149 forceinline
00150 MultZeroOne<View,pc>::MultZeroOne(Space& home, View x0, View x1)
00151 : BinaryPropagator<View,pc>(home,x0,x1) {}
00152
00153 template <class View, PropCond pc>
00154 forceinline RelTest
00155 MultZeroOne<View,pc>::equal(View x, int n) {
00156 if (pc == PC_INT_DOM) {
00157 return rtest_eq_dom(x,n);
00158 } else {
00159 return rtest_eq_bnd(x,n);
00160 }
00161 }
00162
00163 template <class View, PropCond pc>
00164 forceinline ExecStatus
00165 MultZeroOne<View,pc>::post(Space& home, View x0, View x1) {
00166 switch (equal(x0,0)) {
00167 case RT_FALSE:
00168 GECODE_ME_CHECK(x1.eq(home,1));
00169 break;
00170 case RT_TRUE:
00171 break;
00172 case RT_MAYBE:
00173 switch (equal(x1,1)) {
00174 case RT_FALSE:
00175 GECODE_ME_CHECK(x0.eq(home,0));
00176 break;
00177 case RT_TRUE:
00178 break;
00179 case RT_MAYBE:
00180 (void) new (home) MultZeroOne<View,pc>(home,x0,x1);
00181 break;
00182 default: GECODE_NEVER;
00183 }
00184 break;
00185 default: GECODE_NEVER;
00186 }
00187 return ES_OK;
00188 }
00189
00190 template <class View, PropCond pc>
00191 forceinline
00192 MultZeroOne<View,pc>::MultZeroOne(Space& home, bool share,
00193 MultZeroOne<View,pc>& p)
00194 : BinaryPropagator<View,pc>(home,share,p) {}
00195
00196 template <class View, PropCond pc>
00197 Actor*
00198 MultZeroOne<View,pc>::copy(Space& home, bool share) {
00199 return new (home) MultZeroOne<View,pc>(home,share,*this);
00200 }
00201
00202 template <class View, PropCond pc>
00203 ExecStatus
00204 MultZeroOne<View,pc>::propagate(Space& home, const ModEventDelta&) {
00205 switch (equal(x0,0)) {
00206 case RT_FALSE:
00207 GECODE_ME_CHECK(x1.eq(home,1));
00208 break;
00209 case RT_TRUE:
00210 break;
00211 case RT_MAYBE:
00212 switch (equal(x1,1)) {
00213 case RT_FALSE:
00214 GECODE_ME_CHECK(x0.eq(home,0));
00215 break;
00216 case RT_TRUE:
00217 break;
00218 case RT_MAYBE:
00219 return ES_FIX;
00220 default: GECODE_NEVER;
00221 }
00222 break;
00223 default: GECODE_NEVER;
00224 }
00225 return ES_SUBSUMED(*this,home);
00226 }
00227
00228
00229
00230
00231
00232
00233 template <class Val, class VA, class VB, class VC>
00234 forceinline ExecStatus
00235 prop_mult_plus_bnd(Space& home, Propagator& p, VA x0, VB x1, VC x2) {
00236 assert(pos(x0) && pos(x1) && pos(x2));
00237 bool mod;
00238 do {
00239 mod = false;
00240 {
00241 ModEvent me = x2.lq(home,m<Val>(x0.max(),x1.max()));
00242 if (me_failed(me)) return ES_FAILED;
00243 mod |= me_modified(me);
00244 }
00245 {
00246 ModEvent me = x2.gq(home,m<Val>(x0.min(),x1.min()));
00247 if (me_failed(me)) return ES_FAILED;
00248 mod |= me_modified(me);
00249 }
00250 {
00251 ModEvent me = x0.lq(home,f_d_p<Val>(x2.max(),x1.min()));
00252 if (me_failed(me)) return ES_FAILED;
00253 mod |= me_modified(me);
00254 }
00255 {
00256 ModEvent me = x0.gq(home,c_d_p<Val>(x2.min(),x1.max()));
00257 if (me_failed(me)) return ES_FAILED;
00258 mod |= me_modified(me);
00259 }
00260 {
00261 ModEvent me = x1.lq(home,f_d_p<Val>(x2.max(),x0.min()));
00262 if (me_failed(me)) return ES_FAILED;
00263 mod |= me_modified(me);
00264 }
00265 {
00266 ModEvent me = x1.gq(home,c_d_p<Val>(x2.min(),x0.max()));
00267 if (me_failed(me)) return ES_FAILED;
00268 mod |= me_modified(me);
00269 }
00270 } while (mod);
00271 return x0.assigned() && x1.assigned() ?
00272 ES_SUBSUMED(p,sizeof(p)) : ES_FIX;
00273 }
00274
00275 template <class Val, class VA, class VB, class VC>
00276 forceinline
00277 MultPlusBnd<Val,VA,VB,VC>::MultPlusBnd(Space& home, VA x0, VB x1, VC x2)
00278 : MixTernaryPropagator<VA,PC_INT_BND,VB,PC_INT_BND,VC,PC_INT_BND>
00279 (home,x0,x1,x2) {}
00280
00281 template <class Val, class VA, class VB, class VC>
00282 forceinline
00283 MultPlusBnd<Val,VA,VB,VC>::MultPlusBnd(Space& home, bool share,
00284 MultPlusBnd<Val,VA,VB,VC>& p)
00285 : MixTernaryPropagator<VA,PC_INT_BND,VB,PC_INT_BND,VC,PC_INT_BND>
00286 (home,share,p) {}
00287
00288 template <class Val, class VA, class VB, class VC>
00289 Actor*
00290 MultPlusBnd<Val,VA,VB,VC>::copy(Space& home, bool share) {
00291 return new (home) MultPlusBnd<Val,VA,VB,VC>(home,share,*this);
00292 }
00293
00294 template <class Val, class VA, class VB, class VC>
00295 ExecStatus
00296 MultPlusBnd<Val,VA,VB,VC>::propagate(Space& home, const ModEventDelta&) {
00297 return prop_mult_plus_bnd<Val,VA,VB,VC>(home,*this,x0,x1,x2);
00298 }
00299
00300 template <class Val, class VA, class VB, class VC>
00301 forceinline ExecStatus
00302 MultPlusBnd<Val,VA,VB,VC>::post(Space& home, VA x0, VB x1, VC x2) {
00303 GECODE_ME_CHECK(x0.gr(home,0));
00304 GECODE_ME_CHECK(x1.gr(home,0));
00305 GECODE_ME_CHECK(x2.gq(home,(static_cast<double>(x0.min()) *
00306 static_cast<double>(x1.min()))));
00307 double u = static_cast<double>(x0.max()) * static_cast<double>(x1.max());
00308 if (u > INT_MAX) {
00309 (void) new (home) MultPlusBnd<double,VA,VB,VC>(home,x0,x1,x2);
00310 } else {
00311 GECODE_ME_CHECK(x2.lq(home,u));
00312 (void) new (home) MultPlusBnd<int,VA,VB,VC>(home,x0,x1,x2);
00313 }
00314 return ES_OK;
00315 }
00316
00317
00318
00319
00320
00321
00322 template <class View>
00323 forceinline
00324 MultBnd<View>::MultBnd(Space& home, View x0, View x1, View x2)
00325 : TernaryPropagator<View,PC_INT_BND>(home,x0,x1,x2) {}
00326
00327 template <class View>
00328 forceinline
00329 MultBnd<View>::MultBnd(Space& home, bool share, MultBnd<View>& p)
00330 : TernaryPropagator<View,PC_INT_BND>(home,share,p) {}
00331
00332 template <class View>
00333 Actor*
00334 MultBnd<View>::copy(Space& home, bool share) {
00335 return new (home) MultBnd<View>(home,share,*this);
00336 }
00337
00338 template <class View>
00339 ExecStatus
00340 MultBnd<View>::propagate(Space& home, const ModEventDelta&) {
00341 if (pos(x0)) {
00342 if (pos(x1) || pos(x2)) goto rewrite_ppp;
00343 if (neg(x1) || neg(x2)) goto rewrite_pnn;
00344 goto prop_pxx;
00345 }
00346 if (neg(x0)) {
00347 if (neg(x1) || pos(x2)) goto rewrite_nnp;
00348 if (pos(x1) || neg(x2)) goto rewrite_npn;
00349 goto prop_nxx;
00350 }
00351 if (pos(x1)) {
00352 if (pos(x2)) goto rewrite_ppp;
00353 if (neg(x2)) goto rewrite_npn;
00354 goto prop_xpx;
00355 }
00356 if (neg(x1)) {
00357 if (pos(x2)) goto rewrite_nnp;
00358 if (neg(x2)) goto rewrite_pnn;
00359 goto prop_xnx;
00360 }
00361
00362 assert(any(x0) && any(x1));
00363 GECODE_ME_CHECK(x2.lq(home,std::max(m<double>(x0.max(),x1.max()),
00364 m<double>(x0.min(),x1.min()))));
00365 GECODE_ME_CHECK(x2.gq(home,std::min(m<double>(x0.min(),x1.max()),
00366 m<double>(x0.max(),x1.min()))));
00367
00368 if (x0.assigned()) {
00369 assert((x0.val() == 0) && (x2.val() == 0));
00370 return ES_SUBSUMED(*this,home);
00371 }
00372
00373 if (x1.assigned()) {
00374 assert((x1.val() == 0) && (x2.val() == 0));
00375 return ES_SUBSUMED(*this,home);
00376 }
00377
00378 return ES_NOFIX;
00379
00380 prop_xpx:
00381 std::swap(x0,x1);
00382 prop_pxx:
00383 assert(pos(x0) && any(x1) && any(x2));
00384
00385 GECODE_ME_CHECK(x2.lq(home,m<double>(x0.max(),x1.max())));
00386 GECODE_ME_CHECK(x2.gq(home,m<double>(x0.max(),x1.min())));
00387
00388 if (pos(x2)) goto rewrite_ppp;
00389 if (neg(x2)) goto rewrite_pnn;
00390
00391 GECODE_ME_CHECK(x1.lq(home,f_d(x2.max(),x0.min())));
00392 GECODE_ME_CHECK(x1.gq(home,c_d(x2.min(),x0.min())));
00393
00394 if (x0.assigned() && x1.assigned()) {
00395 GECODE_ME_CHECK(x2.eq(home,m<double>(x0.val(),x1.val())));
00396 return ES_SUBSUMED(*this,sizeof(*this));
00397 }
00398
00399 return ES_NOFIX;
00400
00401 prop_xnx:
00402 std::swap(x0,x1);
00403 prop_nxx:
00404 assert(neg(x0) && any(x1) && any(x2));
00405
00406 GECODE_ME_CHECK(x2.lq(home,m<double>(x0.min(),x1.min())));
00407 GECODE_ME_CHECK(x2.gq(home,m<double>(x0.min(),x1.max())));
00408
00409 if (pos(x2)) goto rewrite_nnp;
00410 if (neg(x2)) goto rewrite_npn;
00411
00412 GECODE_ME_CHECK(x1.lq(home,f_d(x2.min(),x0.max())));
00413 GECODE_ME_CHECK(x1.gq(home,c_d(x2.max(),x0.max())));
00414
00415 if (x0.assigned() && x1.assigned()) {
00416 GECODE_ME_CHECK(x2.eq(home,m<double>(x0.val(),x1.val())));
00417 return ES_SUBSUMED(*this,sizeof(*this));
00418 }
00419
00420 return ES_NOFIX;
00421
00422 rewrite_ppp:
00423 GECODE_REWRITE(*this,(MultPlusBnd<double,IntView,IntView,IntView>
00424 ::post(home,x0,x1,x2)));
00425 rewrite_nnp:
00426 GECODE_REWRITE(*this,(MultPlusBnd<double,MinusView,MinusView,IntView>
00427 ::post(home,x0,x1,x2)));
00428 rewrite_pnn:
00429 std::swap(x0,x1);
00430 rewrite_npn:
00431 GECODE_REWRITE(*this,(MultPlusBnd<double,MinusView,IntView,MinusView>
00432 ::post(home,x0,x1,x2)));
00433 }
00434
00435 template <class View>
00436 ExecStatus
00437 MultBnd<View>::post(Space& home, View x0, View x1, View x2) {
00438 if (same(x0,x1))
00439 return SqrBnd<View>::post(home,x0,x2);
00440 if (same(x0,x2))
00441 return MultZeroOne<View,PC_INT_BND>::post(home,x0,x1);
00442 if (same(x1,x2))
00443 return MultZeroOne<View,PC_INT_BND>::post(home,x1,x0);
00444 if (pos(x0)) {
00445 if (pos(x1) || pos(x2)) goto post_ppp;
00446 if (neg(x1) || neg(x2)) goto post_pnn;
00447 } else if (neg(x0)) {
00448 if (neg(x1) || pos(x2)) goto post_nnp;
00449 if (pos(x1) || neg(x2)) goto post_npn;
00450 } else if (pos(x1)) {
00451 if (pos(x2)) goto post_ppp;
00452 if (neg(x2)) goto post_npn;
00453 } else if (neg(x1)) {
00454 if (pos(x2)) goto post_nnp;
00455 if (neg(x2)) goto post_pnn;
00456 }
00457 {
00458 double a =
00459 static_cast<double>(x0.min()) * static_cast<double>(x1.min());
00460 double b =
00461 static_cast<double>(x0.min()) * static_cast<double>(x1.max());
00462 double c =
00463 static_cast<double>(x0.max()) * static_cast<double>(x1.min());
00464 double d =
00465 static_cast<double>(x0.max()) * static_cast<double>(x1.max());
00466 GECODE_ME_CHECK(x2.gq(home,std::min(std::min(a,b),std::min(c,d))));
00467 GECODE_ME_CHECK(x2.lq(home,std::max(std::max(a,b),std::max(c,d))));
00468 (void) new (home) MultBnd<View>(home,x0,x1,x2);
00469 }
00470 return ES_OK;
00471
00472 post_ppp:
00473 return MultPlusBnd<double,IntView,IntView,IntView>::post(home,x0,x1,x2);
00474 post_nnp:
00475 return MultPlusBnd<double,MinusView,MinusView,IntView>::post(home,x0,x1,x2);
00476 post_pnn:
00477 std::swap(x0,x1);
00478 post_npn:
00479 return MultPlusBnd<double,MinusView,IntView,MinusView>::post(home,x0,x1,x2);
00480 }
00481
00482
00483
00484
00485
00486
00487 template <class Val, class View>
00488 forceinline ExecStatus
00489 prop_mult_dom(Space& home, Propagator& p, View x0, View x1, View x2) {
00490 Region r(home);
00491 SupportValues<View,Region> s0(r,x0), s1(r,x1), s2(r,x2);
00492 while (s0()) {
00493 while (s1()) {
00494 if (s2.support(m<Val>(s0.val(),s1.val()))) {
00495 s0.support(); s1.support();
00496 }
00497 ++s1;
00498 }
00499 s1.reset(); ++s0;
00500 }
00501 GECODE_ME_CHECK(s0.tell(home));
00502 GECODE_ME_CHECK(s1.tell(home));
00503 GECODE_ME_CHECK(s2.tell(home));
00504 return x0.assigned() && x1.assigned() ? ES_SUBSUMED(p,sizeof(p)) : ES_FIX;
00505 }
00506
00507 template <class Val, class VA, class VB, class VC>
00508 forceinline
00509 MultPlusDom<Val,VA,VB,VC>::MultPlusDom(Space& home, VA x0, VB x1, VC x2)
00510 : MixTernaryPropagator<VA,PC_INT_DOM,VB,PC_INT_DOM,VC,PC_INT_DOM>
00511 (home,x0,x1,x2) {}
00512
00513 template <class Val, class VA, class VB, class VC>
00514 forceinline
00515 MultPlusDom<Val,VA,VB,VC>::MultPlusDom(Space& home, bool share,
00516 MultPlusDom<Val,VA,VB,VC>& p)
00517 : MixTernaryPropagator<VA,PC_INT_DOM,VB,PC_INT_DOM,VC,PC_INT_DOM>
00518 (home,share,p) {}
00519
00520 template <class Val, class VA, class VB, class VC>
00521 Actor*
00522 MultPlusDom<Val,VA,VB,VC>::copy(Space& home, bool share) {
00523 return new (home) MultPlusDom<Val,VA,VB,VC>(home,share,*this);
00524 }
00525
00526 template <class Val, class VA, class VB, class VC>
00527 PropCost
00528 MultPlusDom<Val,VA,VB,VC>::cost(const Space&,
00529 const ModEventDelta& med) const {
00530 if (VA::me(med) == ME_INT_DOM)
00531 return PropCost::ternary(PropCost::HI);
00532 else
00533 return PropCost::ternary(PropCost::LO);
00534 }
00535
00536 template <class Val, class VA, class VB, class VC>
00537 ExecStatus
00538 MultPlusDom<Val,VA,VB,VC>::propagate(Space& home, const ModEventDelta& med) {
00539 if (VA::me(med) != ME_INT_DOM) {
00540 GECODE_ES_CHECK((prop_mult_plus_bnd<Val,VA,VB,VC>(home,*this,x0,x1,x2)));
00541 return ES_FIX_PARTIAL(*this,VA::med(ME_INT_DOM));
00542 }
00543 IntView y0(x0.var()), y1(x1.var()), y2(x2.var());
00544 return prop_mult_dom<Val,IntView>(home,*this,y0,y1,y2);
00545 }
00546
00547 template <class Val, class VA, class VB, class VC>
00548 forceinline ExecStatus
00549 MultPlusDom<Val,VA,VB,VC>::post(Space& home, VA x0, VB x1, VC x2) {
00550 GECODE_ME_CHECK(x0.gr(home,0));
00551 GECODE_ME_CHECK(x1.gr(home,0));
00552 GECODE_ME_CHECK(x2.gq(home,(static_cast<double>(x0.min()) *
00553 static_cast<double>(x1.min()))));
00554 double u = static_cast<double>(x0.max()) * static_cast<double>(x1.max());
00555 if (u > INT_MAX) {
00556 (void) new (home) MultPlusDom<double,VA,VB,VC>(home,x0,x1,x2);
00557 } else {
00558 GECODE_ME_CHECK(x2.lq(home,u));
00559 (void) new (home) MultPlusDom<int,VA,VB,VC>(home,x0,x1,x2);
00560 }
00561 return ES_OK;
00562 }
00563
00564
00565
00566
00567
00568
00569 template <class View>
00570 forceinline
00571 MultDom<View>::MultDom(Space& home, View x0, View x1, View x2)
00572 : TernaryPropagator<View,PC_INT_DOM>(home,x0,x1,x2) {}
00573
00574 template <class View>
00575 forceinline
00576 MultDom<View>::MultDom(Space& home, bool share, MultDom<View>& p)
00577 : TernaryPropagator<View,PC_INT_DOM>(home,share,p) {}
00578
00579 template <class View>
00580 Actor*
00581 MultDom<View>::copy(Space& home, bool share) {
00582 return new (home) MultDom<View>(home,share,*this);
00583 }
00584
00585 template <class View>
00586 PropCost
00587 MultDom<View>::cost(const Space&, const ModEventDelta& med) const {
00588 if (View::me(med) == ME_INT_DOM)
00589 return PropCost::ternary(PropCost::HI);
00590 else
00591 return PropCost::ternary(PropCost::LO);
00592 }
00593
00594 template <class View>
00595 ExecStatus
00596 MultDom<View>::propagate(Space& home, const ModEventDelta& med) {
00597 if (View::me(med) != ME_INT_DOM) {
00598 if (pos(x0)) {
00599 if (pos(x1) || pos(x2)) goto rewrite_ppp;
00600 if (neg(x1) || neg(x2)) goto rewrite_pnn;
00601 goto prop_pxx;
00602 }
00603 if (neg(x0)) {
00604 if (neg(x1) || pos(x2)) goto rewrite_nnp;
00605 if (pos(x1) || neg(x2)) goto rewrite_npn;
00606 goto prop_nxx;
00607 }
00608 if (pos(x1)) {
00609 if (pos(x2)) goto rewrite_ppp;
00610 if (neg(x2)) goto rewrite_npn;
00611 goto prop_xpx;
00612 }
00613 if (neg(x1)) {
00614 if (pos(x2)) goto rewrite_nnp;
00615 if (neg(x2)) goto rewrite_pnn;
00616 goto prop_xnx;
00617 }
00618
00619 assert(any(x0) && any(x1));
00620 GECODE_ME_CHECK(x2.lq(home,std::max(m<double>(x0.max(),x1.max()),
00621 m<double>(x0.min(),x1.min()))));
00622 GECODE_ME_CHECK(x2.gq(home,std::min(m<double>(x0.min(),x1.max()),
00623 m<double>(x0.max(),x1.min()))));
00624
00625 if (x0.assigned()) {
00626 assert((x0.val() == 0) && (x2.val() == 0));
00627 return ES_SUBSUMED(*this,home);
00628 }
00629
00630 if (x1.assigned()) {
00631 assert((x1.val() == 0) && (x2.val() == 0));
00632 return ES_SUBSUMED(*this,home);
00633 }
00634
00635 return ES_NOFIX_PARTIAL(*this,View::med(ME_INT_DOM));
00636
00637 prop_xpx:
00638 std::swap(x0,x1);
00639 prop_pxx:
00640 assert(pos(x0) && any(x1) && any(x2));
00641
00642 GECODE_ME_CHECK(x2.lq(home,m<double>(x0.max(),x1.max())));
00643 GECODE_ME_CHECK(x2.gq(home,m<double>(x0.max(),x1.min())));
00644
00645 if (pos(x2)) goto rewrite_ppp;
00646 if (neg(x2)) goto rewrite_pnn;
00647
00648 GECODE_ME_CHECK(x1.lq(home,f_d(x2.max(),x0.min())));
00649 GECODE_ME_CHECK(x1.gq(home,c_d(x2.min(),x0.min())));
00650
00651 if (x0.assigned() && x1.assigned()) {
00652 GECODE_ME_CHECK(x2.eq(home,m<double>(x0.val(),x1.val())));
00653 return ES_SUBSUMED(*this,sizeof(*this));
00654 }
00655
00656 return ES_NOFIX_PARTIAL(*this,View::med(ME_INT_DOM));
00657
00658 prop_xnx:
00659 std::swap(x0,x1);
00660 prop_nxx:
00661 assert(neg(x0) && any(x1) && any(x2));
00662
00663 GECODE_ME_CHECK(x2.lq(home,m<double>(x0.min(),x1.min())));
00664 GECODE_ME_CHECK(x2.gq(home,m<double>(x0.min(),x1.max())));
00665
00666 if (pos(x2)) goto rewrite_nnp;
00667 if (neg(x2)) goto rewrite_npn;
00668
00669 GECODE_ME_CHECK(x1.lq(home,f_d(x2.min(),x0.max())));
00670 GECODE_ME_CHECK(x1.gq(home,c_d(x2.max(),x0.max())));
00671
00672 if (x0.assigned() && x1.assigned()) {
00673 GECODE_ME_CHECK(x2.eq(home,m<double>(x0.val(),x1.val())));
00674 return ES_SUBSUMED(*this,sizeof(*this));
00675 }
00676
00677 return ES_NOFIX_PARTIAL(*this,View::med(ME_INT_DOM));
00678
00679 rewrite_ppp:
00680 GECODE_REWRITE(*this,(MultPlusDom<double,IntView,IntView,IntView>
00681 ::post(home,x0,x1,x2)));
00682 rewrite_nnp:
00683 GECODE_REWRITE(*this,(MultPlusDom<double,MinusView,MinusView,IntView>
00684 ::post(home,x0,x1,x2)));
00685 rewrite_pnn:
00686 std::swap(x0,x1);
00687 rewrite_npn:
00688 GECODE_REWRITE(*this,(MultPlusDom<double,MinusView,IntView,MinusView>
00689 ::post(home,x0,x1,x2)));
00690 }
00691 return prop_mult_dom<double,View>(home,*this,x0,x1,x2);
00692 }
00693
00694 template <class View>
00695 ExecStatus
00696 MultDom<View>::post(Space& home, View x0, View x1, View x2) {
00697 if (same(x0,x1))
00698 return SqrDom<View>::post(home,x0,x2);
00699 if (same(x0,x2))
00700 return MultZeroOne<View,PC_INT_DOM>::post(home,x0,x1);
00701 if (same(x1,x2))
00702 return MultZeroOne<View,PC_INT_DOM>::post(home,x1,x0);
00703 if (pos(x0)) {
00704 if (pos(x1) || pos(x2)) goto post_ppp;
00705 if (neg(x1) || neg(x2)) goto post_pnn;
00706 } else if (neg(x0)) {
00707 if (neg(x1) || pos(x2)) goto post_nnp;
00708 if (pos(x1) || neg(x2)) goto post_npn;
00709 } else if (pos(x1)) {
00710 if (pos(x2)) goto post_ppp;
00711 if (neg(x2)) goto post_npn;
00712 } else if (neg(x1)) {
00713 if (pos(x2)) goto post_nnp;
00714 if (neg(x2)) goto post_pnn;
00715 }
00716 {
00717 double a =
00718 static_cast<double>(x0.min()) * static_cast<double>(x1.min());
00719 double b =
00720 static_cast<double>(x0.min()) * static_cast<double>(x1.max());
00721 double c =
00722 static_cast<double>(x0.max()) * static_cast<double>(x1.min());
00723 double d =
00724 static_cast<double>(x0.max()) * static_cast<double>(x1.max());
00725 GECODE_ME_CHECK(x2.gq(home,std::min(std::min(a,b),std::min(c,d))));
00726 GECODE_ME_CHECK(x2.lq(home,std::max(std::max(a,b),std::max(c,d))));
00727 (void) new (home) MultDom<View>(home,x0,x1,x2);
00728 }
00729 return ES_OK;
00730
00731 post_ppp:
00732 return MultPlusDom<double,IntView,IntView,IntView>::post(home,x0,x1,x2);
00733 post_nnp:
00734 return MultPlusDom<double,MinusView,MinusView,IntView>::post(home,x0,x1,x2);
00735 post_pnn:
00736 std::swap(x0,x1);
00737 post_npn:
00738 return MultPlusDom<double,MinusView,IntView,MinusView>::post(home,x0,x1,x2);
00739 }
00740
00741 }}}
00742
00743
00744