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 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
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
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
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
00356