Generated on Tue Mar 5 2013 22:37:15 for Gecode by doxygen 1.8.3.1
divmod.hpp
Go to the documentation of this file.
1 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2 /*
3  * Main authors:
4  * Guido Tack <tack@gecode.org>
5  *
6  * Copyright:
7  * Guido Tack, 2008
8  *
9  * Last modified:
10  * $Date: 2010-03-04 03:32:21 +1100 (Thu, 04 Mar 2010) $ by $Author: schulte $
11  * $Revision: 10364 $
12  *
13  * This file is part of Gecode, the generic constraint
14  * development environment:
15  * http://www.gecode.org
16  *
17  * Permission is hereby granted, free of charge, to any person obtaining
18  * a copy of this software and associated documentation files (the
19  * "Software"), to deal in the Software without restriction, including
20  * without limitation the rights to use, copy, modify, merge, publish,
21  * distribute, sublicense, and/or sell copies of the Software, and to
22  * permit persons to whom the Software is furnished to do so, subject to
23  * the following conditions:
24  *
25  * The above copyright notice and this permission notice shall be
26  * included in all copies or substantial portions of the Software.
27  *
28  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35  *
36  */
37 
38 #include <gecode/int/linear.hh>
39 
40 namespace Gecode { namespace Int { namespace Arithmetic {
41 
42  /*
43  * Positive bounds consistent division
44  *
45  */
46 
47  template<class Val, class VA, class VB, class VC>
50  ::DivPlusBnd(Home home, VA x0, VB x1, VC x2)
52  (home,x0,x1,x2) {}
53 
54  template<class Val, class VA, class VB, class VC>
57  ::DivPlusBnd(Space& home, bool share,
60  (home,share,p) {}
61 
62  template<class Val, class VA, class VB, class VC>
63  Actor*
65  return new (home) DivPlusBnd<Val,VA,VB,VC>(home,share,*this);
66  }
67 
68  template<class Val, class VA, class VB, class VC>
72  assert(pos(x0) && pos(x1) && !neg(x2));
73  bool mod;
74  do {
75  mod = false;
76  GECODE_ME_CHECK_MODIFIED(mod,x2.lq(home,f_d_p<Val>(x0.max(),x1.min())));
77  GECODE_ME_CHECK_MODIFIED(mod,x2.gq(home,f_d_p<Val>(x0.min(),x1.max())));
78  GECODE_ME_CHECK_MODIFIED(mod,x0.le(home,m<Val>(x1.max(),
79  static_cast<Val>(x2.max())+
80  static_cast<Val>(1))));
81  GECODE_ME_CHECK_MODIFIED(mod,x0.gq(home,m<Val>(x1.min(),x2.min())));
82  if (x2.min() > 0) {
84  x1.lq(home,f_d_p<Val>(x0.max(),x2.min())));
85  }
86  GECODE_ME_CHECK_MODIFIED(mod,x1.gq(home,c_d_p<Val>(x0.min(),
87  static_cast<Val>(x2.max())+static_cast<Val>(1))));
88  } while (mod);
89  return x0.assigned() && x1.assigned() ?
90  home.ES_SUBSUMED(*this) : ES_FIX;
91  }
92 
93  template<class Val, class VA, class VB, class VC>
96  ::post(Home home, VA x0, VB x1, VC x2) {
97  GECODE_ME_CHECK(x0.gr(home,0));
98  GECODE_ME_CHECK(x1.gr(home,0));
99  GECODE_ME_CHECK(x2.gq(home,floor(static_cast<double>(x0.min()) /
100  static_cast<double>(x1.max()))));
101  (void)
102  new (home) DivPlusBnd<double,VA,VB,VC>(home,x0,x1,x2);
103  return ES_OK;
104  }
105 
106 
107  /*
108  * Bounds consistent division
109  *
110  */
111  template<class View>
113  DivBnd<View>::DivBnd(Home home, View x0, View x1, View x2)
114  : TernaryPropagator<View,PC_INT_BND>(home,x0,x1,x2) {}
115 
116  template<class View>
118  DivBnd<View>::DivBnd(Space& home, bool share, DivBnd<View>& p)
119  : TernaryPropagator<View,PC_INT_BND>(home,share,p) {}
120 
121  template<class View>
122  Actor*
123  DivBnd<View>::copy(Space& home, bool share) {
124  return new (home) DivBnd<View>(home,share,*this);
125  }
126 
127  template<class View>
128  ExecStatus
130  if (pos(x1)) {
131  if (pos(x2) || pos(x0)) goto rewrite_ppp;
132  if (neg(x2) || neg(x0)) goto rewrite_npn;
133  goto prop_xpx;
134  }
135  if (neg(x1)) {
136  if (neg(x2) || pos(x0)) goto rewrite_pnn;
137  if (pos(x2) || neg(x0)) goto rewrite_nnp;
138  goto prop_xnx;
139  }
140  if (pos(x2)) {
141  if (pos(x0)) goto rewrite_ppp;
142  if (neg(x0)) goto rewrite_nnp;
143  goto prop_xxp;
144  }
145  if (neg(x2)) {
146  if (pos(x0)) goto rewrite_pnn;
147  if (neg(x0)) goto rewrite_npn;
148  goto prop_xxn;
149  }
150  assert(any(x1) && any(x2));
151  GECODE_ME_CHECK(x0.lq(home,std::max(m<double>(x1.max(),x2.max()+1)-1,
152  m<double>(x1.min(),x2.min()-1)-1)));
153  GECODE_ME_CHECK(x0.gq(home,std::min(m<double>(x1.min(),x2.max()+1),
154  m<double>(x1.max(),x2.min()-1))));
155  return ES_NOFIX;
156 
157  prop_xxp:
158  assert(any(x0) && any(x1) && pos(x2));
159 
160  GECODE_ME_CHECK(x0.le(home, m<double>(x1.max(),x2.max()+1)));
161  GECODE_ME_CHECK(x0.gq(home, m<double>(x1.min(),x2.max()+1)));
162 
163  if (pos(x0)) goto rewrite_ppp;
164  if (neg(x0)) goto rewrite_nnp;
165 
166  GECODE_ME_CHECK(x1.lq(home,f_d_p<double>(x0.max(),x2.min())));
167  GECODE_ME_CHECK(x1.gq(home,c_d(x0.min(),x2.min())));
168 
169  if (x0.assigned() && x1.assigned())
170  goto subsumed;
171  return ES_NOFIX;
172 
173  prop_xpx:
174  assert(any(x0) && pos(x1) && any(x2));
175 
176  GECODE_ME_CHECK(x0.le(home, m<double>(x1.max(),x2.max()+1)));
177  GECODE_ME_CHECK(x0.gq(home, m<double>(x1.max(),x2.min()-1)));
178 
179  if (pos(x0)) goto rewrite_ppp;
180  if (neg(x0)) goto rewrite_npn;
181 
182  GECODE_ME_CHECK(x2.lq(home,f_d(x0.max(),x1.min())));
183  GECODE_ME_CHECK(x2.gq(home,f_d(x0.min(),x1.min())));
184 
185  if (x0.assigned() && x1.assigned())
186  goto subsumed;
187  return ES_NOFIX;
188 
189  prop_xxn:
190  assert(any(x0) && any(x1) && neg(x2));
191 
192  GECODE_ME_CHECK(x0.lq(home, m<double>(x1.min(),x2.min()-1)));
193  GECODE_ME_CHECK(x0.gq(home, m<double>(x1.max(),x2.min()-1)));
194 
195  if (pos(x0)) goto rewrite_pnn;
196  if (neg(x0)) goto rewrite_npn;
197 
198  if (x2.max() != -1)
199  GECODE_ME_CHECK(x1.lq(home,c_d(x0.min(),x2.max()+1)));
200  if (x2.max() != -1)
201  GECODE_ME_CHECK(x1.gq(home,c_d(x0.max(),x2.max()+1)));
202 
203  if (x0.assigned() && x1.assigned())
204  goto subsumed;
205  return ES_NOFIX;
206 
207  prop_xnx:
208  assert(any(x0) && neg(x1) && any(x2));
209 
210  GECODE_ME_CHECK(x0.lq(home, m<double>(x1.min(),x2.min()-1)));
211  GECODE_ME_CHECK(x0.gq(home, m<double>(x1.min(),x2.max()+1)));
212 
213  if (pos(x0)) goto rewrite_pnn;
214  if (neg(x0)) goto rewrite_nnp;
215 
216  GECODE_ME_CHECK(x2.lq(home,f_d(x0.min(),x1.max())));
217  GECODE_ME_CHECK(x2.gq(home,f_d(x0.max(),x1.max())));
218 
219  if (x0.assigned() && x1.assigned())
220  goto subsumed;
221  return ES_NOFIX;
222 
223  rewrite_ppp:
225  ::post(home(*this),x0,x1,x2)));
226  rewrite_nnp:
228  ::post(home(*this),MinusView(x0),MinusView(x1),x2)));
229  rewrite_pnn:
231  ::post(home(*this),x0,MinusView(x1),MinusView(x2))));
232  rewrite_npn:
234  ::post(home(*this),MinusView(x0),x1,MinusView(x2))));
235  subsumed:
236  assert(x0.assigned() && x1.assigned());
237  int result = std::abs(x0.val()) / std::abs(x1.val());
238  if (x0.val()/x1.val() < 0)
239  result = -result;
240  GECODE_ME_CHECK(x2.eq(home,result));
241  return home.ES_SUBSUMED(*this);
242  }
243 
244  template<class View>
245  ExecStatus
246  DivBnd<View>::post(Home home, View x0, View x1, View x2) {
247  GECODE_ME_CHECK(x1.nq(home, 0));
248  if (pos(x0)) {
249  if (pos(x1) || pos(x2)) goto post_ppp;
250  if (neg(x1) || neg(x2)) goto post_pnn;
251  } else if (neg(x0)) {
252  if (neg(x1) || pos(x2)) goto post_nnp;
253  if (pos(x1) || neg(x2)) goto post_npn;
254  } else if (pos(x1)) {
255  if (pos(x2)) goto post_ppp;
256  if (neg(x2)) goto post_npn;
257  } else if (neg(x1)) {
258  if (pos(x2)) goto post_nnp;
259  if (neg(x2)) goto post_pnn;
260  }
261  (void) new (home) DivBnd<View>(home,x0,x1,x2);
262  return ES_OK;
263 
264  post_ppp:
266  post_nnp:
268  MinusView(x0),MinusView(x1),x2);
269  post_pnn:
271  x0,MinusView(x1),MinusView(x2));
272  post_npn:
274  MinusView(x0),x1,MinusView(x2));
275  }
276 
277 
278  /*
279  * Propagator for x0 != 0 /\ (x1 != 0 => x0*x1>0) /\ abs(x1)<abs(x0)
280  *
281  */
282 
283  template<class View>
285  DivMod<View>::DivMod(Home home, View x0, View x1, View x2)
286  : TernaryPropagator<View,PC_INT_BND>(home,x0,x1,x2) {}
287 
288  template<class View>
290  DivMod<View>::post(Home home, View x0, View x1, View x2) {
291  GECODE_ME_CHECK(x1.nq(home,0));
292  (void) new (home) DivMod<View>(home,x0,x1,x2);
293  return ES_OK;
294  }
295 
296  template<class View>
298  DivMod<View>::DivMod(Space& home, bool share, DivMod<View>& p)
299  : TernaryPropagator<View,PC_INT_BND>(home,share,p) {}
300 
301  template<class View>
302  Actor*
303  DivMod<View>::copy(Space& home, bool share) {
304  return new (home) DivMod<View>(home,share,*this);
305  }
306 
307  template<class View>
308  ExecStatus
310  bool signIsSame;
311  do {
312  signIsSame = true;
313  // The sign of x0 and x2 is the same
314  if (x0.min() >= 0) {
315  GECODE_ME_CHECK(x2.gq(home, 0));
316  } else if (x0.max() <= 0) {
317  GECODE_ME_CHECK(x2.lq(home, 0));
318  } else if (x2.min() > 0) {
319  GECODE_ME_CHECK(x0.gq(home, 0));
320  } else if (x2.max() < 0) {
321  GECODE_ME_CHECK(x0.lq(home, 0));
322  } else {
323  signIsSame = false;
324  }
325 
326  // abs(x2) is less than abs(x1)
327  int x1max = std::max(x1.max(),std::max(-x1.max(),
328  std::max(x1.min(),-x1.min())));
329  GECODE_ME_CHECK(x2.le(home, x1max));
330  GECODE_ME_CHECK(x2.gr(home, -x1max));
331 
332  int x2absmin = any(x2) ? 0 : (pos(x2) ? x2.min() : -x2.max());
333  Iter::Ranges::Singleton sr(-x2absmin,x2absmin);
334  GECODE_ME_CHECK(x1.minus_r(home,sr,false));
335  } while (!signIsSame &&
336  (x0.min() > 0 || x0.max() < 0 || x2.min() > 0 || x2.max() < 0));
337 
338  if (signIsSame) {
339  int x2max = std::max(x2.max(),std::max(-x2.max(),
340  std::max(x2.min(),-x2.min())));
341  int x1absmin = any(x1) ? 0 : (pos(x1) ? x1.min() : -x1.max());
342  if (x2max < x1absmin)
343  return home.ES_SUBSUMED(*this);
344  }
345  return ES_FIX;
346  }
347 
348 }}}
349 
350 // STATISTICS: int-prop