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