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 void
00192 MultZeroOne<View,pc>::post(Space* home, Reflection::VarMap& vars,
00193 const Reflection::ActorSpec& spec) {
00194 spec.checkArity(2);
00195 View x0(home, vars, spec[0]);
00196 View x1(home, vars, spec[1]);
00197 (void) new (home) MultZeroOne<View,pc>(home,x0,x1);
00198 }
00199
00200 template <class View, PropCond pc>
00201 forceinline
00202 MultZeroOne<View,pc>::MultZeroOne(Space* home, bool share,
00203 MultZeroOne<View,pc>& p)
00204 : BinaryPropagator<View,pc>(home,share,p) {}
00205
00206 template <class View, PropCond pc>
00207 Actor*
00208 MultZeroOne<View,pc>::copy(Space* home, bool share) {
00209 return new (home) MultZeroOne<View,pc>(home,share,*this);
00210 }
00211
00212 template <class View, PropCond pc>
00213 ExecStatus
00214 MultZeroOne<View,pc>::propagate(Space* home, ModEventDelta) {
00215 switch (equal(x0,0)) {
00216 case RT_FALSE:
00217 GECODE_ME_CHECK(x1.eq(home,1));
00218 break;
00219 case RT_TRUE:
00220 break;
00221 case RT_MAYBE:
00222 switch (equal(x1,1)) {
00223 case RT_FALSE:
00224 GECODE_ME_CHECK(x0.eq(home,0));
00225 break;
00226 case RT_TRUE:
00227 break;
00228 case RT_MAYBE:
00229 return ES_FIX;
00230 default: GECODE_NEVER;
00231 }
00232 break;
00233 default: GECODE_NEVER;
00234 }
00235 return ES_SUBSUMED(this,home);
00236 }
00237
00238 template <class View, PropCond pc>
00239 Support::Symbol
00240 MultZeroOne<View,pc>::ati(void) {
00241 return Reflection::mangle<View>
00242 ("Gecode::Int::Arithmetic::MultZeroOne", pc);
00243 }
00244
00245 template <class View, PropCond pc>
00246 Reflection::ActorSpec
00247 MultZeroOne<View,pc>::spec(const Space* home, Reflection::VarMap& m) const {
00248 return BinaryPropagator<View,pc>::spec(home, m, ati());
00249 }
00250
00251
00252
00253
00254
00255
00256 template <class Val, class VA, class VB, class VC>
00257 forceinline ExecStatus
00258 prop_mult_plus_bnd(Space* home, Propagator* p, VA x0, VB x1, VC x2) {
00259 assert(pos(x0) && pos(x1) && pos(x2));
00260 bool mod;
00261 do {
00262 mod = false;
00263 {
00264 ModEvent me = x2.lq(home,m<Val>(x0.max(),x1.max()));
00265 if (me_failed(me)) return ES_FAILED;
00266 mod |= me_modified(me);
00267 }
00268 {
00269 ModEvent me = x2.gq(home,m<Val>(x0.min(),x1.min()));
00270 if (me_failed(me)) return ES_FAILED;
00271 mod |= me_modified(me);
00272 }
00273 {
00274 ModEvent me = x0.lq(home,f_d_p<Val>(x2.max(),x1.min()));
00275 if (me_failed(me)) return ES_FAILED;
00276 mod |= me_modified(me);
00277 }
00278 {
00279 ModEvent me = x0.gq(home,c_d_p<Val>(x2.min(),x1.max()));
00280 if (me_failed(me)) return ES_FAILED;
00281 mod |= me_modified(me);
00282 }
00283 {
00284 ModEvent me = x1.lq(home,f_d_p<Val>(x2.max(),x0.min()));
00285 if (me_failed(me)) return ES_FAILED;
00286 mod |= me_modified(me);
00287 }
00288 {
00289 ModEvent me = x1.gq(home,c_d_p<Val>(x2.min(),x0.max()));
00290 if (me_failed(me)) return ES_FAILED;
00291 mod |= me_modified(me);
00292 }
00293 } while (mod);
00294 return x0.assigned() && x1.assigned() ?
00295 ES_SUBSUMED(p,sizeof(*p)) : ES_FIX;
00296 }
00297
00298 template <class Val, class VA, class VB, class VC>
00299 forceinline
00300 MultPlusBnd<Val,VA,VB,VC>::MultPlusBnd(Space* home, VA x0, VB x1, VC x2)
00301 : MixTernaryPropagator<VA,PC_INT_BND,VB,PC_INT_BND,VC,PC_INT_BND>
00302 (home,x0,x1,x2) {}
00303
00304 template <class Val, class VA, class VB, class VC>
00305 forceinline
00306 MultPlusBnd<Val,VA,VB,VC>::MultPlusBnd(Space* home, bool share,
00307 MultPlusBnd<Val,VA,VB,VC>& p)
00308 : MixTernaryPropagator<VA,PC_INT_BND,VB,PC_INT_BND,VC,PC_INT_BND>
00309 (home,share,p) {}
00310
00311 template <class Val, class VA, class VB, class VC>
00312 Actor*
00313 MultPlusBnd<Val,VA,VB,VC>::copy(Space* home, bool share) {
00314 return new (home) MultPlusBnd<Val,VA,VB,VC>(home,share,*this);
00315 }
00316
00317 template <class Val, class VA, class VB, class VC>
00318 ExecStatus
00319 MultPlusBnd<Val,VA,VB,VC>::propagate(Space* home, ModEventDelta) {
00320 return prop_mult_plus_bnd<Val,VA,VB,VC>(home,this,x0,x1,x2);
00321 }
00322
00323 template <class Val, class VA, class VB, class VC>
00324 forceinline ExecStatus
00325 MultPlusBnd<Val,VA,VB,VC>::post(Space* home, VA x0, VB x1, VC x2) {
00326 GECODE_ME_CHECK(x0.gr(home,0));
00327 GECODE_ME_CHECK(x1.gr(home,0));
00328 GECODE_ME_CHECK(x2.gq(home,(static_cast<double>(x0.min()) *
00329 static_cast<double>(x1.min()))));
00330 double u = static_cast<double>(x0.max()) * static_cast<double>(x1.max());
00331 if (u > INT_MAX) {
00332 (void) new (home) MultPlusBnd<double,VA,VB,VC>(home,x0,x1,x2);
00333 } else {
00334 GECODE_ME_CHECK(x2.lq(home,u));
00335 (void) new (home) MultPlusBnd<int,VA,VB,VC>(home,x0,x1,x2);
00336 }
00337 return ES_OK;
00338 }
00339
00340 template <class Val, class VA, class VB, class VC>
00341 forceinline void
00342 MultPlusBnd<Val,VA,VB,VC>::post(Space* home, Reflection::VarMap& vars,
00343 const Reflection::ActorSpec& spec) {
00344 spec.checkArity(3);
00345 VA x0(home, vars, spec[0]);
00346 VB x1(home, vars, spec[1]);
00347 VC x2(home, vars, spec[2]);
00348 (void) new (home) MultPlusBnd<Val,VA,VB,VC>(home,x0,x1,x2);
00349 }
00350
00351 template <class Val, class VA, class VB, class VC>
00352 Support::Symbol
00353 MultPlusBnd<Val,VA,VB,VC>::ati(void) {
00354 return Reflection::mangle<VA,VB,VC,Val>
00355 ("Gecode::Int::Arithmetic::MultPlusBnd");
00356 }
00357
00358 template <class Val, class VA, class VB, class VC>
00359 Reflection::ActorSpec
00360 MultPlusBnd<Val,VA,VB,VC>::spec(const Space* home,
00361 Reflection::VarMap& m) const {
00362 return MixTernaryPropagator<VA,PC_INT_BND,VB,PC_INT_BND,VC,PC_INT_BND>
00363 ::spec(home, m, ati());
00364 }
00365
00366
00367
00368
00369
00370
00371 template <class View>
00372 forceinline
00373 MultBnd<View>::MultBnd(Space* home, View x0, View x1, View x2)
00374 : TernaryPropagator<View,PC_INT_BND>(home,x0,x1,x2) {}
00375
00376 template <class View>
00377 forceinline
00378 MultBnd<View>::MultBnd(Space* home, bool share, MultBnd<View>& p)
00379 : TernaryPropagator<View,PC_INT_BND>(home,share,p) {}
00380
00381 template <class View>
00382 Actor*
00383 MultBnd<View>::copy(Space* home, bool share) {
00384 return new (home) MultBnd<View>(home,share,*this);
00385 }
00386
00387 template <class View>
00388 ExecStatus
00389 MultBnd<View>::propagate(Space* home, ModEventDelta) {
00390 if (pos(x0)) {
00391 if (pos(x1) || pos(x2)) goto rewrite_ppp;
00392 if (neg(x1) || neg(x2)) goto rewrite_pnn;
00393 goto prop_pxx;
00394 }
00395 if (neg(x0)) {
00396 if (neg(x1) || pos(x2)) goto rewrite_nnp;
00397 if (pos(x1) || neg(x2)) goto rewrite_npn;
00398 goto prop_nxx;
00399 }
00400 if (pos(x1)) {
00401 if (pos(x2)) goto rewrite_ppp;
00402 if (neg(x2)) goto rewrite_npn;
00403 goto prop_xpx;
00404 }
00405 if (neg(x1)) {
00406 if (pos(x2)) goto rewrite_nnp;
00407 if (neg(x2)) goto rewrite_pnn;
00408 goto prop_xnx;
00409 }
00410
00411 assert(any(x0) && any(x1));
00412 GECODE_ME_CHECK(x2.lq(home,std::max(m<double>(x0.max(),x1.max()),
00413 m<double>(x0.min(),x1.min()))));
00414 GECODE_ME_CHECK(x2.gq(home,std::min(m<double>(x0.min(),x1.max()),
00415 m<double>(x0.max(),x1.min()))));
00416
00417 if (x0.assigned()) {
00418 assert((x0.val() == 0) && (x2.val() == 0));
00419 return ES_SUBSUMED(this,home);
00420 }
00421
00422 if (x1.assigned()) {
00423 assert((x1.val() == 0) && (x2.val() == 0));
00424 return ES_SUBSUMED(this,home);
00425 }
00426
00427 return ES_NOFIX;
00428
00429 prop_xpx:
00430 std::swap(x0,x1);
00431 prop_pxx:
00432 assert(pos(x0) && any(x1) && any(x2));
00433
00434 GECODE_ME_CHECK(x2.lq(home,m<double>(x0.max(),x1.max())));
00435 GECODE_ME_CHECK(x2.gq(home,m<double>(x0.max(),x1.min())));
00436
00437 if (pos(x2)) goto rewrite_ppp;
00438 if (neg(x2)) goto rewrite_pnn;
00439
00440 GECODE_ME_CHECK(x1.lq(home,f_d(x2.max(),x0.min())));
00441 GECODE_ME_CHECK(x1.gq(home,c_d(x2.min(),x0.min())));
00442
00443 if (x0.assigned() && x1.assigned()) {
00444 GECODE_ME_CHECK(x2.eq(home,m<double>(x0.val(),x1.val())));
00445 return ES_SUBSUMED(this,sizeof(*this));
00446 }
00447
00448 return ES_NOFIX;
00449
00450 prop_xnx:
00451 std::swap(x0,x1);
00452 prop_nxx:
00453 assert(neg(x0) && any(x1) && any(x2));
00454
00455 GECODE_ME_CHECK(x2.lq(home,m<double>(x0.min(),x1.min())));
00456 GECODE_ME_CHECK(x2.gq(home,m<double>(x0.min(),x1.max())));
00457
00458 if (pos(x2)) goto rewrite_nnp;
00459 if (neg(x2)) goto rewrite_npn;
00460
00461 GECODE_ME_CHECK(x1.lq(home,f_d(x2.min(),x0.max())));
00462 GECODE_ME_CHECK(x1.gq(home,c_d(x2.max(),x0.max())));
00463
00464 if (x0.assigned() && x1.assigned()) {
00465 GECODE_ME_CHECK(x2.eq(home,m<double>(x0.val(),x1.val())));
00466 return ES_SUBSUMED(this,sizeof(*this));
00467 }
00468
00469 return ES_NOFIX;
00470
00471 rewrite_ppp:
00472 GECODE_REWRITE(this,(MultPlusBnd<double,IntView,IntView,IntView>
00473 ::post(home,x0,x1,x2)));
00474 rewrite_nnp:
00475 GECODE_REWRITE(this,(MultPlusBnd<double,MinusView,MinusView,IntView>
00476 ::post(home,x0,x1,x2)));
00477 rewrite_pnn:
00478 std::swap(x0,x1);
00479 rewrite_npn:
00480 GECODE_REWRITE(this,(MultPlusBnd<double,MinusView,IntView,MinusView>
00481 ::post(home,x0,x1,x2)));
00482 }
00483
00484 template <class View>
00485 ExecStatus
00486 MultBnd<View>::post(Space* home, View x0, View x1, View x2) {
00487 if (same(x0,x1))
00488 return SqrBnd<View>::post(home,x0,x2);
00489 if (same(x0,x2))
00490 return MultZeroOne<View,PC_INT_BND>::post(home,x0,x1);
00491 if (same(x1,x2))
00492 return MultZeroOne<View,PC_INT_BND>::post(home,x1,x0);
00493 if (pos(x0)) {
00494 if (pos(x1) || pos(x2)) goto post_ppp;
00495 if (neg(x1) || neg(x2)) goto post_pnn;
00496 } else if (neg(x0)) {
00497 if (neg(x1) || pos(x2)) goto post_nnp;
00498 if (pos(x1) || neg(x2)) goto post_npn;
00499 } else if (pos(x1)) {
00500 if (pos(x2)) goto post_ppp;
00501 if (neg(x2)) goto post_npn;
00502 } else if (neg(x1)) {
00503 if (pos(x2)) goto post_nnp;
00504 if (neg(x2)) goto post_pnn;
00505 }
00506 {
00507 double a =
00508 static_cast<double>(x0.min()) * static_cast<double>(x1.min());
00509 double b =
00510 static_cast<double>(x0.min()) * static_cast<double>(x1.max());
00511 double c =
00512 static_cast<double>(x0.max()) * static_cast<double>(x1.min());
00513 double d =
00514 static_cast<double>(x0.max()) * static_cast<double>(x1.max());
00515 GECODE_ME_CHECK(x2.gq(home,std::min(std::min(a,b),std::min(c,d))));
00516 GECODE_ME_CHECK(x2.lq(home,std::max(std::max(a,b),std::max(c,d))));
00517 (void) new (home) MultBnd<View>(home,x0,x1,x2);
00518 }
00519 return ES_OK;
00520
00521 post_ppp:
00522 return MultPlusBnd<double,IntView,IntView,IntView>::post(home,x0,x1,x2);
00523 post_nnp:
00524 return MultPlusBnd<double,MinusView,MinusView,IntView>::post(home,x0,x1,x2);
00525 post_pnn:
00526 std::swap(x0,x1);
00527 post_npn:
00528 return MultPlusBnd<double,MinusView,IntView,MinusView>::post(home,x0,x1,x2);
00529 }
00530
00531 template <class View>
00532 forceinline void
00533 MultBnd<View>::post(Space* home, Reflection::VarMap& vars,
00534 const Reflection::ActorSpec& spec) {
00535 spec.checkArity(3);
00536 View x0(home, vars, spec[0]);
00537 View x1(home, vars, spec[1]);
00538 View x2(home, vars, spec[2]);
00539 (void) new (home) MultBnd<View>(home,x0,x1,x2);
00540 }
00541
00542 template <class View>
00543 Support::Symbol
00544 MultBnd<View>::ati(void) {
00545 return Reflection::mangle<View>("Gecode::Int::Arithmetic::MultBnd");
00546 }
00547
00548 template <class View>
00549 Reflection::ActorSpec
00550 MultBnd<View>::spec(const Space* home, Reflection::VarMap& m) const {
00551 return TernaryPropagator<View,PC_INT_BND>::spec(home, m, ati());
00552 }
00553
00554
00555
00556
00557
00558
00559
00560 template <class Val, class View>
00561 forceinline ExecStatus
00562 prop_mult_dom(Space* home, Propagator* p, View x0, View x1, View x2) {
00563 SupportValues<View> s0(x0), s1(x1), s2(x2);
00564 while (s0()) {
00565 while (s1()) {
00566 if (s2.support(m<Val>(s0.val(),s1.val()))) {
00567 s0.support(); s1.support();
00568 }
00569 ++s1;
00570 }
00571 s1.reset(); ++s0;
00572 }
00573 GECODE_ME_CHECK(s0.tell(home));
00574 GECODE_ME_CHECK(s1.tell(home));
00575 GECODE_ME_CHECK(s2.tell(home));
00576 return x0.assigned() && x1.assigned() ? ES_SUBSUMED(p,sizeof(*p)) : ES_FIX;
00577 }
00578
00579 template <class Val, class VA, class VB, class VC>
00580 forceinline
00581 MultPlusDom<Val,VA,VB,VC>::MultPlusDom(Space* home, VA x0, VB x1, VC x2)
00582 : MixTernaryPropagator<VA,PC_INT_DOM,VB,PC_INT_DOM,VC,PC_INT_DOM>
00583 (home,x0,x1,x2) {}
00584
00585 template <class Val, class VA, class VB, class VC>
00586 forceinline
00587 MultPlusDom<Val,VA,VB,VC>::MultPlusDom(Space* home, bool share,
00588 MultPlusDom<Val,VA,VB,VC>& p)
00589 : MixTernaryPropagator<VA,PC_INT_DOM,VB,PC_INT_DOM,VC,PC_INT_DOM>
00590 (home,share,p) {}
00591
00592 template <class Val, class VA, class VB, class VC>
00593 Actor*
00594 MultPlusDom<Val,VA,VB,VC>::copy(Space* home, bool share) {
00595 return new (home) MultPlusDom<Val,VA,VB,VC>(home,share,*this);
00596 }
00597
00598 template <class Val, class VA, class VB, class VC>
00599 PropCost
00600 MultPlusDom<Val,VA,VB,VC>::cost(ModEventDelta med) const {
00601 return (VA::me(med) == ME_INT_DOM) ? PC_TERNARY_HI : PC_TERNARY_LO;
00602 }
00603
00604 template <class Val, class VA, class VB, class VC>
00605 ExecStatus
00606 MultPlusDom<Val,VA,VB,VC>::propagate(Space* home, ModEventDelta med) {
00607 if (VA::me(med) != ME_INT_DOM) {
00608 GECODE_ES_CHECK((prop_mult_plus_bnd<Val,VA,VB,VC>(home,this,x0,x1,x2)));
00609 return ES_FIX_PARTIAL(this,VA::med(ME_INT_DOM));
00610 }
00611 IntView y0(x0.var()), y1(x1.var()), y2(x2.var());
00612 return prop_mult_dom<Val,IntView>(home,this,y0,y1,y2);
00613 }
00614
00615 template <class Val, class VA, class VB, class VC>
00616 forceinline ExecStatus
00617 MultPlusDom<Val,VA,VB,VC>::post(Space* home, VA x0, VB x1, VC x2) {
00618 GECODE_ME_CHECK(x0.gr(home,0));
00619 GECODE_ME_CHECK(x1.gr(home,0));
00620 GECODE_ME_CHECK(x2.gq(home,(static_cast<double>(x0.min()) *
00621 static_cast<double>(x1.min()))));
00622 double u = static_cast<double>(x0.max()) * static_cast<double>(x1.max());
00623 if (u > INT_MAX) {
00624 (void) new (home) MultPlusDom<double,VA,VB,VC>(home,x0,x1,x2);
00625 } else {
00626 GECODE_ME_CHECK(x2.lq(home,u));
00627 (void) new (home) MultPlusDom<int,VA,VB,VC>(home,x0,x1,x2);
00628 }
00629 return ES_OK;
00630 }
00631
00632 template <class Val, class VA, class VB, class VC>
00633 forceinline void
00634 MultPlusDom<Val,VA,VB,VC>::post(Space* home, Reflection::VarMap& vars,
00635 const Reflection::ActorSpec& spec) {
00636 spec.checkArity(3);
00637 VA x0(home, vars, spec[0]);
00638 VB x1(home, vars, spec[1]);
00639 VC x2(home, vars, spec[2]);
00640 (void) new (home) MultPlusDom<Val,VA,VB,VC>(home,x0,x1,x2);
00641 }
00642
00643 template <class Val, class VA, class VB, class VC>
00644 Support::Symbol
00645 MultPlusDom<Val,VA,VB,VC>::ati(void) {
00646 return Reflection::mangle<VA,VB,VC,Val>
00647 ("Gecode::Int::Arithmetic::MultPlusDom");
00648 }
00649
00650 template <class Val, class VA, class VB, class VC>
00651 Reflection::ActorSpec
00652 MultPlusDom<Val,VA,VB,VC>::spec(const Space* home,
00653 Reflection::VarMap& m) const {
00654 return MixTernaryPropagator<VA,PC_INT_DOM,VB,PC_INT_DOM,VC,PC_INT_DOM>
00655 ::spec(home, m, ati());
00656 }
00657
00658
00659
00660
00661
00662
00663 template <class View>
00664 forceinline
00665 MultDom<View>::MultDom(Space* home, View x0, View x1, View x2)
00666 : TernaryPropagator<View,PC_INT_DOM>(home,x0,x1,x2) {}
00667
00668 template <class View>
00669 forceinline
00670 MultDom<View>::MultDom(Space* home, bool share, MultDom<View>& p)
00671 : TernaryPropagator<View,PC_INT_DOM>(home,share,p) {}
00672
00673 template <class View>
00674 Actor*
00675 MultDom<View>::copy(Space* home, bool share) {
00676 return new (home) MultDom<View>(home,share,*this);
00677 }
00678
00679 template <class View>
00680 PropCost
00681 MultDom<View>::cost(ModEventDelta med) const {
00682 return (View::me(med) == ME_INT_DOM) ? PC_TERNARY_HI : PC_TERNARY_LO;
00683 }
00684
00685 template <class View>
00686 ExecStatus
00687 MultDom<View>::propagate(Space* home, ModEventDelta med) {
00688 if (View::me(med) != ME_INT_DOM) {
00689 if (pos(x0)) {
00690 if (pos(x1) || pos(x2)) goto rewrite_ppp;
00691 if (neg(x1) || neg(x2)) goto rewrite_pnn;
00692 goto prop_pxx;
00693 }
00694 if (neg(x0)) {
00695 if (neg(x1) || pos(x2)) goto rewrite_nnp;
00696 if (pos(x1) || neg(x2)) goto rewrite_npn;
00697 goto prop_nxx;
00698 }
00699 if (pos(x1)) {
00700 if (pos(x2)) goto rewrite_ppp;
00701 if (neg(x2)) goto rewrite_npn;
00702 goto prop_xpx;
00703 }
00704 if (neg(x1)) {
00705 if (pos(x2)) goto rewrite_nnp;
00706 if (neg(x2)) goto rewrite_pnn;
00707 goto prop_xnx;
00708 }
00709
00710 assert(any(x0) && any(x1));
00711 GECODE_ME_CHECK(x2.lq(home,std::max(m<double>(x0.max(),x1.max()),
00712 m<double>(x0.min(),x1.min()))));
00713 GECODE_ME_CHECK(x2.gq(home,std::min(m<double>(x0.min(),x1.max()),
00714 m<double>(x0.max(),x1.min()))));
00715
00716 if (x0.assigned()) {
00717 assert((x0.val() == 0) && (x2.val() == 0));
00718 return ES_SUBSUMED(this,home);
00719 }
00720
00721 if (x1.assigned()) {
00722 assert((x1.val() == 0) && (x2.val() == 0));
00723 return ES_SUBSUMED(this,home);
00724 }
00725
00726 return ES_NOFIX_PARTIAL(this,View::med(ME_INT_DOM));
00727
00728 prop_xpx:
00729 std::swap(x0,x1);
00730 prop_pxx:
00731 assert(pos(x0) && any(x1) && any(x2));
00732
00733 GECODE_ME_CHECK(x2.lq(home,m<double>(x0.max(),x1.max())));
00734 GECODE_ME_CHECK(x2.gq(home,m<double>(x0.max(),x1.min())));
00735
00736 if (pos(x2)) goto rewrite_ppp;
00737 if (neg(x2)) goto rewrite_pnn;
00738
00739 GECODE_ME_CHECK(x1.lq(home,f_d(x2.max(),x0.min())));
00740 GECODE_ME_CHECK(x1.gq(home,c_d(x2.min(),x0.min())));
00741
00742 if (x0.assigned() && x1.assigned()) {
00743 GECODE_ME_CHECK(x2.eq(home,m<double>(x0.val(),x1.val())));
00744 return ES_SUBSUMED(this,sizeof(*this));
00745 }
00746
00747 return ES_NOFIX_PARTIAL(this,View::med(ME_INT_DOM));
00748
00749 prop_xnx:
00750 std::swap(x0,x1);
00751 prop_nxx:
00752 assert(neg(x0) && any(x1) && any(x2));
00753
00754 GECODE_ME_CHECK(x2.lq(home,m<double>(x0.min(),x1.min())));
00755 GECODE_ME_CHECK(x2.gq(home,m<double>(x0.min(),x1.max())));
00756
00757 if (pos(x2)) goto rewrite_nnp;
00758 if (neg(x2)) goto rewrite_npn;
00759
00760 GECODE_ME_CHECK(x1.lq(home,f_d(x2.min(),x0.max())));
00761 GECODE_ME_CHECK(x1.gq(home,c_d(x2.max(),x0.max())));
00762
00763 if (x0.assigned() && x1.assigned()) {
00764 GECODE_ME_CHECK(x2.eq(home,m<double>(x0.val(),x1.val())));
00765 return ES_SUBSUMED(this,sizeof(*this));
00766 }
00767
00768 return ES_NOFIX_PARTIAL(this,View::med(ME_INT_DOM));
00769
00770 rewrite_ppp:
00771 GECODE_REWRITE(this,(MultPlusDom<double,IntView,IntView,IntView>
00772 ::post(home,x0,x1,x2)));
00773 rewrite_nnp:
00774 GECODE_REWRITE(this,(MultPlusDom<double,MinusView,MinusView,IntView>
00775 ::post(home,x0,x1,x2)));
00776 rewrite_pnn:
00777 std::swap(x0,x1);
00778 rewrite_npn:
00779 GECODE_REWRITE(this,(MultPlusDom<double,MinusView,IntView,MinusView>
00780 ::post(home,x0,x1,x2)));
00781 }
00782 return prop_mult_dom<double,View>(home,this,x0,x1,x2);
00783 }
00784
00785 template <class View>
00786 ExecStatus
00787 MultDom<View>::post(Space* home, View x0, View x1, View x2) {
00788 if (same(x0,x1))
00789 return SqrDom<View>::post(home,x0,x2);
00790 if (same(x0,x2))
00791 return MultZeroOne<View,PC_INT_DOM>::post(home,x0,x1);
00792 if (same(x1,x2))
00793 return MultZeroOne<View,PC_INT_DOM>::post(home,x1,x0);
00794 if (pos(x0)) {
00795 if (pos(x1) || pos(x2)) goto post_ppp;
00796 if (neg(x1) || neg(x2)) goto post_pnn;
00797 } else if (neg(x0)) {
00798 if (neg(x1) || pos(x2)) goto post_nnp;
00799 if (pos(x1) || neg(x2)) goto post_npn;
00800 } else if (pos(x1)) {
00801 if (pos(x2)) goto post_ppp;
00802 if (neg(x2)) goto post_npn;
00803 } else if (neg(x1)) {
00804 if (pos(x2)) goto post_nnp;
00805 if (neg(x2)) goto post_pnn;
00806 }
00807 {
00808 double a =
00809 static_cast<double>(x0.min()) * static_cast<double>(x1.min());
00810 double b =
00811 static_cast<double>(x0.min()) * static_cast<double>(x1.max());
00812 double c =
00813 static_cast<double>(x0.max()) * static_cast<double>(x1.min());
00814 double d =
00815 static_cast<double>(x0.max()) * static_cast<double>(x1.max());
00816 GECODE_ME_CHECK(x2.gq(home,std::min(std::min(a,b),std::min(c,d))));
00817 GECODE_ME_CHECK(x2.lq(home,std::max(std::max(a,b),std::max(c,d))));
00818 (void) new (home) MultDom<View>(home,x0,x1,x2);
00819 }
00820 return ES_OK;
00821
00822 post_ppp:
00823 return MultPlusDom<double,IntView,IntView,IntView>::post(home,x0,x1,x2);
00824 post_nnp:
00825 return MultPlusDom<double,MinusView,MinusView,IntView>::post(home,x0,x1,x2);
00826 post_pnn:
00827 std::swap(x0,x1);
00828 post_npn:
00829 return MultPlusDom<double,MinusView,IntView,MinusView>::post(home,x0,x1,x2);
00830 }
00831
00832 template <class View>
00833 forceinline void
00834 MultDom<View>::post(Space* home, Reflection::VarMap& vars,
00835 const Reflection::ActorSpec& spec) {
00836 spec.checkArity(3);
00837 View x0(home, vars, spec[0]);
00838 View x1(home, vars, spec[1]);
00839 View x2(home, vars, spec[2]);
00840 (void) new (home) MultDom<View>(home,x0,x1,x2);
00841 }
00842
00843 template <class View>
00844 Support::Symbol
00845 MultDom<View>::ati(void) {
00846 return Reflection::mangle<View>("Gecode::Int::Arithmetic::MultDom");
00847 }
00848
00849 template <class View>
00850 Reflection::ActorSpec
00851 MultDom<View>::spec(const Space* home, Reflection::VarMap& m) const {
00852 return TernaryPropagator<View,PC_INT_DOM>::spec(home, m, ati());
00853 }
00854
00855 }}}
00856
00857
00858