Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

wrapper.h

Go to the documentation of this file.
00001 // -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; indent-tabs-mode: nil; -*-
00002 //
00003 // Filename : wrapper.h
00004 //
00005 // Wrapper from the DBM library to SWIG.
00006 //
00007 // This file is a part of the UPPAAL toolkit.
00008 // Copyright (c) 1995 - 2003, Uppsala University and Aalborg University.
00009 // All right reserved.
00010 //
00011 // $Id: wrapper.h,v 1.1 2005/09/17 16:37:23 adavid Exp $
00012 //
00013 ///////////////////////////////////////////////////////////////////
00014 
00015 #ifndef DBM_RUBY_WRAPPER_H
00016 #define DBM_RUBY_WRAPPER_H
00017 
00018 // This is for swig
00019 
00020 #ifndef INCLUDE_BASE_RELATION_H
00021 typedef int relation_t;
00022 #endif
00023 
00024 namespace udbm
00025 {
00026     // Exceptions
00027 
00028     class IndexOutOfRange {};
00029     class EmptyDBM {};
00030     class InvalidDimension {};
00031     class DimensionTooLarge {};
00032     class ForbiddenMinusInfinity {};
00033     class InvalidDBMMatrix {};
00034     class OutOfMemory {};
00035     class IncompatibleDBM {};
00036     class IncompatibleFed {};
00037     class IncompatibleDBMVector {};
00038     class IncompatibleDBMPoint {};
00039     class InvalidBoundValue {};
00040     class IllegalFirstValue {};
00041     class FatalError {};
00042 
00043 #define CHECKD(A)    if (    dim() != (A).dim()) throw IncompatibleDBM()
00044 #define CHECKSD(A,B) if ((A).dim() != (B).dim()) throw IncompatibleDBM()
00045 #define CHECKF(A)    if (    dim() != (A).dim()) throw IncompatibleFed()
00046 #define CHECKSF(A,B) if ((A).dim() != (B).dim()) throw IncompatibleFed()
00047 
00048     // Class declared that are visible for the user:
00049 
00050     class Constraint; // wraps constraints of the form <x or <=x
00051     class DBMMatrix;  // helper class to construct DBMs
00052     class FedArray;   // helper class to construct federations
00053     class DBM;        // user's DBM in the target language
00054     class Fed;        // user's federation in the target language
00055     class DBMVector;  // int vectors for DBMs, 1st element always == 0
00056     class DBMPoint;   // & similarly double vectors
00057 
00058     // To reduce the awful high number of copies we have.
00059     // Resizable referenced arrays of scalar & pointers.
00060 
00061     template<class T> class PointerAS;
00062     template<class P> class PointerAP;
00063 
00064     template<class T>
00065     class ZArrayScal : public base::Object
00066     {
00067         friend class PointerAS<T>;
00068     public:
00069         // size of the array
00070         int size() const { return dataSize; }
00071 
00072         // simple reading
00073         const T get(int index) const throw(IndexOutOfRange) {
00074             if (index < 0 || index >= size())
00075             {
00076                 throw IndexOutOfRange();
00077             }
00078             return data[index];
00079         }
00080 
00081         T* begin() { return data; } // caution!
00082         const T* begin() const { return data; }
00083         const T* end()   const { return data + size(); }
00084 
00085     private:
00086         // write: check size & if it is mutable, may copy itself
00087         ZArrayScal<T>* setScalar(int index, T val) throw(OutOfMemory) {
00088             assert(index >= 0);
00089             ZArrayScal<T>* arr = ensureMutableScalars(index+1);
00090             arr->data[index] = val;
00091             return arr;
00092         }
00093 
00094         // add an element
00095         ZArrayScal<T>* addScalar(T val) throw(OutOfMemory) {
00096             return setScalar(size(), val);
00097         }
00098 
00099         // check mutable & size
00100         ZArrayScal<T>* ensureMutableScalars(int size) throw(OutOfMemory,std::bad_alloc) {
00101             int oldSize = dataSize;
00102             if (base::Object::isMutable())
00103             {
00104                 if (size > oldSize)
00105                 {
00106                     data = (T*) realloc(data, size*sizeof(T));
00107                     if (!data)
00108                     {
00109                         throw OutOfMemory();
00110                     }
00111                     memset(data+oldSize, 0, (size-oldSize)*sizeof(T));
00112                     dataSize = size;
00113                 }
00114                 return this;
00115             }
00116             else // not mutable!
00117             {
00118                 ZArrayScal<T>* other = new ZArrayScal<T>(oldSize >= size ? oldSize : size, false);
00119                 memcpy(other->data, data, oldSize*sizeof(T));
00120                 if (size > oldSize)
00121                 {
00122                     memset(other->data, 0, (size-oldSize)*sizeof(T));
00123                 }
00124                 other->addReference();
00125                 base::Object::dropReference();
00126                 return other;
00127             }
00128         }
00129 
00130     protected:
00131         // constructor only via create
00132         ZArrayScal(int theSize, bool reset) throw(OutOfMemory)
00133             : dataSize(theSize), data((T*)malloc(theSize*sizeof(T))) {
00134             if (!data)
00135             {
00136                 throw OutOfMemory();
00137             }
00138             if (reset)
00139             {
00140                 memset(data, 0, theSize*sizeof(T));
00141             }
00142         }
00143 
00144         virtual ~ZArrayScal() { if (data) { free(data); } }
00145 
00146         int dataSize;
00147         T *data;
00148     };
00149 
00150     template<class O>
00151     class ZArrayPtr : public ZArrayScal<O*>
00152     {
00153         friend class PointerAP<O>;        
00154     private:
00155         ZArrayPtr<O>* setPointer(int index, O* val) throw(OutOfMemory) {
00156             assert(index >=0);
00157             ZArrayPtr<O>* arr = ensureMutablePointers(index+1);
00158             arr->data[index] = val;
00159             return arr;
00160         }   
00161 
00162         ZArrayPtr<O>* addPointer(O* val) throw(OutOfMemory) {
00163             return setPointer(ZArrayScal<O*>::dataSize, val);
00164         }
00165 
00166         ZArrayPtr<O>* ensureMutablePointers(int size) throw(OutOfMemory,std::bad_alloc) {
00167             int oldSize = ZArrayScal<O*>::dataSize;
00168             if (base::Object::isMutable())
00169             {
00170                 if (size > oldSize)
00171                 {
00172                     ZArrayScal<O*>::data = (O**) realloc(ZArrayScal<O*>::data, size*sizeof(O*));
00173                     if (!ZArrayScal<O*>::data)
00174                     {
00175                         throw OutOfMemory();
00176                     }
00177                     memset(ZArrayScal<O*>::data+oldSize, 0, (size-oldSize)*sizeof(O*));
00178                     ZArrayScal<O*>::dataSize = size;
00179                 }
00180                 return this;
00181             }
00182             else // not mutable!
00183             {
00184                 O** thisData = ZArrayScal<O*>::data;
00185                 ZArrayPtr<O>* other = new ZArrayPtr<O>(oldSize >= size ? oldSize : size, false);
00186                 int i;
00187                 for(i = 0; i < oldSize; ++i)
00188                 {
00189                     other->data[i] = thisData[i] ? new O(*thisData[i]) : NULL;
00190                 }
00191                 for( ; i < size; ++i)
00192                 {
00193                     other->data[i] = NULL;
00194                 }
00195                 other->addReference();
00196                 base::Object::dropReference();
00197                 return other;
00198             }
00199         }
00200 
00201         ZArrayPtr(int theSize, bool reset) throw(OutOfMemory)
00202             : ZArrayScal<O*>(theSize, reset) {}
00203 
00204         virtual ~ZArrayPtr() {
00205              O** data = ZArrayScal<O*>::data;
00206             int dataSize = ZArrayScal<O*>::dataSize;
00207             for(int i = 0; i < dataSize; ++i)
00208             {
00209                 if (data[i]) { delete data[i]; }
00210             }
00211         }
00212     };
00213 
00214     // Pointer to resizable arrays.
00215 
00216     template<class S>
00217     class PointerAS : public base::Pointer<ZArrayScal<S> >
00218     {
00219     public:
00220         static ZArrayScal<S>* create(int size, bool reset = true) throw(OutOfMemory,std::bad_alloc) {
00221             return new ZArrayScal<S>(size, reset);
00222         }
00223         PointerAS(const PointerAS<S> &ptr)
00224             : base::Pointer<ZArrayScal<S> >(ptr) {}
00225 
00226         PointerAS(ZArrayScal<S>* obj)
00227             : base::Pointer<ZArrayScal<S> >(obj) {}
00228 
00229         void addScalar(S val) throw(OutOfMemory,std::bad_alloc) {
00230             assert(base::Pointer<ZArrayScal<S> >::getPtr());
00231             setPtr(base::Pointer<ZArrayScal<S> >::getPtr()->addScalar(val));
00232         }
00233         void setScalar(int index, S val) throw(OutOfMemory,std::bad_alloc) {
00234             assert(base::Pointer<ZArrayScal<S> >::getPtr());
00235             setPtr(base::Pointer<ZArrayScal<S> >::getPtr()->setScalar(index, val));
00236         }
00237         void enlarge(int size) throw(OutOfMemory,std::bad_alloc) {
00238             assert(base::Pointer<ZArrayScal<S> >::getPtr());
00239             setPtr(base::Pointer<ZArrayScal<S> >::getPtr()->ensureMutableScalars(size));
00240         }
00241         S get(int index) const {
00242             assert(base::Pointer<ZArrayScal<S> >::getPtr());
00243             return base::Pointer<ZArrayScal<S> >::getPtr()->get(index);
00244         }
00245     };
00246 
00247     template<class P>
00248     class PointerAP : public base::Pointer<ZArrayPtr<P> >
00249     {
00250     public:
00251         static ZArrayPtr<P>* create(int size, bool reset = true) throw(OutOfMemory,std::bad_alloc) {
00252             return new ZArrayPtr<P>(size, reset);
00253         }
00254         PointerAP(const PointerAP<P> &ptr)
00255             : base::Pointer<ZArrayPtr<P> >(ptr) {}
00256 
00257         PointerAP(ZArrayPtr<P>* obj)
00258             : base::Pointer<ZArrayPtr<P> >(obj) {}
00259 
00260         void addPointer(P* val) throw(OutOfMemory,std::bad_alloc) {
00261             assert(base::Pointer<ZArrayPtr<P> >::getPtr());
00262             setPtr(base::Pointer<ZArrayPtr<P> >::getPtr()->addPointer(val));
00263         }
00264         void setPointer(int index, P* val) throw(OutOfMemory,std::bad_alloc) {
00265             assert(base::Pointer<ZArrayPtr<P> >::getPtr());
00266             setPtr(base::Pointer<ZArrayPtr<P> >::getPtr()->setPointer(index, val));
00267         }
00268         P* get(int index) const {
00269             assert(base::Pointer<ZArrayPtr<P> >::getPtr());
00270             return base::Pointer<ZArrayPtr<P> >::getPtr()->get(index);
00271         }
00272     };
00273 
00274     // Wrap a constraint=bound + strictness, special for ruby.
00275     // We could store internally a raw_t, which is, an int, but
00276     // but but, in ruby an int looses its lower bit for internal
00277     // coding, which fits perfectly with constraint bounds but
00278     // not with raw_t because we need a full int. So don't bother
00279     // and use a bound and a bool for strictness.
00280     
00281     class Constraint
00282     {
00283     public:
00284         // Default: <inf
00285         Constraint()
00286             : str(NULL), cBound(dbm_INFINITY), cStrict(true) {}
00287 
00288         // Default with a bound: <=bound, except if infinity
00289         Constraint(int aBound) throw(ForbiddenMinusInfinity,InvalidBoundValue)
00290             : str(NULL) { setConstraint(aBound, false); }
00291 
00292         // Normal constructor, ignore strictness in case of infinity
00293         Constraint(int aBound, bool aStrict) throw(ForbiddenMinusInfinity,InvalidBoundValue)
00294             : str(NULL) { setConstraint(aBound, aStrict); }
00295 
00296         Constraint(const Constraint& arg)
00297             : str(NULL), cBound(arg.cBound), cStrict(arg.cStrict) {}
00298 
00299         Constraint& operator = (const Constraint& arg) {
00300             if (str) { delete [] str; str = NULL; }
00301             cBound = arg.cBound;
00302             cStrict = arg.cStrict;
00303             return *this;
00304         }
00305 
00306         ~Constraint() { if (str) { delete [] str; } }
00307         
00308         Constraint& setConstraint(int aBound, bool aStrict) throw(ForbiddenMinusInfinity,InvalidBoundValue) {
00309             setBound(aBound);
00310             setStrict(aStrict);
00311             return *this;
00312         }
00313 
00314         // read access
00315 
00316         int getBound()  const { return cBound; }
00317         bool isStrict() const { return cStrict; }
00318 
00319         // checked write access
00320 
00321         Constraint& setBound(int aBound) throw(ForbiddenMinusInfinity,InvalidBoundValue) {
00322             if (aBound == -dbm_INFINITY)
00323             {
00324                 throw ForbiddenMinusInfinity();
00325             }
00326             if (aBound < -dbm_INFINITY || aBound > dbm_INFINITY)
00327             {
00328                 throw InvalidBoundValue();
00329             }
00330             cBound = aBound;
00331             return *this;
00332         }
00333 
00334         Constraint& setStrict(bool aStrict) {
00335             cStrict = aStrict || cBound == dbm_INFINITY;
00336             return *this;
00337         }
00338 
00339         // very useful for ruby
00340         char* to_s() throw(std::bad_alloc) {
00341             if (!str)
00342             {
00343                 str = new char[16];
00344             }
00345             if (cBound != dbm_INFINITY)
00346             {
00347                 snprintf(str, 16, "%s%d", cStrict ? "<" : "<=", cBound);
00348             }
00349             else
00350             {
00351                 strcpy(str, "<inf");
00352             }
00353             return str;
00354         }
00355         
00356         // General comparison method.
00357         int cmp(const Constraint& arg) {
00358             raw_t me = dbm_boundbool2raw(cBound, cStrict);
00359             raw_t other = dbm_boundbool2raw(arg.cBound, arg.cStrict);
00360             if (me < other)
00361             {
00362                 return -1;
00363             }
00364             else if (me == other)
00365             {
00366                 return 0;
00367             }
00368             else
00369             {
00370                 return 1;
00371             }
00372         }
00373         
00374         // Special addition between constraints.
00375         Constraint operator + (const Constraint& arg) const {
00376             raw_t sum = dbm_addRawRaw(dbm_boundbool2raw(cBound, cStrict),
00377                                       dbm_boundbool2raw(arg.cBound, arg.cStrict));
00378             return Constraint(dbm_raw2bound(sum), dbm_rawIsStrict(sum));
00379         }
00380         
00381         // Same as *this + arg.neg, but avoid intermediate allocations.
00382         Constraint operator - (const Constraint& arg) const throw(ForbiddenMinusInfinity) {
00383             if (arg.cBound == dbm_INFINITY)
00384             {
00385                 throw ForbiddenMinusInfinity();
00386             }
00387             raw_t sum = dbm_addRawRaw(dbm_boundbool2raw(cBound, cStrict),
00388                                       dbm_boundbool2raw(-arg.cBound, !arg.cStrict));
00389             return Constraint(dbm_raw2bound(sum), dbm_rawIsStrict(sum));
00390         }
00391         
00392         // Constraint negation.
00393         Constraint neg() const throw(ForbiddenMinusInfinity) {
00394             if (cBound == dbm_INFINITY)
00395             {
00396                 throw ForbiddenMinusInfinity();
00397             }
00398             return Constraint(-cBound,!cStrict);
00399         }
00400         
00401     private:
00402         char *str;   // we manage our strings to avoid leaks
00403         int cBound;  // constraint bound
00404         bool cStrict;// constraint strictness flag
00405     };
00406 
00407     // Class used only to construct Federations with an easy syntax.
00408     class FedArray
00409     {
00410         typedef PointerAP<DBMMatrix> matrixptr_t;
00411     public:
00412         FedArray() throw(OutOfMemory)
00413             : matrixSize(0), matrices(matrixptr_t::create(0)) {}
00414 
00415         FedArray(const DBMMatrix& m) throw(OutOfMemory,IncompatibleDBM) 
00416             : matrixSize(0), matrices(matrixptr_t::create(0)) { *this | m; }
00417 
00418         // Add DBM matrices: this is a complete misuse of
00419         // +, it should be += *but* += cannot always be defined
00420         // as we wish, e.g. like in ruby.
00421 
00422         FedArray& operator | (const DBMMatrix& m) throw(OutOfMemory,IncompatibleDBM,std::bad_alloc);
00423 
00424         int size() const { return matrices->size(); }
00425         const DBMMatrix& get(int index) const { return *matrices->get(index); }
00426 
00427     private:
00428         int matrixSize;
00429         matrixptr_t matrices;
00430     };
00431     
00432     // Class used only to construct a DBM with an easy syntax.
00433     class DBMMatrix
00434     {
00435         typedef PointerAS<int> matrix_t;
00436     public:
00437         DBMMatrix() throw(OutOfMemory)
00438             : matrix(matrix_t::create(0)) {}
00439         
00440         // Add constraints
00441         DBMMatrix& operator < (int bound) throw(OutOfMemory,std::bad_alloc) {
00442             return add(bound, true);
00443         }
00444         DBMMatrix& operator <= (int bound) throw(OutOfMemory,std::bad_alloc) {
00445             return add(bound, false);
00446         }
00447         DBMMatrix& add(int bound, bool strict) throw(OutOfMemory,std::bad_alloc) {
00448             matrix.addScalar(dbm_boundbool2raw(bound, strict || bound == dbm_INFINITY));
00449             return *this;
00450         }
00451 
00452         // Add another matrix -> FedArray
00453         FedArray operator | (const DBMMatrix& m) throw(OutOfMemory,IncompatibleDBM) {
00454             return FedArray(*this) | m;
00455         }
00456         
00457         // Number of constraints
00458         int size() const { return matrix->size(); }
00459         
00460         // This returns a raw_t in fact, not supposed to be visible
00461         // to the user but we need to read constraints.
00462         int get(int index) const { return matrix->get(index); }
00463 
00464         // Direct access to the matrix.
00465         const int* getMatrix() const { return matrix->begin(); }
00466 
00467     private:
00468         matrix_t matrix;
00469     };
00470 
00471     // An arrays with the invariant '1st element == 0'
00472     class DBMVector
00473     {
00474         typedef PointerAS<int> ivec_t;
00475     public:
00476         DBMVector() throw(OutOfMemory,std::bad_alloc)
00477             : str(NULL), vec(ivec_t::create(1)) {}
00478 
00479         DBMVector(const DBMVector& arg) throw(OutOfMemory,IllegalFirstValue)
00480             : str(NULL), vec(arg.vec) {}
00481 
00482         DBMVector(int n) throw(OutOfMemory,InvalidDimension,std::bad_alloc)
00483             : str(NULL), vec(ivec_t::create(n)) {
00484             if (n < 1)
00485             {
00486                 throw InvalidDimension();
00487             }
00488         }
00489 
00490         DBMVector& operator = (const DBMVector& arg) throw(OutOfMemory,IllegalFirstValue) {
00491             if (str) { delete [] str; str = NULL; }
00492             vec = arg.vec;
00493             return *this;
00494         }
00495 
00496         ~DBMVector() { if (str) { delete [] str; } }
00497 
00498         int size() const { return vec->size(); }
00499         int get(int i) const throw(IndexOutOfRange) { return vec->get(i); }
00500         const int* begin() const { return vec->begin(); }
00501         const int* end() const { return vec->end(); }
00502 
00503         // set bound elements, except the 1st
00504         DBMVector& set(int i, int v) throw(IndexOutOfRange,InvalidBoundValue,std::bad_alloc) {
00505             if (i <= 0) // may not change 0
00506             {
00507                 throw IndexOutOfRange();
00508             }
00509             if (v <= -dbm_INFINITY || v > dbm_INFINITY)
00510             {
00511                 throw InvalidBoundValue();
00512             }
00513             vec.setScalar(i,v);
00514             return *this;
00515         }
00516 
00517         // Add elements on-the-fly
00518         DBMVector& operator << (int v) throw(OutOfMemory,InvalidBoundValue,std::bad_alloc) {
00519             if (v <= -dbm_INFINITY || v > dbm_INFINITY)
00520             {
00521                 throw InvalidBoundValue();
00522             }
00523             vec.addScalar(v);
00524             return *this;
00525         }
00526 
00527         // Concatenation, skip 1st element
00528         DBMVector& operator << (const DBMVector& a) throw(OutOfMemory,InvalidBoundValue,std::bad_alloc) {
00529             int n = a.size();
00530             vec.enlarge(size() + n - 1); // reduce reallocations
00531             for(int j = 1; j < n; ++j) // jump 1st element of a
00532             {
00533                 *this << a.get(j);
00534             }
00535             return *this;
00536         }
00537 
00538         // useful for ruby
00539         char* to_s() throw(std::bad_alloc) {
00540             if (str) { delete [] str; }
00541             int nb = size();
00542             int asize = nb*12+11;
00543             str = new char[asize];
00544             strncpy(str, "DBMVector(", asize);
00545             int len = 10;
00546             asize -= len;
00547             const int *data = vec->begin();
00548             for(int i = 0; i < nb; ++i)
00549             {
00550                 snprintf(str+len, asize, i > 0 ? ",%d" : "%d", data[i]);
00551                 int l = strlen(str+len);
00552                 len += l;
00553                 asize -= l;
00554             }
00555             strncpy(str+len, ")", asize);
00556             return str;
00557         }
00558 
00559     private:
00560         char *str; // manage our own char* to avoid leaks
00561         ivec_t vec;
00562     };
00563     
00564     // An arrays with the invariant 1st element == 0
00565     class DBMPoint
00566     {
00567         typedef PointerAS<double> dvec_t;
00568     public:
00569         DBMPoint() throw(OutOfMemory,std::bad_alloc)
00570             : str(NULL), vec(dvec_t::create(1)) {}
00571 
00572         DBMPoint(const DBMPoint& arg) throw(OutOfMemory,IllegalFirstValue)
00573             : str(NULL), vec(arg.vec) {}
00574 
00575         DBMPoint(int n) throw(OutOfMemory,InvalidDimension,std::bad_alloc)
00576             : str(NULL), vec(dvec_t::create(n)) {
00577             if (n < 1)
00578             {
00579                 throw InvalidDimension();
00580             }
00581         }
00582 
00583         DBMPoint(const double *val, int n) throw(OutOfMemory,IllegalFirstValue,std::bad_alloc,InvalidDimension)
00584             : str(NULL), vec(dvec_t::create(n)) {
00585             if (n < 1)
00586             {
00587                 throw InvalidDimension();
00588             }
00589             if (fabs(val[0]) > 1e-200) // test != 0.0 fails, 'feature' with double
00590             {
00591                 throw IllegalFirstValue();
00592             }
00593             memcpy(vec->begin(), val, n*sizeof(double));
00594         }
00595 
00596         DBMPoint& operator = (const DBMPoint& arg) {
00597             if (str) { delete [] str; str = NULL; }
00598             vec = arg.vec;
00599             return *this;
00600         }
00601 
00602         ~DBMPoint() { if (str) { delete [] str; } }
00603 
00604         int size() const { return vec->size(); }
00605         double get(int i) const throw(IndexOutOfRange) { return vec->get(i); }
00606         const double* begin() const { return vec->begin(); }
00607         const double* end() const { return vec->end(); }
00608 
00609         // set bound elements, except the 1st
00610         DBMPoint& set(int i, double v) throw(IndexOutOfRange,InvalidBoundValue,std::bad_alloc) {
00611             if (i <= 0) // may not change 0
00612             {
00613                 throw IndexOutOfRange();
00614             }
00615             if (v <= -dbm_INFINITY || v > dbm_INFINITY)
00616             {
00617                 throw InvalidBoundValue();
00618             }
00619             vec.setScalar(i,v);
00620             return *this;
00621         }
00622 
00623         // Add elements on-the-fly
00624         DBMPoint& operator << (int v) throw(OutOfMemory,InvalidBoundValue,std::bad_alloc) {
00625             return *this << (double) v;
00626         }
00627         DBMPoint& operator << (double v) throw(OutOfMemory,InvalidBoundValue,std::bad_alloc) {
00628             if (v <= -dbm_INFINITY || v > dbm_INFINITY)
00629             {
00630                 throw InvalidBoundValue();
00631             }
00632             vec.addScalar(v);
00633             return *this;
00634         }
00635 
00636         // Concatenation, skip 1st element
00637         DBMPoint& operator << (const DBMPoint& a) throw(OutOfMemory,InvalidBoundValue,std::bad_alloc) {
00638             int n = a.size();
00639             vec.enlarge(size() + n - 1); // reduce reallocations
00640             for(int j = 1; j < n; ++j) // jump 1st element of a
00641             {
00642                 *this << a.get(j);
00643             }
00644             return *this;
00645         }
00646         DBMPoint& operator << (const DBMVector& a) throw(OutOfMemory,InvalidBoundValue,std::bad_alloc) {
00647             int n = a.size();
00648             vec.enlarge(size() + n - 1); // reduce reallocations
00649             for(int j = 1; j < n; ++j) // jump 1st element of a
00650             {
00651                 *this << a.get(j);
00652             }
00653             return *this;
00654         }
00655 
00656         // useful for ruby
00657         char* to_s() throw(std::bad_alloc) {
00658             if (str) { delete [] str; }
00659             int nb = size();
00660             int asize = nb*30+10;
00661             str = new char[asize];
00662             strncpy(str, "DBMPoint(", asize);
00663             int len = 9;
00664             asize -= len;
00665             const double *data = vec->begin();
00666             for(int i = 0; i < nb; ++i)
00667             {
00668                 snprintf(str+len, asize, i > 0 ? ",%.3f" : "%.3f", data[i]);
00669                 int l = strlen(str+len);
00670                 len += l;
00671                 asize -= l;
00672             }
00673             strncpy(str+len, ")", asize);
00674             return str;
00675         }
00676 
00677     private:
00678         char *str; // manage our own char* to avoid leaks
00679         dvec_t vec;
00680     };
00681 
00682     // Wrap dbm_t, only high level methods & operators.
00683     class DBM
00684     {
00685         friend class Fed;
00686     public:
00687         DBM(int d) throw(InvalidDimension,DimensionTooLarge)
00688             : str(NULL), wdbm(d) {
00689             if (d < 1)
00690             {
00691                 throw InvalidDimension();
00692             }
00693             if (d > 0xffff)
00694             {
00695                 throw DimensionTooLarge();
00696             }
00697         }
00698 
00699         DBM(const DBM& arg)
00700             : str(NULL), wdbm(arg.wdbm) {}
00701 
00702         DBM(const DBMMatrix& arg) throw(InvalidDBMMatrix,InvalidDimension,DimensionTooLarge)
00703             : str(NULL) { setDBM(wdbm, arg); }
00704 
00705         DBM& operator = (const DBM& arg) {
00706             if (str) { delete [] str; str = NULL; }
00707             wdbm = arg.wdbm;
00708             return *this;
00709         }
00710 
00711         // Deallocate own managed string!
00712         ~DBM() { if (str) { delete [] str; } }
00713         
00714         // Special for ruby.
00715         char* to_s() throw(std::bad_alloc) {
00716             if (str) { delete [] str; }
00717             int d = dim();
00718             const raw_t *m = wdbm();
00719             if (m)
00720             {
00721                 int size = allocSize(d);
00722                 str = new char[size];
00723                 // prefix
00724                 snprintf(str, size, "DBM(%d) { matrix\\\n", d);
00725                 int len = strlen(str);
00726                 size -= len;
00727                 // matrix
00728                 int mlen = write(str+len, size, m, d);
00729                 len += mlen;
00730                 size -= mlen;
00731                 // suffix
00732                 strncpy(str+len, "}", size);
00733                 assert(size-1 >= 0);
00734             }
00735             else
00736             {
00737                 str = new char[20];
00738                 snprintf(str, 20, "DBM(%d) {}", d);
00739             }
00740             return str;
00741         }
00742         
00743         // Accessing a constraint in a high level manner.
00744         Constraint read(int i, int j) const throw(IndexOutOfRange,EmptyDBM) {
00745             int d = wdbm.getDimension();
00746             if (i < 0 || j < 0 || i >= d || j >= d)
00747             {
00748                 throw IndexOutOfRange();
00749             }
00750             const raw_t *m = wdbm();
00751             if (!m)
00752             {
00753                 throw EmptyDBM();
00754             }
00755             raw_t c = m[i*d+j];
00756             return Constraint(dbm_raw2bound(c), dbm_rawIsStrict(c));
00757         }
00758 
00759         // For convenience: Generate DBMs.
00760 
00761         static DBM init(int dim) throw(InvalidDimension,DimensionTooLarge) {
00762             if (dim < 1)
00763             {
00764                 throw InvalidDimension();
00765             }
00766             if (dim > 0xffff)
00767             {
00768                 throw DimensionTooLarge();
00769             }
00770             dbm::dbm_t tmp(dim);
00771             tmp.setInit();
00772             return DBM(tmp);
00773         }
00774         static DBM zero(int dim) throw(InvalidDimension,DimensionTooLarge) {
00775             if (dim < 1)
00776             {
00777                 throw InvalidDimension();
00778             }
00779             if (dim > 0xffff)
00780             {
00781                 throw DimensionTooLarge();
00782             }
00783             dbm::dbm_t tmp(dim);
00784             tmp.setZero();
00785             return DBM(tmp);
00786         }
00787 
00788         // Wrapped methods & operators, see dbm_t
00789 
00790         int  dim()         const { return wdbm.getDimension(); }
00791         bool isEmpty()     const { return wdbm.isEmpty(); }
00792         DBM  copy()        const { return DBM(wdbm); }
00793         bool isUnbounded() const { return wdbm.isUnbounded(); }
00794 
00795         void setEmpty() { wdbm.setEmpty(); }
00796         void intern()   { if (str) { delete [] str; str = NULL; } wdbm.intern(); }
00797         void setZero()  { wdbm.setZero(); }
00798         void setInit()  { wdbm.setInit(); }
00799 
00800         relation_t relation(const DBM& arg) const throw(IncompatibleDBM) {
00801             CHECKD(arg);
00802             return wdbm.relation(arg.wdbm);
00803         }
00804         relation_t relation(const Fed& arg)      const throw(IncompatibleFed);
00805         relation_t exactRelation(const DBM& arg) const throw(IncompatibleDBM) {
00806             CHECKD(arg);
00807             return wdbm.exactRelation(arg.wdbm);
00808         }
00809         relation_t exactRelation(const Fed& arg) const throw(IncompatibleFed);
00810 
00811         DBM operator + (const DBM& arg) const throw(IncompatibleDBM) {
00812             CHECKD(arg);
00813             return DBM(dbm::dbm_t(wdbm) += arg.wdbm);
00814         }
00815         DBM operator + (const Fed& arg) const throw(IncompatibleFed);
00816         DBM& convexHull(const DBM& arg) throw(IncompatibleDBM) {
00817             CHECKD(arg);
00818             wdbm += arg.wdbm;
00819             return *this;
00820         }
00821         DBM& convexHull(const Fed& arg) throw(IncompatibleFed);            
00822 
00823         bool constrainClock(int clk, int value) { return wdbm.constrain(clk, value); }
00824         bool constrain(int i, int j, Constraint& c) { return constrain(i, j, c.getBound(), c.isStrict()); }
00825         bool constrain(int i, int j, int bound, bool strict) { return wdbm.constrain(i, j, bound, strict); }
00826 
00827         DBM operator & (const DBM& arg) throw(IncompatibleDBM) {
00828             CHECKD(arg);
00829             return DBM(dbm::dbm_t(wdbm) &= arg.wdbm);
00830         }
00831         Fed operator & (const Fed& arg) throw(IncompatibleFed);
00832         bool intersects(const DBM& arg) const throw(IncompatibleDBM) {
00833             CHECKD(arg);
00834             return wdbm.intersects(arg.wdbm);
00835         }
00836         bool intersects(const Fed& arg) const throw(IncompatibleFed);
00837         DBM& intersectionWith(const DBM& arg) throw(IncompatibleDBM) {
00838             CHECKD(arg);
00839             wdbm &= arg.wdbm;
00840             return *this;
00841         }
00842         //DBM& intersectionWith(const Fed& arg) not possible!
00843 
00844         DBM& applyUp()               { wdbm.up(); return *this; }
00845         DBM& applyDown()             { wdbm.down(); return *this; }
00846         DBM& applyFreeClock(int clk) { wdbm.freeClock(clk); return *this; }
00847         DBM& applyFreeUp(int clk)    { wdbm.freeUp(clk); return *this; }
00848         DBM& applyFreeDown(int clk)  { wdbm.freeDown(clk); return *this; }
00849         DBM& applyFreeAllUp()        { wdbm.freeAllUp(); return *this; }
00850         DBM& applyFreeAllDown()      { wdbm.freeAllDown(); return *this; }
00851 
00852         DBM& updateValue(int x, int v)          { wdbm.updateValue(x,v); return *this; }
00853         DBM& updateClock(int x, int y)          { wdbm.updateClock(x,y); return *this; }
00854         DBM& updateIncrement(int x, int v)      { wdbm.updateIncrement(x,v); return *this; }
00855         DBM& updateGeneral(int x, int y, int v) { wdbm.update(x,y,v); return *this; }
00856 
00857         bool satisfies(int i, int j, int bound, bool strict) const { return wdbm.satisfies(i,j,dbm_boundbool2raw(bound,strict)); }
00858         bool satisfies(int i, int j, const Constraint& c)    const { return satisfies(i,j,c.getBound(),c.isStrict()); }
00859 
00860         DBM& relaxUp()        { wdbm.relaxUp(); return *this; }
00861         DBM& relaxDown()      { wdbm.relaxDown(); return *this; }
00862         DBM& relaxUp(int k)   { wdbm.relaxUpClock(k); return *this; }
00863         DBM& relaxDown(int k) { wdbm.relaxDownClock(k); return *this; }
00864         DBM& relaxAll()       { wdbm.relaxAll(); return *this; }
00865 
00866         bool isSubtractionEmpty(const DBM& arg) const throw(IncompatibleDBM) {
00867             CHECKD(arg);
00868             return wdbm.isSubtractionEmpty(arg.wdbm);
00869         }
00870         bool isSubtractionEmpty(const Fed& arg) const throw(IncompatibleFed);
00871 
00872         // Relation operator: the problem is that we
00873         // cannot define a 'cmp' method like for Constraint
00874         // because DBMs are not necesseraly comparable!
00875         // Relations in the sense of set inclusion:
00876 
00877         bool operator <  (const DBM& arg) const throw(IncompatibleDBM) { CHECKD(arg); return wdbm < arg.wdbm; }
00878         bool operator >  (const DBM& arg) const throw(IncompatibleDBM) { CHECKD(arg); return wdbm > arg.wdbm; }
00879         bool operator <= (const DBM& arg) const throw(IncompatibleDBM) { CHECKD(arg); return wdbm <= arg.wdbm; }
00880         bool operator >= (const DBM& arg) const throw(IncompatibleDBM) { CHECKD(arg); return wdbm >= arg.wdbm; }
00881         bool operator == (const DBM& arg) const throw(IncompatibleDBM) { CHECKD(arg); return wdbm == arg.wdbm; }
00882         bool operator <  (const Fed& arg) const throw(IncompatibleFed);
00883         bool operator >  (const Fed& arg) const throw(IncompatibleFed);
00884         bool operator <= (const Fed& arg) const throw(IncompatibleFed);
00885         bool operator >= (const Fed& arg) const throw(IncompatibleFed);
00886         bool operator == (const Fed& arg) const throw(IncompatibleFed);
00887 
00888         // Relations in the sense of DBM inclusion.
00889 
00890         bool isIncludedIn(const DBM& arg)         const throw(IncompatibleDBM) { CHECKD(arg); return wdbm <= arg.wdbm; }
00891         bool isIncludedIn(const Fed& arg)         const throw(IncompatibleFed);
00892         bool isStrictlyIncludedIn(const DBM& arg) const throw(IncompatibleDBM) { CHECKD(arg); return wdbm < arg.wdbm; }
00893         bool isStrictlyIncludedIn(const Fed& arg) const throw(IncompatibleFed);
00894 
00895         // Interaction with DBMVector and DBMPoint
00896 
00897         bool contains(const DBMVector& v) const throw(IncompatibleDBMVector) {
00898             if (dim() != v.size())
00899             {
00900                 throw IncompatibleDBMVector();
00901             }
00902             return wdbm.contains(v.begin(), v.size());
00903         }
00904         bool contains(const DBMPoint& v) const throw(IncompatibleDBMPoint) {
00905             if (dim() != v.size())
00906             {
00907                 throw IncompatibleDBMPoint();
00908             }
00909             return wdbm.contains(v.begin(), v.size());
00910         }
00911         DBM& extrapolateMaxBounds(const DBMVector& v) throw(IncompatibleDBMVector) {
00912             if (dim() != v.size())
00913             {
00914                 throw IncompatibleDBMVector();
00915             }
00916             wdbm.extrapolateMaxBounds(v.begin());
00917             return *this;
00918         }
00919         DBM& diagonalExtrapolateMaxBounds(const DBMVector& v) throw(IncompatibleDBMVector) {
00920             if (dim() != v.size())
00921             {
00922                 throw IncompatibleDBMVector();
00923             }
00924             wdbm.diagonalExtrapolateMaxBounds(v.begin());
00925             return *this;
00926         }
00927         DBM& extrapolateLUBounds(const DBMVector& l, const DBMVector& u) throw(IncompatibleDBMVector) {
00928             if (dim() != l.size() || dim() != u.size())
00929             {
00930                 throw IncompatibleDBMVector();
00931             }
00932             wdbm.extrapolateLUBounds(l.begin(), u.begin());
00933             return *this;
00934         }
00935         DBM& diagonalExtrapolateLUBounds(const DBMVector& l, const DBMVector& u) throw(IncompatibleDBMVector) {
00936             if (dim() != l.size() || dim() != u.size())
00937             {
00938                 throw IncompatibleDBMVector();
00939             }
00940             wdbm.diagonalExtrapolateLUBounds(l.begin(), u.begin());
00941             return *this;
00942         }
00943         DBMPoint getPoint() const throw(std::out_of_range,OutOfMemory,IllegalFirstValue,InvalidDimension) {
00944             int d = dim();
00945             dbm::DoubleValuation val(d);
00946             wdbm.getValuation(val);
00947             return DBMPoint(val.begin(), d);
00948         }
00949 
00950     private:
00951         // max int = 2147483647 = 10 char + sign + <= + space = 14
00952         // matrix = dim*dim*14 + 2*dim (2 char for end of line \\\n)
00953         // prefix 'DBM(x) { matrix\\\n' = 16 + max dim 64534 (5) = 21
00954         // suffix '}' = 1
00955         static int allocSize(int dim) { return dim*(dim*14+2)+22; }
00956 
00957         // write a DBM in a large enough string
00958         static int write(char *s, int size, const raw_t *m, int dim);
00959 
00960         // init a dbm_t from a DBMMatrix
00961         static void setDBM(dbm::dbm_t& wdbm, const DBMMatrix& arg)
00962             throw(InvalidDBMMatrix,InvalidDimension,DimensionTooLarge);
00963 
00964         DBM(const dbm::dbm_t& arg)
00965             : str(NULL), wdbm(arg) {}
00966 
00967         char *str;       // we manage our strings, otherwise leaks
00968         dbm::dbm_t wdbm; // wrapped dbm_t
00969     };
00970     
00971     // Wrap fed_t, only high level methods & operators.
00972     class Fed
00973     {
00974         friend class DBM;
00975     public:
00976         Fed(int d) throw(InvalidDimension)
00977             : str(NULL), wfed(d) {
00978             if (d <= 0)
00979             {
00980                 throw InvalidDimension();
00981             }
00982         }
00983 
00984         Fed(const DBM& arg)
00985             : str(NULL), wfed(arg.wdbm) {}
00986 
00987         Fed(const Fed& arg)
00988             : str(NULL), wfed(arg.wfed) {}
00989 
00990         Fed& operator = (const Fed& arg) {
00991             if (str) { delete [] str; str = NULL; }
00992             wfed = arg.wfed;
00993             return *this;
00994         }
00995                 
00996         // Deallocate own managed string!
00997         ~Fed() { if (str) { delete [] str; } }
00998         
00999         // Add DBMs
01000         Fed& add(const FedArray& arr) throw(IncompatibleDBM) {
01001             int n = arr.size();
01002             for(int i = 0; i < n; ++i)
01003             {
01004                 add(arr.get(i));
01005             }
01006             return *this;
01007         }
01008         Fed& add(const DBMMatrix &m) throw(IncompatibleDBM) {
01009             dbm::dbm_t tmp;
01010             DBM::setDBM(tmp, m);
01011             if ((int)tmp.getDimension() != dim())
01012             {
01013                 throw IncompatibleDBM();
01014             }
01015             wfed |= tmp;
01016             return *this;
01017         }
01018         Fed& add(const DBM& arg) throw(IncompatibleDBM) {
01019             CHECKD(arg);
01020             wfed |= arg.wdbm;
01021             return *this;
01022         }
01023         Fed& add(const Fed& arg) throw(IncompatibleFed) {
01024             CHECKF(arg);
01025             wfed |= arg.wfed;
01026             return *this;
01027         }
01028 
01029         // Special for ruby.
01030         char* to_s() throw(std::bad_alloc) {
01031             if (str) { delete [] str; }
01032             int fedSize = size();
01033             if (fedSize)
01034             {
01035                 int asize = allocSize(fedSize, dim());
01036                 str = new char[asize];
01037                 // prefix
01038                 snprintf(str, asize, "Fed(%d) %s", dim(), fedSize > 1 ? "{[\n" : "{");
01039                 int len = strlen(str);
01040                 asize -= len;
01041                 // list of DBMs
01042                 bool isFirst = true;
01043                 int d = dim();
01044                 for(dbm::fed_t::const_iterator i = wfed.begin(); !i.null(); ++i)
01045                 {
01046                     // in principle no empty DBM
01047                     const raw_t *m = i();
01048                     if (m)
01049                     {
01050                         // DBM prefix
01051                         strncpy(str+len, isFirst ? " matrix\\\n" : ",matrix\\\n", asize);
01052                         len += 9;
01053                         asize -= 9;
01054                         // matrix
01055                         int mlen = DBM::write(str+len, asize, m, d);
01056                         len += mlen;
01057                         asize -= mlen;
01058                         isFirst = false;
01059                     }
01060                     else
01061                     {
01062                         fprintf(stderr, "Warning: Empty DBM found in Fed!\n");
01063                     }
01064                 }
01065                 // suffix
01066                 strncpy(str+len, fedSize > 1 ? "]}" : "}", asize);
01067                 assert(asize-2 >= 0);
01068             }
01069             else
01070             {
01071                 str = new char[20];
01072                 snprintf(str, 20, "Fed(%d) {}", dim());
01073             }
01074             return str;
01075         }
01076         
01077         // For convenience: Generate Feds.
01078 
01079         static Fed init(int dim) throw(InvalidDimension,DimensionTooLarge) {
01080             if (dim < 1)
01081             {
01082                 throw InvalidDimension();
01083             }
01084             if (dim > 0xffff)
01085             {
01086                 throw DimensionTooLarge();
01087             }
01088             dbm::fed_t tmp(dim);
01089             tmp.setInit();
01090             return Fed(tmp);
01091         }
01092         static Fed zero(int dim) throw(InvalidDimension,DimensionTooLarge) {
01093             if (dim < 1)
01094             {
01095                 throw InvalidDimension();
01096             }
01097             if (dim > 0xffff)
01098             {
01099                 throw DimensionTooLarge();
01100             }
01101             dbm::fed_t tmp(dim);
01102             tmp.setZero();
01103             return Fed(tmp);
01104         }
01105 
01106         // Wrapped methods & operators, see fed_t
01107 
01108         int size()         const { return wfed.size(); }
01109         int dim()          const { return wfed.getDimension(); }
01110         bool isEmpty()     const { return wfed.isEmpty(); }
01111         Fed copy()         const { return Fed(wfed); }
01112         bool isUnbounded() const { return wfed.isUnbounded(); }
01113 
01114         void setEmpty() { wfed.setEmpty(); }
01115         void intern()   { if (str) { delete [] str; str = NULL; } wfed.intern(); }
01116         void setZero()  { wfed.setZero(); }
01117         void setInit()  { wfed.setInit(); }
01118 
01119         relation_t relation(const DBM& arg) const throw(IncompatibleDBM) {
01120             CHECKD(arg);
01121             return wfed.relation(arg.wdbm);
01122         }
01123         relation_t relation(const Fed& arg) const throw(IncompatibleFed) {
01124             CHECKF(arg);
01125             return wfed.relation(arg.wfed);
01126         }
01127         relation_t exactRelation(const DBM& arg) const throw(IncompatibleDBM) {
01128             CHECKD(arg);
01129             return wfed.exactRelation(arg.wdbm);
01130         }
01131         relation_t exactRelation(const Fed& arg) const throw(IncompatibleFed) {
01132             CHECKF(arg);
01133             return wfed.exactRelation(arg.wfed);
01134         }
01135 
01136         Fed operator + (const DBM& arg) const throw(IncompatibleDBM) {
01137             CHECKD(arg);
01138             return Fed(dbm::fed_t(wfed) += arg.wdbm);
01139         }
01140         Fed operator + (const Fed& arg) const throw(IncompatibleFed) {
01141             CHECKF(arg);
01142             return Fed(dbm::fed_t(wfed) += arg.wfed);
01143         }
01144         Fed& convexHull(const DBM& arg) throw(IncompatibleDBM) {
01145             CHECKD(arg);
01146             wfed += arg.wdbm;
01147             return *this;
01148         }
01149         Fed& convexHull(const Fed& arg) throw(IncompatibleFed) {
01150             CHECKF(arg);
01151             wfed += arg.wfed;
01152             return *this;
01153         }
01154         Fed& convexHull() { wfed.convexHull(); return *this; }
01155 
01156         bool constrainClock(int clk, int value) { return wfed.constrain(clk, value); }
01157         bool constrain(int i, int j, Constraint& c) { return constrain(i, j, c.getBound(), c.isStrict()); }
01158         bool constrain(int i, int j, int bound, bool strict) { return wfed.constrain(i, j, bound, strict); }
01159 
01160         Fed operator & (const DBM& arg) throw(IncompatibleDBM) {
01161             CHECKD(arg);
01162             return Fed(dbm::fed_t(wfed) &= arg.wdbm);
01163         }
01164         Fed operator & (const Fed& arg) throw(IncompatibleFed) {
01165             CHECKF(arg);
01166             return Fed(dbm::fed_t(wfed) &= arg.wfed);
01167         }
01168         bool intersects(const DBM& arg) const throw(IncompatibleDBM) {
01169             CHECKD(arg);
01170             return wfed.intersects(arg.wdbm);
01171         }
01172         bool intersects(const Fed& arg) const throw(IncompatibleFed) {
01173             CHECKF(arg);
01174             return wfed.intersects(arg.wfed);
01175         }
01176         Fed& intersectionWith(const DBM& arg) throw(IncompatibleDBM) {
01177             CHECKD(arg);
01178             wfed &= arg.wdbm;
01179             return *this;
01180         }
01181         Fed& intersectionWith(const Fed& arg) throw(IncompatibleFed) {
01182             CHECKF(arg);
01183             wfed &= arg.wfed;
01184             return *this;
01185         }
01186         bool has(const DBM& arg) const throw(IncompatibleDBM) {
01187             CHECKD(arg);
01188             return wfed.has(arg.wdbm);
01189         }
01190 
01191         Fed& applyUp()               { wfed.up(); return *this; }
01192         Fed& applyDown()             { wfed.down(); return *this; }
01193         Fed& applyFreeClock(int clk) { wfed.freeClock(clk); return *this; }
01194         Fed& applyFreeUp(int clk)    { wfed.freeUp(clk); return *this; }
01195         Fed& applyFreeDown(int clk)  { wfed.freeDown(clk); return *this; }
01196         Fed& applyFreeAllUp()        { wfed.freeAllUp(); return *this; }
01197         Fed& applyFreeAllDown()      { wfed.freeAllDown(); return *this; }
01198 
01199         Fed& updateValue(int x, int v)          { wfed.updateValue(x,v); return *this; }
01200         Fed& updateClock(int x, int y)          { wfed.updateClock(x,y); return *this; }
01201         Fed& updateIncrement(int x, int v)      { wfed.updateIncrement(x,v); return *this; }
01202         Fed& updateGeneral(int x, int y, int v) { wfed.update(x,y,v);  return *this; }
01203 
01204         bool satisfies(int i, int j, int bound, bool strict) const { return wfed.satisfies(i,j,dbm_boundbool2raw(bound,strict)); }
01205         bool satisfies(int i, int j, const Constraint& c) const { return satisfies(i,j,c.getBound(),c.isStrict()); }
01206 
01207         Fed& relaxUp()        { wfed.relaxUp(); return *this; }
01208         Fed& relaxDown()      { wfed.relaxDown(); return *this; }
01209         Fed& relaxUp(int k)   { wfed.relaxUpClock(k); return *this; }
01210         Fed& relaxDown(int k) { wfed.relaxDownClock(k); return *this; }
01211         Fed& relaxAll()       { wfed.relaxAll(); return *this; }
01212 
01213         bool isSubtractionEmpty(const DBM& arg) const throw(IncompatibleDBM) {
01214             CHECKD(arg);
01215             return wfed.isSubtractionEmpty(arg.wdbm);
01216         }
01217         bool isSubtractionEmpty(const Fed& arg) const throw(IncompatibleFed) {
01218             CHECKF(arg);
01219             return wfed.isSubtractionEmpty(arg.wfed);
01220         }
01221 
01222         Fed operator | (const DBM& arg) const throw(IncompatibleDBM) {
01223             CHECKD(arg);
01224             return Fed(dbm::fed_t(wfed) |= arg.wdbm);
01225         }
01226         Fed operator | (const Fed& arg) const throw(IncompatibleFed) {
01227             CHECKF(arg);
01228             return Fed(dbm::fed_t(wfed) |= arg.wfed);
01229         }
01230         Fed& unionWith(const DBM& arg) throw(IncompatibleDBM) {
01231             CHECKD(arg);
01232             wfed |= arg.wdbm;
01233             return *this;
01234         }
01235         Fed& unionWith(const Fed& arg) throw(IncompatibleFed) {
01236             CHECKF(arg);
01237             wfed |= arg.wfed;
01238             return *this;
01239         }
01240 
01241         Fed operator - (const DBM& arg) const throw(IncompatibleDBM) {
01242             CHECKD(arg);
01243             return Fed(dbm::fed_t(wfed) -= arg.wdbm);
01244         }
01245         Fed operator - (const Fed& arg) const throw(IncompatibleFed) {
01246             CHECKF(arg);
01247             return Fed(dbm::fed_t(wfed) -= arg.wfed);
01248         }
01249         Fed& subtract(const DBM& arg) throw(IncompatibleDBM) {
01250             CHECKD(arg);
01251             wfed -= arg.wdbm;
01252             return *this;
01253         }
01254         Fed& subtract(const Fed& arg) throw(IncompatibleFed) {
01255             CHECKF(arg);
01256             wfed -= arg.wfed;
01257             return *this;
01258         }
01259 
01260         Fed& mergeReduce()     { wfed.mergeReduce(); return *this; }
01261         Fed& partitionReduce() { wfed.partitionReduce(); return *this; }
01262 
01263         Fed& applyPredt(const DBM& bad) throw(IncompatibleDBM) {
01264             CHECKD(bad);
01265             wfed.predt(bad.wdbm);
01266             return *this;
01267         }
01268         Fed& applyPredt(const Fed& bad) throw(IncompatibleFed) {
01269             CHECKF(bad);
01270             wfed.predt(bad.wfed);
01271             return *this;
01272         }
01273 
01274         Fed& removeIncludedIn(const DBM& arg) throw(IncompatibleDBM) {
01275             CHECKD(arg);
01276             wfed.removeIncludedIn(arg.wdbm);
01277             return *this;
01278         }
01279         Fed& removeIncludedIn(const Fed& arg) throw(IncompatibleFed) {
01280             CHECKF(arg);
01281             wfed.removeIncludedIn(arg.wfed);
01282             return *this;
01283         }
01284 
01285         // Relation operator: the *big* problem is that we
01286         // cannot define a 'cmp' method like for Constraint
01287         // because DBMs are not necesseraly comparable!
01288         // Relations in the sense of set inclusion:
01289 
01290         bool operator <  (const DBM& arg) const throw(IncompatibleDBM) { CHECKD(arg); return wfed.lt(arg.wdbm); }
01291         bool operator >  (const DBM& arg) const throw(IncompatibleDBM) { CHECKD(arg); return wfed.gt(arg.wdbm); }
01292         bool operator <= (const DBM& arg) const throw(IncompatibleDBM) { CHECKD(arg); return wfed.le(arg.wdbm); }
01293         bool operator >= (const DBM& arg) const throw(IncompatibleDBM) { CHECKD(arg); return wfed.ge(arg.wdbm); }
01294         bool operator == (const DBM& arg) const throw(IncompatibleDBM) { CHECKD(arg); return wfed.eq(arg.wdbm); }
01295         bool operator <  (const Fed& arg) const throw(IncompatibleFed) { CHECKF(arg); return wfed.lt(arg.wfed); }
01296         bool operator >  (const Fed& arg) const throw(IncompatibleFed) { CHECKF(arg); return wfed.gt(arg.wfed); }
01297         bool operator <= (const Fed& arg) const throw(IncompatibleFed) { CHECKF(arg); return wfed.le(arg.wfed); }
01298         bool operator >= (const Fed& arg) const throw(IncompatibleFed) { CHECKF(arg); return wfed.ge(arg.wfed); }
01299         bool operator == (const Fed& arg) const throw(IncompatibleFed) { CHECKF(arg); return wfed.eq(arg.wfed); }
01300 
01301         // Relations in the sense of DBM inclusion.
01302 
01303         bool isIncludedIn(const DBM& arg)         const throw(IncompatibleDBM) { CHECKD(arg); return wfed <= arg.wdbm; }
01304         bool isIncludedIn(const Fed& arg)         const throw(IncompatibleFed) { CHECKF(arg); return wfed <= arg.wfed; }
01305         bool isStrictlyIncludedIn(const DBM& arg) const throw(IncompatibleDBM) { CHECKD(arg); return wfed < arg.wdbm; }
01306         bool isStrictlyIncludedIn(const Fed& arg) const throw(IncompatibleFed) { CHECKF(arg); return wfed < arg.wfed; }
01307 
01308         // Interaction with DBMVector and DBMPoint
01309 
01310         bool contains(const DBMVector& v) const throw(IncompatibleDBMVector) {
01311             if (dim() != v.size())
01312             {
01313                 throw IncompatibleDBMVector();
01314             }
01315             return wfed.contains(v.begin(), v.size());
01316         }
01317         bool contains(const DBMPoint& v) const throw(IncompatibleDBMPoint) {
01318             if (dim() != v.size())
01319             {
01320                 throw IncompatibleDBMPoint();
01321             }
01322             return wfed.contains(v.begin(), v.size());
01323         }
01324         double possibleBackDelay(const DBMPoint& pt) const throw(IncompatibleDBMPoint) {
01325             if (dim() != pt.size())
01326             {
01327                 throw IncompatibleDBMPoint();
01328             }
01329             return wfed.possibleBackDelay(pt.begin(), pt.size());
01330         }
01331         Fed& extrapolateMaxBounds(const DBMVector& v) throw(IncompatibleDBMVector) {
01332             if (dim() != v.size())
01333             {
01334                 throw IncompatibleDBMVector();
01335             }
01336             wfed.extrapolateMaxBounds(v.begin());
01337             return *this;
01338         }
01339         Fed& diagonalExtrapolateMaxBounds(const DBMVector& v) throw(IncompatibleDBMVector) {
01340             if (dim() != v.size())
01341             {
01342                 throw IncompatibleDBMVector();
01343             }
01344             wfed.diagonalExtrapolateMaxBounds(v.begin());
01345             return *this;
01346         }
01347         Fed& extrapolateLUBounds(const DBMVector& l, const DBMVector& u) throw(IncompatibleDBMVector) {
01348             if (dim() != l.size() || dim() != u.size())
01349             {
01350                 throw IncompatibleDBMVector();
01351             }
01352             wfed.extrapolateLUBounds(l.begin(), u.begin());
01353             return *this;
01354         }
01355         Fed& diagonalExtrapolateLUBounds(const DBMVector& l, const DBMVector& u) throw(IncompatibleDBMVector) {
01356             if (dim() != l.size() || dim() != u.size())
01357             {
01358                 throw IncompatibleDBMVector();
01359             }
01360             wfed.diagonalExtrapolateLUBounds(l.begin(), u.begin());
01361             return *this;
01362         }
01363         DBMPoint getPoint() const throw(std::out_of_range,OutOfMemory,IllegalFirstValue,InvalidDimension) {
01364             int d = dim();
01365             dbm::DoubleValuation val(d);
01366             wfed.getValuation(val);
01367             return DBMPoint(val.begin(), d);
01368         }
01369 
01370     private:
01371         // size per DBM=dim*(dim*14+2)
01372         // prefix: 'Fed(dim) {[\n' [9+5]
01373         //        + ' matrix\\n' for 1st [9]
01374         //        + ',matrix\\n' for others [9]
01375         // suffix: ']}' [2]
01376         // total = 16+size*(9+sizeofDBM)
01377         static int allocSize(int size, int dim) { return 16+size*(9+dim*(dim*14+2)); }
01378 
01379         Fed(const dbm::fed_t& arg)
01380             : str(NULL), wfed(arg) {}
01381 
01382         char *str;       // we manage our strings, otherwise leaks
01383         dbm::fed_t wfed; // wrapped fed_t
01384     };
01385 
01386     // Implementation of methods that have dependency problems.
01387 
01388     inline bool DBM::operator <  (const Fed& arg) const throw(IncompatibleFed)
01389     {
01390         CHECKF(arg);
01391         return wdbm.lt(arg.wfed);
01392     }
01393     inline bool DBM::operator >  (const Fed& arg) const throw(IncompatibleFed)
01394     {
01395         CHECKF(arg);
01396         return wdbm.gt(arg.wfed);
01397     }
01398     inline bool DBM::operator <= (const Fed& arg) const throw(IncompatibleFed)
01399     {
01400         CHECKF(arg);
01401         return wdbm.le(arg.wfed);
01402     }
01403     inline bool DBM::operator >= (const Fed& arg) const throw(IncompatibleFed)
01404     {
01405         CHECKF(arg);
01406         return wdbm.ge(arg.wfed);
01407     }
01408     inline bool DBM::operator == (const Fed& arg) const throw(IncompatibleFed)
01409     {
01410         CHECKF(arg);
01411         return wdbm.eq(arg.wfed);
01412     }
01413     inline bool DBM::isIncludedIn(const Fed& arg) const throw(IncompatibleFed)
01414     {
01415         CHECKF(arg);
01416         return wdbm <= arg.wfed;
01417     }
01418     inline bool DBM::isStrictlyIncludedIn(const Fed& arg) const throw(IncompatibleFed)
01419     {
01420         CHECKF(arg);
01421         return wdbm < arg.wfed;
01422     }
01423     inline relation_t DBM::relation(const Fed& arg) const throw(IncompatibleFed)
01424     {
01425         CHECKF(arg);
01426         return wdbm.relation(arg.wfed);
01427     }
01428     inline relation_t DBM::exactRelation(const Fed& arg) const throw(IncompatibleFed)
01429     {
01430         CHECKF(arg);
01431         return wdbm.exactRelation(arg.wfed);
01432     }
01433     inline DBM DBM::operator + (const Fed& arg) const throw(IncompatibleFed)
01434     {
01435         CHECKF(arg);
01436         return DBM(dbm::dbm_t(wdbm) += dbm::fed_t(arg.wfed));
01437     }
01438     inline DBM& DBM::convexHull(const Fed& arg) throw(IncompatibleFed)
01439     {
01440         CHECKF(arg);
01441         wdbm += arg.wfed; return *this;
01442     }
01443     inline Fed DBM::operator & (const Fed& arg) throw(IncompatibleFed)
01444     {
01445         CHECKF(arg);
01446         return Fed(dbm::fed_t(arg.wfed) &= wdbm);
01447     }
01448     inline bool DBM::intersects(const Fed& arg) const throw(IncompatibleFed)
01449     {
01450         CHECKF(arg);
01451         return wdbm.intersects(arg.wfed);
01452     }
01453     inline bool DBM::isSubtractionEmpty(const Fed& arg) const throw(IncompatibleFed)
01454     {
01455         CHECKF(arg);
01456         return wdbm.isSubtractionEmpty(arg.wfed);
01457     }
01458     inline Fed operator - (const DBM& arg1, const DBM& arg2) throw(IncompatibleDBM)
01459     {
01460         CHECKSD(arg1,arg2);
01461         return Fed(arg1) - arg2;
01462     }
01463     inline Fed operator - (const DBM& arg1, const Fed& arg2) throw(IncompatibleFed)
01464     {
01465         CHECKSF(arg1,arg2);
01466         return Fed(arg1) - arg2;
01467     }
01468 
01469     // Don't bother with limitations of certain language on constant naming.
01470 
01471     static inline int inf() { return dbm_INFINITY; }
01472     
01473     // Constants
01474 
01475     static const Constraint ZERO = Constraint(0);
01476     static const Constraint INF = Constraint(dbm_INFINITY);
01477 
01478     enum { DIFFERENT = 0,
01479            SUPERSET = 1,
01480            SUBSET = 2,
01481            EQUAL = 3 };
01482 
01483 }
01484 
01485 #endif // DBM_RUBY_WRAPPER_H

Generated on Fri Jun 30 00:02:45 2006 for Module dbm by  doxygen 1.4.2