template<class T, class Rounding> inline T pow_dn(const T& x_, int pwr, Rounding& rnd) // x and pwr are positive { T x = x_; T y = (pwr & 1) ? x_ : static_cast<T>(1); pwr >>= 1; while (pwr > 0) { x = rnd.mul_down(x, x); if (pwr & 1) y = rnd.mul_down(x, y); pwr >>= 1; } return y; }
forceinline ExecStatus MultPlus<VA,VB,VC>::post(Home home, VA x0, VB x1, VC x2) { GECODE_ME_CHECK(x0.gq(home,0.0)); GECODE_ME_CHECK(x1.gq(home,0.0)); Rounding r; GECODE_ME_CHECK(x2.gq(home,r.mul_down(x0.min(),x1.min()))); (void) new (home) MultPlus<VA,VB,VC>(home,x0,x1,x2); return ES_OK; }
forceinline Gecode::FloatNum RandomAssignment::randval(void) { using namespace Gecode; using namespace Gecode::Float; Rounding r; return r.add_down( d.min(), r.mul_down( r.div_down( Base::rand(static_cast<unsigned int>(Gecode::Int::Limits::max)), static_cast<FloatNum>(Gecode::Int::Limits::max) ), r.sub_down(d.max(),d.min()) ) ); }
ExecStatus Mult<View>::propagate(Space& home, const ModEventDelta&) { Rounding r; if (pos(x0)) { if (pos(x1) || pos(x2)) goto rewrite_ppp; if (neg(x1) || neg(x2)) goto rewrite_pnn; goto prop_pxx; } if (neg(x0)) { if (neg(x1) || pos(x2)) goto rewrite_nnp; if (pos(x1) || neg(x2)) goto rewrite_npn; goto prop_nxx; } if (pos(x1)) { if (pos(x2)) goto rewrite_ppp; if (neg(x2)) goto rewrite_npn; goto prop_xpx; } if (neg(x1)) { if (pos(x2)) goto rewrite_nnp; if (neg(x2)) goto rewrite_pnn; goto prop_xnx; } assert(any(x0) && any(x1)); GECODE_ME_CHECK(x2.lq(home,std::max(r.mul_up(x0.max(),x1.max()), r.mul_up(x0.min(),x1.min())))); GECODE_ME_CHECK(x2.gq(home,std::min(r.mul_down(x0.min(),x1.max()), r.mul_down(x0.max(),x1.min())))); if (pos(x2)) { if (r.div_up(x2.min(),x1.min()) < x0.min()) GECODE_ME_CHECK(x0.gq(home,0)); if (r.div_up(x2.min(),x0.min()) < x1.min()) GECODE_ME_CHECK(x1.gq(home,0)); } if (neg(x2)) { if (r.div_up(x2.max(),x1.max()) < x0.min()) GECODE_ME_CHECK(x0.gq(home,0)); if (r.div_up(x2.max(),x0.max()) < x1.min()) GECODE_ME_CHECK(x1.gq(home,0)); } if (x0.assigned()) { assert((x0.val() == 0.0) && (x2.val() == 0.0)); return home.ES_SUBSUMED(*this); } if (x1.assigned()) { assert((x1.val() == 0.0) && (x2.val() == 0.0)); return home.ES_SUBSUMED(*this); } return ES_NOFIX; prop_xpx: std::swap(x0,x1); prop_pxx: assert(pos(x0) && any(x1) && any(x2)); GECODE_ME_CHECK(x2.lq(home,r.mul_up(x0.max(),x1.max()))); GECODE_ME_CHECK(x2.gq(home,r.mul_down(x0.max(),x1.min()))); if (pos(x2)) goto rewrite_ppp; if (neg(x2)) goto rewrite_pnn; GECODE_ME_CHECK(x1.lq(home,r.div_up(x2.max(),x0.min()))); GECODE_ME_CHECK(x1.gq(home,r.div_down(x2.min(),x0.min()))); if (x0.assigned() && x1.assigned()) { GECODE_ME_CHECK(x2.eq(home,x0.val()*x1.val())); return home.ES_SUBSUMED(*this); } return ES_NOFIX; prop_xnx: std::swap(x0,x1); prop_nxx: assert(neg(x0) && any(x1) && any(x2)); GECODE_ME_CHECK(x2.lq(home,r.mul_up(x0.min(),x1.min()))); GECODE_ME_CHECK(x2.gq(home,r.mul_down(x0.min(),x1.max()))); if (pos(x2)) goto rewrite_nnp; if (neg(x2)) goto rewrite_npn; if (x0.max() != 0.0) { GECODE_ME_CHECK(x1.lq(home,r.div_up(x2.min(),x0.max()))); GECODE_ME_CHECK(x1.gq(home,r.div_down(x2.max(),x0.max()))); } if (x0.assigned() && x1.assigned()) { GECODE_ME_CHECK(x2.eq(home,x0.val()*x1.val())); return home.ES_SUBSUMED(*this); } return ES_NOFIX; rewrite_ppp: GECODE_REWRITE(*this,(MultPlus<FloatView,FloatView,FloatView> ::post(home(*this),x0,x1,x2))); rewrite_nnp: GECODE_REWRITE(*this,(MultPlus<MinusView,MinusView,FloatView> ::post(home(*this),MinusView(x0),MinusView(x1),x2))); rewrite_pnn: std::swap(x0,x1); rewrite_npn: GECODE_REWRITE(*this,(MultPlus<MinusView,FloatView,MinusView> ::post(home(*this),MinusView(x0),x1,MinusView(x2)))); }