00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #ifndef INCLUDE_DBM_FEDERATION_H
00015 #define INCLUDE_DBM_FEDERATION_H
00016
00017 #include <new>
00018 #include <cstddef>
00019 #include <iostream>
00020 #include "dbm/dbmfederation.h"
00021 #include "base/bitstring.h"
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #define ASSERT_CLOCK_INDEX(I) \
00032 assert(dbmAllocator && (I) < dbmAllocator->maxDim && indexTable[I] < getNumberOfClocks())
00033
00034
00035
00036
00037
00038
00039
00040
00041 #define LOCAL_FEDERATION(NAME, NBCLOCKS, FACTORY) \
00042 char local_##NAME[Federation::getSizeOfFederationFor((FACTORY)->maxDim)];\
00043 Federation *NAME = (Federation*) local_##NAME; \
00044 NAME->initFederation(FACTORY, NBCLOCKS)
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #define LOCAL_ACTIVE_FEDERATION(NAME, NBCLOCKS, FACTORY, ACTIVE, ACTIVESIZE) \
00056 char local_##NAME[Federation::getSizeOfFederationFor((FACTORY)->maxDim)];\
00057 Federation *NAME = (Federation*) local_##NAME; \
00058 NAME->initFederation(FACTORY, NBCLOCKS, ACTIVE, ACTIVESIZE)
00059
00060
00061 namespace state
00062 {
00063 class SymbolicState;
00064 }
00065
00066 namespace dbm
00067 {
00068 class Federation
00069 {
00070 public:
00071
00072
00073
00074
00075
00076
00077 static Federation* createFederation(DBMAllocator_t *factory, cindex_t nbClocks) throw (std::bad_alloc)
00078 {
00079 assert(factory && nbClocks && factory->maxDim >= nbClocks);
00080 return new (allocateFor(factory->maxDim)) Federation(factory, nbClocks);
00081 }
00082
00083
00084
00085
00086
00087 static Federation* createFederation(const Federation *original) throw (std::bad_alloc)
00088 {
00089 assert(original);
00090 return new (allocateFor(original->dbmAllocator->maxDim)) Federation(*original);
00091 }
00092
00093
00094
00095
00096
00097
00098
00099 static Federation* createFederation(DBMAllocator_t *factory, cindex_t nbClocks,
00100 const uint32_t *activeClocks, size_t size) throw (std::bad_alloc)
00101 {
00102 assert(factory && nbClocks && factory->maxDim >= nbClocks);
00103 assert(activeClocks && size <= factory->maxDim);
00104 return new (allocateFor(factory->maxDim)) Federation(factory, nbClocks, activeClocks, size);
00105 }
00106
00107
00108
00109
00110
00111
00112
00113 ~Federation();
00114
00115
00116
00117 void unshareAllocator() { dbmf_initFactory(dbmAllocator, dbmFederation.dim); }
00118
00119
00120
00121
00122
00123 Federation& operator = (const Federation& original) throw (std::bad_alloc)
00124 {
00125 assert(dbmAllocator == original.dbmAllocator);
00126 if (dbmf_copy(&dbmFederation, original.dbmFederation, dbmAllocator))
00127 {
00128 throw std::bad_alloc();
00129 }
00130 base_copySmall(indexTable, original.indexTable,
00131 (sizeof(cindex_t) == sizeof(uint32_t))
00132 ? original.dbmAllocator->maxDim
00133 : intsizeof(cindex_t[original.dbmAllocator->maxDim]));
00134 return *this;
00135 }
00136
00137
00138
00139
00140
00141
00142 void stealDBMs(Federation *fed)
00143 {
00144 assert(fed && getNumberOfClocks() == fed->getNumberOfClocks());
00145 if (fed->dbmFederation.dbmList)
00146 {
00147 dbmf_union(&dbmFederation, fed->dbmFederation.dbmList, dbmAllocator);
00148 fed->dbmFederation.dbmList = NULL;
00149 }
00150 }
00151
00152
00153
00154
00155 std::ostream& serialize(std::ostream& os) const;
00156
00157
00158
00159
00160 void unserialize(std::istream& is) throw (std::bad_alloc);
00161
00162
00163
00164
00165 std::ostream& prettyPrint(std::ostream& os) const;
00166
00167
00168
00169
00170
00171 cindex_t getNumberOfClocks() const { return dbmFederation.dim; }
00172
00173
00174
00175
00176 void initToZero();
00177
00178
00179
00180
00181 void initUnconstrained();
00182
00183
00184
00185
00186
00187
00188 bool intersection(const raw_t *dbm)
00189 {
00190 assert(dbm);
00191 return (bool) dbmf_intersectsDBM(&dbmFederation, dbm, dbmAllocator);
00192 }
00193
00194
00195
00196
00197
00198 bool intersection(const Federation *anotherFed) throw (std::bad_alloc)
00199 {
00200 assert(anotherFed);
00201 if (dbmf_intersectsFederation(&dbmFederation, anotherFed->dbmFederation.dbmList, dbmAllocator))
00202 {
00203 throw std::bad_alloc();
00204 }
00205 return dbmFederation.dbmList != NULL;
00206 }
00207
00208
00209
00210
00211
00212
00213
00214 bool constrain(cindex_t clockIndexI, cindex_t clockIndexJ, raw_t rawBound)
00215 {
00216 ASSERT_CLOCK_INDEX(clockIndexI);
00217 ASSERT_CLOCK_INDEX(clockIndexJ);
00218 dbmf_constrain1(&dbmFederation,
00219 indexTable[clockIndexI], indexTable[clockIndexJ], rawBound,
00220 dbmAllocator);
00221 return dbmFederation.dbmList != NULL;
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231 bool constrainN(const constraint_t *constraints, size_t n)
00232 {
00233 dbmf_constrainIndexedN(&dbmFederation, indexTable,
00234 constraints, n,
00235 dbmAllocator);
00236 return dbmFederation.dbmList != NULL;
00237 }
00238
00239
00240
00241
00242 bool constrain(constraint_t c)
00243 {
00244 return constrain(c.i, c.j, c.value);
00245 }
00246
00247
00248
00249
00250
00251
00252
00253 bool constrain(cindex_t clockIndexI, cindex_t clockIndexJ, int32_t bound, bool isStrict)
00254 {
00255 return constrain(clockIndexI, clockIndexJ, dbm_boundbool2raw(bound, (BOOL) isStrict));
00256 }
00257
00258
00259
00260
00261
00262
00263
00264 bool constrain(cindex_t clockIndexI, cindex_t clockIndexJ, int32_t bound, strictness_t strictness)
00265 {
00266 return constrain(clockIndexI, clockIndexJ, dbm_bound2raw(bound, strictness));
00267 }
00268
00269
00270
00271
00272
00273
00274
00275 bool satisfies(cindex_t clockIndexI, cindex_t clockIndexJ, raw_t rawConstraint) const
00276 {
00277 ASSERT_CLOCK_INDEX(clockIndexI);
00278 ASSERT_CLOCK_INDEX(clockIndexJ);
00279 return (bool) dbmf_satisfies(dbmFederation,
00280 indexTable[clockIndexI], indexTable[clockIndexJ], rawConstraint);
00281 }
00282
00283
00284
00285
00286
00287 bool satisfies(constraint_t constraint) const
00288 {
00289 return satisfies(constraint.i, constraint.j, constraint.value);
00290 }
00291
00292
00293
00294
00295
00296
00297 bool satisfies(cindex_t clockIndexI, cindex_t clockIndexJ, int32_t bound, bool isStrict) const
00298 {
00299 return satisfies(clockIndexI, clockIndexJ, dbm_boundbool2raw(bound, (BOOL) isStrict));
00300 }
00301
00302
00303
00304
00305
00306
00307 bool satisfies(cindex_t clockIndexI, cindex_t clockIndexJ, int32_t bound, strictness_t strictness) const
00308 {
00309 return satisfies(clockIndexI, clockIndexJ, dbm_bound2raw(bound, strictness));
00310 }
00311
00312
00313
00314
00315 void up()
00316 {
00317 dbmf_up(dbmFederation);
00318 }
00319
00320
00321
00322
00323 void down()
00324 {
00325 dbmf_down(dbmFederation);
00326 }
00327
00328
00329
00330
00331 bool isUnbounded() const
00332 {
00333 return (bool) dbmf_isUnbounded(dbmFederation);
00334 }
00335
00336
00337
00338 bool isEmpty() const
00339 {
00340 return dbmFederation.dbmList == NULL;
00341 }
00342
00343
00344
00345
00346 void microDelay()
00347 {
00348 dbmf_microDelay(dbmFederation);
00349 }
00350
00351
00352
00353
00354
00355
00356 bool substract(const raw_t *dbm) throw (std::bad_alloc)
00357 {
00358 if (dbmf_substractDBM(&dbmFederation, dbm, dbmAllocator))
00359 {
00360 throw std::bad_alloc();
00361 }
00362 return dbmFederation.dbmList != NULL;
00363 }
00364
00365
00366
00367
00368
00369
00370
00371 bool substract(const Federation *fed) throw (std::bad_alloc)
00372 {
00373 assert(fed && fed->getNumberOfClocks() == getNumberOfClocks() &&
00374 fed->dbmAllocator == dbmAllocator);
00375 if (dbmf_substractFederation(&dbmFederation, fed->dbmFederation.dbmList, dbmAllocator))
00376 {
00377 throw std::bad_alloc();
00378 }
00379 return dbmFederation.dbmList != NULL;
00380 }
00381
00382
00383
00384
00385 Federation& operator -= (const Federation& fed) throw (std::bad_alloc)
00386 {
00387 assert(fed.getNumberOfClocks() == getNumberOfClocks() &&
00388 fed.dbmAllocator == dbmAllocator);
00389 if (dbmf_substractFederation(&dbmFederation, fed.dbmFederation.dbmList, dbmAllocator))
00390 {
00391 throw std::bad_alloc();
00392 }
00393 return *this;
00394 }
00395
00396
00397
00398
00399
00400
00401
00402 bool isMaybeIncludedIn(const Federation *fed)
00403 {
00404 assert(fed && fed->getNumberOfClocks() == getNumberOfClocks() &&
00405 fed->dbmAllocator == dbmAllocator);
00406 return dbmf_areDBMsIncludedIn(dbmFederation.dbmList, fed->dbmFederation.dbmList, getNumberOfClocks());
00407 }
00408
00409
00410
00411
00412
00413 bool isReallyIncludedIn(const Federation *fed)
00414 {
00415 assert(fed && fed->getNumberOfClocks() == getNumberOfClocks() &&
00416 fed->dbmAllocator == dbmAllocator);
00417 BOOL valid;
00418 BOOL isIn = dbmf_areDBMsReallyIncludedIn(dbmFederation.dbmList, fed->dbmFederation, &valid, dbmAllocator);
00419 if (!valid) throw std::bad_alloc();
00420 return isIn;
00421 }
00422
00423
00424
00425
00426
00427
00428 void freeClock(cindex_t clockIndex)
00429 {
00430 ASSERT_CLOCK_INDEX(clockIndex);
00431 dbmf_freeClock(dbmFederation, indexTable[clockIndex]);
00432 }
00433
00434
00435
00436
00437
00438
00439
00440 void updateValue(cindex_t clockIndex, int32_t value)
00441 {
00442 ASSERT_CLOCK_INDEX(clockIndex);
00443 dbmf_updateValue(dbmFederation, indexTable[clockIndex], value);
00444 }
00445
00446
00447
00448
00449
00450 void updateClock(cindex_t clockIndexI, cindex_t clockIndexJ)
00451 {
00452 ASSERT_CLOCK_INDEX(clockIndexI);
00453 ASSERT_CLOCK_INDEX(clockIndexJ);
00454 dbmf_updateClock(dbmFederation, indexTable[clockIndexI], indexTable[clockIndexJ]);
00455 }
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 void updateIncrement(cindex_t clockIndex, int32_t increment)
00467 {
00468 ASSERT_CLOCK_INDEX(clockIndex);
00469 dbmf_updateIncrement(dbmFederation, indexTable[clockIndex], increment);
00470 }
00471
00472
00473
00474
00475
00476
00477
00478 void update(cindex_t clockIndexI, cindex_t clockIndexJ, int32_t increment)
00479 {
00480 ASSERT_CLOCK_INDEX(clockIndexI);
00481 ASSERT_CLOCK_INDEX(clockIndexJ);
00482 dbmf_update(dbmFederation, indexTable[clockIndexI], indexTable[clockIndexJ], increment);
00483 }
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500 relation_t partialRelation(const raw_t *dbm) const
00501 {
00502 return dbmf_partialRelation(dbm, dbmFederation);
00503 }
00504
00505
00506
00507
00508
00509
00510
00511 relation_t relation(const raw_t *dbm) const throw (std::bad_alloc)
00512 {
00513 BOOL valid;
00514 relation_t result = dbmf_relation(dbm, dbmFederation, &valid, dbmAllocator);
00515 if (!valid) throw std::bad_alloc();
00516 return result;
00517 }
00518
00519
00520
00521
00522
00523 void unionWith(DBMList_t *fed)
00524 {
00525 dbmf_union(&dbmFederation, fed, dbmAllocator);
00526 }
00527
00528
00529
00530
00531 void unionWithCopy(const DBMList_t *fed) throw (std::bad_alloc)
00532 {
00533 BOOL valid;
00534 dbmf_unionWithCopy(&dbmFederation, fed, dbmAllocator, &valid);
00535 if (!valid) throw std::bad_alloc();
00536 }
00537
00538
00539
00540 void convexUnion()
00541 {
00542 dbmf_convexUnionWithSelf(&dbmFederation, dbmAllocator);
00543 }
00544
00545
00546
00547 void stretchUp()
00548 {
00549 dbmf_stretchUp(dbmFederation);
00550 }
00551
00552
00553
00554
00555
00556 void stretchDown(cindex_t clockIndex)
00557 {
00558 ASSERT_CLOCK_INDEX(clockIndex);
00559 dbmf_stretchDown(dbmFederation, indexTable[clockIndex]);
00560 }
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570 void predt(Federation *bad)
00571 {
00572 if (dbmf_predt(&dbmFederation, &bad->dbmFederation, dbmAllocator)) throw std::bad_alloc();
00573 }
00574
00575
00576
00577
00578
00579 void add(const DBMList_t *dbmList) throw (std::bad_alloc)
00580 {
00581 if (dbmf_addCopy(&dbmFederation, dbmList, dbmAllocator)) throw std::bad_alloc();
00582 }
00583
00584
00585
00586
00587 Federation* add(const Federation *arg) throw (std::bad_alloc)
00588 {
00589 assert(arg && arg->getNumberOfClocks() == getNumberOfClocks());
00590 add(arg->dbmFederation.dbmList);
00591 return this;
00592 }
00593
00594
00595
00596 Federation& operator += (const Federation& arg) throw (std::bad_alloc)
00597 {
00598 assert(arg.getNumberOfClocks() == getNumberOfClocks());
00599 add(arg.dbmFederation.dbmList);
00600 return *this;
00601 }
00602
00603
00604
00605 void reduce()
00606 {
00607 dbmf_reduce(&dbmFederation, dbmAllocator);
00608 }
00609
00610
00611
00612 void expensiveReduce()
00613 {
00614 dbmf_expensiveReduce(&dbmFederation, dbmAllocator);
00615 }
00616
00617
00618
00619
00620
00621 bool removePartialIncludedIn(const Federation *arg)
00622 {
00623 assert(arg);
00624 return dbmf_removePartialIncluded(&dbmFederation, arg->dbmFederation.dbmList, dbmAllocator);
00625 }
00626
00627
00628
00629
00630 DBMAllocator_t *getAllocator()
00631 {
00632 return dbmAllocator;
00633 }
00634
00635
00636
00637 const DBMAllocator_t* getAllocator() const
00638 {
00639 return dbmAllocator;
00640 }
00641
00642
00643
00644
00645 const DBMList_t* getDBMList() const
00646 {
00647 return dbmFederation.dbmList;
00648 }
00649
00650
00651
00652
00653 DBMList_t* getDBMList()
00654 {
00655 return dbmFederation.dbmList;
00656 }
00657
00658
00659
00660
00661 DBMList_t** getAtDBMList()
00662 {
00663 return &dbmFederation.dbmList;
00664 }
00665
00666
00667
00668
00669 raw_t *getFirstDBM()
00670 {
00671 assert(dbmFederation.dbmList);
00672 return dbmFederation.dbmList->dbm;
00673 }
00674
00675
00676
00677
00678 size_t getSize() const
00679 {
00680 return dbmf_getSize(dbmFederation.dbmList);
00681 }
00682
00683
00684
00685
00686
00687
00688 raw_t *newDBM() throw (std::bad_alloc())
00689 {
00690 DBMList_t *freshNew = dbmf_allocate(dbmAllocator);
00691 if (!freshNew) throw std::bad_alloc();
00692 dbmf_addDBM(freshNew, &dbmFederation);
00693 return freshNew->dbm;
00694 }
00695
00696
00697
00698 void reset()
00699 {
00700 if (dbmFederation.dbmList)
00701 {
00702 dbmf_deallocateList(dbmAllocator, dbmFederation.dbmList);
00703 dbmFederation.dbmList = NULL;
00704 }
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714 void extrapolateMaxBounds(const int32_t *max)
00715 {
00716 dbmf_extrapolateMaxBounds(dbmFederation, max);
00717 }
00718
00719
00720
00721
00722
00723
00724
00725
00726 void diagonalExtrapolateMaxBounds(const int32_t *max)
00727 {
00728 dbmf_diagonalExtrapolateMaxBounds(dbmFederation, max);
00729 }
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739 void extrapolateLUBounds(const int32_t *lower, const int32_t *upper)
00740 {
00741 dbmf_extrapolateLUBounds(dbmFederation, lower, upper);
00742 }
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753 void diagonalExtrapolateLUBounds(const int32_t *lower, const int32_t *upper)
00754 {
00755 dbmf_diagonalExtrapolateLUBounds(dbmFederation, lower, upper);
00756 }
00757
00758
00759
00760
00761
00762 void initIndexTable(cindex_t newDim)
00763 {
00764 assert(dbmAllocator && dbmAllocator->maxDim && dbmAllocator->maxDim >= newDim);
00765
00766 dbmFederation.dim = newDim;
00767 reset();
00768
00769 cindex_t i = 0, max = dbmAllocator->maxDim;
00770 cindex_t *table = indexTable;
00771 do { table[i] = i; } while(++i < max);
00772 }
00773
00774
00775
00776
00777
00778
00779
00780 void initIndexTable(const uint32_t *activeClocks, size_t size)
00781 {
00782 assert(activeClocks && size);
00783 dbmFederation.dim = base_countBitsN(activeClocks, size);
00784 reset();
00785 base_bits2indexTable(activeClocks, size, indexTable);
00786 }
00787
00788
00789
00790
00791
00792
00793 void initFederation(DBMAllocator_t *dbmf, cindex_t nbClocks)
00794 {
00795 dbmAllocator = dbmf;
00796 dbmFederation.dbmList = NULL;
00797 initIndexTable(nbClocks);
00798 }
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809 void initFederation(DBMAllocator_t *dbmf, cindex_t nbClocks,
00810 const uint32_t *activeClocks, size_t size)
00811 {
00812 assert(dbmf && activeClocks && nbClocks < dbmf->maxDim &&
00813 size <= (size_t) ((dbmf->maxDim + 31) >> 5));
00814 dbmf_initFederation(&dbmFederation, nbClocks);
00815 dbmAllocator = dbmf;
00816 initIndexTable(activeClocks, size);
00817 }
00818
00819
00820
00821
00822
00823
00824
00825
00826 void changeClocks(const uint32_t *oldClocks, const uint32_t *newClocks, size_t size)
00827 {
00828 if (!base_areBitsEqual(oldClocks, newClocks, size))
00829 {
00830 dbmf_shrinkExpand(&dbmFederation, oldClocks, newClocks, size, indexTable, dbmAllocator);
00831 }
00832 }
00833
00834 private:
00835
00836 friend class state::SymbolicState;
00837
00838
00839
00840
00841 void copyFromFederation(const Federation *original) throw (std::bad_alloc)
00842 {
00843 assert(original && dbmAllocator == original->dbmAllocator);
00844 if (dbmf_copy(&dbmFederation, original->dbmFederation, dbmAllocator))
00845 {
00846 throw std::bad_alloc();
00847 }
00848 }
00849
00850
00851
00852
00853
00854 static void* allocateFor(cindex_t maxDim)
00855 {
00856 return new char[getSizeOfFederationFor(maxDim)];
00857 }
00858
00859
00860
00861 static size_t getSizeOfFederationFor(cindex_t maxDim)
00862 {
00863 return sizeof(Federation)+sizeof(cindex_t[maxDim]);
00864 }
00865
00866
00867
00868
00869
00870
00871 static size_t getPaddedIntOffsetFor(cindex_t maxDim)
00872 {
00873
00874 return (sizeof(uintptr_t) == sizeof(uint32_t) || (intsizeof(Federation) & 1))
00875 ? ((sizeof(cindex_t) == sizeof(uint32_t)) ? maxDim : intsizeof(cindex_t[maxDim]))
00876 : ((sizeof(cindex_t[maxDim]) + 7) >> 3);
00877 }
00878
00879
00880
00881
00882
00883
00884 Federation(DBMAllocator_t *dbmf, cindex_t nbClocks)
00885 {
00886 initFederation(dbmf, nbClocks);
00887 }
00888
00889
00890
00891
00892 Federation(const Federation& original) throw (std::bad_alloc)
00893 {
00894 dbmAllocator = original.dbmAllocator;
00895
00896
00897 dbmFederation.dim = original.dbmFederation.dim;
00898 dbmFederation.dbmList = NULL;
00899 *this = original;
00900 }
00901
00902
00903
00904
00905
00906
00907
00908 Federation(DBMAllocator_t *dbmf, cindex_t nbClocks,
00909 const uint32_t *activeClocks, size_t size)
00910 {
00911 initFederation(dbmf, nbClocks, activeClocks, size);
00912 }
00913
00914
00915 DBMFederation_t dbmFederation;
00916 DBMAllocator_t *dbmAllocator;
00917 cindex_t indexTable[];
00918 };
00919
00920 }
00921
00922
00923
00924
00925 static inline
00926 std::ostream& operator << (std::ostream& os, const dbm::Federation& fed)
00927 {
00928 return fed.serialize(os);
00929 }
00930
00931 static inline
00932 void operator >> (std::istream& is, dbm::Federation& fed)
00933 {
00934 fed.unserialize(is);
00935 }
00936
00937 #endif // INCLUDE_DBM_FEDERATION_H
00938