Generated on Thu Mar 22 10:39:42 2012 for Gecode by doxygen 1.6.3

ranges-union.hpp

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  *
00006  *  Copyright:
00007  *     Christian Schulte, 2004
00008  *
00009  *  Last modified:
00010  *     $Date: 2011-08-08 18:04:53 +0200 (Mon, 08 Aug 2011) $ by $Author: schulte $
00011  *     $Revision: 12253 $
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *  Permission is hereby granted, free of charge, to any person obtaining
00018  *  a copy of this software and associated documentation files (the
00019  *  "Software"), to deal in the Software without restriction, including
00020  *  without limitation the rights to use, copy, modify, merge, publish,
00021  *  distribute, sublicense, and/or sell copies of the Software, and to
00022  *  permit persons to whom the Software is furnished to do so, subject to
00023  *  the following conditions:
00024  *
00025  *  The above copyright notice and this permission notice shall be
00026  *  included in all copies or substantial portions of the Software.
00027  *
00028  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00035  *
00036  */
00037 
00038 #include <algorithm>
00039 
00040 namespace Gecode { namespace Iter { namespace Ranges {
00041 
00047   template<class I, class J>
00048   class Union : public MinMax {
00049   protected:
00051     I i;
00053     J j;
00054   public:
00056 
00057 
00058     Union(void);
00060     Union(I& i, J& j);
00062     void init(I& i, J& j);
00064 
00066 
00067 
00068     void operator ++(void);
00070   };
00071 
00072 
00078   class NaryUnion : public RangeListIter {
00079   protected:
00081     RangeList* f;
00083     template<class I, class J>
00084     RangeList* two(I& i, J& j);
00086     template<class I>
00087     void insert(I& i, RangeList*& u);
00088   public:
00090 
00091 
00092     NaryUnion(void);
00094     template<class I>
00095     NaryUnion(Region& r, I& i);
00097     template<class I, class J>
00098     NaryUnion(Region& r, I& i, J& j);
00100     template<class I>
00101     NaryUnion(Region& r, I* i, int n);
00103     template<class I>
00104     void init(Region& r, I& i);
00106     template<class I, class J>
00107     void init(Region& r, I& i, J& j);
00109     template<class I>
00110     void init(Region& r, I* i, int n);
00112     template<class I>
00113     void operator |=(I& i);
00115     NaryUnion& operator =(const NaryUnion& m);
00117   };
00118 
00119 
00120 
00121   /*
00122    * Binary union
00123    *
00124    */
00125 
00126   template<class I, class J>
00127   inline void
00128   Union<I,J>::operator ++(void) {
00129     if (!i() && !j()) {
00130       finish(); return;
00131     }
00132 
00133     if (!i() || (j() && (j.max()+1 < i.min()))) {
00134       mi = j.min(); ma = j.max(); ++j; return;
00135     }
00136     if (!j() || (i() && (i.max()+1 < j.min()))) {
00137       mi = i.min(); ma = i.max(); ++i; return;
00138     }
00139 
00140     mi = std::min(i.min(),j.min());
00141     ma = std::max(i.max(),j.max());
00142 
00143     ++i; ++j;
00144 
00145   next:
00146     if (i() && (i.min() <= ma+1)) {
00147       ma = std::max(ma,i.max()); ++i;
00148       goto next;
00149     }
00150     if (j() && (j.min() <= ma+1)) {
00151       ma = std::max(ma,j.max()); ++j;
00152       goto next;
00153     }
00154   }
00155 
00156 
00157   template<class I, class J>
00158   forceinline
00159   Union<I,J>::Union(void) {}
00160 
00161   template<class I, class J>
00162   forceinline
00163   Union<I,J>::Union(I& i0, J& j0)
00164     : i(i0), j(j0) {
00165     operator ++();
00166   }
00167 
00168   template<class I, class J>
00169   forceinline void
00170   Union<I,J>::init(I& i0, J& j0) {
00171     i = i0; j = j0;
00172     operator ++();
00173   }
00174 
00175 
00176 
00177   /*
00178    * Nary union
00179    *
00180    */
00181 
00182   template<class I, class J>
00183   RangeListIter::RangeList*
00184   NaryUnion::two(I& i, J& j) {
00185     RangeList*  h;
00186     RangeList** c = &h;
00187     
00188     while (i() && j())
00189       if (i.max()+1 < j.min()) {
00190         RangeList* t = range(i); ++i;
00191         *c = t; c = &t->next;
00192       } else if (j.max()+1 < i.min()) {
00193         RangeList* t = range(j); ++j;
00194         *c = t; c = &t->next;
00195       } else {
00196         int min = std::min(i.min(),j.min());
00197         int max = std::max(i.max(),j.max());
00198         ++i; ++j;
00199 
00200       nexta:
00201         if (i() && (i.min() <= max+1)) {
00202           max = std::max(max,i.max()); ++i;
00203           goto nexta;
00204         }
00205         if (j() && (j.min() <= max+1)) {
00206           max = std::max(max,j.max()); ++j;
00207           goto nexta;
00208         }
00209  
00210         RangeList* t = range(min,max);
00211         *c = t; c = &t->next;
00212       }
00213     for ( ; i(); ++i) {
00214       RangeList* t = range(i);
00215       *c = t; c = &t->next;
00216     }
00217     for ( ; j(); ++j) {
00218       RangeList* t = range(j);
00219       *c = t; c = &t->next;
00220     }
00221     *c = NULL;
00222     return h;
00223   }
00224 
00225   template<class I>
00226   void
00227   NaryUnion::insert(I& i, RangeList*& u) {
00228     // The current rangelist
00229     RangeList** c = &u;
00230         
00231     while ((*c != NULL) && i())
00232       if ((*c)->max+1 < i.min()) {
00233         // Keep range from union
00234         c = &(*c)->next;
00235       } else if (i.max()+1 < (*c)->min) {
00236         // Copy range from iterator
00237         RangeList* t = range(i,f); ++i;
00238         // Insert
00239         t->next = *c; *c = t; c = &t->next;
00240       } else {
00241         // Ranges overlap
00242         // Compute new minimum
00243         (*c)->min = std::min((*c)->min,i.min());
00244         // Compute new maximum
00245         int max = std::max((*c)->max,i.max());
00246         
00247         // Scan from the next range in the union
00248         RangeList* s = (*c)->next; 
00249         ++i;
00250         
00251       nextb:
00252         if ((s != NULL) && (s->min <= max+1)) {
00253           max = std::max(max,s->max);
00254           RangeList* t = s;
00255           s = s->next;
00256           // Put deleted element into freelist
00257           t->next = f; f = t;
00258           goto nextb;
00259         }
00260         if (i() && (i.min() <= max+1)) {
00261           max = std::max(max,i.max()); ++i;
00262           goto nextb;
00263         }
00264         // Store computed max and shunt skipped ranges from union
00265         (*c)->max = max; (*c)->next = s;
00266       }
00267     if (*c == NULL) {
00268       // Copy remaining ranges from iterator
00269       for ( ; i(); ++i) {
00270         RangeList* t = range(i,f);
00271         *c = t; c = &t->next;
00272       }
00273       *c = NULL;
00274     }
00275   }
00276 
00277 
00278   forceinline
00279   NaryUnion::NaryUnion(void) {}
00280 
00281   template<class I>
00282   forceinline void
00283   NaryUnion::init(Region& r, I& i) {
00284     RangeListIter::init(r);
00285     f = NULL;
00286     set(copy(i));
00287   }
00288 
00289   template<class I, class J>
00290   forceinline void
00291   NaryUnion::init(Region& r, I& i, J& j) {
00292     RangeListIter::init(r);
00293     f = NULL;
00294     set(two(i,j));
00295   }
00296 
00297   template<class I>
00298   forceinline void
00299   NaryUnion::init(Region& r, I* i, int n) {
00300     f = NULL;
00301     RangeListIter::init(r);
00302 
00303     int m = 0;
00304     while ((m < n) && !i[m]())
00305       m++;
00306 
00307     // Union is empty
00308     if (m >= n)
00309       return;
00310 
00311     n--;
00312     while (!i[n]())
00313       n--;
00314 
00315     if (m == n) {
00316       // Union is just a single iterator
00317       set(copy(i[m]));
00318     } else {
00319       // At least two iterators
00320       RangeList* u = two(i[m++],i[n--]);
00321       // Insert the remaining iterators
00322       for ( ; m<=n; m++)
00323         insert(i[m], u);
00324       set(u);
00325     }
00326   }
00327 
00328   template<class I>
00329   forceinline
00330   NaryUnion::NaryUnion(Region& r, I& i) {
00331     init(r, i);
00332   }
00333   template<class I, class J>
00334   forceinline
00335   NaryUnion::NaryUnion(Region& r, I& i, J& j) {
00336     init(r, i, j);
00337   }
00338   template<class I>
00339   forceinline
00340   NaryUnion::NaryUnion(Region& r, I* i, int n) {
00341     init(r, i, n);
00342   }
00343 
00344   template<class I>
00345   forceinline void
00346   NaryUnion::operator |=(I& i) {
00347     RangeList* u = get();
00348     insert(i, u);
00349     set(u);
00350   }
00351 
00352   forceinline NaryUnion&
00353   NaryUnion::operator =(const NaryUnion& m) {
00354     f = NULL;
00355     return static_cast<NaryUnion&>(RangeListIter::operator =(m));
00356   }
00357 
00358 }}}
00359 
00360 // STATISTICS: iter-any
00361