this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2/* 3 * Main authors: 4 * Christian Schulte <schulte@gecode.org> 5 * Vincent Barichard <Vincent.Barichard@univ-angers.fr> 6 * 7 * Copyright: 8 * Christian Schulte, 2004 9 * Vincent Barichard, 2012 10 * 11 * This file is part of Gecode, the generic constraint 12 * development environment: 13 * http://www.gecode.org 14 * 15 * Permission is hereby granted, free of charge, to any person obtaining 16 * a copy of this software and associated documentation files (the 17 * "Software"), to deal in the Software without restriction, including 18 * without limitation the rights to use, copy, modify, merge, publish, 19 * distribute, sublicense, and/or sell copies of the Software, and to 20 * permit persons to whom the Software is furnished to do so, subject to 21 * the following conditions: 22 * 23 * The above copyright notice and this permission notice shall be 24 * included in all copies or substantial portions of the Software. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 30 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 31 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 32 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 33 * 34 */ 35 36namespace Gecode { namespace Float { namespace Arithmetic { 37 38 /// Test whether \a x is postive 39 template<class View> 40 forceinline bool 41 pos(const View& x) { 42 return x.min() >= 0.0; 43 } 44 /// Test whether \a x is negative 45 template<class View> 46 forceinline bool 47 neg(const View& x) { 48 return x.max() <= 0.0; 49 } 50 /// Test whether \a x is neither positive nor negative 51 template<class View> 52 forceinline bool 53 any(const View& x) { 54 return (x.min() <= 0.0) && (x.max() >= 0.0); 55 } 56 57 /* 58 * Propagator for x * y = x 59 * 60 */ 61 62 template<class View> 63 forceinline 64 MultZeroOne<View>::MultZeroOne(Home home, View x0, View x1) 65 : BinaryPropagator<View,PC_FLOAT_BND>(home,x0,x1) {} 66 67 template<class View> 68 forceinline ExecStatus 69 MultZeroOne<View>::post(Home home, View x0, View x1) { 70 switch (rtest_eq(x0,0.0)) { 71 case RT_FALSE: 72 GECODE_ME_CHECK(x1.eq(home,1.0)); 73 break; 74 case RT_TRUE: 75 break; 76 case RT_MAYBE: 77 switch (rtest_eq(x1,1.0)) { 78 case RT_FALSE: 79 GECODE_ME_CHECK(x0.eq(home,0.0)); 80 break; 81 case RT_TRUE: 82 break; 83 case RT_MAYBE: 84 (void) new (home) MultZeroOne<View>(home,x0,x1); 85 break; 86 default: GECODE_NEVER; 87 } 88 break; 89 default: GECODE_NEVER; 90 } 91 return ES_OK; 92 } 93 94 template<class View> 95 forceinline 96 MultZeroOne<View>::MultZeroOne(Space& home, MultZeroOne<View>& p) 97 : BinaryPropagator<View,PC_FLOAT_BND>(home,p) {} 98 99 template<class View> 100 Actor* 101 MultZeroOne<View>::copy(Space& home) { 102 return new (home) MultZeroOne<View>(home,*this); 103 } 104 105 template<class View> 106 ExecStatus 107 MultZeroOne<View>::propagate(Space& home, const ModEventDelta&) { 108 switch (rtest_eq(x0,0.0)) { 109 case RT_FALSE: 110 GECODE_ME_CHECK(x1.eq(home,1.0)); 111 break; 112 case RT_TRUE: 113 break; 114 case RT_MAYBE: 115 switch (rtest_eq(x1,1.0)) { 116 case RT_FALSE: 117 GECODE_ME_CHECK(x0.eq(home,0.0)); 118 break; 119 case RT_TRUE: 120 break; 121 case RT_MAYBE: 122 return ES_FIX; 123 default: GECODE_NEVER; 124 } 125 break; 126 default: GECODE_NEVER; 127 } 128 return home.ES_SUBSUMED(*this); 129 } 130 131 132 /* 133 * Positive bounds consistent multiplication 134 * 135 */ 136 template<class VA, class VB, class VC> 137 forceinline 138 MultPlus<VA,VB,VC>::MultPlus(Home home, VA x0, VB x1, VC x2) 139 : MixTernaryPropagator<VA,PC_FLOAT_BND,VB,PC_FLOAT_BND,VC,PC_FLOAT_BND> 140 (home,x0,x1,x2) {} 141 142 template<class VA, class VB, class VC> 143 forceinline 144 MultPlus<VA,VB,VC>::MultPlus(Space& home, MultPlus<VA,VB,VC>& p) 145 : MixTernaryPropagator<VA,PC_FLOAT_BND,VB,PC_FLOAT_BND,VC,PC_FLOAT_BND> 146 (home,p) {} 147 148 template<class VA, class VB, class VC> 149 Actor* 150 MultPlus<VA,VB,VC>::copy(Space& home) { 151 return new (home) MultPlus<VA,VB,VC>(home,*this); 152 } 153 154 template<class VA, class VB, class VC> 155 ExecStatus 156 MultPlus<VA,VB,VC>::propagate(Space& home, const ModEventDelta&) { 157 if (x1.min() != 0.0) 158 GECODE_ME_CHECK(x0.eq(home,x2.val() / x1.val())); 159 if (x0.min() != 0.0) 160 GECODE_ME_CHECK(x1.eq(home,x2.val() / x0.val())); 161 GECODE_ME_CHECK(x2.eq(home,x0.val() * x1.val())); 162 if (x0.assigned() && x1.assigned() && x2.assigned()) 163 return home.ES_SUBSUMED(*this); 164 return ES_NOFIX; 165 } 166 167 template<class VA, class VB, class VC> 168 forceinline ExecStatus 169 MultPlus<VA,VB,VC>::post(Home home, VA x0, VB x1, VC x2) { 170 GECODE_ME_CHECK(x0.gq(home,0.0)); 171 GECODE_ME_CHECK(x1.gq(home,0.0)); 172 Rounding r; 173 GECODE_ME_CHECK(x2.gq(home,r.mul_down(x0.min(),x1.min()))); 174 (void) new (home) MultPlus<VA,VB,VC>(home,x0,x1,x2); 175 return ES_OK; 176 } 177 178 179 /* 180 * Bounds consistent multiplication 181 * 182 */ 183 template<class View> 184 forceinline 185 Mult<View>::Mult(Home home, View x0, View x1, View x2) 186 : TernaryPropagator<View,PC_FLOAT_BND>(home,x0,x1,x2) {} 187 188 template<class View> 189 forceinline 190 Mult<View>::Mult(Space& home, Mult<View>& p) 191 : TernaryPropagator<View,PC_FLOAT_BND>(home,p) {} 192 193 template<class View> 194 Actor* 195 Mult<View>::copy(Space& home) { 196 return new (home) Mult<View>(home,*this); 197 } 198 199 template<class View> 200 ExecStatus 201 Mult<View>::propagate(Space& home, const ModEventDelta&) { 202 Rounding r; 203 if (pos(x0)) { 204 if (pos(x1) || pos(x2)) goto rewrite_ppp; 205 if (neg(x1) || neg(x2)) goto rewrite_pnn; 206 goto prop_pxx; 207 } 208 if (neg(x0)) { 209 if (neg(x1) || pos(x2)) goto rewrite_nnp; 210 if (pos(x1) || neg(x2)) goto rewrite_npn; 211 goto prop_nxx; 212 } 213 if (pos(x1)) { 214 if (pos(x2)) goto rewrite_ppp; 215 if (neg(x2)) goto rewrite_npn; 216 goto prop_xpx; 217 } 218 if (neg(x1)) { 219 if (pos(x2)) goto rewrite_nnp; 220 if (neg(x2)) goto rewrite_pnn; 221 goto prop_xnx; 222 } 223 224 assert(any(x0) && any(x1)); 225 GECODE_ME_CHECK(x2.lq(home,std::max(r.mul_up(x0.max(),x1.max()), 226 r.mul_up(x0.min(),x1.min())))); 227 GECODE_ME_CHECK(x2.gq(home,std::min(r.mul_down(x0.min(),x1.max()), 228 r.mul_down(x0.max(),x1.min())))); 229 230 if (pos(x2)) { 231 if (r.div_up(x2.min(),x1.min()) < x0.min()) 232 GECODE_ME_CHECK(x0.gq(home,0)); 233 if (r.div_up(x2.min(),x0.min()) < x1.min()) 234 GECODE_ME_CHECK(x1.gq(home,0)); 235 } 236 if (neg(x2)) { 237 if (r.div_up(x2.max(),x1.max()) < x0.min()) 238 GECODE_ME_CHECK(x0.gq(home,0)); 239 if (r.div_up(x2.max(),x0.max()) < x1.min()) 240 GECODE_ME_CHECK(x1.gq(home,0)); 241 } 242 243 if (x0.assigned()) { 244 assert((x0.val() == 0.0) && (x2.val() == 0.0)); 245 return home.ES_SUBSUMED(*this); 246 } 247 248 if (x1.assigned()) { 249 assert((x1.val() == 0.0) && (x2.val() == 0.0)); 250 return home.ES_SUBSUMED(*this); 251 } 252 253 return ES_NOFIX; 254 255 prop_xpx: 256 std::swap(x0,x1); 257 prop_pxx: 258 assert(pos(x0) && any(x1) && any(x2)); 259 260 GECODE_ME_CHECK(x2.lq(home,r.mul_up(x0.max(),x1.max()))); 261 GECODE_ME_CHECK(x2.gq(home,r.mul_down(x0.max(),x1.min()))); 262 263 if (pos(x2)) goto rewrite_ppp; 264 if (neg(x2)) goto rewrite_pnn; 265 266 GECODE_ME_CHECK(x1.lq(home,r.div_up(x2.max(),x0.min()))); 267 GECODE_ME_CHECK(x1.gq(home,r.div_down(x2.min(),x0.min()))); 268 269 if (x0.assigned() && x1.assigned()) { 270 GECODE_ME_CHECK(x2.eq(home,x0.val()*x1.val())); 271 return home.ES_SUBSUMED(*this); 272 } 273 274 return ES_NOFIX; 275 276 prop_xnx: 277 std::swap(x0,x1); 278 prop_nxx: 279 assert(neg(x0) && any(x1) && any(x2)); 280 281 GECODE_ME_CHECK(x2.lq(home,r.mul_up(x0.min(),x1.min()))); 282 GECODE_ME_CHECK(x2.gq(home,r.mul_down(x0.min(),x1.max()))); 283 284 if (pos(x2)) goto rewrite_nnp; 285 if (neg(x2)) goto rewrite_npn; 286 287 if (x0.max() != 0.0) { 288 GECODE_ME_CHECK(x1.lq(home,r.div_up(x2.min(),x0.max()))); 289 GECODE_ME_CHECK(x1.gq(home,r.div_down(x2.max(),x0.max()))); 290 } 291 292 if (x0.assigned() && x1.assigned()) { 293 GECODE_ME_CHECK(x2.eq(home,x0.val()*x1.val())); 294 return home.ES_SUBSUMED(*this); 295 } 296 297 return ES_NOFIX; 298 299 rewrite_ppp: 300 GECODE_REWRITE(*this,(MultPlus<FloatView,FloatView,FloatView> 301 ::post(home(*this),x0,x1,x2))); 302 rewrite_nnp: 303 GECODE_REWRITE(*this,(MultPlus<MinusView,MinusView,FloatView> 304 ::post(home(*this),MinusView(x0),MinusView(x1),x2))); 305 rewrite_pnn: 306 std::swap(x0,x1); 307 rewrite_npn: 308 GECODE_REWRITE(*this,(MultPlus<MinusView,FloatView,MinusView> 309 ::post(home(*this),MinusView(x0),x1,MinusView(x2)))); 310 } 311 312 template<class View> 313 ExecStatus 314 Mult<View>::post(Home home, View x0, View x1, View x2) { 315 if (x0 == x1) 316 return Sqr<View>::post(home,x0,x2); 317 if (x0 == x2) 318 return MultZeroOne<View>::post(home,x0,x1); 319 if (x1 == x2) 320 return MultZeroOne<View>::post(home,x1,x0); 321 if (pos(x0)) { 322 if (pos(x1) || pos(x2)) goto post_ppp; 323 if (neg(x1) || neg(x2)) goto post_pnn; 324 } else if (neg(x0)) { 325 if (neg(x1) || pos(x2)) goto post_nnp; 326 if (pos(x1) || neg(x2)) goto post_npn; 327 } else if (pos(x1)) { 328 if (pos(x2)) goto post_ppp; 329 if (neg(x2)) goto post_npn; 330 } else if (neg(x1)) { 331 if (pos(x2)) goto post_nnp; 332 if (neg(x2)) goto post_pnn; 333 } 334 { 335 GECODE_ME_CHECK(x2.eq(home,x0.val()*x1.val())); 336 (void) new (home) Mult<View>(home,x0,x1,x2); 337 } 338 return ES_OK; 339 340 post_ppp: 341 return MultPlus<FloatView,FloatView,FloatView>::post(home,x0,x1,x2); 342 post_nnp: 343 return MultPlus<MinusView,MinusView,FloatView>::post(home, 344 MinusView(x0),MinusView(x1),x2); 345 post_pnn: 346 std::swap(x0,x1); 347 post_npn: 348 return MultPlus<MinusView,FloatView,MinusView>::post(home, 349 MinusView(x0),x1,MinusView(x2)); 350 } 351 352 353}}} 354 355// STATISTICS: float-prop 356