00001
00002
00003
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #ifndef _CHOMP_STRUCT_HASHSETS_H_
00041 #define _CHOMP_STRUCT_HASHSETS_H_
00042
00043 #include "chomp/system/config.h"
00044 #include "chomp/system/textfile.h"
00045 #include "chomp/struct/multitab.h"
00046
00047 #include <cstdlib>
00048 #include <ctime>
00049 #include <iostream>
00050
00051 namespace chomp {
00052 namespace homology {
00053
00054
00055
00056 template <class element>
00057 class hashedset;
00058 template <class domelement, class imgelement>
00059 class mvmap;
00060
00061
00062
00063
00064
00065
00068 class hashstat
00069 {
00070 public:
00072 hashstat ();
00073
00075 std::time_t creationtime;
00076
00079 unsigned long hashhits;
00080
00083 unsigned long hashmisses;
00084
00087 unsigned long rehashcount;
00088
00089 };
00090
00091
00092
00093 inline hashstat::hashstat ()
00094 {
00095 std::time (&creationtime);
00096 hashhits = 0;
00097 hashmisses = 0;
00098 rehashcount = 0;
00099 return;
00100 }
00101
00102
00103
00106 inline std::ostream &operator << (std::ostream &out, const hashstat &s)
00107 {
00108 if (!s. hashhits)
00109 return out;
00110 out << "hashing: " << s. hashhits << " hits, avg " <<
00111 ((s. hashhits + s. hashmisses) / s. hashhits) << "." <<
00112 ((s. hashhits + s. hashmisses) * 10 / s. hashhits) % 10 <<
00113 " attempts (" << s. rehashcount << " times rehashed)";
00114 return out;
00115 }
00116
00117
00118
00119
00120
00121
00129 template <class element>
00130 class hashedset
00131 {
00132 public:
00134 typedef element value_type;
00135
00139 explicit hashedset (int_t initialsize = 0, int bequiet = 1);
00140
00142 hashedset (const hashedset<element> &s);
00143
00145 hashedset &operator = (const hashedset<element> &s);
00146
00148 ~hashedset (void);
00149
00152 int_t getnumber (const element &e) const;
00153
00158 bool checknum (int_t n) const;
00159
00162 bool check (const element &e) const;
00163
00165 const element &operator [] (int_t n) const;
00166
00168 const element &get (int_t n) const;
00169
00171 const element &front () const;
00172
00174 const element &top () const;
00175
00179 int_t add (const element &e);
00180
00182 int_t push (const element &e);
00183
00185 int_t push_back (const element &e);
00186
00189 int remove (const element &e);
00190
00193 int removenum (int_t n);
00194
00197 int_t pop ();
00198
00200 hashedset<element> &add (const hashedset<element> &s);
00201
00203 hashedset<element> &remove (const hashedset<element> &s);
00204
00206 int_t size () const;
00207
00209 bool empty () const;
00210
00212 void swap (hashedset<element> &other);
00213
00216 bool operator == (const hashedset<element> &other) const;
00217
00220 void intersection (const hashedset<element> &s1,
00221 const hashedset<element> &s2);
00222
00226 hashstat *stat;
00227
00228 private:
00230 static const int_t InitHashSize;
00231
00233 static const int_t InitTabSize;
00234
00240 static const int_t StartHashingSize;
00241
00243 int_t nelem;
00244
00246 multitable<element> tab;
00247
00249 int hashing;
00250
00252 int_t hashsize;
00253
00255 int_t hashcleared;
00256
00259 multitable<int_t> hashtable;
00260
00266 int_t hashfind (const element &e, int_t *addpos = NULL) const;
00267
00271 void rehash (int_t newsize = 0);
00272
00275 static bool numberisprime (const int_t &n);
00276
00278 static int_t rounduptoprime (int_t n);
00279
00280 };
00281
00282
00283
00284 template <class element>
00285 const int_t hashedset<element>::InitHashSize (137);
00286
00287 template <class element>
00288 const int_t hashedset<element>::InitTabSize (30);
00289
00290 template <class element>
00291 const int_t hashedset<element>::StartHashingSize (30);
00292
00293
00294
00295 template <class element>
00296 hashedset<element>::hashedset (int_t initialsize, int bequiet):
00297 nelem (0), tab ((initialsize > 0) ? initialsize :
00298 int_t (InitTabSize)),
00299 hashing (0),
00300 hashsize (initialsize + (initialsize >> 2) + InitHashSize),
00301 hashcleared (0), hashtable (hashsize)
00302 {
00303 hashedset<element>::rounduptoprime (hashsize);
00304 if (bequiet)
00305 stat = NULL;
00306 else
00307 stat = new hashstat;
00308 return;
00309 }
00310
00311 template <class element>
00312 hashedset<element>::hashedset (const hashedset<element> &s):
00313 nelem (s. nelem), tab (s. tab),
00314 hashing (s. hashing), hashsize (s. hashsize),
00315 hashcleared (s. hashcleared), hashtable (s. hashtable)
00316 {
00317 if (s. stat)
00318 stat = new hashstat;
00319 else
00320 stat = NULL;
00321 return;
00322 }
00323
00324 template <class element>
00325 hashedset<element> &hashedset<element>::operator =
00326 (const hashedset<element> &s)
00327 {
00328 if (this == &s)
00329 return *this;
00330
00331 if (s. stat)
00332 stat = new hashstat (*stat);
00333 nelem = s. nelem;
00334 tab = s. tab;
00335 hashing = s. hashing;
00336 hashsize = s. hashsize;
00337 hashcleared = s. hashcleared;
00338 hashtable = s. hashtable;
00339
00340 return *this;
00341 }
00342
00343 template <class element>
00344 hashedset<element>::~hashedset ()
00345 {
00346 if (!stat)
00347 return;
00348 sout << " " << *stat << '\n';
00349 delete stat;
00350 stat = NULL;
00351 return;
00352 }
00353
00354 template <class element>
00355 int_t hashedset<element>::getnumber (const element &e) const
00356 {
00357 if (hashing)
00358 {
00359 int_t pos = hashfind (e);
00360 return (hashtable (pos));
00361 }
00362 else
00363 {
00364 for (int_t i = 0; i < nelem; ++ i)
00365 {
00366 if (tab (i) == e)
00367 return i;
00368 }
00369 return -1;
00370 }
00371 }
00372
00373 template <class element>
00374 inline bool hashedset<element>::checknum (int_t n) const
00375 {
00376 return ((n >= 0) && (n < nelem));
00377 }
00378
00379 template <class element>
00380 inline bool hashedset<element>::check (const element &e) const
00381 {
00382 return (getnumber (e) >= 0);
00383 }
00384
00385
00386 template <class element>
00387 inline const element &hashedset<element>::get (int_t n) const
00388 {
00389 if ((n < 0) || (n >= nelem))
00390 throw "Trying to get an element out of range.";
00391 return tab (n);
00392 }
00393
00394 template <class element>
00395 inline const element &hashedset<element>::operator [] (int_t n) const
00396 {
00397 return get (n);
00398 }
00399
00400 template <class element>
00401 inline const element &hashedset<element>::front () const
00402 {
00403 return get (nelem - 1);
00404 }
00405
00406 template <class element>
00407 inline const element &hashedset<element>::top () const
00408 {
00409 return get (nelem - 1);
00410 }
00411
00412 template <class element>
00413 int_t hashedset<element>::add (const element &e)
00414 {
00415 if (!hashing)
00416 {
00417 for (int_t i = 0; i < nelem; ++ i)
00418 {
00419 if (tab (i) == e)
00420 return i;
00421 }
00422 tab [nelem ++] = e;
00423 if (nelem >= StartHashingSize)
00424 {
00425 hashing = 1;
00426 rehash ();
00427 }
00428 return (nelem - 1);
00429 }
00430
00431
00432 if (hashsize - hashcleared < nelem + (nelem >> 1) + 19)
00433 rehash ();
00434
00435
00436 int_t addpos = -1;
00437 int_t pos = hashfind (e, &addpos);
00438
00439
00440 if (hashtable (pos) >= 0)
00441 return hashtable (pos);
00442
00443
00444 if (addpos >= 0)
00445 pos = addpos;
00446 hashtable [pos] = nelem;
00447 tab [nelem] = e;
00448 return nelem ++;
00449 }
00450
00451 template <class element>
00452 inline int_t hashedset<element>::push (const element &e)
00453 {
00454 return add (e);
00455 }
00456
00457 template <class element>
00458 inline int_t hashedset<element>::push_back (const element &e)
00459 {
00460 return add (e);
00461 }
00462
00463 template <class element>
00464 int hashedset<element>::remove (const element &e)
00465 {
00466 if (!hashing)
00467 {
00468 for (int_t i = 0; i < nelem; ++ i)
00469 {
00470 if (tab (i) == e)
00471 {
00472 tab [i] = tab (-- nelem);
00473 return 0;
00474 }
00475 }
00476 return -1;
00477 }
00478
00479
00480 int_t pos = hashfind (e);
00481
00482
00483 if (hashtable (pos) < 0)
00484 return -1;
00485 int_t n = hashtable (pos);
00486
00487
00488 hashtable [pos] = -2;
00489 -- nelem;
00490 ++ hashcleared;
00491
00492
00493
00494 if (n != nelem)
00495 {
00496 pos = hashfind (tab (nelem));
00497 hashtable [pos] = n;
00498 tab [n] = tab (nelem);
00499 }
00500
00501
00502 if (nelem < StartHashingSize / 2)
00503 {
00504 hashing = 0;
00505 }
00506
00507
00508 else if (hashcleared > nelem + 19)
00509 rehash ();
00510
00511 return 0;
00512 }
00513
00514 template <class element>
00515 inline int hashedset<element>::removenum (int_t n)
00516 {
00517 if ((n < 0) || (n >= nelem))
00518 return -1;
00519 if (!hashing)
00520 {
00521 -- nelem;
00522 if (n != nelem)
00523 tab [n] = tab (nelem);
00524 return 0;
00525 }
00526 return remove (tab (n));
00527 }
00528
00529 template <class element>
00530 inline int_t hashedset<element>::pop ()
00531 {
00532 if (!nelem)
00533 throw "Trying to remove an element from an empty set.";
00534 return removenum (nelem - 1);
00535 }
00536
00537 template <class element>
00538 hashedset<element> &hashedset<element>::add (const hashedset<element> &s)
00539 {
00540 int_t n = s. size ();
00541 for (int_t i = 0; i < n; ++ i)
00542 add (s [i]);
00543 return *this;
00544 }
00545
00546 template <class element>
00547 hashedset<element> &hashedset<element>::remove (const hashedset<element> &s)
00548 {
00549 if (this -> size () < s. size ())
00550 {
00551 for (int_t i = 0; i < this -> size (); ++ i)
00552 {
00553 if (s. check ((*this) [i]))
00554 this -> removenum (i --);
00555 }
00556 }
00557 else
00558 {
00559 int_t n = s. size ();
00560 for (int_t i = 0; i < n; ++ i)
00561 remove (s [i]);
00562 }
00563 return *this;
00564 }
00565
00566 template <class element>
00567 inline bool hashedset<element>::empty () const
00568 {
00569 return !nelem;
00570 }
00571
00572 template <class element>
00573 inline int_t hashedset<element>::size () const
00574 {
00575 return nelem;
00576 }
00577
00578 template <class element>
00579 inline void hashedset<element>::swap (hashedset<element> &other)
00580 {
00581 my_swap (stat, other. stat);
00582 my_swap (nelem, other. nelem);
00583 tab. swap (other. tab);
00584 my_swap (hashing, other. hashing);
00585 my_swap (hashsize, other. hashsize);
00586 my_swap (hashcleared, other. hashcleared);
00587 hashtable. swap (other. hashtable);
00588 return;
00589 }
00590
00591 template <class element>
00592 inline bool hashedset<element>::operator ==
00593 (const hashedset<element> &other) const
00594 {
00595 if (this -> nelem != other. nelem)
00596 return false;
00597 for (int_t i = 0; i < nelem; ++ i)
00598 {
00599 if (!other. check (this -> tab [i]))
00600 return false;
00601 }
00602 return true;
00603 }
00604
00605 template <class element>
00606 inline void hashedset<element>::intersection (const hashedset<element> &s1,
00607 const hashedset<element> &s2)
00608 {
00609 int_t size1 = s1. size ();
00610 int_t size2 = s2. size ();
00611
00612 if (size1 <= size2)
00613 {
00614 for (int_t i = 0; i < size1; ++ i)
00615 {
00616 const element &elem = s1. tab [i];
00617 if (s2. check (elem))
00618 this -> add (elem);
00619 }
00620 }
00621 else
00622 {
00623 for (int_t i = 0; i < size2; ++ i)
00624 {
00625 const element &elem = s2. tab [i];
00626 if (s1. check (elem))
00627 this -> add (elem);
00628 }
00629 }
00630 return;
00631 }
00632
00633 template <class element>
00634 int_t hashedset<element>::hashfind (const element &e, int_t *addpos) const
00635 {
00636 if (!hashing)
00637 throw "Hashing is turned off.";
00638
00639 int_t key = hashkey1 (e);
00640 if (key < 0)
00641 key = -(key + 1);
00642 int_t pos = key % hashsize;
00643 if (addpos)
00644 *addpos = -1;
00645
00646
00647 if (stat)
00648 ++ (stat -> hashhits);
00649
00650
00651 int_t number;
00652 int_t add = 0;
00653 while ((number = hashtable (pos)) != -1)
00654 {
00655 if ((number >= 0) && (e == tab (number)))
00656 return (pos);
00657 if (addpos && (*addpos < 0) && (number == -2))
00658 *addpos = pos;
00659 if (!add)
00660 {
00661 int_t key = hashkey2 (e);
00662 if (key < 0)
00663 key = -(key + 1);
00664 add = key % (hashsize - 1) + 1;
00665 }
00666 pos += add;
00667 if (pos >= hashsize)
00668 pos -= hashsize;
00669 if (stat)
00670 ++ (stat -> hashmisses);
00671 }
00672
00673
00674 return (pos);
00675
00676 }
00677
00678 template <class element>
00679 void hashedset<element>::rehash (int_t newsize)
00680 {
00681 if (stat)
00682 ++ (stat -> rehashcount);
00683
00684
00685 if ((newsize < (nelem << 1) + InitHashSize) ||
00686 (newsize > (nelem << 2) + InitHashSize))
00687 newsize = (nelem << 1) + nelem + InitHashSize;
00688
00689
00690
00691
00692
00693
00694 int_t x = 0xFFFF;
00695 if ((x < 0) && (newsize >= 16384))
00696 throw "Set too large for this 16-bit program.";
00697
00698
00699 if (newsize < hashsize)
00700 {
00701 multitable<int_t> empty;
00702 hashtable = empty;
00703 }
00704
00705
00706 hashsize = hashedset<element>::rounduptoprime (newsize);
00707 hashcleared = 0;
00708
00709
00710 hashtable. fill (-1, hashsize);
00711 for (int_t i = 0; i < nelem; ++ i)
00712 {
00713 int_t pos = hashfind (tab (i));
00714 if (hashtable (pos) != -1)
00715 throw "A repeated element in a set!";
00716 hashtable [pos] = i;
00717 }
00718
00719 return;
00720 }
00721
00722 template <class element>
00723 inline bool hashedset<element>::numberisprime (const int_t &n)
00724 {
00725 if (n < 2)
00726 return 0;
00727
00728 int_t i = 2;
00729 while (i * i <= n)
00730 {
00731 if (!(n % i))
00732 return false;
00733 ++ i;
00734 }
00735
00736 return true;
00737 }
00738
00739 template <class element>
00740 int_t hashedset<element>::rounduptoprime (int_t n)
00741 {
00742 while (!hashedset<element>::numberisprime (n))
00743 ++ n;
00744
00745 return n;
00746 }
00747
00748
00749
00750
00755 #define SMALL_SIZE true
00756
00762 #define LARGE_SIZE false
00763
00767 template <class stream, class element>
00768 stream &write (stream &out, const hashedset<element> &s, bool size)
00769 {
00770 if (size == SMALL_SIZE)
00771 {
00772 out << '{';
00773 int_t n = s. size ();
00774 for (int_t i = 0; i < n; ++ i)
00775 out << (i ? " " : "") << s [i];
00776 out << '}';
00777 }
00778 else
00779 {
00780 int_t n = s. size ();
00781 if (!s. empty ())
00782 {
00783 out << "; " << n << ((n == 1) ? " element." :
00784 " elements.") << '\n';
00785 }
00786 if (s. stat && s. stat -> hashhits)
00787 out << ';' << *(s. stat) << '\n';
00788 for (int_t i = 0; i < n; ++ i)
00789 out << s [i] << '\n';
00790 }
00791 return out;
00792 }
00793
00796 template <class element>
00797 std::ostream &operator << (std::ostream &out, const hashedset<element> &s)
00798 {
00799 return write (out, s, LARGE_SIZE);
00800 }
00801
00804 template <class stream, class element>
00805 stream &read (stream &in, hashedset<element> &s, bool size)
00806 {
00807
00808 ignorecomments (in);
00809
00810
00811
00812 int closing = EOF;
00813 if (size == SMALL_SIZE)
00814 {
00815 closing = readparenthesis (in);
00816 if (closing == EOF)
00817 throw "An opening parenthesis expected in a set.";
00818 ignorecomments (in);
00819 }
00820
00821
00822 while (in. peek () != closing)
00823 {
00824 element e;
00825 in >> e;
00826
00827
00828 s. add (e);
00829 ignorecomments (in);
00830
00831
00832 if (in. peek () == ',')
00833 {
00834 in. get ();
00835 ignorecomments (in);
00836 }
00837 }
00838
00839
00840 if (closing != EOF)
00841 in. get ();
00842
00843 return in;
00844 }
00845
00848 template <class element>
00849 std::istream &operator >> (std::istream &in, hashedset<element> &s)
00850 {
00851 return read (in, s, LARGE_SIZE);
00852 }
00853
00855 template <class element>
00856 inline hashedset<element> &operator += (hashedset<element> &s,
00857 const hashedset<element> &u)
00858 {
00859 s. add (u);
00860 return s;
00861 }
00862
00864 template <class element>
00865 inline hashedset<element> &operator -= (hashedset<element> &s,
00866 const hashedset<element> &u)
00867 {
00868 s. remove (u);
00869 return s;
00870 }
00871
00872
00873
00875 inline int_t hashkey1 (const unsigned long &number)
00876 {
00877 return static_cast<int_t> (number);
00878 }
00879
00881 inline int_t hashkey2 (const unsigned long &number)
00882 {
00883 return static_cast<int_t> (number ^ 0xFA5A75A7ul) << 8;
00884 }
00885
00890 #define DEFHASHKEYS(type) \
00891 inline int_t hashkey1 (const type &number) \
00892 { return hashkey1 (static_cast<const unsigned long> (number)); } \
00893 inline int_t hashkey2 (const type &number) \
00894 { return hashkey2 (static_cast<const unsigned long> (number)); }
00895
00896 DEFHASHKEYS(unsigned int)
00897 DEFHASHKEYS(signed int)
00898
00899 DEFHASHKEYS(signed long)
00900 DEFHASHKEYS(unsigned short)
00901 DEFHASHKEYS(signed short)
00902 DEFHASHKEYS(unsigned char)
00903 DEFHASHKEYS(signed char)
00904
00905 #undef DEFHASHKEYS
00906
00910 template <class T>
00911 inline int_t hashkey1 (const T &x)
00912 {
00913 return x. hashkey1 ();
00914 }
00915
00919 template <class T>
00920 inline int_t hashkey2 (const T &x)
00921 {
00922 return x. hashkey2 ();
00923 }
00924
00925
00926
00927
00928
00929
00937 template <class domelement, class imgelement>
00938 class mvmap
00939 {
00940 public:
00945 explicit mvmap (int bequiet = 1);
00946
00948 ~mvmap ();
00949
00951 const domelement &get (int_t n) const;
00952
00954 const hashedset<domelement> &getdomain () const;
00955
00958 const hashedset<imgelement> &operator () (int_t n) const;
00959
00962 const hashedset<imgelement> &operator ()
00963 (const domelement &x) const;
00964
00966 hashedset<imgelement> &operator [] (int_t n);
00967
00971 hashedset<imgelement> &operator [] (const domelement &x);
00972
00974 int_t size () const;
00975
00978 bool remove (const domelement &x);
00979
00981 bool removenum (int_t n);
00982
00984 void remove (const hashedset<domelement> &x);
00985
00987 void swap (mvmap<domelement,imgelement> &other);
00988
00992 int quiet;
00993
00994 private:
00996 hashedset<domelement> domain;
00997
01000 multitable<hashedset<imgelement> > images;
01001
01002 };
01003
01004
01005
01006 template <class domelement, class imgelement>
01007 inline mvmap<domelement,imgelement>::mvmap (int bequiet):
01008 domain (0, bequiet), images ()
01009 {
01010 return;
01011 }
01012
01013 template <class domelement, class imgelement>
01014 inline mvmap<domelement,imgelement>::~mvmap ()
01015 {
01016 return;
01017 }
01018
01019 template <class domelement, class imgelement>
01020 inline const domelement &mvmap<domelement,imgelement>::get (int_t n) const
01021 {
01022 if ((n < 0) || (n >= domain. size ()))
01023 throw "Domain element number out of range.";
01024 return domain [n];
01025 }
01026
01027 template <class domelement, class imgelement>
01028 inline const hashedset<domelement> &
01029 mvmap<domelement,imgelement>::getdomain () const
01030 {
01031 return domain;
01032 }
01033
01034 template <class domelement, class imgelement>
01035 inline const hashedset<imgelement>
01036 &mvmap<domelement,imgelement>::operator () (int_t n) const
01037 {
01038 if ((n < 0) || (n >= domain. size ()))
01039 throw "Domain element number out of range.";
01040 return images (n);
01041 }
01042
01043 template <class domelement, class imgelement>
01044 inline const hashedset<imgelement>
01045 &mvmap<domelement,imgelement>::operator ()
01046 (const domelement &q) const
01047 {
01048 int_t n = domain. getnumber (q);
01049 if (n < 0)
01050 throw "Element not in the domain.";
01051 return images (n);
01052 }
01053
01054 template <class domelement, class imgelement>
01055 inline hashedset<imgelement>
01056 &mvmap<domelement,imgelement>::operator [] (int_t n)
01057 {
01058 if ((n < 0) || (n >= domain. size ()))
01059 throw "Domain element number out of range.";
01060 return images [n];
01061 }
01062
01063 template <class domelement, class imgelement>
01064 inline hashedset<imgelement>
01065 &mvmap<domelement,imgelement>::operator []
01066 (const domelement &q)
01067 {
01068 int_t n = domain. add (q);
01069 return images [n];
01070 }
01071
01072 template <class domelement, class imgelement>
01073 inline int_t mvmap<domelement,imgelement>::size () const
01074 {
01075 return domain. size ();
01076 }
01077
01078 template <class domelement, class imgelement>
01079 inline bool mvmap<domelement,imgelement>::removenum (int_t n)
01080
01081
01082 {
01083 if ((n < 0) || (n >= domain. size ()))
01084 return false;
01085 domain. removenum (n);
01086 if (n != domain. size ())
01087 images [n] = images [domain. size ()];
01088 hashedset<imgelement> empty;
01089 images [domain. size ()] = empty;
01090 return true;
01091 }
01092
01093 template <class domelement, class imgelement>
01094 inline bool mvmap<domelement,imgelement>::remove (const domelement &x)
01095 {
01096 return removenum (domain. getnumber (x));
01097 }
01098
01099 template <class domelement, class imgelement>
01100 inline void mvmap<domelement,imgelement>::remove
01101 (const hashedset<domelement> &x)
01102 {
01103 int_t n = x. size ();
01104 for (int_t i = 0; i < n; ++ i)
01105 remove (x [i]);
01106 return;
01107 }
01108
01109 template <class domelement, class imgelement>
01110 inline void mvmap<domelement,imgelement>::swap
01111 (mvmap<domelement,imgelement> &other)
01112 {
01113 domain. swap (other. domain);
01114 images. swap (other. images);
01115 return;
01116 }
01117
01118
01119
01121 template <class domelement, class imgelement>
01122 hashedset<imgelement> &retrieveimage (const mvmap<domelement,imgelement> &m,
01123 hashedset<imgelement> &img)
01124 {
01125 int_t n = m. getdomain (). size ();
01126 for (int_t i = 0; i < n; ++ i)
01127 img. add (m (i));
01128 return img;
01129 }
01130
01134 template <class domelement, class imgelement>
01135 hashedset<imgelement> &creategraph (const mvmap<domelement,imgelement> &m,
01136 hashedset<imgelement> &graph)
01137 {
01138 for (int_t i = 0; i < m. getdomain (). size (); ++ i)
01139 {
01140 const domelement &e = m. get (i);
01141 const hashedset<imgelement> &f = m (i);
01142 int_t n = f. size ();
01143 for (int_t j = 0; j < n; ++ j)
01144 graph. add (e * f [j]);
01145 }
01146 return graph;
01147 }
01148
01149
01150
01152 template <class domelement, class imgelement>
01153 std::istream &readdomain (std::istream &in, hashedset<domelement> &dom,
01154 const mvmap<domelement,imgelement> &)
01155 {
01156 ignorecomments (in);
01157 while (in. peek () != EOF)
01158 {
01159 domelement e;
01160 in >> e;
01161
01162
01163 dom. add (e);
01164
01165
01166 ignorecomments (in);
01167 while (in. peek () == '-')
01168 in. get ();
01169 if (in. peek () == '>')
01170 in. get ();
01171
01172 ignorecomments (in);
01173 int closing = readparenthesis (in);
01174
01175 ignorecomments (in);
01176 while (in. peek () != closing)
01177 {
01178 imgelement junk;
01179 in >> junk;
01180
01181
01182 ignorecomments (in);
01183 if (in. peek () == ',')
01184 {
01185 in. get ();
01186 ignorecomments (in);
01187 }
01188 }
01189
01190 if (closing != EOF)
01191 in. get ();
01192 ignorecomments (in);
01193 }
01194 return in;
01195 }
01196
01198 template <class domelement, class imgelement>
01199 std::istream &readimage (std::istream &in, hashedset<imgelement> &img,
01200 const mvmap<domelement,imgelement> &)
01201 {
01202 ignorecomments (in);
01203 while (in. peek () != EOF)
01204 {
01205 domelement e;
01206 in >> e;
01207
01208
01209
01210
01211 ignorecomments (in);
01212 while (in. peek () == '-')
01213 in. get ();
01214 if (in. peek () == '>')
01215 in. get ();
01216
01217 ignorecomments (in);
01218 read (in, img, SMALL_SIZE);
01219
01220 ignorecomments (in);
01221 }
01222 return in;
01223 }
01224
01226 template <class domelement, class imgelement>
01227 std::istream &readselective (std::istream &in, mvmap<domelement,imgelement> &m,
01228 const hashedset<domelement> &dom1, const hashedset<domelement> &dom2)
01229 {
01230 if (dom1. empty () && dom2. empty ())
01231 {
01232 sout << "Warning: The domain of the map is empty.\n";
01233 return in;
01234 }
01235
01236 ignorecomments (in);
01237 while (in. peek () != EOF)
01238 {
01239 domelement e;
01240 in >> e;
01241
01242
01243
01244
01245 ignorecomments (in);
01246 while (in. peek () == '-')
01247 in. get ();
01248 if (in. peek () == '>')
01249 in. get ();
01250
01251 ignorecomments (in);
01252 if (dom1. check (e) || dom2. check (e))
01253 read (in, m [e], SMALL_SIZE);
01254 else
01255 {
01256 int closing = readparenthesis (in);
01257
01258 ignorecomments (in);
01259 while (in. peek () != closing)
01260 {
01261 imgelement junk;
01262 in >> junk;
01263
01264
01265 ignorecomments (in);
01266 if (in. peek () == ',')
01267 {
01268 in. get ();
01269 ignorecomments (in);
01270 }
01271 }
01272
01273 if (closing != EOF)
01274 in. get ();
01275 }
01276 ignorecomments (in);
01277 }
01278 return in;
01279 }
01280
01282 template <class domelement, class imgelement>
01283 std::istream &readrestriction (std::istream &in,
01284 mvmap<domelement,imgelement> &m, const hashedset<domelement> &dom,
01285 const hashedset<imgelement> &img)
01286 {
01287 if (dom. empty ())
01288 {
01289 sout << "Warning: The domain of the map is empty.\n";
01290 return in;
01291 }
01292
01293 ignorecomments (in);
01294 while (in. peek () != EOF)
01295 {
01296 domelement e;
01297 in >> e;
01298
01299
01300
01301
01302 ignorecomments (in);
01303 while (in. peek () == '-')
01304 in. get ();
01305 if (in. peek () == '>')
01306 in. get ();
01307
01308 ignorecomments (in);
01309 if (dom. check (e))
01310 {
01311 hashedset<imgelement> &y = m [e];
01312 hashedset<domelement> x;
01313 read (in, x, SMALL_SIZE);
01314 int_t n = x. size ();
01315 for (int_t i = 0; i < n; ++ i)
01316 {
01317 if (img. check (x [i]))
01318 y. add (x [i]);
01319 }
01320 }
01321 else
01322 {
01323 int closing = readparenthesis (in);
01324
01325 ignorecomments (in);
01326 while (in. peek () != closing)
01327 {
01328 imgelement junk;
01329 in >> junk;
01330
01331
01332 ignorecomments (in);
01333 if (in. peek () == ',')
01334 {
01335 in. get ();
01336 ignorecomments (in);
01337 }
01338 }
01339
01340 if (closing != EOF)
01341 in. get ();
01342 }
01343 ignorecomments (in);
01344 }
01345 return in;
01346 }
01347
01349 template <class domelement, class imgelement>
01350 inline std::istream &readselective (std::istream &in,
01351 mvmap<domelement,imgelement> &m, const hashedset<domelement> &dom)
01352 {
01353 hashedset<domelement> empty;
01354 return readselective (in, m, dom, empty);
01355 }
01356
01357
01358
01359
01364 template <class domelement, class imgelement>
01365 std::ostream &operator << (std::ostream &out,
01366 const mvmap<domelement,imgelement> &m)
01367 {
01368 int_t n = m. getdomain (). size ();
01369 for (int_t i = 0; i < n; ++ i)
01370 {
01371 out << m. get (i) << " -> ";
01372 write (out, m (i), SMALL_SIZE) << '\n';
01373 }
01374 return out;
01375 }
01376
01378 template <class domelement, class imgelement>
01379 std::istream &operator >> (std::istream &in, mvmap<domelement,imgelement> &m)
01380 {
01381 ignorecomments (in);
01382 while (in. peek () != EOF)
01383 {
01384 domelement e;
01385 in >> e;
01386
01387
01388
01389
01390 ignorecomments (in);
01391 while (in. peek () == '-')
01392 in. get ();
01393 if (in. peek () == '>')
01394 in. get ();
01395
01396 ignorecomments (in);
01397 read (in, m [e], SMALL_SIZE);
01398
01399 ignorecomments (in);
01400 }
01401 return in;
01402 }
01403
01404
01405 }
01406 }
01407
01408 #endif // _CHOMP_STRUCT_HASHSETS_H_
01409
01411