The Original CHomP Software
hashsets.h
Go to the documentation of this file.
1
3
19
20// Copyright (C) 1997-2020 by Pawel Pilarczyk.
21//
22// This file is part of my research software package. This is free software:
23// you can redistribute it and/or modify it under the terms of the GNU
24// General Public License as published by the Free Software Foundation,
25// either version 3 of the License, or (at your option) any later version.
26//
27// This software is distributed in the hope that it will be useful,
28// but WITHOUT ANY WARRANTY; without even the implied warranty of
29// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30// GNU General Public License for more details.
31//
32// You should have received a copy of the GNU General Public License
33// along with this software; see the file "license.txt". If not,
34// please, see <https://www.gnu.org/licenses/>.
35
36// Started in January 2002. Last revision: October 24, 2013.
37
38
39#ifndef _CHOMP_STRUCT_HASHSETS_H_
40#define _CHOMP_STRUCT_HASHSETS_H_
41
42#include "chomp/system/config.h"
46
47#include <cstdlib>
48#include <ctime>
49#include <iostream>
50#include <algorithm>
51
52// make the chomp::homology hashkey methods global ones
53//using chomp::homology::hashkey1;
54//using chomp::homology::hashkey2;
55
56namespace chomp {
57namespace homology {
58
59// import the global hashkey functions to the chomp::homology namespace
62
63// class templates defined within this header file (in this order):
64template <class element, class hashing>
65class hashedset;
66template <class domelement, class imgelement>
67class mvmap;
68
69
70// --------------------------------------------------
71// ------------------- hash stat --------------------
72// --------------------------------------------------
73
77{
78public:
80 hashstat ();
81
83 std::time_t creationtime;
84
87 unsigned long hashhits;
88
91 unsigned long hashmisses;
92
95 unsigned long rehashcount;
96
97}; /* class hashstat */
98
99// --------------------------------------------------
100
102{
103 std::time (&creationtime);
104 hashhits = 0;
105 hashmisses = 0;
106 rehashcount = 0;
107 return;
108} /* hashstat::hashstat */
109
110// --------------------------------------------------
111
114inline std::ostream &operator << (std::ostream &out, const hashstat &s)
115{
116 if (!s. hashhits)
117 return out;
118 out << "hashing: " << s. hashhits << " hits, avg " <<
119 ((s. hashhits + s. hashmisses) / s. hashhits) << "." <<
120 ((s. hashhits + s. hashmisses) * 10 / s. hashhits) % 10 <<
121 " attempts (" << s. rehashcount << " times rehashed)";
122 return out;
123} /* operator << */
124
125
126// --------------------------------------------------
127// ------------- basic hashing methods --------------
128// --------------------------------------------------
129
132template <class element>
134{
135public:
137 static int_t hashkey1 (const element &x)
138 {
139 return chomp::homology::hashkey1 (x);
140 }
141
143 static int_t hashkey2 (const element &x)
144 {
145 return chomp::homology::hashkey2 (x);
146 }
147
148}; /* class HashingGlobal */
149
150
153template <class element>
155{
156public:
158 static int_t hashkey1 (const element &x)
159 {
160 return x. hashkey1 ();
161 }
162
164 static int_t hashkey2 (const element &x)
165 {
166 return x. hashkey2 ();
167 }
168
169}; /* class HashingMember */
170
171
172// --------------------------------------------------
173// ------------------- hashed set -------------------
174// --------------------------------------------------
175
183template <class element, class hashkeys = HashingGlobal<element> >
185{
186public:
188 typedef element value_type;
189
191 typedef hashkeys hashing_method;
192
196 explicit hashedset (int_t initialsize = 0, int bequiet = 1);
197
200
203
206
209 int_t getnumber (const element &e) const;
210
215 bool checknum (int_t n) const;
216
219 bool check (const element &e) const;
220
222 const element &operator [] (int_t n) const;
223
225 const element &get (int_t n) const;
226
228 const element &front () const;
229
231 const element &top () const;
232
236 int_t add (const element &e);
237
239 int_t push (const element &e);
240
242 int_t push_back (const element &e);
243
246 int remove (const element &e);
247
251
255
259
263
265 int_t size () const;
266
268 bool empty () const;
269
272
276
281
286
287private:
289 static const int_t InitHashSize;
290
292 static const int_t InitTabSize;
293
300
303
306
309
312
315
319
325 int_t hashfind (const element &e, int_t *addpos = NULL) const;
326
330 void rehash (int_t newsize = 0);
331
334 static bool numberisprime (const int_t &n);
335
338
339}; /* class hashedset */
340
341// --------------------------------------------------
342
343template <class element, class hashkeys>
345
346template <class element, class hashkeys>
348
349template <class element, class hashkeys>
351
352// --------------------------------------------------
353
354template <class element, class hashkeys>
356 nelem (0), tab ((initialsize > 0) ? initialsize :
357 int_t (InitTabSize)),
358 hashing (0),
359 hashsize (initialsize + (initialsize >> 2) + InitHashSize),
360 hashcleared (0), hashtable (hashsize)
361{
363 if (bequiet)
364 stat = NULL;
365 else
366 stat = new hashstat;
367 return;
368} /* hashedset<element,hashkeys>::hashedset */
369
370template <class element, class hashkeys>
372 nelem (s. nelem), tab (s. tab),
373 hashing (s. hashing), hashsize (s. hashsize),
374 hashcleared (s. hashcleared), hashtable (s. hashtable)
375{
376 if (s. stat)
377 stat = new hashstat;
378 else
379 stat = NULL;
380 return;
381} /* hashedset<element,hashkeys>::hashedset */
382
383template <class element, class hashkeys>
386{
387 if (this == &s)
388 return *this;
389
390 if (s. stat)
391 stat = new hashstat (*stat);
392 nelem = s. nelem;
393 tab = s. tab;
394 hashing = s. hashing;
395 hashsize = s. hashsize;
396 hashcleared = s. hashcleared;
397 hashtable = s. hashtable;
398
399 return *this;
400} /* multitable<element,hashkeys>::operator = */
401
402template <class element, class hashkeys>
404{
405 if (!stat)
406 return;
407 sout << " " << *stat << '\n';
408 delete stat;
409 stat = NULL;
410 return;
411} /* hashedset<element,hashkeys>::~hashedset */
412
413template <class element, class hashkeys>
415{
416 if (hashing)
417 {
418 int_t pos = hashfind (e);
419 return (hashtable (pos));
420 }
421 else
422 {
423 for (int_t i = 0; i < nelem; ++ i)
424 {
425 if (tab (i) == e)
426 return i;
427 }
428 return -1;
429 }
430} /* hashedset<element,hashkeys>::getnumber */
431
432template <class element, class hashkeys>
434{
435 return ((n >= 0) && (n < nelem));
436} /* hashedset<element,hashkeys>::checknum */
437
438template <class element, class hashkeys>
439inline bool hashedset<element,hashkeys>::check (const element &e) const
440{
441 return (getnumber (e) >= 0);
442} /* hashedset<element,hashkeys>::check */
443
444template <class element, class hashkeys>
445inline const element &hashedset<element,hashkeys>::get (int_t n) const
446{
447 if ((n < 0) || (n >= nelem))
448 throw "Trying to get an element out of range.";
449 return tab (n);
450} /* hashedset<element,hashkeys>::get */
451
452template <class element, class hashkeys>
454{
455 return get (n);
456} /* hashedset<element,hashkeys>::operator [] */
457
458template <class element, class hashkeys>
459inline const element &hashedset<element,hashkeys>::front () const
460{
461 return get (nelem - 1);
462} /* hashedset<element,hashkeys>::front */
463
464template <class element, class hashkeys>
465inline const element &hashedset<element,hashkeys>::top () const
466{
467 return get (nelem - 1);
468} /* hashedset<element,hashkeys>::top */
469
470template <class element, class hashkeys>
472{
473 if (!hashing)
474 {
475 for (int_t i = 0; i < nelem; ++ i)
476 {
477 if (tab (i) == e)
478 return i;
479 }
480 tab [nelem ++] = e;
481 if (nelem >= StartHashingSize)
482 {
483 hashing = 1;
484 rehash ();
485 }
486 return (nelem - 1);
487 }
488
489 // rehash if there is very little free space in the hashing table
490 if (hashsize - hashcleared < nelem + (nelem >> 1) + 19)
491 rehash ();
492
493 // find the position of the element's number in the hashing table
494 int_t addpos = -1;
495 int_t pos = hashfind (e, &addpos);
496
497 // if it alread was in the set, then just return its number
498 if (hashtable (pos) >= 0)
499 return hashtable (pos);
500
501 // add this element to the set and return its new number
502 if (addpos >= 0)
503 pos = addpos;
504 hashtable [pos] = nelem;
505 tab [nelem] = e;
506 return nelem ++;
507} /* hashedset<element,hashkeys>::add */
508
509template <class element, class hashkeys>
511{
512 return add (e);
513} /* hashedset<element,hashkeys>::push */
514
515template <class element, class hashkeys>
517{
518 return add (e);
519} /* hashedset<element,hashkeys>::push_back */
520
521template <class element, class hashkeys>
523{
524 if (!hashing)
525 {
526 for (int_t i = 0; i < nelem; ++ i)
527 {
528 if (tab (i) == e)
529 {
530 tab [i] = tab (-- nelem);
531 return 0;
532 }
533 }
534 return -1;
535 }
536
537 // find the position in the hashing table with this element's number
538 int_t pos = hashfind (e);
539
540 // if it was not there, then finish
541 if (hashtable (pos) < 0)
542 return -1;
543 int_t n = hashtable (pos);
544
545 // update the hashing table and the number of elements in the set
546 hashtable [pos] = -2;
547 -- nelem;
548 ++ hashcleared;
549
550 // if it was not the last element in the set, move the last one
551 // to the vacated place
552 if (n != nelem)
553 {
554 pos = hashfind (tab (nelem));
555 hashtable [pos] = n;
556 tab [n] = tab (nelem);
557 }
558
559 // if there are very few elements in the table, turn off hashing
560 if (nelem < StartHashingSize / 2)
561 {
562 hashing = 0;
563 }
564
565 // if there are very many cleared entries, then rehash
566 else if (hashcleared > nelem + 19)
567 rehash ();
568
569 return 0;
570} /* hashedset<element,hashkeys>::remove */
571
572template <class element, class hashkeys>
574{
575 if ((n < 0) || (n >= nelem))
576 return -1;
577 if (!hashing)
578 {
579 -- nelem;
580 if (n != nelem)
581 tab [n] = tab (nelem);
582 return 0;
583 }
584 return remove (tab (n));
585} /* hashedset<element,hashkeys>::removenum */
586
587template <class element, class hashkeys>
589{
590 if (!nelem)
591 throw "Trying to remove an element from an empty set.";
592 return removenum (nelem - 1);
593} /* hashedset<element,hashkeys>::pop */
594
595template <class element, class hashkeys>
597{
598 int_t n = s. size ();
599 for (int_t i = 0; i < n; ++ i)
600 add (s [i]);
601 return *this;
602} /* hashedset<element,hashkeys>::add */
603
604template <class element, class hashkeys>
606{
607 if (this -> size () < s. size ())
608 {
609 for (int_t i = 0; i < this -> size (); ++ i)
610 {
611 if (s. check ((*this) [i]))
612 this -> removenum (i --);
613 }
614 }
615 else
616 {
617 int_t n = s. size ();
618 for (int_t i = 0; i < n; ++ i)
619 remove (s [i]);
620 }
621 return *this;
622} /* hashedset<element,hashkeys>::remove */
623
624template <class element, class hashkeys>
626{
627 return !nelem;
628} /* hashedset<element,hashkeys>::empty */
629
630template <class element, class hashkeys>
632{
633 return nelem;
634} /* hashedset<element,hashkeys>::size */
635
636template <class element, class hashkeys>
638{
639 std::swap (stat, other. stat);
640 std::swap (nelem, other. nelem);
641 tab. swap (other. tab);
642 std::swap (hashing, other. hashing);
643 std::swap (hashsize, other. hashsize);
644 std::swap (hashcleared, other. hashcleared);
645 hashtable. swap (other. hashtable);
646 return;
647} /* hashedset<element,hashkeys>::swap */
648
649template <class element, class hashkeys>
651 (const hashedset<element,hashkeys> &other) const
652{
653 if (this -> nelem != other. nelem)
654 return false;
655 for (int_t i = 0; i < nelem; ++ i)
656 {
657 if (!other. check (this -> tab [i]))
658 return false;
659 }
660 return true;
661} /* hashedset<element,hashkeys>::swap */
662
663template <class element, class hashkeys>
666{
667 int_t size1 = s1. size ();
668 int_t size2 = s2. size ();
669
670 if (size1 <= size2)
671 {
672 for (int_t i = 0; i < size1; ++ i)
673 {
674 const element &elem = s1. tab [i];
675 if (s2. check (elem))
676 this -> add (elem);
677 }
678 }
679 else
680 {
681 for (int_t i = 0; i < size2; ++ i)
682 {
683 const element &elem = s2. tab [i];
684 if (s1. check (elem))
685 this -> add (elem);
686 }
687 }
688 return;
689} /* hashedset<element,hashkeys>::intersection */
690
691template <class element, class hashkeys>
692int_t hashedset<element,hashkeys>::hashfind (const element &e, int_t *addpos) const
693{
694 if (!hashing)
695 throw "Hashing is turned off.";
696
697 int_t key = hashkey1 (e);
698 if (key < 0)
699 key = -(key + 1);
700 int_t pos = key % hashsize;
701 if (addpos)
702 *addpos = -1;
703
704 // start updating hashing statistics
705 if (stat)
706 ++ (stat -> hashhits);
707
708 // find the position of the element in the hashing table
709 int_t number;
710 int_t add = 0;
711 while ((number = hashtable (pos)) != -1)
712 {
713 if ((number >= 0) && (e == tab (number)))
714 return (pos);
715 if (addpos && (*addpos < 0) && (number == -2))
716 *addpos = pos;
717 if (!add)
718 {
719 int_t key = hashkey2 (e);
720 if (key < 0)
721 key = -(key + 1);
722 add = key % (hashsize - 1) + 1;
723 }
724 pos += add;
725 if (pos >= hashsize)
726 pos -= hashsize;
727 if (stat)
728 ++ (stat -> hashmisses);
729 }
730
731 // return the position located in the hashing table
732 return (pos);
733
734} /* hashedset<element,hashkeys>::hashfind */
735
736template <class element, class hashkeys>
738{
739 if (stat)
740 ++ (stat -> rehashcount);
741
742 // adjust the new size of the hashing table
743 if ((newsize < (nelem << 1) + InitHashSize) ||
744 (newsize > (nelem << 2) + InitHashSize))
745 newsize = (nelem << 1) + nelem + InitHashSize;
746
747 // DEBUG
748// sbug << "(rehash: nelem=" << nelem <<
749// ", hashsize=" << hashsize << ", newsize=" << newsize << ")\n";
750
751 // check if it is not too large for 16-bit programs
752 int_t x = 0xFFFF;
753 if ((x < 0) && (newsize >= 16384))
754 throw "Set too large for this 16-bit program.";
755
756 // free unused memory if desired
757 if (newsize < hashsize)
758 {
759 multitable<int_t> empty;
760 hashtable = empty;
761 }
762
763 // set the new value of the hashing table and re-buid it
765 hashcleared = 0;
766
767 // build the entire hash table from the beginning
768 hashtable. fill (-1, hashsize);
769 for (int_t i = 0; i < nelem; ++ i)
770 {
771 int_t pos = hashfind (tab (i));
772 if (hashtable (pos) != -1)
773 throw "A repeated element in a set!";
774 hashtable [pos] = i;
775 }
776
777 return;
778} /* hashedset<element,hashkeys>::rehash */
779
780template <class element, class hashkeys>
782{
783 if (n < 2)
784 return 0;
785
786 int_t i = 2;
787 while (i * i <= n)
788 {
789 if (!(n % i))
790 return false;
791 ++ i;
792 }
793
794 return true;
795} /* hashedset<element,hashkeys>::numberisprime */
796
797template <class element, class hashkeys>
799{
801 ++ n;
802
803 return n;
804} /* hashedset<element,hashkeys>::rounduptoprime */
805
806
807// --------------------------------------------------
808
813#define SMALL_SIZE true
814
820#define LARGE_SIZE false
821
825template <class stream, class element, class hashkeys>
826stream &write (stream &out, const hashedset<element,hashkeys> &s, bool size)
827{
828 if (size == SMALL_SIZE)
829 {
830 out << '{';
831 int_t n = s. size ();
832 for (int_t i = 0; i < n; ++ i)
833 out << (i ? " " : "") << s [i];
834 out << '}';
835 }
836 else
837 {
838 int_t n = s. size ();
839 if (!s. empty ())
840 {
841 out << "; " << n << ((n == 1) ? " element." :
842 " elements.") << '\n';
843 }
844 if (s. stat && s. stat -> hashhits)
845 out << ';' << *(s. stat) << '\n';
846 for (int_t i = 0; i < n; ++ i)
847 out << s [i] << '\n';
848 }
849 return out;
850} /* write */
851
854template <class element, class hashkeys>
855std::ostream &operator << (std::ostream &out,
857{
858 return write (out, s, LARGE_SIZE);
859} /* operator << */
860
863template <class stream, class element, class hashkeys>
864stream &read (stream &in, hashedset<element,hashkeys> &s, bool size)
865{
866 // ignore all the comments at the beginning of the input stream
867 ignorecomments (in);
868
869 // determine the closing parenthesis
870 // and read the opening one if applicable
871 int closing = EOF;
872 if (size == SMALL_SIZE)
873 {
874 closing = readparenthesis (in);
875 if (closing == EOF)
876 throw "An opening parenthesis expected in a set.";
877 ignorecomments (in);
878 }
879
880 // read the elements until the closing parenthesis is found
881 while (in. peek () != closing)
882 {
883 element e;
884 in >> e;
885 // if (!in)
886 // throw "Failed to read an element of a set.";
887 s. add (e);
888 ignorecomments (in);
889
890 // read a comma between the elements if it is there
891 if (in. peek () == ',')
892 {
893 in. get ();
894 ignorecomments (in);
895 }
896 }
897
898 // read the closing parenthesis if any
899 if (closing != EOF)
900 in. get ();
901
902 return in;
903} /* read */
904
907template <class element, class hashkeys>
908std::istream &operator >> (std::istream &in, hashedset<element,hashkeys> &s)
909{
910 return read (in, s, LARGE_SIZE);
911} /* operator >> */
912
914template <class element, class hashkeys>
917{
918 s. add (u);
919 return s;
920} /* operator += */
921
923template <class element, class hashkeys>
926{
927 s. remove (u);
928 return s;
929} /* operator -= */
930
931
932// --------------------------------------------------
933// ---------------- multivalued map -----------------
934// --------------------------------------------------
935
943template <class domelement, class imgelement>
944class mvmap
945{
946public:
951 explicit mvmap (int bequiet = 1);
952
955
957 const domelement &get (int_t n) const;
958
961
965
968 const hashedset<imgelement> &operator ()
969 (const domelement &x) const;
970
973
977 hashedset<imgelement> &operator [] (const domelement &x);
978
980 int_t size () const;
981
984 bool remove (const domelement &x);
985
987 bool removenum (int_t n);
988
991
994
998 int quiet;
999
1000private:
1003
1007
1008}; /* class mvmap */
1009
1010// --------------------------------------------------
1011
1012template <class domelement, class imgelement>
1014 domain (0, bequiet), images ()
1015{
1016 return;
1017} /* mvmap::mvmap */
1018
1019template <class domelement, class imgelement>
1021{
1022 return;
1023} /* mvmap::~mvmap */
1024
1025template <class domelement, class imgelement>
1026inline const domelement &mvmap<domelement,imgelement>::get (int_t n) const
1027{
1028 if ((n < 0) || (n >= domain. size ()))
1029 throw "Domain element number out of range.";
1030 return domain [n];
1031} /* mvmap::get */
1032
1033template <class domelement, class imgelement>
1034inline const hashedset<domelement> &
1036{
1037 return domain;
1038} /* mvmap::getdomain */
1039
1040template <class domelement, class imgelement>
1041inline const hashedset<imgelement>
1043{
1044 if ((n < 0) || (n >= domain. size ()))
1045 throw "Domain element number out of range.";
1046 return images (n);
1047} /* mvmap::operator () */
1048
1049template <class domelement, class imgelement>
1050inline const hashedset<imgelement>
1052 (const domelement &q) const
1053{
1054 int_t n = domain. getnumber (q);
1055 if (n < 0)
1056 throw "Element not in the domain.";
1057 return images (n);
1058} /* mvmap::operator () */
1059
1060template <class domelement, class imgelement>
1063{
1064 if ((n < 0) || (n >= domain. size ()))
1065 throw "Domain element number out of range.";
1066 return images [n];
1067} /* mvmap::operator [] */
1068
1069template <class domelement, class imgelement>
1072 (const domelement &q)
1073{
1074 int_t n = domain. add (q);
1075 return images [n];
1076} /* mvmap::operator [] */
1077
1078template <class domelement, class imgelement>
1080{
1081 return domain. size ();
1082} /* mvmap::size */
1083
1084template <class domelement, class imgelement>
1086// WARNING: This procedure uses the specific way elements are removed from
1087// a hashed set. If that way is changed, this procedure may not work anymore.
1088{
1089 if ((n < 0) || (n >= domain. size ()))
1090 return false;
1091 domain. removenum (n);
1092 if (n != domain. size ())
1093 images [n] = images [domain. size ()];
1095 images [domain. size ()] = empty;
1096 return true;
1097} /* mvmap::removenum */
1098
1099template <class domelement, class imgelement>
1100inline bool mvmap<domelement,imgelement>::remove (const domelement &x)
1101{
1102 return removenum (domain. getnumber (x));
1103} /* mvmap::remove */
1104
1105template <class domelement, class imgelement>
1107 (const hashedset<domelement> &x)
1108{
1109 int_t n = x. size ();
1110 for (int_t i = 0; i < n; ++ i)
1111 remove (x [i]);
1112 return;
1113} /* mvmap::remove */
1114
1115template <class domelement, class imgelement>
1118{
1119 domain. swap (other. domain);
1120 images. swap (other. images);
1121 return;
1122} /* mvmap::swap */
1123
1124// --------------------------------------------------
1125
1127template <class domelement, class imgelement>
1130{
1131 int_t n = m. getdomain (). size ();
1132 for (int_t i = 0; i < n; ++ i)
1133 img. add (m (i));
1134 return img;
1135} /* retrieveimage */
1136
1140template <class domelement, class imgelement>
1142 hashedset<imgelement> &graph)
1143{
1144 for (int_t i = 0; i < m. getdomain (). size (); ++ i)
1145 {
1146 const domelement &e = m. get (i);
1147 const hashedset<imgelement> &f = m (i);
1148 int_t n = f. size ();
1149 for (int_t j = 0; j < n; ++ j)
1150 graph. add (e * f [j]);
1151 }
1152 return graph;
1153} /* creategraph */
1154
1155// --------------------------------------------------
1156
1158template <class domelement, class imgelement>
1159std::istream &readdomain (std::istream &in, hashedset<domelement> &dom,
1161{
1162 ignorecomments (in);
1163 while (in. peek () != EOF)
1164 {
1165 domelement e;
1166 in >> e;
1167 // if (!in)
1168 // throw "Failed to read a domain element of a map.";
1169 dom. add (e);
1170
1171 // read the map's arrow
1172 ignorecomments (in);
1173 while (in. peek () == '-')
1174 in. get ();
1175 if (in. peek () == '>')
1176 in. get ();
1177
1178 ignorecomments (in);
1179 int closing = readparenthesis (in);
1180
1181 ignorecomments (in);
1182 while (in. peek () != closing)
1183 {
1184 imgelement junk;
1185 in >> junk;
1186 // if (!in)
1187 // throw "Failed to read an image element.";
1188 ignorecomments (in);
1189 if (in. peek () == ',')
1190 {
1191 in. get ();
1192 ignorecomments (in);
1193 }
1194 }
1195
1196 if (closing != EOF)
1197 in. get ();
1198 ignorecomments (in);
1199 }
1200 return in;
1201} /* readdomain */
1202
1204template <class domelement, class imgelement>
1205std::istream &readimage (std::istream &in, hashedset<imgelement> &img,
1207{
1208 ignorecomments (in);
1209 while (in. peek () != EOF)
1210 {
1211 domelement e;
1212 in >> e;
1213 // if (!in)
1214 // throw "Failed to read a domain element of a map.";
1215
1216 // read the map's arrow
1217 ignorecomments (in);
1218 while (in. peek () == '-')
1219 in. get ();
1220 if (in. peek () == '>')
1221 in. get ();
1222
1223 ignorecomments (in);
1224 read (in, img, SMALL_SIZE);
1225
1226 ignorecomments (in);
1227 }
1228 return in;
1229} /* readimage */
1230
1232template <class domelement, class imgelement>
1233std::istream &readselective (std::istream &in, mvmap<domelement,imgelement> &m,
1234 const hashedset<domelement> &dom1, const hashedset<domelement> &dom2)
1235{
1236 if (dom1. empty () && dom2. empty ())
1237 {
1238 sout << "Warning: The domain of the map is empty.\n";
1239 return in;
1240 }
1241
1242 ignorecomments (in);
1243 while (in. peek () != EOF)
1244 {
1245 domelement e;
1246 in >> e;
1247 // if (!in)
1248 // throw "Failed to read a domain element of a map.";
1249
1250 // read the map's arrow
1251 ignorecomments (in);
1252 while (in. peek () == '-')
1253 in. get ();
1254 if (in. peek () == '>')
1255 in. get ();
1256
1257 ignorecomments (in);
1258 if (dom1. check (e) || dom2. check (e))
1259 read (in, m [e], SMALL_SIZE);
1260 else
1261 {
1262 int closing = readparenthesis (in);
1263
1264 ignorecomments (in);
1265 while (in. peek () != closing)
1266 {
1267 imgelement junk;
1268 in >> junk;
1269 // if (!in)
1270 // throw "Failed to read an img elem.";
1271 ignorecomments (in);
1272 if (in. peek () == ',')
1273 {
1274 in. get ();
1275 ignorecomments (in);
1276 }
1277 }
1278
1279 if (closing != EOF)
1280 in. get ();
1281 }
1282 ignorecomments (in);
1283 }
1284 return in;
1285} /* readselective */
1286
1288template <class domelement, class imgelement>
1289std::istream &readrestriction (std::istream &in,
1291 const hashedset<imgelement> &img)
1292{
1293 if (dom. empty ())
1294 {
1295 sout << "Warning: The domain of the map is empty.\n";
1296 return in;
1297 }
1298
1299 ignorecomments (in);
1300 while (in. peek () != EOF)
1301 {
1302 domelement e;
1303 in >> e;
1304 // if (!in)
1305 // throw "Failed to read a domain element of a map.";
1306
1307 // read the map's arrow
1308 ignorecomments (in);
1309 while (in. peek () == '-')
1310 in. get ();
1311 if (in. peek () == '>')
1312 in. get ();
1313
1314 ignorecomments (in);
1315 if (dom. check (e))
1316 {
1317 hashedset<imgelement> &y = m [e];
1319 read (in, x, SMALL_SIZE);
1320 int_t n = x. size ();
1321 for (int_t i = 0; i < n; ++ i)
1322 {
1323 if (img. check (x [i]))
1324 y. add (x [i]);
1325 }
1326 }
1327 else
1328 {
1329 int closing = readparenthesis (in);
1330
1331 ignorecomments (in);
1332 while (in. peek () != closing)
1333 {
1334 imgelement junk;
1335 in >> junk;
1336 // if (!in)
1337 // throw "Failed to read an img elem.";
1338 ignorecomments (in);
1339 if (in. peek () == ',')
1340 {
1341 in. get ();
1342 ignorecomments (in);
1343 }
1344 }
1345
1346 if (closing != EOF)
1347 in. get ();
1348 }
1349 ignorecomments (in);
1350 }
1351 return in;
1352} /* readrestriction */
1353
1355template <class domelement, class imgelement>
1356inline std::istream &readselective (std::istream &in,
1358{
1360 return readselective (in, m, dom, empty);
1361} /* readselective */
1362
1363
1364// --------------------------------------------------
1365
1370template <class domelement, class imgelement>
1371std::ostream &operator << (std::ostream &out,
1373{
1374 int_t n = m. getdomain (). size ();
1375 for (int_t i = 0; i < n; ++ i)
1376 {
1377 out << m. get (i) << " -> ";
1378 write (out, m (i), SMALL_SIZE) << '\n';
1379 }
1380 return out;
1381} /* operator << */
1382
1384template <class domelement, class imgelement>
1385std::istream &operator >> (std::istream &in, mvmap<domelement,imgelement> &m)
1386{
1387 ignorecomments (in);
1388 while (in. peek () != EOF)
1389 {
1390 domelement e;
1391 in >> e;
1392 // if (!in)
1393 // throw "Failed to read a domain element of a map.";
1394
1395 // read the map's arrow
1396 ignorecomments (in);
1397 while (in. peek () == '-')
1398 in. get ();
1399 if (in. peek () == '>')
1400 in. get ();
1401
1402 ignorecomments (in);
1403 read (in, m [e], SMALL_SIZE);
1404
1405 ignorecomments (in);
1406 }
1407 return in;
1408} /* operator >> */
1409
1410
1411} // namespace homology
1412} // namespace chomp
1413
1414#endif // _CHOMP_STRUCT_HASHSETS_H_
1415
1417
A hashing method using globally defined functions that calculate the two required hashing keys.
Definition: hashsets.h:134
static int_t hashkey2(const element &x)
Returns the second hashing key of the element.
Definition: hashsets.h:143
static int_t hashkey1(const element &x)
Returns the first hashing key of the element.
Definition: hashsets.h:137
A hashing method using member functions that calculate the two required hashing keys.
Definition: hashsets.h:155
static int_t hashkey1(const element &x)
Returns the first hashing key of the element.
Definition: hashsets.h:158
static int_t hashkey2(const element &x)
Returns the second hashing key of the element.
Definition: hashsets.h:164
This is a template for a set of objects of the given type.
Definition: hashsets.h:185
bool operator==(const hashedset< element, hashkeys > &other) const
Verifies whether two hashed sets have the same elements.
Definition: hashsets.h:651
bool checknum(int_t n) const
Checks if the given number is an index of some element in the set, that is, if the number is non-nega...
Definition: hashsets.h:433
const element & get(int_t n) const
Returns the element with the given number from the set.
Definition: hashsets.h:445
hashkeys hashing_method
The type of hashing.
Definition: hashsets.h:191
hashedset(int_t initialsize=0, int bequiet=1)
The default constructor for creating an empty set of objects.
Definition: hashsets.h:355
const element & front() const
Returns the last element in the set.
Definition: hashsets.h:459
int_t nelem
The number of elements stored in the set.
Definition: hashsets.h:302
int hashing
Is the hashing table in use?
Definition: hashsets.h:308
static const int_t StartHashingSize
The minimal number of elements above which hashing table is actually used.
Definition: hashsets.h:299
void rehash(int_t newsize=0)
Replace the old hashing table with a new one.
Definition: hashsets.h:737
void intersection(const hashedset< element, hashkeys > &s1, const hashedset< element, hashkeys > &s2)
Computes the intersection of two hashed sets and adds the result to the current set.
Definition: hashsets.h:664
int removenum(int_t n)
Returns an element with the given number from the set.
Definition: hashsets.h:573
static const int_t InitTabSize
The initial size of a table in a hashed set.
Definition: hashsets.h:292
int_t hashfind(const element &e, int_t *addpos=NULL) const
Finds the position in the hashing table at which the number of the given element should be.
Definition: hashsets.h:692
int remove(const element &e)
Removes the given element from the set.
Definition: hashsets.h:522
bool empty() const
Returns true if the set is empty. Otherwise returns false.
Definition: hashsets.h:625
hashedset & operator=(const hashedset< element, hashkeys > &s)
The assignment operator.
Definition: hashsets.h:385
static int_t rounduptoprime(int_t n)
Rounds up the given number to a prime number.
Definition: hashsets.h:798
element value_type
The type of elements stored in the set.
Definition: hashsets.h:188
void swap(hashedset< element, hashkeys > &other)
Swaps two hashed sets by swapping their internal data.
Definition: hashsets.h:637
multitable< element > tab
The table of these elements.
Definition: hashsets.h:305
multitable< int_t > hashtable
The hashing table.
Definition: hashsets.h:318
hashedset(const hashedset< element, hashkeys > &s)
The copy constructor.
Definition: hashsets.h:371
static bool numberisprime(const int_t &n)
Verifies whether the given number is prime or not.
Definition: hashsets.h:781
hashstat * stat
Hashed set statistics.
Definition: hashsets.h:285
static const int_t InitHashSize
The default initial size of a hashing table.
Definition: hashsets.h:289
hashedset< element, hashkeys > & remove(const hashedset< element, hashkeys > &s)
Removes an entire set of elements from the set.
Definition: hashsets.h:605
int_t hashcleared
The number of cleared entries in the hashing table.
Definition: hashsets.h:314
int_t push_back(const element &e)
Adds an element to the set (this is an equivalent of 'add').
Definition: hashsets.h:516
const element & operator[](int_t n) const
Returns the element with the given number from the set.
Definition: hashsets.h:453
int_t pop()
Removes the last element from the set.
Definition: hashsets.h:588
hashedset< element, hashkeys > & add(const hashedset< element, hashkeys > &s)
Adds an entire set of elements to the set.
Definition: hashsets.h:596
int_t hashsize
The size of the hashing table.
Definition: hashsets.h:311
int_t push(const element &e)
Adds an element to the set (this is an equivalent of 'add').
Definition: hashsets.h:510
bool check(const element &e) const
Checks if the given element is in the set.
Definition: hashsets.h:439
int_t size() const
Returns the number of elements in the set.
Definition: hashsets.h:631
const element & top() const
Returns the last element in the set.
Definition: hashsets.h:465
int_t add(const element &e)
Adds the given element to the set and returns its number.
Definition: hashsets.h:471
int_t getnumber(const element &e) const
Finds the given element and returns its number.
Definition: hashsets.h:414
~hashedset(void)
The destructor.
Definition: hashsets.h:403
This is a small class used to gather and display hashing statistics for the hashing tables in the cla...
Definition: hashsets.h:77
unsigned long hashhits
The number of times that an element was found in the hashing table.
Definition: hashsets.h:87
unsigned long hashmisses
The number of times that an element was not found in the hashing table, because that entry was used f...
Definition: hashsets.h:91
std::time_t creationtime
The creation time of the hashed set.
Definition: hashsets.h:83
hashstat()
The constructor.
Definition: hashsets.h:101
unsigned long rehashcount
The number of rehashing the table when the size of the hashing table was changed and all the elements...
Definition: hashsets.h:95
A container for elements placed in a table (like a vector) that is actually built of many smaller tab...
Definition: multitab.h:65
This class defines a multivalued map.
Definition: hashsets.h:945
const hashedset< imgelement > & operator()(int_t n) const
Retrieve the image of the n-th element for reading only.
Definition: hashsets.h:1042
hashedset< domelement > domain
The domain of the map.
Definition: hashsets.h:1002
void swap(mvmap< domelement, imgelement > &other)
Swaps the internal data of two multivalued maps.
Definition: hashsets.h:1117
bool removenum(int_t n)
Removes the n-th element from the domain of the map.
Definition: hashsets.h:1085
const domelement & get(int_t n) const
Retrieves the n-th element from the domain for reading only.
Definition: hashsets.h:1026
~mvmap()
The destructor.
Definition: hashsets.h:1020
const hashedset< domelement > & getdomain() const
Retrieves the domain of the map for reading only.
Definition: hashsets.h:1035
multitable< hashedset< imgelement > > images
The images of cubes from the domain.
Definition: hashsets.h:1006
hashedset< imgelement > & operator[](int_t n)
Returns the image of the n-th element for writing.
Definition: hashsets.h:1062
mvmap(int bequiet=1)
The default constructor.
Definition: hashsets.h:1013
void remove(const hashedset< domelement > &x)
Removes a set of elements from the domain of the map.
Definition: hashsets.h:1107
int quiet
This variable indicates whether the map should be quiet.
Definition: hashsets.h:998
bool remove(const domelement &x)
Removes an element from the domain of the map.
Definition: hashsets.h:1100
int_t size() const
Returns the number of elements in the domain of the map.
Definition: hashsets.h:1079
This file contains some precompiler definitions which indicate the operating system and/or compiler u...
int int_t
Index type for indexing arrays, counting cubes, etc.
Definition: config.h:115
#define SMALL_SIZE
This constant passed to the function 'write' makes the hashed set be displayed in a way that is appro...
Definition: hashsets.h:813
#define LARGE_SIZE
This constant passed to the function 'write' makes the hashed set be displayed in a way that is appro...
Definition: hashsets.h:820
This file contains the definition of two hashing methods for integers.
This file contains the definition of the container "multitable" which is essentially an automatically...
std::istream & readrestriction(std::istream &in, mvmap< domelement, imgelement > &m, const hashedset< domelement > &dom, const hashedset< imgelement > &img)
Reads a restriction of a multivalued map to the two given sets.
Definition: hashsets.h:1289
hashedset< element, hashkeys > & operator-=(hashedset< element, hashkeys > &s, const hashedset< element, hashkeys > &u)
Operator -= removes the contents of one set from another.
Definition: hashsets.h:924
outputstream sout
A replacement for standard output stream, with optional logging and other features provided by the cl...
std::ostream & operator<<(std::ostream &out, const bincube< Dim, twoPower > &b)
Definition: bincube.h:907
int write(std::ostream &out, const coordtype *c, int dim, char parenthesis=40, char closing=0)
Definition: pointset.h:2148
int_t hashkey2(const hashNumber< Number > &n)
The second hashing key.
Definition: bincube.h:1036
int readparenthesis(std::istream &in)
Reads an opening parenthesis from the input file.
Definition: textfile.h:432
std::istream & readimage(std::istream &in, hashedset< tCube > &img)
Reads the image of a multivalued cubical map.
Definition: cubmaps.h:437
int read(textfile &f, coordtype *c, int maxdim)
Reads a point from a text file and removes a pair of parentheses, braces or brackets if present.
Definition: pointset.h:1994
std::istream & readselective(std::istream &in, const hashedset< tCube > &dom1, const hashedset< tCube > &dom2, mvmap< tCube, tCube > &m)
Reads the restriction of a multivalued map to the given pair of sets.
Definition: cubmaps.h:598
hashedset< imgelement > & retrieveimage(const mvmap< domelement, imgelement > &m, hashedset< imgelement > &img)
Adds images of all the elements from the domain of the map to 'img'.
Definition: hashsets.h:1128
std::istream & operator>>(std::istream &in, bincube< Dim, twoPower > &b)
Definition: bincube.h:914
int_t hashkey1(const hashNumber< Number > &n)
The first hashing key.
Definition: bincube.h:1029
void ignorecomments(std::istream &in)
Ignores white characters (spaces, tabulators, CRs and LFs), as well as comments from the input text f...
Definition: textfile.h:385
std::istream & readdomain(std::istream &in, hashedset< tCube > &dom)
Reads the domain of a multivalued cubical map.
Definition: cubmaps.h:406
hashedset< element, hashkeys > & operator+=(hashedset< element, hashkeys > &s, const hashedset< element, hashkeys > &u)
Operator += adds one hashed set to another.
Definition: hashsets.h:915
gcomplex< cell, euclidom > & creategraph(const mvmap< cell, cell > &m, gcomplex< cell, euclidom > &graph)
Add a graph of a multivalued cell map to the cell complex.
Definition: gcomplex.h:1429
void swap(mwWorkerData &data1, mwWorkerData &data2)
Definition: mwcoord.h:108
This namespace contains the entire CHomP library interface.
Definition: bitmaps.h:51
This file contains some useful functions related to the text input/output procedures.