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, 2002
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 {
37
38 void
39 abs(Home home, IntVar x0, IntVar x1, IntPropLevel ipl) {
40 using namespace Int;
41 GECODE_POST;
42 if (vbd(ipl) == IPL_DOM) {
43 GECODE_ES_FAIL(Arithmetic::AbsDom<IntView>::post(home,x0,x1));
44 } else {
45 GECODE_ES_FAIL(Arithmetic::AbsBnd<IntView>::post(home,x0,x1));
46 }
47 }
48
49
50 void
51 max(Home home, IntVar x0, IntVar x1, IntVar x2,
52 IntPropLevel ipl) {
53 using namespace Int;
54 GECODE_POST;
55 if (vbd(ipl) == IPL_DOM) {
56 GECODE_ES_FAIL(Arithmetic::MaxDom<IntView>::post(home,x0,x1,x2));
57 } else {
58 GECODE_ES_FAIL(Arithmetic::MaxBnd<IntView>::post(home,x0,x1,x2));
59 }
60 }
61
62 void
63 max(Home home, const IntVarArgs& x, IntVar y,
64 IntPropLevel ipl) {
65 using namespace Int;
66 if (x.size() == 0)
67 throw TooFewArguments("Int::max");
68 GECODE_POST;
69 ViewArray<IntView> xv(home,x);
70 if (vbd(ipl) == IPL_DOM) {
71 GECODE_ES_FAIL(Arithmetic::NaryMaxDom<IntView>::post(home,xv,y));
72 } else {
73 GECODE_ES_FAIL(Arithmetic::NaryMaxBnd<IntView>::post(home,xv,y));
74 }
75 }
76
77 void
78 min(Home home, IntVar x0, IntVar x1, IntVar x2,
79 IntPropLevel ipl) {
80 using namespace Int;
81 GECODE_POST;
82 MinusView m0(x0); MinusView m1(x1); MinusView m2(x2);
83 if (vbd(ipl) == IPL_DOM) {
84 GECODE_ES_FAIL(Arithmetic::MaxDom<MinusView>::post(home,m0,m1,m2));
85 } else {
86 GECODE_ES_FAIL(Arithmetic::MaxBnd<MinusView>::post(home,m0,m1,m2));
87 }
88 }
89
90 void
91 min(Home home, const IntVarArgs& x, IntVar y,
92 IntPropLevel ipl) {
93 using namespace Int;
94 if (x.size() == 0)
95 throw TooFewArguments("Int::min");
96 GECODE_POST;
97 ViewArray<MinusView> m(home,x.size());
98 for (int i=0; i<x.size(); i++)
99 m[i] = MinusView(x[i]);
100 MinusView my(y);
101 if (vbd(ipl) == IPL_DOM) {
102 GECODE_ES_FAIL(Arithmetic::NaryMaxDom<MinusView>::post(home,m,my));
103 } else {
104 GECODE_ES_FAIL(Arithmetic::NaryMaxBnd<MinusView>::post(home,m,my));
105 }
106 }
107
108
109 void
110 argmax(Home home, const IntVarArgs& x, IntVar y, bool tiebreak,
111 IntPropLevel) {
112 using namespace Int;
113 if (x.size() == 0)
114 throw TooFewArguments("Int::argmax");
115 if (same(x,y))
116 throw ArgumentSame("Int::argmax");
117 GECODE_POST;
118 // Constrain y properly
119 IntView yv(y);
120 GECODE_ME_FAIL(yv.gq(home,0));
121 GECODE_ME_FAIL(yv.le(home,x.size()));
122 // Construct index view array
123 IdxViewArray<IntView> ix(home,x.size());
124 for (int i=0; i<x.size(); i++) {
125 ix[i].idx=i; ix[i].view=x[i];
126 }
127 if (tiebreak)
128 GECODE_ES_FAIL((Arithmetic::ArgMax<IntView,IntView,true>
129 ::post(home,ix,yv)));
130 else
131 GECODE_ES_FAIL((Arithmetic::ArgMax<IntView,IntView,false>
132 ::post(home,ix,yv)));
133 }
134
135 void
136 argmax(Home home, const IntVarArgs& x, int o, IntVar y, bool tiebreak,
137 IntPropLevel) {
138 using namespace Int;
139 Limits::nonnegative(o,"Int::argmax");
140 if (x.size() == 0)
141 throw TooFewArguments("Int::argmax");
142 if (same(x,y))
143 throw ArgumentSame("Int::argmax");
144 GECODE_POST;
145 // Constrain y properly
146 OffsetView yv(y,-o);
147 GECODE_ME_FAIL(yv.gq(home,0));
148 GECODE_ME_FAIL(yv.le(home,x.size()));
149 // Construct index view array
150 IdxViewArray<IntView> ix(home,x.size());
151 for (int i=0; i<x.size(); i++) {
152 ix[i].idx=i; ix[i].view=x[i];
153 }
154 if (tiebreak)
155 GECODE_ES_FAIL((Arithmetic::ArgMax<IntView,OffsetView,true>
156 ::post(home,ix,yv)));
157 else
158 GECODE_ES_FAIL((Arithmetic::ArgMax<IntView,OffsetView,false>
159 ::post(home,ix,yv)));
160 }
161
162 void
163 argmin(Home home, const IntVarArgs& x, IntVar y, bool tiebreak,
164 IntPropLevel) {
165 using namespace Int;
166 if (x.size() == 0)
167 throw TooFewArguments("Int::argmin");
168 if (same(x,y))
169 throw ArgumentSame("Int::argmin");
170 GECODE_POST;
171 // Constrain y properly
172 IntView yv(y);
173 GECODE_ME_FAIL(yv.gq(home,0));
174 GECODE_ME_FAIL(yv.le(home,x.size()));
175 // Construct index view array
176 IdxViewArray<MinusView> ix(home,x.size());
177 for (int i=0; i<x.size(); i++) {
178 ix[i].idx=i; ix[i].view=MinusView(x[i]);
179 }
180 if (tiebreak)
181 GECODE_ES_FAIL((Arithmetic::ArgMax<MinusView,IntView,true>
182 ::post(home,ix,yv)));
183 else
184 GECODE_ES_FAIL((Arithmetic::ArgMax<MinusView,IntView,false>
185 ::post(home,ix,yv)));
186 }
187
188 void
189 argmin(Home home, const IntVarArgs& x, int o, IntVar y, bool tiebreak,
190 IntPropLevel) {
191 using namespace Int;
192 Limits::nonnegative(o,"Int::argmin");
193 if (x.size() == 0)
194 throw TooFewArguments("Int::argmin");
195 if (same(x,y))
196 throw ArgumentSame("Int::argmin");
197 GECODE_POST;
198 // Constrain y properly
199 OffsetView yv(y,-o);
200 GECODE_ME_FAIL(yv.gq(home,0));
201 GECODE_ME_FAIL(yv.le(home,x.size()));
202 // Construct index view array
203 IdxViewArray<MinusView> ix(home,x.size());
204 for (int i=0; i<x.size(); i++) {
205 ix[i].idx=i; ix[i].view=MinusView(x[i]);
206 }
207 if (tiebreak)
208 GECODE_ES_FAIL((Arithmetic::ArgMax<MinusView,OffsetView,true>
209 ::post(home,ix,yv)));
210 else
211 GECODE_ES_FAIL((Arithmetic::ArgMax<MinusView,OffsetView,false>
212 ::post(home,ix,yv)));
213 }
214
215 void
216 argmax(Home home, const BoolVarArgs& x, IntVar y, bool tiebreak,
217 IntPropLevel) {
218 using namespace Int;
219 if (x.size() == 0)
220 throw TooFewArguments("Int::argmax");
221 GECODE_POST;
222 // Constrain y properly
223 IntView yv(y);
224 GECODE_ME_FAIL(yv.gq(home,0));
225 GECODE_ME_FAIL(yv.le(home,x.size()));
226 // Construct index view array
227 IdxViewArray<BoolView> ix(home,x.size());
228 for (int i=x.size(); i--; ) {
229 ix[i].idx=i; ix[i].view=x[i];
230 }
231 if (tiebreak)
232 GECODE_ES_FAIL((Arithmetic::ArgMax<BoolView,IntView,true>
233 ::post(home,ix,yv)));
234 else
235 GECODE_ES_FAIL((Arithmetic::ArgMax<BoolView,IntView,false>
236 ::post(home,ix,yv)));
237 }
238
239 void
240 argmax(Home home, const BoolVarArgs& x, int o, IntVar y, bool tiebreak,
241 IntPropLevel) {
242 using namespace Int;
243 Limits::nonnegative(o,"Int::argmax");
244 if (x.size() == 0)
245 throw TooFewArguments("Int::argmax");
246 GECODE_POST;
247 // Constrain y properly
248 OffsetView yv(y,-o);
249 GECODE_ME_FAIL(yv.gq(home,0));
250 GECODE_ME_FAIL(yv.le(home,x.size()));
251 // Construct index view array
252 IdxViewArray<BoolView> ix(home,x.size());
253 for (int i=x.size(); i--; ) {
254 ix[i].idx=i; ix[i].view=x[i];
255 }
256 if (tiebreak)
257 GECODE_ES_FAIL((Arithmetic::ArgMax<BoolView,OffsetView,true>
258 ::post(home,ix,yv)));
259 else
260 GECODE_ES_FAIL((Arithmetic::ArgMax<BoolView,OffsetView,false>
261 ::post(home,ix,yv)));
262 }
263
264 void
265 argmin(Home home, const BoolVarArgs& x, IntVar y, bool tiebreak,
266 IntPropLevel) {
267 using namespace Int;
268 if (x.size() == 0)
269 throw TooFewArguments("Int::argmin");
270 GECODE_POST;
271 // Constrain y properly
272 IntView yv(y);
273 GECODE_ME_FAIL(yv.gq(home,0));
274 GECODE_ME_FAIL(yv.le(home,x.size()));
275 // Construct index view array
276 IdxViewArray<NegBoolView> ix(home,x.size());
277 for (int i=x.size(); i--; ) {
278 ix[i].idx=i; ix[i].view=NegBoolView(x[i]);
279 }
280 if (tiebreak)
281 GECODE_ES_FAIL((Arithmetic::ArgMax<NegBoolView,IntView,true>
282 ::post(home,ix,yv)));
283 else
284 GECODE_ES_FAIL((Arithmetic::ArgMax<NegBoolView,IntView,false>
285 ::post(home,ix,yv)));
286 }
287
288 void
289 argmin(Home home, const BoolVarArgs& x, int o, IntVar y, bool tiebreak,
290 IntPropLevel) {
291 using namespace Int;
292 Limits::nonnegative(o,"Int::argmin");
293 if (x.size() == 0)
294 throw TooFewArguments("Int::argmin");
295 GECODE_POST;
296 // Constrain y properly
297 OffsetView yv(y,-o);
298 GECODE_ME_FAIL(yv.gq(home,0));
299 GECODE_ME_FAIL(yv.le(home,x.size()));
300 // Construct index view array
301 IdxViewArray<NegBoolView> ix(home,x.size());
302 for (int i=x.size(); i--; ) {
303 ix[i].idx=i; ix[i].view=NegBoolView(x[i]);
304 }
305 if (tiebreak)
306 GECODE_ES_FAIL((Arithmetic::ArgMax<NegBoolView,OffsetView,true>
307 ::post(home,ix,yv)));
308 else
309 GECODE_ES_FAIL((Arithmetic::ArgMax<NegBoolView,OffsetView,false>
310 ::post(home,ix,yv)));
311 }
312
313 void
314 mult(Home home, IntVar x0, IntVar x1, IntVar x2,
315 IntPropLevel ipl) {
316 using namespace Int;
317 GECODE_POST;
318 if (vbd(ipl) == IPL_DOM) {
319 GECODE_ES_FAIL(Arithmetic::MultDom::post(home,x0,x1,x2));
320 } else {
321 GECODE_ES_FAIL(Arithmetic::MultBnd::post(home,x0,x1,x2));
322 }
323 }
324
325
326 void
327 divmod(Home home, IntVar x0, IntVar x1, IntVar x2, IntVar x3,
328 IntPropLevel) {
329 using namespace Int;
330 GECODE_POST;
331
332 IntVar prod(home, Int::Limits::min, Int::Limits::max);
333 GECODE_ES_FAIL(Arithmetic::MultBnd::post(home,x1,x2,prod));
334 Linear::Term<IntView> t[3];
335 t[0].a = 1; t[0].x = prod;
336 t[1].a = 1; t[1].x = x3;
337 int min, max;
338 Linear::estimate(t,2,0,min,max);
339 IntView x0v(x0);
340 GECODE_ME_FAIL(x0v.gq(home,min));
341 GECODE_ME_FAIL(x0v.lq(home,max));
342 t[2].a=-1; t[2].x=x0;
343 Linear::post(home,t,3,IRT_EQ,0,IPL_BND);
344 if (home.failed()) return;
345 IntView x1v(x1);
346 GECODE_ES_FAIL(
347 Arithmetic::DivMod<IntView>::post(home,x0,x1,x3));
348 }
349
350 void
351 div(Home home, IntVar x0, IntVar x1, IntVar x2,
352 IntPropLevel) {
353 using namespace Int;
354 GECODE_POST;
355 GECODE_ES_FAIL(
356 (Arithmetic::DivBnd<IntView>::post(home,x0,x1,x2)));
357 }
358
359 void
360 mod(Home home, IntVar x0, IntVar x1, IntVar x2,
361 IntPropLevel ipl) {
362 using namespace Int;
363 GECODE_POST;
364 IntVar _div(home, Int::Limits::min, Int::Limits::max);
365 divmod(home, x0, x1, _div, x2, ipl);
366 }
367
368 void
369 sqr(Home home, IntVar x0, IntVar x1, IntPropLevel ipl) {
370 using namespace Int;
371 GECODE_POST;
372 Arithmetic::SqrOps ops;
373 if (vbd(ipl) == IPL_DOM) {
374 GECODE_ES_FAIL(Arithmetic::PowDom<Arithmetic::SqrOps>
375 ::post(home,x0,x1,ops));
376 } else {
377 GECODE_ES_FAIL(Arithmetic::PowBnd<Arithmetic::SqrOps>
378 ::post(home,x0,x1,ops));
379 }
380 }
381
382 void
383 sqrt(Home home, IntVar x0, IntVar x1, IntPropLevel ipl) {
384 using namespace Int;
385 GECODE_POST;
386 Arithmetic::SqrOps ops;
387 if (vbd(ipl) == IPL_DOM) {
388 GECODE_ES_FAIL(Arithmetic::NrootDom<Arithmetic::SqrOps>
389 ::post(home,x0,x1,ops));
390 } else {
391 GECODE_ES_FAIL(Arithmetic::NrootBnd<Arithmetic::SqrOps>
392 ::post(home,x0,x1,ops));
393 }
394 }
395
396 void
397 pow(Home home, IntVar x0, int n, IntVar x1, IntPropLevel ipl) {
398 using namespace Int;
399 Limits::nonnegative(n,"Int::pow");
400 GECODE_POST;
401 if (n == 2) {
402 sqr(home, x0, x1, ipl);
403 return;
404 }
405 Arithmetic::PowOps ops(n);
406 if (vbd(ipl) == IPL_DOM) {
407 GECODE_ES_FAIL(Arithmetic::PowDom<Arithmetic::PowOps>
408 ::post(home,x0,x1,ops));
409 } else {
410 GECODE_ES_FAIL(Arithmetic::PowBnd<Arithmetic::PowOps>
411 ::post(home,x0,x1,ops));
412 }
413 }
414
415 void
416 nroot(Home home, IntVar x0, int n, IntVar x1, IntPropLevel ipl) {
417 using namespace Int;
418 Limits::positive(n,"Int::nroot");
419 GECODE_POST;
420 if (n == 2) {
421 sqrt(home, x0, x1, ipl);
422 return;
423 }
424 Arithmetic::PowOps ops(n);
425 if (vbd(ipl) == IPL_DOM) {
426 GECODE_ES_FAIL(Arithmetic::NrootDom<Arithmetic::PowOps>
427 ::post(home,x0,x1,ops));
428 } else {
429 GECODE_ES_FAIL(Arithmetic::NrootBnd<Arithmetic::PowOps>
430 ::post(home,x0,x1,ops));
431 }
432 }
433
434}
435
436// STATISTICS: int-post