~ubuntu-branches/ubuntu/natty/gecode/natty

« back to all changes in this revision

Viewing changes to int/arithmetic/mult.icc

  • Committer: Bazaar Package Importer
  • Author(s): Kari Pahula
  • Date: 2005-12-24 07:51:25 UTC
  • Revision ID: james.westby@ubuntu.com-20051224075125-klkiqofvbfvusfvt
Tags: upstream-1.0.0.dfsg.1
ImportĀ upstreamĀ versionĀ 1.0.0.dfsg.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Main authors:
 
3
 *     Christian Schulte <schulte@gecode.org>
 
4
 *
 
5
 *  Copyright:
 
6
 *     Christian Schulte, 2004
 
7
 *
 
8
 *  Last modified:
 
9
 *     $Date: 2005-11-23 21:29:36 +0100 (Wed, 23 Nov 2005) $ by $Author: schulte $
 
10
 *     $Revision: 2628 $
 
11
 *
 
12
 *  This file is part of Gecode, the generic constraint
 
13
 *  development environment:
 
14
 *     http://www.gecode.org
 
15
 *
 
16
 *  See the file "LICENSE" for information on usage and
 
17
 *  redistribution of this file, and for a
 
18
 *     DISCLAIMER OF ALL WARRANTIES.
 
19
 *
 
20
 */
 
21
 
 
22
#include <cmath>
 
23
 
 
24
namespace Gecode { namespace Int { namespace Arithmetic {
 
25
 
 
26
  /*
 
27
   * Arithmetic help functions
 
28
   *
 
29
   */
 
30
 
 
31
  /// Multiply \a a and \a b as double
 
32
  forceinline double 
 
33
  m(int a, int b) {
 
34
    return static_cast<double>(a)*static_cast<double>(b);
 
35
  }
 
36
 
 
37
  /// Compute \f$\lfloor x/y\rfloor\f$
 
38
  forceinline int
 
39
  f_d(int x, int y) {
 
40
    return static_cast<int>(floor(static_cast<double>(x) /
 
41
                                  static_cast<double>(y)));
 
42
  }
 
43
 
 
44
  /// Compute \f$\lceil x/y\rceil\f$
 
45
  forceinline int
 
46
  c_d(int x, int y) {
 
47
    return static_cast<int>(ceil(static_cast<double>(x) /
 
48
                                 static_cast<double>(y)));
 
49
  }
 
50
 
 
51
  /// Test whether \a x is postive
 
52
  template <class View>
 
53
  forceinline bool 
 
54
  p(const View& x) {
 
55
    return x.min() > 0;
 
56
  }
 
57
  /// Test whether \a x is negative
 
58
  template <class View>
 
59
  forceinline bool 
 
60
  n(const View& x) {
 
61
    return x.max() < 0;
 
62
  }
 
63
  /// Test whether \a x is neither positive nor negative
 
64
  template <class View>
 
65
  forceinline bool 
 
66
  x(const View& x) {
 
67
    return (x.min() <= 0) && (x.max() >= 0);
 
68
  }
 
69
 
 
70
 
 
71
  /// Performs \a TELL operation and sets \a mod, if modified
 
72
#define GECODE_CM(TELL)                         \
 
73
{                                               \
 
74
  ModEvent me = (TELL);                         \
 
75
  if (me_failed(me))   return ES_FAILED;        \
 
76
  if (me_modified(me)) mod = true;              \
 
77
}
 
78
 
 
79
 
 
80
  /*
 
81
   * Positive bounds-consistent squaring
 
82
   *
 
83
   */
 
84
  template <class VA, class VB>
 
85
  forceinline
 
86
  SquarePlus<VA,VB>::SquarePlus(Space* home, VA y0, VB y1) 
 
87
    : Propagator(home), x0(y0), x1(y1) {
 
88
    x0.subscribe(home,this,PC_INT_BND);
 
89
    x1.subscribe(home,this,PC_INT_BND);
 
90
  }
 
91
 
 
92
  template <class VA, class VB>
 
93
  forceinline ExecStatus
 
94
  SquarePlus<VA,VB>::post(Space* home, VA x0, VB x1) {
 
95
    (void) new (home) SquarePlus<VA,VB>(home,x0,x1);
 
96
    return ES_OK;
 
97
  }
 
98
 
 
99
  template <class VA, class VB>
 
100
  forceinline
 
101
  SquarePlus<VA,VB>::SquarePlus(Space* home, bool share, SquarePlus<VA,VB>& p)
 
102
    : Propagator(home,share,p) {
 
103
    x0.update(home,share,p.x0);
 
104
    x1.update(home,share,p.x1);
 
105
  }
 
106
  
 
107
  template <class VA, class VB>
 
108
  Actor*
 
109
  SquarePlus<VA,VB>::copy(Space* home, bool share) {
 
110
    return new (home) SquarePlus<VA,VB>(home,share,*this);
 
111
  }
 
112
 
 
113
  template <class VA, class VB>
 
114
  PropCost
 
115
  SquarePlus<VA,VB>::cost(void) const {
 
116
    return PC_TERNARY_HI;
 
117
  }
 
118
  
 
119
  template <class VA, class VB>
 
120
  ExecStatus
 
121
  SquarePlus<VA,VB>::propagate(Space* home) {
 
122
    bool mod;
 
123
    do {
 
124
      mod = false;
 
125
      GECODE_CM(x0.lq(home,floor(sqrt(static_cast<double>(x1.max())))));
 
126
      GECODE_CM(x0.gq(home,ceil(sqrt(static_cast<double>(x1.min())))));
 
127
      GECODE_CM(x1.lq(home,x0.max()*x0.max()));
 
128
      GECODE_CM(x1.gq(home,x0.min()*x0.min()));
 
129
    } while (mod);
 
130
    return x0.assigned() ? ES_SUBSUMED : ES_FIX;
 
131
  }
 
132
  
 
133
  template <class VA, class VB>
 
134
  SquarePlus<VA,VB>::~SquarePlus(void) {
 
135
    x0.cancel(this,PC_INT_BND);
 
136
    x1.cancel(this,PC_INT_BND);
 
137
  }
 
138
  
 
139
  
 
140
  /*
 
141
   * Bounds-consistent Square
 
142
   *
 
143
   */
 
144
 
 
145
  template <class View>
 
146
  forceinline
 
147
  Square<View>::Square(Space* home, View x0, View x1)
 
148
    : BinaryPropagator<View,PC_INT_BND>(home,x0,x1) {}
 
149
 
 
150
  template <class View>
 
151
  forceinline ExecStatus
 
152
  Square<View>::post(Space* home, View x0, View x1) {
 
153
    GECODE_ME_CHECK(x1.gq(home,0));
 
154
    GECODE_ME_CHECK(x0.lq(home,floor(sqrt(static_cast<double>(Limits::Int::int_max)))));
 
155
    if (x0.min() >= 0)
 
156
      return SquarePlus<IntView,IntView>::post(home,x0,x1);
 
157
    if (x0.max() <= 0)
 
158
      return SquarePlus<MinusView,IntView>::post(home,x0,x1);
 
159
    (void) new (home) Square<View>(home,x0,x1);
 
160
    return ES_OK;
 
161
  }
 
162
 
 
163
  template <class View>
 
164
  forceinline
 
165
  Square<View>::Square(Space* home, bool share, Square<View>& p)
 
166
    : BinaryPropagator<View,PC_INT_BND>(home,share,p) {}
 
167
 
 
168
  template <class View>
 
169
  Actor*
 
170
  Square<View>::copy(Space* home, bool share) {
 
171
    return new (home) Square<View>(home,share,*this);
 
172
  }
 
173
 
 
174
  template <class View>
 
175
  PropCost
 
176
  Square<View>::cost(void) const {
 
177
    return PC_BINARY_HI;
 
178
  }
 
179
 
 
180
  template <class View>
 
181
  ExecStatus
 
182
  Square<View>::propagate(Space* home) {
 
183
    // x0 * x0 = x1
 
184
    assert(x1.min() >= 0);
 
185
    if (x0.min() >= 0)
 
186
      return (SquarePlus<IntView,IntView>::post(home,x0,x1) 
 
187
              == ES_FAILED) ? ES_FAILED : ES_SUBSUMED;
 
188
    if (x0.max() <= 0)
 
189
      return (SquarePlus<MinusView,IntView>::post(home,x0,x1) 
 
190
              == ES_FAILED) ? ES_FAILED : ES_SUBSUMED;
 
191
 
 
192
    bool mod;
 
193
    do {
 
194
      mod = false;
 
195
      GECODE_CM(x1.lq(home,std::max(x0.min()*x0.min(),x0.max()*x0.max())));
 
196
      int s = static_cast<int>(floor(sqrt(static_cast<double>(x1.max()))));
 
197
      GECODE_CM(x0.gq(home,-s));
 
198
      GECODE_CM(x0.lq(home,s));
 
199
    } while (mod);
 
200
    return x0.assigned() && x1.assigned() ? ES_SUBSUMED : ES_FIX;
 
201
  }
 
202
 
 
203
 
 
204
  /*
 
205
   * Positive bounds-consistent multiplication
 
206
   *
 
207
   */
 
208
  template <class VA, class VB, class VC>
 
209
  inline
 
210
  MultPlus<VA,VB,VC>::MultPlus(Space* home, VA y0, VB y1, VC y2) 
 
211
    : Propagator(home), x0(y0), x1(y1), x2(y2) {
 
212
    x0.subscribe(home,this,PC_INT_BND);
 
213
    x1.subscribe(home,this,PC_INT_BND);
 
214
    x2.subscribe(home,this,PC_INT_BND);
 
215
  }
 
216
 
 
217
  template <class VA, class VB, class VC>
 
218
  inline ExecStatus
 
219
  MultPlus<VA,VB,VC>::post(Space* home, VA x0, VB x1, VC x2) {
 
220
    GECODE_ME_CHECK(x0.gr(home,0));
 
221
    GECODE_ME_CHECK(x1.gr(home,0));
 
222
    GECODE_ME_CHECK(x2.gr(home,0));
 
223
    (void) new (home) MultPlus<VA,VB,VC>(home,x0,x1,x2);
 
224
    return ES_OK;
 
225
  }
 
226
 
 
227
  template <class VA, class VB, class VC>
 
228
  forceinline
 
229
  MultPlus<VA,VB,VC>::MultPlus(Space* home, bool share, MultPlus<VA,VB,VC>& p)
 
230
    : Propagator(home,share,p) {
 
231
    x0.update(home,share,p.x0);
 
232
    x1.update(home,share,p.x1);
 
233
    x2.update(home,share,p.x2);
 
234
  }
 
235
  
 
236
  template <class VA, class VB, class VC>
 
237
  Actor*
 
238
  MultPlus<VA,VB,VC>::copy(Space* home, bool share) {
 
239
    return new (home) MultPlus<VA,VB,VC>(home,share,*this);
 
240
  }
 
241
 
 
242
  template <class VA, class VB, class VC>
 
243
  PropCost
 
244
  MultPlus<VA,VB,VC>::cost(void) const {
 
245
    return PC_TERNARY_HI;
 
246
  }
 
247
  
 
248
  template <class VA, class VB, class VC>
 
249
  ExecStatus
 
250
  MultPlus<VA,VB,VC>::propagate(Space* home) {
 
251
    assert(p(x0) && p(x1) && p(x2));
 
252
    bool mod;
 
253
    do {
 
254
      mod = false;
 
255
      GECODE_CM(x2.lq(home,m(x0.max(),x1.max())));
 
256
      GECODE_CM(x2.gq(home,m(x0.min(),x1.min())));
 
257
      GECODE_CM(x0.lq(home,f_d(x2.max(),x1.min())));
 
258
      GECODE_CM(x0.gq(home,c_d(x2.min(),x1.max())));
 
259
      GECODE_CM(x1.lq(home,f_d(x2.max(),x0.min())));
 
260
      GECODE_CM(x1.gq(home,c_d(x2.min(),x0.max())));
 
261
    } while (mod);
 
262
    return x0.assigned() && x1.assigned() ? ES_SUBSUMED : ES_FIX;
 
263
  }
 
264
  
 
265
  template <class VA, class VB, class VC>
 
266
  MultPlus<VA,VB,VC>::~MultPlus(void) {
 
267
    x0.cancel(this,PC_INT_BND);
 
268
    x1.cancel(this,PC_INT_BND);
 
269
    x2.cancel(this,PC_INT_BND);
 
270
  }
 
271
  
 
272
  
 
273
  /*
 
274
   * Bounds-consistent multiplication
 
275
   *
 
276
   */
 
277
 
 
278
  template <class View>
 
279
  forceinline
 
280
  Mult<View>::Mult(Space* home, View x0, View x1, View x2)
 
281
    : TernaryPropagator<View,PC_INT_BND>(home,x0,x1,x2) {}
 
282
 
 
283
  template <class View>
 
284
  forceinline
 
285
  Mult<View>::Mult(Space* home, bool share, Mult<View>& p)
 
286
    : TernaryPropagator<View,PC_INT_BND>(home,share,p) {}
 
287
 
 
288
  template <class View>
 
289
  Actor*
 
290
  Mult<View>::copy(Space* home, bool share) {
 
291
    return new (home) Mult<View>(home,share,*this);
 
292
  }
 
293
 
 
294
  template <class View>
 
295
  PropCost
 
296
  Mult<View>::cost(void) const {
 
297
    return PC_TERNARY_HI;
 
298
  }
 
299
 
 
300
  template <class View>
 
301
  ExecStatus
 
302
  Mult<View>::propagate(Space* home) {
 
303
    if (p(x0)) {
 
304
      if (p(x1) || p(x2)) goto rewrite_ppp;
 
305
      if (n(x1) || n(x2)) goto rewrite_pnn;
 
306
      goto prop_pxx;
 
307
    }
 
308
    if (n(x0)) {
 
309
      if (n(x1) || p(x2)) goto rewrite_nnp;
 
310
      if (p(x1) || n(x2)) goto rewrite_npn;
 
311
      goto prop_nxx; 
 
312
    }
 
313
    if (p(x1)) {
 
314
      if (p(x2)) goto rewrite_ppp;
 
315
      if (n(x2)) goto rewrite_npn;
 
316
      goto prop_xpx; 
 
317
    }
 
318
    if (n(x1)) {
 
319
      if (p(x2)) goto rewrite_nnp;
 
320
      if (n(x2)) goto rewrite_pnn;
 
321
      goto prop_xnx; 
 
322
    }
 
323
 
 
324
    assert(x(x0) && x(x1));
 
325
    GECODE_ME_CHECK(x2.lq(home,std::max(m(x0.max(),x1.max()),
 
326
                                        m(x0.min(),x1.min()))));
 
327
    GECODE_ME_CHECK(x2.gq(home,std::min(m(x0.min(),x1.max()),
 
328
                                        m(x0.max(),x1.min()))));
 
329
 
 
330
    if (x0.assigned()) {
 
331
      assert((x0.val() == 0) && (x2.val() == 0));
 
332
      return ES_SUBSUMED;
 
333
    }
 
334
 
 
335
    if (x1.assigned()) {
 
336
      assert((x1.val() == 0) && (x2.val() == 0));
 
337
      return ES_SUBSUMED;
 
338
    }
 
339
 
 
340
    return ES_NOFIX;
 
341
 
 
342
  prop_xpx:
 
343
    std::swap(x0,x1);
 
344
  prop_pxx:
 
345
    assert(p(x0) && x(x1) && x(x2));
 
346
 
 
347
    GECODE_ME_CHECK(x2.lq(home,m(x0.max(),x1.max())));
 
348
    GECODE_ME_CHECK(x2.gq(home,m(x0.max(),x1.min())));
 
349
    
 
350
    if (p(x2)) goto rewrite_ppp;
 
351
    if (n(x2)) goto rewrite_pnn;
 
352
    
 
353
    GECODE_ME_CHECK(x1.lq(home,f_d(x2.max(),x0.min())));
 
354
    GECODE_ME_CHECK(x1.gq(home,c_d(x2.min(),x0.min())));
 
355
    
 
356
    if (x0.assigned() && x1.assigned()) {
 
357
      GECODE_ME_CHECK(x2.eq(home,m(x0.val(),x1.val())));
 
358
      return ES_SUBSUMED;
 
359
    }
 
360
 
 
361
    return ES_NOFIX;
 
362
 
 
363
  prop_xnx:
 
364
    std::swap(x0,x1);
 
365
  prop_nxx:
 
366
    assert(n(x0) && x(x1) && x(x2));
 
367
 
 
368
    GECODE_ME_CHECK(x2.lq(home,m(x0.min(),x1.min())));
 
369
    GECODE_ME_CHECK(x2.gq(home,m(x0.min(),x1.max())));
 
370
    
 
371
    if (p(x2)) goto rewrite_nnp;
 
372
    if (n(x2)) goto rewrite_npn;
 
373
    
 
374
    GECODE_ME_CHECK(x1.lq(home,f_d(x2.min(),x0.max())));
 
375
    GECODE_ME_CHECK(x1.gq(home,c_d(x2.max(),x0.max())));
 
376
    
 
377
    if (x0.assigned() && x1.assigned()) {
 
378
      GECODE_ME_CHECK(x2.eq(home,m(x0.val(),x1.val())));
 
379
      return ES_SUBSUMED;
 
380
    }
 
381
 
 
382
    return ES_NOFIX;
 
383
 
 
384
  rewrite_ppp:
 
385
    return (MultPlus<IntView,IntView,IntView>::post(home,x0,x1,x2) 
 
386
            == ES_FAILED) ? ES_FAILED : ES_SUBSUMED;
 
387
 
 
388
  rewrite_nnp:
 
389
    return (MultPlus<MinusView,MinusView,IntView>::post(home,x0,x1,x2) 
 
390
            == ES_FAILED) ? ES_FAILED : ES_SUBSUMED;
 
391
 
 
392
  rewrite_pnn:
 
393
    std::swap(x0,x1);   
 
394
  rewrite_npn:
 
395
    return (MultPlus<MinusView,IntView,MinusView>::post(home,x0,x1,x2) 
 
396
            == ES_FAILED) ? ES_FAILED : ES_SUBSUMED;
 
397
 
 
398
  }
 
399
 
 
400
  template <class View>
 
401
  ExecStatus
 
402
  Mult<View>::post(Space* home, View x0, View x1, View x2) {
 
403
    if (same(x0,x1))
 
404
      return Square<View>::post(home,x0,x2);
 
405
    if (p(x0)) {
 
406
      if (p(x1) || p(x2)) goto post_ppp;
 
407
      if (n(x1) || n(x2)) goto post_pnn;
 
408
    } else if (n(x0)) {
 
409
      if (n(x1) || p(x2)) goto post_nnp;
 
410
      if (p(x1) || n(x2)) goto post_npn;
 
411
    } else if (p(x1)) {
 
412
      if (p(x2)) goto post_ppp;
 
413
      if (n(x2)) goto post_npn;
 
414
    } else if (n(x1)) {
 
415
      if (p(x2)) goto post_nnp;
 
416
      if (n(x2)) goto post_pnn;
 
417
    }
 
418
    (void) new (home) Mult<View>(home,x0,x1,x2);
 
419
    return ES_OK;
 
420
 
 
421
  post_ppp:
 
422
    return MultPlus<IntView,IntView,IntView>::post(home,x0,x1,x2);
 
423
  post_nnp:
 
424
    return MultPlus<MinusView,MinusView,IntView>::post(home,x0,x1,x2);
 
425
  post_pnn:
 
426
    std::swap(x0,x1);   
 
427
  post_npn:
 
428
    return MultPlus<MinusView,IntView,MinusView>::post(home,x0,x1,x2);
 
429
  }
 
430
 
 
431
 
 
432
#undef GECODE_CM
 
433
 
 
434
}}}
 
435
 
 
436
// STATISTICS: int-prop
 
437