Generated on Tue Apr 18 10:21:56 2017 for Gecode by doxygen 1.6.3

bool-post.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *     Tias Guns <tias.guns@cs.kuleuven.be>
00006  *
00007  *  Copyright:
00008  *     Christian Schulte, 2002
00009  *     Tias Guns, 2009
00010  *
00011  *  Last modified:
00012  *     $Date: 2017-03-09 09:51:58 +0100 (Thu, 09 Mar 2017) $ by $Author: schulte $
00013  *     $Revision: 15565 $
00014  *
00015  *  This file is part of Gecode, the generic constraint
00016  *  development environment:
00017  *     http://www.gecode.org
00018  *
00019  *  Permission is hereby granted, free of charge, to any person obtaining
00020  *  a copy of this software and associated documentation files (the
00021  *  "Software"), to deal in the Software without restriction, including
00022  *  without limitation the rights to use, copy, modify, merge, publish,
00023  *  distribute, sublicense, and/or sell copies of the Software, and to
00024  *  permit persons to whom the Software is furnished to do so, subject to
00025  *  the following conditions:
00026  *
00027  *  The above copyright notice and this permission notice shall be
00028  *  included in all copies or substantial portions of the Software.
00029  *
00030  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00031  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00032  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00033  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00034  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00035  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00036  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00037  *
00038  */
00039 
00040 #include <gecode/int/linear.hh>
00041 #include <gecode/int/div.hh>
00042 
00043 namespace Gecode { namespace Int { namespace Linear {
00044 
00046   forceinline void
00047   eliminate(Term<BoolView>* t, int &n, long long int& d) {
00048     for (int i=n; i--; )
00049       if (t[i].x.one()) {
00050         d -= t[i].a; t[i]=t[--n];
00051       } else if (t[i].x.zero()) {
00052         t[i]=t[--n];
00053       }
00054     Limits::check(d,"Int::linear");
00055   }
00056 
00058   forceinline void
00059   rewrite(IntRelType &r, long long int &d) {
00060       switch (r) {
00061       case IRT_EQ: case IRT_NQ: case IRT_LQ: case IRT_GQ:
00062         break;
00063       case IRT_LE:
00064         d--; r = IRT_LQ; break;
00065       case IRT_GR:
00066         d++; r = IRT_GQ; break;
00067       default:
00068         throw UnknownRelation("Int::linear");
00069       }
00070   }
00071 
00072   forceinline void
00073   post_pos_unit(Home home,
00074                 Term<BoolView>* t_p, int n_p,
00075                 IntRelType irt, IntView y, int c) {
00076     switch (irt) {
00077     case IRT_EQ:
00078       {
00079         ViewArray<BoolView> x(home,n_p);
00080         for (int i=n_p; i--; )
00081           x[i]=t_p[i].x;
00082         GECODE_ES_FAIL((EqBoolView<BoolView,IntView>
00083                              ::post(home,x,y,c)));
00084       }
00085       break;
00086     case IRT_NQ:
00087       {
00088         ViewArray<BoolView> x(home,n_p);
00089         for (int i=n_p; i--; )
00090           x[i]=t_p[i].x;
00091         GECODE_ES_FAIL((NqBoolView<BoolView,IntView>
00092                              ::post(home,x,y,c)));
00093       }
00094       break;
00095     case IRT_GQ:
00096       {
00097         ViewArray<BoolView> x(home,n_p);
00098         for (int i=n_p; i--; )
00099           x[i]=t_p[i].x;
00100         GECODE_ES_FAIL((GqBoolView<BoolView,IntView>
00101                              ::post(home,x,y,c)));
00102       }
00103       break;
00104     case IRT_LQ:
00105       {
00106         ViewArray<NegBoolView> x(home,n_p);
00107         for (int i=n_p; i--; )
00108           x[i]=NegBoolView(t_p[i].x);
00109         MinusView z(y);
00110         GECODE_ES_FAIL((GqBoolView<NegBoolView,MinusView>
00111                              ::post(home,x,z,n_p-c)));
00112       }
00113       break;
00114     default: GECODE_NEVER;
00115     }
00116   }
00117 
00118   forceinline void
00119   post_pos_unit(Home home,
00120                 Term<BoolView>* t_p, int n_p,
00121                 IntRelType irt, ZeroIntView, int c) {
00122     switch (irt) {
00123     case IRT_EQ:
00124       {
00125         ViewArray<BoolView> x(home,n_p);
00126         for (int i=n_p; i--; )
00127           x[i]=t_p[i].x;
00128         GECODE_ES_FAIL((EqBoolInt<BoolView>::post(home,x,c)));
00129       }
00130       break;
00131     case IRT_NQ:
00132       {
00133         ViewArray<BoolView> x(home,n_p);
00134         for (int i=n_p; i--; )
00135           x[i]=t_p[i].x;
00136         GECODE_ES_FAIL((NqBoolInt<BoolView>::post(home,x,c)));
00137       }
00138       break;
00139     case IRT_GQ:
00140       {
00141         ViewArray<BoolView> x(home,n_p);
00142         for (int i=n_p; i--; )
00143           x[i]=t_p[i].x;
00144         GECODE_ES_FAIL((GqBoolInt<BoolView>::post(home,x,c)));
00145       }
00146       break;
00147     case IRT_LQ:
00148       {
00149         ViewArray<NegBoolView> x(home,n_p);
00150         for (int i=n_p; i--; )
00151           x[i]=NegBoolView(t_p[i].x);
00152         GECODE_ES_FAIL((GqBoolInt<NegBoolView>::post(home,x,n_p-c)));
00153       }
00154       break;
00155     default: GECODE_NEVER;
00156     }
00157   }
00158 
00159   forceinline void
00160   post_pos_unit(Home home,
00161                 Term<BoolView>* t_p, int n_p,
00162                 IntRelType irt, int c, Reify r,
00163                 IntPropLevel) {
00164     switch (irt) {
00165     case IRT_EQ:
00166       {
00167         ViewArray<BoolView> x(home,n_p);
00168         for (int i=n_p; i--; )
00169           x[i]=t_p[i].x;
00170         switch (r.mode()) {
00171         case RM_EQV:
00172           GECODE_ES_FAIL((ReEqBoolInt<BoolView,BoolView,RM_EQV>::
00173                           post(home,x,c,r.var())));
00174           break;
00175         case RM_IMP:
00176           GECODE_ES_FAIL((ReEqBoolInt<BoolView,BoolView,RM_IMP>::
00177                           post(home,x,c,r.var())));
00178           break;
00179         case RM_PMI:
00180           GECODE_ES_FAIL((ReEqBoolInt<BoolView,BoolView,RM_PMI>::
00181                           post(home,x,c,r.var())));
00182           break;
00183         default: GECODE_NEVER;
00184         }
00185       }
00186       break;
00187     case IRT_NQ:
00188       {
00189         ViewArray<BoolView> x(home,n_p);
00190         for (int i=n_p; i--; )
00191           x[i]=t_p[i].x;
00192         NegBoolView nb(r.var());
00193         switch (r.mode()) {
00194         case RM_EQV:
00195           GECODE_ES_FAIL((ReEqBoolInt<BoolView,NegBoolView,RM_EQV>::
00196                           post(home,x,c,nb)));
00197           break;
00198         case RM_IMP:
00199           GECODE_ES_FAIL((ReEqBoolInt<BoolView,NegBoolView,RM_PMI>::
00200                           post(home,x,c,nb)));
00201           break;
00202         case RM_PMI:
00203           GECODE_ES_FAIL((ReEqBoolInt<BoolView,NegBoolView,RM_IMP>::
00204                           post(home,x,c,nb)));
00205           break;
00206         default: GECODE_NEVER;
00207         }
00208       }
00209       break;
00210     case IRT_GQ:
00211       {
00212         ViewArray<BoolView> x(home,n_p);
00213         for (int i=n_p; i--; )
00214           x[i]=t_p[i].x;
00215         switch (r.mode()) {
00216         case RM_EQV:
00217           GECODE_ES_FAIL((ReGqBoolInt<BoolView,BoolView,RM_EQV>::
00218                           post(home,x,c,r.var())));
00219           break;
00220         case RM_IMP:
00221           GECODE_ES_FAIL((ReGqBoolInt<BoolView,BoolView,RM_IMP>::
00222                           post(home,x,c,r.var())));
00223           break;
00224         case RM_PMI:
00225           GECODE_ES_FAIL((ReGqBoolInt<BoolView,BoolView,RM_PMI>::
00226                           post(home,x,c,r.var())));
00227           break;
00228         default: GECODE_NEVER;
00229         }
00230       }
00231       break;
00232     case IRT_LQ:
00233       {
00234         ViewArray<NegBoolView> x(home,n_p);
00235         for (int i=n_p; i--; )
00236           x[i]=NegBoolView(t_p[i].x);
00237         switch (r.mode()) {
00238         case RM_EQV:
00239           GECODE_ES_FAIL((ReGqBoolInt<NegBoolView,BoolView,RM_EQV>::
00240                           post(home,x,n_p-c,r.var())));
00241           break;
00242         case RM_IMP:
00243           GECODE_ES_FAIL((ReGqBoolInt<NegBoolView,BoolView,RM_IMP>::
00244                           post(home,x,n_p-c,r.var())));
00245           break;
00246         case RM_PMI:
00247           GECODE_ES_FAIL((ReGqBoolInt<NegBoolView,BoolView,RM_PMI>::
00248                           post(home,x,n_p-c,r.var())));
00249           break;
00250         default: GECODE_NEVER;
00251         }
00252       }
00253       break;
00254     default: GECODE_NEVER;
00255     }
00256   }
00257 
00258   forceinline void
00259   post_neg_unit(Home home,
00260                 Term<BoolView>* t_n, int n_n,
00261                 IntRelType irt, IntView y, int c) {
00262     switch (irt) {
00263     case IRT_EQ:
00264       {
00265         ViewArray<BoolView> x(home,n_n);
00266         for (int i=n_n; i--; )
00267           x[i]=t_n[i].x;
00268         MinusView z(y);
00269         GECODE_ES_FAIL((EqBoolView<BoolView,MinusView>
00270                         ::post(home,x,z,-c)));
00271       }
00272       break;
00273     case IRT_NQ:
00274       {
00275         ViewArray<BoolView> x(home,n_n);
00276         for (int i=n_n; i--; )
00277           x[i]=t_n[i].x;
00278         MinusView z(y);
00279         GECODE_ES_FAIL((NqBoolView<BoolView,MinusView>
00280                         ::post(home,x,z,-c)));
00281       }
00282       break;
00283     case IRT_GQ:
00284       {
00285         ViewArray<NegBoolView> x(home,n_n);
00286         for (int i=n_n; i--; )
00287           x[i]=NegBoolView(t_n[i].x);
00288         GECODE_ES_FAIL((GqBoolView<NegBoolView,IntView>
00289                         ::post(home,x,y,n_n+c)));
00290       }
00291       break;
00292     case IRT_LQ:
00293       {
00294         ViewArray<BoolView> x(home,n_n);
00295         for (int i=n_n; i--; )
00296           x[i]=t_n[i].x;
00297         MinusView z(y);
00298         GECODE_ES_FAIL((GqBoolView<BoolView,MinusView>
00299                         ::post(home,x,z,-c)));
00300       }
00301       break;
00302     default: GECODE_NEVER;
00303     }
00304   }
00305 
00306   forceinline void
00307   post_neg_unit(Home home,
00308                 Term<BoolView>* t_n, int n_n,
00309                 IntRelType irt, ZeroIntView, int c) {
00310     switch (irt) {
00311     case IRT_EQ:
00312       {
00313         ViewArray<BoolView> x(home,n_n);
00314         for (int i=n_n; i--; )
00315           x[i]=t_n[i].x;
00316         GECODE_ES_FAIL((EqBoolInt<BoolView>::post(home,x,-c)));
00317       }
00318       break;
00319     case IRT_NQ:
00320       {
00321         ViewArray<BoolView> x(home,n_n);
00322         for (int i=n_n; i--; )
00323           x[i]=t_n[i].x;
00324         GECODE_ES_FAIL((NqBoolInt<BoolView>::post(home,x,-c)));
00325       }
00326       break;
00327     case IRT_GQ:
00328       {
00329         ViewArray<NegBoolView> x(home,n_n);
00330         for (int i=n_n; i--; )
00331           x[i]=NegBoolView(t_n[i].x);
00332         GECODE_ES_FAIL((GqBoolInt<NegBoolView>::post(home,x,n_n+c)));
00333       }
00334       break;
00335     case IRT_LQ:
00336       {
00337         ViewArray<BoolView> x(home,n_n);
00338         for (int i=n_n; i--; )
00339           x[i]=t_n[i].x;
00340         GECODE_ES_FAIL((GqBoolInt<BoolView>::post(home,x,-c)));
00341       }
00342       break;
00343     default: GECODE_NEVER;
00344     }
00345   }
00346 
00347   forceinline void
00348   post_neg_unit(Home home,
00349                 Term<BoolView>* t_n, int n_n,
00350                 IntRelType irt, int c, Reify r,
00351                 IntPropLevel) {
00352     switch (irt) {
00353     case IRT_EQ:
00354       {
00355         ViewArray<BoolView> x(home,n_n);
00356         for (int i=n_n; i--; )
00357           x[i]=t_n[i].x;
00358         switch (r.mode()) {
00359         case RM_EQV:
00360           GECODE_ES_FAIL((ReEqBoolInt<BoolView,BoolView,RM_EQV>::
00361                           post(home,x,-c,r.var())));
00362           break;
00363         case RM_IMP:
00364           GECODE_ES_FAIL((ReEqBoolInt<BoolView,BoolView,RM_IMP>::
00365                           post(home,x,-c,r.var())));
00366           break;
00367         case RM_PMI:
00368           GECODE_ES_FAIL((ReEqBoolInt<BoolView,BoolView,RM_PMI>::
00369                           post(home,x,-c,r.var())));
00370           break;
00371         default: GECODE_NEVER;
00372         }
00373       }
00374       break;
00375     case IRT_NQ:
00376       {
00377         ViewArray<BoolView> x(home,n_n);
00378         for (int i=n_n; i--; )
00379           x[i]=t_n[i].x;
00380         NegBoolView nb(r.var());
00381         switch (r.mode()) {
00382         case RM_EQV:
00383           GECODE_ES_FAIL((ReEqBoolInt<BoolView,NegBoolView,RM_EQV>::
00384                           post(home,x,-c,nb)));
00385           break;
00386         case RM_IMP:
00387           GECODE_ES_FAIL((ReEqBoolInt<BoolView,NegBoolView,RM_PMI>::
00388                           post(home,x,-c,nb)));
00389           break;
00390         case RM_PMI:
00391           GECODE_ES_FAIL((ReEqBoolInt<BoolView,NegBoolView,RM_IMP>::
00392                           post(home,x,-c,nb)));
00393           break;
00394         default: GECODE_NEVER;
00395         }
00396       }
00397       break;
00398     case IRT_GQ:
00399       {
00400         ViewArray<NegBoolView> x(home,n_n);
00401         for (int i=n_n; i--; )
00402           x[i]=NegBoolView(t_n[i].x);
00403         switch (r.mode()) {
00404         case RM_EQV:
00405           GECODE_ES_FAIL((ReGqBoolInt<NegBoolView,BoolView,RM_EQV>::
00406                           post(home,x,n_n+c,r.var())));
00407           break;
00408         case RM_IMP:
00409           GECODE_ES_FAIL((ReGqBoolInt<NegBoolView,BoolView,RM_IMP>::
00410                           post(home,x,n_n+c,r.var())));
00411           break;
00412         case RM_PMI:
00413           GECODE_ES_FAIL((ReGqBoolInt<NegBoolView,BoolView,RM_PMI>::
00414                           post(home,x,n_n+c,r.var())));
00415           break;
00416         default: GECODE_NEVER;
00417         }
00418       }
00419       break;
00420     case IRT_LQ:
00421       {
00422         ViewArray<BoolView> x(home,n_n);
00423         for (int i=n_n; i--; )
00424           x[i]=t_n[i].x;
00425         switch (r.mode()) {
00426         case RM_EQV:
00427           GECODE_ES_FAIL((ReGqBoolInt<BoolView,BoolView,RM_EQV>::
00428                           post(home,x,-c,r.var())));
00429           break;
00430         case RM_IMP:
00431           GECODE_ES_FAIL((ReGqBoolInt<BoolView,BoolView,RM_IMP>::
00432                           post(home,x,-c,r.var())));
00433           break;
00434         case RM_PMI:
00435           GECODE_ES_FAIL((ReGqBoolInt<BoolView,BoolView,RM_PMI>::
00436                           post(home,x,-c,r.var())));
00437           break;
00438         default: GECODE_NEVER;
00439         }
00440       }
00441       break;
00442     default: GECODE_NEVER;
00443     }
00444   }
00445 
00446   forceinline void
00447   post_mixed(Home home,
00448              Term<BoolView>* t_p, int n_p,
00449              Term<BoolView>* t_n, int n_n,
00450              IntRelType irt, IntView y, int c) {
00451     ScaleBoolArray b_p(home,n_p);
00452     {
00453       ScaleBool* f=b_p.fst();
00454       for (int i=n_p; i--; ) {
00455         f[i].x=t_p[i].x; f[i].a=t_p[i].a;
00456       }
00457     }
00458     ScaleBoolArray b_n(home,n_n);
00459     {
00460       ScaleBool* f=b_n.fst();
00461       for (int i=n_n; i--; ) {
00462         f[i].x=t_n[i].x; f[i].a=t_n[i].a;
00463       }
00464     }
00465     switch (irt) {
00466     case IRT_EQ:
00467       GECODE_ES_FAIL((EqBoolScale<ScaleBoolArray,ScaleBoolArray,IntView>
00468                       ::post(home,b_p,b_n,y,c)));
00469       break;
00470     case IRT_NQ:
00471       GECODE_ES_FAIL((NqBoolScale<ScaleBoolArray,ScaleBoolArray,IntView>
00472                       ::post(home,b_p,b_n,y,c)));
00473       break;
00474     case IRT_LQ:
00475       GECODE_ES_FAIL((LqBoolScale<ScaleBoolArray,ScaleBoolArray,IntView>
00476                       ::post(home,b_p,b_n,y,c)));
00477       break;
00478     case IRT_GQ:
00479       {
00480         MinusView m(y);
00481         GECODE_ES_FAIL((LqBoolScale<ScaleBoolArray,ScaleBoolArray,MinusView>
00482                         ::post(home,b_n,b_p,m,-c)));
00483       }
00484       break;
00485     default:
00486       GECODE_NEVER;
00487     }
00488   }
00489 
00490 
00491   forceinline void
00492   post_mixed(Home home,
00493              Term<BoolView>* t_p, int n_p,
00494              Term<BoolView>* t_n, int n_n,
00495              IntRelType irt, ZeroIntView y, int c) {
00496     ScaleBoolArray b_p(home,n_p);
00497     {
00498       ScaleBool* f=b_p.fst();
00499       for (int i=n_p; i--; ) {
00500         f[i].x=t_p[i].x; f[i].a=t_p[i].a;
00501       }
00502     }
00503     ScaleBoolArray b_n(home,n_n);
00504     {
00505       ScaleBool* f=b_n.fst();
00506       for (int i=n_n; i--; ) {
00507         f[i].x=t_n[i].x; f[i].a=t_n[i].a;
00508       }
00509     }
00510     switch (irt) {
00511     case IRT_EQ:
00512       GECODE_ES_FAIL(
00513                      (EqBoolScale<ScaleBoolArray,ScaleBoolArray,ZeroIntView>
00514                       ::post(home,b_p,b_n,y,c)));
00515       break;
00516     case IRT_NQ:
00517       GECODE_ES_FAIL(
00518                      (NqBoolScale<ScaleBoolArray,ScaleBoolArray,ZeroIntView>
00519                       ::post(home,b_p,b_n,y,c)));
00520       break;
00521     case IRT_LQ:
00522       GECODE_ES_FAIL(
00523                      (LqBoolScale<ScaleBoolArray,ScaleBoolArray,ZeroIntView>
00524                       ::post(home,b_p,b_n,y,c)));
00525       break;
00526     case IRT_GQ:
00527       GECODE_ES_FAIL(
00528                      (LqBoolScale<ScaleBoolArray,ScaleBoolArray,ZeroIntView>
00529                       ::post(home,b_n,b_p,y,-c)));
00530       break;
00531     default:
00532       GECODE_NEVER;
00533     }
00534   }
00535 
00536   template<class View>
00537   forceinline void
00538   post_all(Home home,
00539            Term<BoolView>* t, int n,
00540            IntRelType irt, View x, int c) {
00541 
00542     Limits::check(c,"Int::linear");
00543 
00544     long long int d = c;
00545 
00546     eliminate(t,n,d);
00547 
00548     Term<BoolView> *t_p, *t_n;
00549     int n_p, n_n, gcd=0;
00550     bool unit = normalize<BoolView>(t,n,t_p,n_p,t_n,n_n,gcd);
00551 
00552     rewrite(irt,d);
00553 
00554     c = static_cast<int>(d);
00555 
00556     if (n == 0) {
00557       switch (irt) {
00558       case IRT_EQ: GECODE_ME_FAIL(x.eq(home,-c)); break;
00559       case IRT_NQ: GECODE_ME_FAIL(x.nq(home,-c)); break;
00560       case IRT_GQ: GECODE_ME_FAIL(x.lq(home,-c)); break;
00561       case IRT_LQ: GECODE_ME_FAIL(x.gq(home,-c)); break;
00562       default: GECODE_NEVER;
00563       }
00564       return;
00565     }
00566 
00567     // Check for overflow
00568     {
00569       long long int sl = static_cast<long long int>(x.max())+c;
00570       long long int su = static_cast<long long int>(x.min())+c;
00571       for (int i=n_p; i--; )
00572         su -= t_p[i].a;
00573       for (int i=n_n; i--; )
00574         sl += t_n[i].a;
00575       Limits::check(sl,"Int::linear");
00576       Limits::check(su,"Int::linear");
00577     }
00578 
00579     if (unit && (n_n == 0)) {
00581       post_pos_unit(home,t_p,n_p,irt,x,c);
00582     } else if (unit && (n_p == 0)) {
00583       // All coefficients are -1
00584       post_neg_unit(home,t_n,n_n,irt,x,c);
00585     } else {
00586       // Mixed coefficients
00587       post_mixed(home,t_p,n_p,t_n,n_n,irt,x,c);
00588     }
00589   }
00590 
00591 
00592   void
00593   post(Home home,
00594        Term<BoolView>* t, int n, IntRelType irt, IntView x, int c,
00595        IntPropLevel) {
00596     post_all(home,t,n,irt,x,c);
00597   }
00598 
00599   void
00600   post(Home home,
00601        Term<BoolView>* t, int n, IntRelType irt, int c,
00602        IntPropLevel) {
00603     ZeroIntView x;
00604     post_all(home,t,n,irt,x,c);
00605   }
00606 
00607   void
00608   post(Home home,
00609        Term<BoolView>* t, int n, IntRelType irt, IntView x, Reify r,
00610        IntPropLevel ipl) {
00611     int l, u;
00612     estimate(t,n,0,l,u);
00613     IntVar z(home,l,u); IntView zv(z);
00614     post_all(home,t,n,IRT_EQ,zv,0);
00615     rel(home,z,irt,x,r,ipl);
00616   }
00617 
00618   void
00619   post(Home home,
00620        Term<BoolView>* t, int n, IntRelType irt, int c, Reify r,
00621        IntPropLevel ipl) {
00622 
00623     if (r.var().one()) {
00624       if (r.mode() != RM_PMI)
00625         post(home,t,n,irt,c,ipl);
00626       return;
00627     }
00628     if (r.var().zero()) {
00629       if (r.mode() != RM_IMP)
00630         post(home,t,n,neg(irt),c,ipl);
00631       return;
00632     }
00633 
00634     Limits::check(c,"Int::linear");
00635 
00636     long long int d = c;
00637 
00638     eliminate(t,n,d);
00639 
00640     Term<BoolView> *t_p, *t_n;
00641     int n_p, n_n, gcd=1;
00642     bool unit = normalize<BoolView>(t,n,t_p,n_p,t_n,n_n,gcd);
00643 
00644     rewrite(irt,d);
00645 
00646     // Divide by gcd
00647     if (gcd > 1) {
00648       switch (irt) {
00649       case IRT_EQ:
00650         if ((d % gcd) != 0) {
00651           if (r.mode() != RM_PMI)
00652             GECODE_ME_FAIL(BoolView(r.var()).zero(home));
00653           return;
00654         }
00655         d /= gcd;
00656         break;
00657       case IRT_NQ:
00658         if ((d % gcd) == 0) {
00659           if (r.mode() != RM_IMP)
00660             GECODE_ME_FAIL(BoolView(r.var()).one(home));
00661           return;
00662         }
00663         d /= gcd;
00664         break;
00665       case IRT_LQ:
00666         d = floor_div_xp(d,static_cast<long long int>(gcd));
00667         break;
00668       case IRT_GQ:
00669         d = ceil_div_xp(d,static_cast<long long int>(gcd));
00670         break;
00671       default: GECODE_NEVER;
00672       }
00673     }
00674 
00675     c = static_cast<int>(d);
00676 
00677     if (n == 0) {
00678       bool fail = false;
00679       switch (irt) {
00680       case IRT_EQ: fail = (0 != c); break;
00681       case IRT_NQ: fail = (0 == c); break;
00682       case IRT_GQ: fail = (0 < c); break;
00683       case IRT_LQ: fail = (0 > c); break;
00684       default: GECODE_NEVER;
00685       }
00686       if (fail) {
00687         if (r.mode() != RM_PMI)
00688           GECODE_ME_FAIL(BoolView(r.var()).zero(home));
00689       } else {
00690         if (r.mode() != RM_IMP)
00691           GECODE_ME_FAIL(BoolView(r.var()).one(home));
00692       }
00693       return;
00694     }
00695 
00696     // Check for overflow
00697     {
00698       long long int sl = c;
00699       long long int su = c;
00700       for (int i=n_p; i--; )
00701         su -= t_p[i].a;
00702       for (int i=n_n; i--; )
00703         sl += t_n[i].a;
00704       Limits::check(sl,"Int::linear");
00705       Limits::check(su,"Int::linear");
00706     }
00707 
00708     if (unit && (n_n == 0)) {
00710       post_pos_unit(home,t_p,n_p,irt,c,r,ipl);
00711     } else if (unit && (n_p == 0)) {
00712       // All coefficients are -1
00713       post_neg_unit(home,t_n,n_n,irt,c,r,ipl);
00714     } else {
00715       // Mixed coefficients
00716       /*
00717        * Denormalize: Make all t_n coefficients negative again
00718        * (t_p and t_n are shared in t)
00719        */
00720       for (int i=n_n; i--; )
00721         t_n[i].a = -t_n[i].a;
00722 
00723       // Note: still slow implementation
00724       int l, u;
00725       estimate(t,n,0,l,u);
00726       IntVar z(home,l,u); IntView zv(z);
00727       post_all(home,t,n,IRT_EQ,zv,0);
00728       rel(home,z,irt,c,r,ipl);
00729     }
00730   }
00731 
00732 }}}
00733 
00734 // STATISTICS: int-post
00735