The Original CHomP Software
pointset.h
Go to the documentation of this file.
1
3
25
26// Copyright (C) 1997-2020 by Pawel Pilarczyk.
27//
28// This file is part of my research software package. This is free software:
29// you can redistribute it and/or modify it under the terms of the GNU
30// General Public License as published by the Free Software Foundation,
31// either version 3 of the License, or (at your option) any later version.
32//
33// This software is distributed in the hope that it will be useful,
34// but WITHOUT ANY WARRANTY; without even the implied warranty of
35// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36// GNU General Public License for more details.
37//
38// You should have received a copy of the GNU General Public License
39// along with this software; see the file "license.txt". If not,
40// please, see <https://www.gnu.org/licenses/>.
41
42// Started in December 1997. Last revision: July 8, 2017.
43
44
45#ifndef _CHOMP_CUBES_POINTSET_H_
46#define _CHOMP_CUBES_POINTSET_H_
47
48#include "chomp/system/config.h"
50
51#include <iostream>
52#include <fstream>
53#include <ctime>
54#include <cstdlib>
55#include <cctype>
56#include <algorithm>
57
58namespace chomp {
59namespace homology {
60
61
63typedef short int coordinate;
64
65// a class for gathering hashing statistics in a set of points
66class psethashstat;
67
68// a template for a set of points with 'integer' coordinates
69template <class coordtype>
70class tPointset;
71
72// a template for a class used to list all the neighbors of a given point
73template <class coordtype>
74class tNeighbors;
75
76// a template for a class used to list all the points in a given scope
77template <class coordtype>
78class tRectangle;
79
82
85
88
89
90// --------------------------------------------------
91// ---------------- various functions ---------------
92// --------------------------------------------------
93// Various small or large functions used by
94// or manipulating with the class 'pointset'.
95
97template <class coordtype>
98inline int thesame (const coordtype *c1, const coordtype *c2, int dim)
99{
100 for (int i = 0; i < dim; ++ i)
101 if (c1 [i] != c2 [i])
102 return 0;
103 return 1;
104} /* thesame */
105
107template <class coordtype>
108inline void copycoord (coordtype *destination, const coordtype *source,
109 int dim)
110{
111 for (int i = 0; i < dim; ++ i)
112 destination [i] = source [i];
113 return;
114} /* copycoord */
115
118template <class coordtype>
119inline void wrapcoord (coordtype *destination, const coordtype *source,
120 const coordtype *wrap, int dim)
121{
122 if (!destination || !source)
123 throw "Trying to wrap NULL coordinates.";
124
125 for (int i = 0; i < dim; ++ i)
126 if (wrap [i])
127 {
128 destination [i] =
129 (coordtype) (source [i] % wrap [i]);
130 if (destination [i] < 0)
131 destination [i] += wrap [i];
132 }
133 else
134 destination [i] = source [i];
135
136 return;
137} /* wrapcoord */
138
141template <>
142inline void wrapcoord<double> (double *destination, const double *source,
143 const double *wrap, int dim)
144{
145 if (!destination || !source)
146 throw "Trying to wrap NULL coordinates.";
147
148 throw "Wrapping 'double' coordinates not implemented yet!";
149
150 return;
151} /* wrapcoord */
152
155inline bool numberisprime (unsigned n)
156{
157 if (n < 2)
158 return false;
159
160 unsigned i = 2;
161 while (i * i <= n)
162 if (!(n % i ++))
163 return false;
164
165 return true;
166} /* numberisprime */
167
170inline unsigned ceilprimenumber (unsigned n)
171{
172 while (!numberisprime (n))
173 ++ n;
174
175 return n;
176} /* prime number */
177
179template <class coordtype>
180int_t pointhashkey (const coordtype *c, int dim, int_t hashsize)
181{
182 int_t key = 13;
183 for (int i = 0; i < dim; ++ i)
184 {
185 key ^= static_cast<int_t> ((c [i] > 0) ? c [i] : -c [i]) <<
186 ((i << 3) % 19);
187 }
188 if (key < 0)
189 key = -(key + 1);
190
191 // return the key reduced to the given size
192 return (key % hashsize);
193
194} /* pointhashkey */
195
197template <class coordtype>
198int_t pointhashadd (const coordtype *c, int dim, int_t hashsize)
199{
200 int_t add = 1313;
201 for (int i = 0; i < dim; ++ i)
202 add ^= static_cast<int_t> ((c [i] > 0) ? c [i] : -c [i]) <<
203 (((i << 4) + 3) % 21);
204 if (add < 0)
205 add = -(add + 1);
206
207 // return the key reduced to the given size
208 return (add % (hashsize - 1) + 1);
209
210} /* pointhashadd */
211
213template <class coordtype>
214inline coordtype rounddown (double x)
215{
216 if ((x >= 0) || ((double) (coordtype) x == x))
217 return (coordtype) x;
218 else
219 return -(coordtype) (-x) - 1;
220} /* rounddown */
221
225template <class coordtype>
226inline void roundpoint (const double *p, coordtype *c, const double *grid,
227 int dim)
228{
229 if (grid)
230 {
231 for (int i = 0; i < dim; ++ i)
232 c [i] = rounddown<coordtype> (p [i] / grid [i]);
233 }
234 else
235 {
236 for (int i = 0; i < dim; ++ i)
237 c [i] = rounddown<coordtype> (p [i]);
238 }
239 return;
240} /* roundpoint */
241
244template <class coordtype>
245inline void cubemiddle (coordtype *c, double *p, double *grid, int dim)
246{
247 if (grid)
248 {
249 for (int i = 0; i < dim; ++ i)
250 p [i] = (c [i] + 0.5) * grid [i];
251 }
252 else
253 {
254 for (int i = 0; i < dim; ++ i)
255 p [i] = c [i] + 0.5;
256 }
257 return;
258} /* cubemiddle */
259
261template <class coordtype>
262inline coordtype *allocatepoint (int dim, char *errormessage = NULL)
263{
264 coordtype *temp = new coordtype [dim];
265 if (!temp)
266 {
267 throw (errormessage ? errormessage :
268 "Can't allocate memory for a temporary point.");
269 }
270 return temp;
271} /* allocatepoint */
272
273#define INSIDE 1
274#define OUTSIDE 0
275
281template <class coordtype>
282int countneighbors (const tPointset<coordtype> &p, const coordtype *c,
283 int which = INSIDE, int maxcount = 0);
284
286template <class coordtype>
288 const tPointset<coordtype> &q, const coordtype *c,
289 int which = INSIDE, int maxcount = 0);
290
292template <class coordtype>
293int attheborder (const tPointset<coordtype> &p, const coordtype *c);
294
299template <class coordtype>
301 int direction = 1);
302
304template <class coordtype>
306 tPointset<coordtype> &q, int_t n, int direction = 1);
307
309template <class coordtype>
311
314template <class coordtype>
316
319template <class coordtype>
320void enhancepoint (tPointset<coordtype> &p, coordtype *c);
321
324template <class coordtype>
326
329template <class coordtype>
331
332
338template <class coordtype>
339int read (textfile &f, coordtype *c, int maxdim);
340
346template <class coordtype>
347int read (std::istream &in, coordtype *c, int maxdim);
348
349// write a point to a text file; the coordinates are separated with commas,
350// and a pair of parentheses, braces or brackets is added (use 0 for none);
351// no end-of-line character is added after the point has been written
352template <class coordtype>
353int write (std::ostream &out, const coordtype *c, int dim,
354 char parenthesis = 40, char closing = 0);
355
356#define CELL 0
357#define CUBE 1
358
364template <class coordtype>
365int readcubeorcell (std::istream &in, coordtype *left, coordtype *right,
366 int maxdim, int *type = NULL);
367
368
371template <class coordtype>
372int_t read (textfile &f, tPointset<coordtype> &p,
373 int_t first = 0, int_t howmany = -1,
374 coordtype *wrap = NULL, int maxdim = 0, int quiet = 0,
375 tPointset<coordtype> *notthese = NULL);
376
379template <class coordtype>
380int_t read (std::istream &in, tPointset<coordtype> &p,
381 int_t first = 0, int_t howmany = -1,
382 coordtype *wrap = NULL, int maxdim = 0, int quiet = 0,
383 tPointset<coordtype> *notthese = NULL);
384
387template <class coordtype>
388int_t read (textfile &f, tPointset<coordtype> &p,
389 coordtype *wrap, int maxdim,
390 int quiet = 0, tPointset<coordtype> *notthese = NULL);
391
394template <class coordtype>
395int_t read (std::istream &in, tPointset<coordtype> &p,
396 coordtype *wrap, int maxdim,
397 int quiet = 0, tPointset<coordtype> *notthese = NULL);
398
400template <class coordtype>
401textfile &operator >> (textfile &f, tPointset<coordtype> &p);
402
404template <class coordtype>
405std::istream &operator >> (std::istream &in, tPointset<coordtype> &p);
406
410template <class coordtype>
411int_t write (std::ostream &out, tPointset<coordtype> &p,
412 int_t first = 0, int_t howmany = -1, int quiet = 0);
413
415template <class coordtype>
416std::ostream &operator << (std::ostream &out, tPointset<coordtype> &p);
417
418
419// --------------------------------------------------
420// ----------------- pset hash stat -----------------
421// --------------------------------------------------
422
426{
427public:
429 psethashstat ();
430
432 std::time_t creationtime;
433
436 unsigned long hashhits;
437
440 unsigned long hashmisses;
441
444 unsigned long rehashcount;
445
446}; /* class psethashstat */
447
448// --------------------------------------------------
449
451{
452 std::time (&creationtime);
453 hashhits = 0;
454 hashmisses = 0;
455 rehashcount = 0;
456 return;
457} /* psethashstat::psethashstat */
458
459// --------------------------------------------------
460
463inline std::ostream &operator << (std::ostream &out, const psethashstat &s)
464{
465 if (!s. hashhits)
466 return out;
467 out << "hashing: " << s. hashhits << " hits, avg " <<
468 ((s. hashhits + s. hashmisses) / s. hashhits) << "." <<
469 ((s. hashhits + s. hashmisses) * 10 / s. hashhits) % 10 <<
470 " attempts (" << s. rehashcount << " times rehashed)";
471 return out;
472} /* operator << */
473
474
475// --------------------------------------------------
476// -------------------- POINTSET --------------------
477// --------------------------------------------------
478
480template <class coordtype>
482{
483public:
485 typedef coordtype CoordType;
486
487 // CONSTRUCTORS AND DESTRUCTORS OF THE SET OF POINTS
488
496 tPointset (int_t initialsize = 0, int bequiet = 1);
497
500
503
505 ~tPointset ();
506
507
508 // METHODS FOR SETTING BASIC PROPERTIES OF THE SET OF POINTS
509
511 int dimension (int d);
512
514 int dimension () const;
515
517 static int defaultdimension (int d = 0);
518
520 double *gridsize (double *g = 0);
521
523 double *gridsize (double g);
524
526 double *gridsize (int direction, double g);
527
528 // get or set space wrapping;
529 // use '0' for no space wrapping in a particular direction
530 const coordtype *wrapspace (const coordtype *w = NULL);
531 // set space wrapping (if the same in all the directions)
532 const coordtype *wrapspace (coordtype w);
533 // set space wrapping in one particular direction
534 const coordtype *wrapspace (int direction, coordtype w);
535
536
537 // METHODS FOR ADDING, FINDING, CHECKING AND REMOVING POINTS
538
539 // Note: Real coordinates are rounded down with 'floor'.
540 // Integer coordinates are internally wrapped if needed.
541
542 // check if a point is in the set; return: 1 = Yes, 0 = No
543 int check (int_t n) const;
544 int check (const coordtype *c) const;
545 int checkRounded (const double *c) const;
546
547 // find a point in the set;
548 // return its number or -1 if not found
549 int_t getnumber (const coordtype *c) const;
550 int_t getnumberRounded (const double *c) const;
551
552 // get a pointer to the coordinates (stored in internal
553 // tables) of the point which has the number or the
554 // coordinates given; if the last case, fill in the coords
555 coordtype *operator [] (int_t n) const;
556 coordtype *getpoint (int_t n) const;
557 coordtype *getpoint (coordtype *c) const;
558 coordtype *getpointRounded (double *c) const;
559 coordtype *getpointMiddle (int_t n, double *c) const;
560
561 // add a point (if not in the set, yet); return its number
562 int_t add (const coordtype *c);
563 int_t addRounded (double *c);
564 // add an entire set
566
567 // remove the point with the given number or coordinates;
568 // return 0 if removed or -1 if does not belong to the set;
569 // warning: the order of the points in the set changes if
570 // a point other than the last one in the set is removed
571 int remove (int_t n);
572 int remove (const coordtype *c);
573 int removeRounded (const double *c);
574 // remove an entire set
575 int remove (const tPointset<coordtype> &p);
576
577
578 // OTHER
579
581 int_t size () const;
582
584 bool empty () const;
585
590// operator int () const;
591
592 // run quietly (or show many unnecessary messages otherwise)
593 int quiet;
594
595 // get the size of the hashing table (you may need this
596 // if you are curious about memory usage or so)
597 int_t gethashsize () const;
598
600 void swap (tPointset<coordtype> &other);
601
602 // OPTIONAL STATISTICS (entirely public for easy access)
603
604 // hash statistics
606
607 // point scope statistics
608 coordtype *minimal, *maximal;
609
610 // were there any points removed from the set?
611 // note: this variable is used only for generate an output
612 // warning and to modify statistics notice, that's why
613 // it may be public for instant access
615
616
617protected:
618
619 // INTERNAL DATA OF THE SET OF POINTS
620
621 // dimension of the points; '0' if not set yet
622 int dim;
623
624 // the number of points in the set
626
627 // the number of tables containing points' coordinates
629
630 // the number of points stored in a single table
632
633 // the table of tables for points' coordinates;
634 // note: some tables may not be allocated (these are NULLs)
635 coordtype **tables;
636
637 // the size of the grid in R^n (a pointer to a table)
638 double *grid;
639
640 // space wrapping
641 coordtype *wrap;
642
643 // a point for temporary usage while adding or checking:
644 // its coordinates are wrapped if needed
645 coordtype *temp;
646
647 // the default parameters used for new pointsets
648 static int defaultdim;
649 static double *defaultgrid;
650 static coordtype *defaultwrap;
651
652 // protected functions for initialization and deallocation
653 void initialize (int_t initialsize, int bequiet);
654 void deallocate ();
655
656
657 // HASHING
658
659 // the size of the hashing table
661
662 // the number of cleared entries in the hashing table
664
665 // hashing table (if any): -1 = free entry, -2 = cleared
667
668 // the expected number of points in the set (0 if unknown)
669 unsigned initsize;
670
671 // find an entry corresponding to the point in the hashing
672 // table; may fill in a position at which a new point should
673 // be added; 'wrapped' says if the coordinates have already
674 // been wrapped
675 int_t hashfindpoint (const coordtype *c,
676 int_t *addposition = NULL, int wrapped = 0) const;
677
678 // replace the old hashing table with a new one;
679 // a desired size may be given, otherwise an optimal size
680 // is determined and the new table is made bigger or smaller
681 void rehash (int_t newsize = 0);
682
683}; /* class tPointset */
684
685// --------------------------------------------------
686
687template <class coordtype>
689
690template <class coordtype>
692
693template <class coordtype>
694coordtype *tPointset<coordtype>::defaultwrap = NULL;
695
696// --------------------------------------------------
697
698template <class coordtype>
700{
701 // set the default dimension if needed
702 if (d > 0)
703 {
704 // remove the two tables if the new dimension is higher
705 if (d > defaultdim)
706 {
707 if (defaultgrid)
708 delete [] defaultgrid;
709 defaultgrid = NULL;
710 if (defaultwrap)
711 delete [] defaultwrap;
712 defaultwrap = NULL;
713 }
714
715 // store the default dimension in the global variable
716 defaultdim = d;
717 }
718
719 // return the default dimension of points
720 return defaultdim;
721} /* tPointset::defaultdimension */
722
723template <class coordtype>
724inline double *tPointset<coordtype>::gridsize (int direction, double g)
725{
726 // if this is a question or wrong parameters are given,
727 // return the grid
728 if ((direction < 0) || (direction >= dim) || !dim || (g <= 0))
729 return grid;
730
731 // allocate memory for a new grid table if needed
732 if (!grid)
733 {
734 grid = new double [dim];
735 if (!grid)
736 throw "Can't allocate memory for the grid.";
737 for (int i = 0; i < dim; ++ i)
738 grid [i] = 1.0;
739 }
740
741 // update the dimension if it was different
742 if (dim != defaultdim)
743 defaultdimension (dim);
744
745 // create a new default grid table if needed
746 if (!defaultgrid)
747 {
748 defaultgrid = new double [dim];
749 if (!defaultgrid)
750 throw "Can't alloc mem for the default grid.";
751 for (int i = 0; i < dim; ++ i)
752 defaultgrid [i] = grid [i];
753 }
754
755 // set the grid and the default grid coordinates
756 grid [direction] = g;
757 defaultgrid [direction] = g;
758
759 // return the new grid
760 return grid;
761} /* point::gridsize */
762
763template <class coordtype>
764inline double *tPointset<coordtype>::gridsize (double g)
765{
766 // set all the directions of the grid
767 for (int i = 0; i < dim; ++ i)
768 gridsize (i, g);
769
770 // return the new grid
771 return grid;
772} /* point::gridsize */
773
774template <class coordtype>
775inline double *tPointset<coordtype>::gridsize (double *g)
776{
777 // if this is only a question, return the current grid
778 if (!g)
779 return grid;
780
781 // set all the directions of the grid
782 for (int i = 0; i < dim; ++ i)
783 gridsize (i, g [i]);
784
785 // return the new grid
786 return grid;
787} /* point::gridsize */
788
789template <class coordtype>
790inline const coordtype *tPointset<coordtype>::wrapspace
791 (int direction, coordtype w)
792{
793 // if this is a question or wrong parameters are given,
794 // return the wrap table
795 if ((direction < 0) || (direction >= dim) || !dim || (w < 0))
796 return wrap;
797
798 // allocate memory for a new wrap table if needed
799 if (!wrap)
800 {
801 wrap = new coordtype [dim];
802 if (!wrap)
803 throw "Can't alloc mem for the wrap table.";
804 for (int i = 0; i < dim; ++ i)
805 wrap [i] = 0;
806 }
807
808 // update the dimension if it was different
809 if (dim != defaultdim)
810 defaultdimension (dim);
811
812 // create a new default wrap table if needed
813 if (!defaultwrap)
814 {
815 defaultwrap = new coordtype [dim];
816 if (!defaultwrap)
817 throw "Can't alloc mem for the def. WrapTab.";
818 for (int i = 0; i < dim; ++ i)
819 defaultwrap [i] = wrap [i];
820 }
821
822 // set the wrap and the default wrap coordinates
823 wrap [direction] = w;
824 defaultwrap [direction] = w;
825
826 // return the new wrap table
827 return wrap;
828} /* point::wrapspace */
829
830template <class coordtype>
831inline const coordtype *tPointset<coordtype>::wrapspace (coordtype w)
832{
833 // set all the directions of the wrap table
834 for (int i = 0; i < dim; ++ i)
835 wrapspace (i, w);
836
837 // return the new wrap table
838 return wrap;
839} /* point::wrapspace */
840
841template <class coordtype>
842inline const coordtype *tPointset<coordtype>::wrapspace (const coordtype *w)
843{
844 // if this is only a question, return the current wrap
845 if (!w)
846 return wrap;
847
848 // set all the directions of the wrap table
849 for (int i = 0; i < dim; ++ i)
850 wrapspace (i, w [i]);
851
852 // return the new wrap table
853 return wrap;
854} /* point::wrapspace */
855
856template <class coordtype>
858{
859 // set the default dimension if needed
860 if (d > 0)
861 defaultdimension (d);
862
863 // change the dimension if the set is empty and not a subset
864 if (!npoints && (d > 0))
865 {
866 // remove allocated tables if the new dimension is higher
867 if (d > dim)
868 {
869 if (grid)
870 delete [] grid;
871 grid = NULL;
872 gridsize (defaultgrid);
873 if (wrap)
874 delete [] wrap;
875 wrap = NULL;
876 wrapspace (defaultwrap);
877 if (temp)
878 delete [] temp;
879 temp = NULL;
880 }
881
882 // store the dimension in the structure
883 dim = d;
884 }
885
886 // return the dimension of points
887 return dim;
888} /* tPointset::dimension */
889
890template <class coordtype>
892{
893 return dim;
894} /* tPointset::dimension */
895
896template <class coordtype>
898{
899 return npoints;
900} /* tPointset::size */
901
902template <class coordtype>
903inline bool tPointset<coordtype>::empty () const
904{
905 return !npoints;
906} /* tPointset::empty */
907
908template <class coordtype>
910{
911 if (this == &other)
912 return;
913 std::swap (this -> quiet, other. quiet);
914 std::swap (this -> stat, other. stat);
915 std::swap (this -> minimal, other. minimal);
916 std::swap (this -> maximal, other. maximal);
917 std::swap (this -> wereremoved, other. wereremoved);
918 std::swap (this -> dim, other. dim);
919 std::swap (this -> npoints, other. npoints);
920 std::swap (this -> ntables, other. ntables);
921 std::swap (this -> tablepoints, other. tablepoints);
922 std::swap (this -> tables, other. tables);
923 std::swap (this -> grid, other. grid);
924 std::swap (this -> wrap, other. wrap);
925 std::swap (this -> temp, other. temp);
926 std::swap (this -> hashsize, other. hashsize);
927 std::swap (this -> hashcleared, other. hashcleared);
928 std::swap (this -> hashtable, other. hashtable);
929 std::swap (this -> initsize, other. initsize);
930 return;
931} /* tPointset::tPointset */
932
933//template <class coordtype>
934//inline tPointset<coordtype>::operator int () const
935//{
936// return npoints;
937//} /* tPointset::operator int */
938
939template <class coordtype>
941{
942 if ((n < 0) || (n >= npoints))
943 return NULL;
944
945 return (tables [n / tablepoints] + (n % tablepoints) * dim);
946} /* tPointset::operator [] */
947
948template <class coordtype>
950 int_t *addpos, int wrapped) const
951{
952 // if there are no points or there is no hashing table, return NULL
953 if (!hashsize)
954 return -1;
955
956 // wrap coordinates if needed
957 if (!wrapped && wrap)
958 {
959 if (!temp)
960 throw "Unable to wrap point's coordinates.";
961 wrapcoord (temp, c, wrap, dim);
962 c = temp;
963 }
964
965 // prepare hashing keys
966 int_t pos = pointhashkey (c, dim, hashsize);
967 int_t add = 0;
968
969 // start updating hashing statistics
970 ++ (stat -> hashhits);
971
972 // find the position of the point in the hashing table
973 int_t number;
974 while ((number = hashtable [pos]) != -1)
975 {
976 if ((number >= 0) && thesame ((*this) [number], c, dim))
977 return (pos);
978 if (addpos && (*addpos < 0) && (number == -2))
979 *addpos = pos;
980 if (!add)
981 add = pointhashadd (c, dim, hashsize);
982 pos = (pos + add) % hashsize;
983 ++ (stat -> hashmisses);
984 }
985
986 // return the position in the hashing table
987 return (pos);
988} /* hashfindpoint */
989
990template <class coordtype>
992{
993 // adjust the size of the hashing table if needed
994 if (newsize)
995 newsize = ceilprimenumber (newsize);
996 else if (!npoints && initsize && !hashsize)
997 newsize = ceilprimenumber (initsize);
998
999 // if the new size is too small, make it bigger
1000 if (newsize <= npoints + npoints / 5)
1001 {
1002 // compute an optimal new size for adding points
1003 newsize = ceilprimenumber ((npoints << 1) + 131);
1004
1005 // check if it is not too large for 16-bit programs
1006 int x = 0xFFFF;
1007 if ((x < 0) && (newsize >= 16384))
1008 throw "Pointset too large for a 16-bit prog.";
1009 }
1010
1011 // show a message if needed
1012 if (hashsize && !quiet)
1013 sout << "(Changing the hashing table from " << hashsize <<
1014 " to " << newsize << " at " << npoints << " points) ";
1015 else if (!quiet)
1016 sout << "(Using a hashing table for " << newsize << " ";
1017
1018 // remove the old hashing table and allocate a new one
1019 hashsize = newsize;
1020 if (hashtable)
1021 delete [] hashtable;
1022 hashtable = new int_t [hashsize];
1023 if (!hashtable)
1024 throw "Can't allocate memory for a hashing table.";
1025 for (int_t i = 0; i < hashsize; ++ i)
1026 hashtable [i] = -1;
1027 hashcleared = 0;
1028
1029 // build a new hashing table
1030 for (int_t j = 0; j < npoints; ++ j)
1031 {
1032 int_t n = hashfindpoint ((*this) [j], NULL, 1);
1033 if (hashtable [n] != -1)
1034 throw "A repeated point found in the hashing table.";
1035 hashtable [n] = j;
1036 }
1037
1038 ++ (stat -> rehashcount);
1039
1040 if (!quiet)
1041 sout << "points.)\n";
1042
1043 return;
1044} /* tPointset::rehash */
1045
1046template <class coordtype>
1047inline int_t tPointset<coordtype>::add (const coordtype *c)
1048{
1049 // prevent from adding a 'NULL' point
1050 if (!c)
1051 return -1;
1052
1053 // check if the dimension of the point is known
1054 if (!dim)
1055 throw "Trying to add a point of unknown dimension.";
1056
1057 // wrap the point's coordinates if needed
1058 if (wrap)
1059 {
1060 if (!temp)
1061 temp = allocatepoint<coordtype> (dim);
1062 wrapcoord (temp, c, wrap, dim);
1063 c = temp;
1064 }
1065
1066 // increase the size of the hashing table if needed
1067 if (hashsize - hashcleared <= npoints + npoints / 5)
1068 rehash ();
1069
1070 // find a place for the new point
1071 int_t addpos = -1;
1072 int_t pos = hashfindpoint (c, &addpos, 1);
1073
1074 // if the point is already in the set, return its number
1075 if (hashtable [pos] >= 0)
1076 return hashtable [pos];
1077
1078 // update the range of coordinates for statistical purposes
1079 if (minimal)
1080 {
1081 for (int i = 0; i < dim; ++ i)
1082 if (minimal [i] > c [i])
1083 minimal [i] = c [i];
1084 }
1085 else
1086 {
1087 minimal = allocatepoint<coordtype> (dim);
1088 copycoord (minimal, c, dim);
1089 }
1090
1091 if (maximal)
1092 {
1093 for (int i = 0; i < dim; ++ i)
1094 if (maximal [i] < c [i])
1095 maximal [i] = c [i];
1096 }
1097 else
1098 {
1099 maximal = allocatepoint<coordtype> (dim);
1100 copycoord (maximal, c, dim);
1101 }
1102
1103 // write the point's number into the hashing table
1104 if (addpos >= 0)
1105 {
1106 pos = addpos;
1107 if (hashtable [pos] == -2)
1108 -- hashcleared;
1109 }
1110 hashtable [pos] = npoints;
1111
1112 // compute the number of the table in which the point's coordinates
1113 // should be stored
1114 int_t tablenumber = npoints / tablepoints;
1115
1116 // if there are not enough tables, add some
1117 if (tablenumber >= ntables)
1118 {
1119 int_t moretables = (ntables << 1) + 13;
1120 coordtype **newtables = new coordtype * [moretables];
1121 if (!newtables)
1122 throw "Unable to alloc a table for tables.";
1123 for (int_t i = 0; i < moretables; ++ i)
1124 newtables [i] = (i < ntables) ? (tables [i]) :
1125 (coordtype *) NULL;
1126 if (tables)
1127 delete [] tables;
1128 tables = newtables;
1129 ntables = moretables;
1130 }
1131
1132 // if the appropriate table has not been allocate yet, allocate it
1133 if (tables [tablenumber] == NULL)
1134 {
1135 tables [tablenumber] = new coordtype [tablepoints * dim];
1136 if (!tables [tablenumber])
1137 throw "Unable to alloc a table for coords.";
1138 }
1139
1140 // copy the point's coordinates into the table
1141 copycoord (tables [tablenumber] +
1142 ((npoints % tablepoints) * dim), c, dim);
1143
1144 // return the point's number and increase the number of points
1145 // in the set
1146 return (npoints ++);
1147} /* tPointset::add */
1148
1149template <class coordtype>
1151{
1152 // prevent from adding a 'NULL' point
1153 if (!c)
1154 return -1;
1155
1156 if (!dim)
1157 throw "Trying to add a point of unknown dimension.";
1158 if (!temp)
1159 temp = allocatepoint<coordtype> (dim);
1160 roundpoint (c, temp, grid, dim);
1161 return add (temp);
1162} /* tPointset::addRounded */
1163
1164template <class coordtype>
1166 (const tPointset<coordtype> &p)
1167{
1168 int_t size = p. size ();
1169 for (int_t i = 0; i < size; ++ i)
1170 this -> add (p [i]);
1171 return *this;
1172} /* tPointset::add */
1173
1174template <class coordtype>
1175inline void tPointset<coordtype>::initialize (int_t initialsize, int bequiet)
1176{
1177 // set the 'quiet' variable
1178 quiet = bequiet;
1179
1180 // correct the initial size if wrong
1181 if (initialsize < 0)
1182 initialsize = 0;
1183
1184 // initialize the point tables
1185 npoints = 0;
1186 ntables = 0;
1187 if (initialsize <= 0)
1188 tablepoints = 3000;
1189 else if (initialsize > 10000)
1190 tablepoints = 10000;
1191 else
1192 tablepoints = static_cast<int> (initialsize);
1193 tables = NULL;
1194
1195 // initialize default parameters
1196 dim = 0;
1197 grid = NULL;
1198 wrap = NULL;
1199 temp = NULL;
1200 wereremoved = 0;
1201 dimension (defaultdimension ());
1202 gridsize (defaultgrid);
1203 wrapspace (defaultwrap);
1204
1205 // initialize hashing
1206 hashsize = 0;
1207 hashcleared = 0;
1208 hashtable = NULL;
1209 if (initialsize)
1210 initsize = initialsize + initialsize / 5 + 3;
1211 else
1212 initsize = 0;
1213
1214 // optional statistic data
1215 stat = new psethashstat;
1216 minimal = NULL;
1217 maximal = NULL;
1218
1219 return;
1220} /* tPointset::initialize */
1221
1222template <class coordtype>
1223inline tPointset<coordtype>::tPointset (int_t initialsize, int bequiet)
1224{
1225 initialize (initialsize, bequiet);
1226 return;
1227} /* tPointset::tPointset */
1228
1229template <class coordtype>
1231{
1232 initialize (p. size (), p. quiet);
1233 add (p);
1234 return;
1235} /* tPointset::tPointset */
1236
1237template <class coordtype>
1239{
1240 // free the point tables
1241 for (int_t i = 0; i < ntables; ++ i)
1242 {
1243 if (tables [i])
1244 delete [] (tables [i]);
1245 }
1246 if (tables)
1247 delete [] tables;
1248
1249 // remove the grid and wrap tables
1250 if (grid)
1251 delete [] grid;
1252 if (wrap)
1253 delete [] wrap;
1254
1255 // remove the temporary point table
1256 if (temp)
1257 delete [] temp;
1258
1259 // remove the minimal and maximal coordinates
1260 if (minimal)
1261 delete [] minimal;
1262 if (maximal)
1263 delete [] maximal;
1264
1265 // turn off hashing
1266 if (hashtable)
1267 delete [] hashtable;
1268
1269 if (stat)
1270 delete stat;
1271
1272 return;
1273} /* tPointset::deallocate */
1274
1275template <class coordtype>
1277 (const tPointset<coordtype> &p)
1278{
1279 if (this == &p)
1280 return *this;
1281 deallocate ();
1282 initialize (p. size (), p. quiet);
1283 add (p);
1284 return *this;
1285} /* tPointset::operator = */
1286
1287template <class coordtype>
1289{
1290 deallocate ();
1291 return;
1292} /* tPointset::~tPointset */
1293
1294template <class coordtype>
1295inline int_t tPointset<coordtype>::getnumber (const coordtype *c) const
1296{
1297 // prevent from looking for a 'NULL' point
1298 if (!c)
1299 return -1;
1300
1301 // find the position corresponding to this point in the hashing table
1302 int_t pos = hashfindpoint (c);
1303
1304 // return the point's number found in the table
1305 return ((pos >= 0) ? hashtable [pos] : static_cast<int_t> (-1));
1306} /* tPointset::getnumber */
1307
1308template <class coordtype>
1309inline int_t tPointset<coordtype>::getnumberRounded (const double *c) const
1310{
1311 if (!npoints)
1312 return -1;
1313 if (!temp)
1314 throw "Cannot round point's coordinates.";
1315 roundpoint (c, temp, grid, dim);
1316 int_t pos = hashfindpoint (temp);
1317 return ((pos >= 0) ? hashtable [pos] : static_cast<int_t> (-1));
1318} /* tPointset::getnumberRounded */
1319
1320template <class coordtype>
1322{
1323 return ((n >= 0) && (n < npoints));
1324} /* tPointset::check */
1325
1326template <class coordtype>
1327inline int tPointset<coordtype>::check (const coordtype *c) const
1328{
1329 return (getnumber (c) != -1);
1330} /* tPointset::check */
1331
1332template <class coordtype>
1333inline int tPointset<coordtype>::checkRounded (const double *c) const
1334{
1335 return (getnumber (c) != -1);
1336} /* tPointset::checkRounded */
1337
1338template <class coordtype>
1339inline coordtype *tPointset<coordtype>::getpoint (int_t n) const
1340{
1341 return (*this) [n];
1342} /* tPointset::getpoint */
1343
1344template <class coordtype>
1345inline coordtype *tPointset<coordtype>::getpoint (coordtype *c) const
1346{
1347 return (*this) [getnumber (c)];
1348} /* tPointset::getpoint */
1349
1350template <class coordtype>
1351inline coordtype *tPointset<coordtype>::getpointRounded (double *c) const
1352{
1353 return (*this) [getnumberRounded (c)];
1354} /* tPointset::getpointRounded */
1355
1356template <class coordtype>
1357inline coordtype *tPointset<coordtype>::getpointMiddle (int_t n, double *c) const
1358{
1359 coordtype *coord = (*this) [n];
1360 if (coord && c)
1361 {
1362 for (int i = 0; i < dim; ++ i)
1363 c [i] = (grid ? grid [i] : 1.0) * (0.5 + coord [i]);
1364 }
1365
1366 return coord;
1367} /* tPointset::getpointMiddle */
1368
1369template <class coordtype>
1371{
1372 if ((n < 0) || (n >= npoints))
1373 return -1;
1374 wereremoved = 1;
1375
1376 // find the point's place in the hashing table
1377 coordtype *coord = (*this) [n];
1378 int_t pos = hashfindpoint (coord);
1379
1380 // fill in this entry in the hashing table with -2 (cleared)
1381 hashtable [pos] = -2;
1382
1383 // copy the last point in the set to replace the point being removed
1384 if (n != npoints - 1)
1385 {
1386 coordtype *lastcoord = (*this) [npoints - 1];
1387 int_t lastpos = hashfindpoint (lastcoord);
1388 hashtable [lastpos] = n;
1389 copycoord (coord, lastcoord, dim);
1390 }
1391
1392 // free an unused table with points' coordinates if it is sensible
1393 int_t tablenumber = npoints / tablepoints;
1394 if ((tablenumber + 2 < ntables) && tables [tablenumber + 2])
1395 {
1396 delete [] (tables [tablenumber + 2]);
1397 tables [tablenumber + 2] = NULL;
1398 }
1399
1400 // decrease the number of points in the set
1401 -- npoints;
1402
1403 // update the number of cleared entries in the hashing table
1404 ++ hashcleared;
1405
1406 // rehash if recommended
1407 if (hashcleared > npoints + 13)
1408 rehash (13);
1409
1410 return (0);
1411} /* tPointset::remove */
1412
1413template <class coordtype>
1414inline int tPointset<coordtype>::remove (const coordtype *c)
1415{
1416 return remove (getnumber (c));
1417} /* tPointset::remove */
1418
1419template <class coordtype>
1420inline int tPointset<coordtype>::removeRounded (const double *c)
1421{
1422 return remove (getnumberRounded (c));
1423} /* tPointset::removeRounded */
1424
1425template <class coordtype>
1427{
1428 int_t size = p. size ();
1429 for (int_t i = 0; i < size; ++ i)
1430 remove (p [i]);
1431 return 0;
1432} /* tPointset::remove */
1433
1434template <class coordtype>
1436{
1437 return hashsize;
1438} /* tPointset::gethashsize */
1439
1440
1441// --------------------------------------------------
1442// ------------------- NEIGHBORS --------------------
1443// --------------------------------------------------
1444
1448template <class coordtype>
1450{
1451public:
1453 tNeighbors (const coordtype *_source = NULL, int _dim = 0,
1454 const coordtype *_wrap = NULL);
1455
1458
1461
1463 ~tNeighbors ();
1464
1467 coordtype *get ();
1468
1470 void reset ();
1471
1473 void set (coordtype *_source);
1474
1475private:
1477 int dim;
1478
1480 const coordtype *source;
1481
1483 coordtype *neighbor;
1484
1486 signed char *counters;
1487
1489 const coordtype *wrap;
1490
1492 void initialize (const coordtype *_source = NULL,
1493 int _dim = 0, const coordtype *_wrap = NULL);
1494
1496 void deallocate ();
1497
1498}; /* class tNeighbors */
1499
1500// --------------------------------------------------
1501
1502template <class coordtype>
1503void tNeighbors<coordtype>::initialize (const coordtype *_source, int _dim,
1504 const coordtype *_wrap)
1505{
1506 source = _source;
1507 wrap = _wrap;
1508 dim = _dim;
1509 if (dim <= 0)
1510 {
1511 dim = 0;
1512 neighbor = NULL;
1513 counters = NULL;
1514 return;
1515 }
1516 neighbor = new coordtype [dim];
1517 counters = new signed char [dim];
1518 if (!neighbor || !counters)
1519 throw "Can't allocate memory for neighbors.";
1520 reset ();
1521 return;
1522} /* tNeighbors::initialize */
1523
1524template <class coordtype>
1525tNeighbors<coordtype>::tNeighbors (const coordtype *_source, int _dim,
1526 const coordtype *_wrap)
1527{
1528 initialize (_source, _dim, _wrap);
1529 return;
1530} /* tNeighbors::tNeighbors */
1531
1532template <class coordtype>
1534{
1535 initialize (n. source, n. dim, n. wrap);
1536 return;
1537} /* tNeighbors::tNeighbors */
1538
1539template <class coordtype>
1541 (const tNeighbors<coordtype> &n)
1542{
1543 deallocate ();
1544 initialize (n. source, n. dim, n. wrap);
1545 return *this;
1546} /* tNeighbors::operator = */
1547
1548template <class coordtype>
1550{
1551 if (neighbor)
1552 delete [] neighbor;
1553 if (counters)
1554 delete [] counters;
1555 return;
1556} /* tNeighbors::deallocate */
1557
1558template <class coordtype>
1560{
1561 deallocate ();
1562 return;
1563} /* tNeighbors::~tNeighbors */
1564
1565template <class coordtype>
1567{
1568 if (counters)
1569 {
1570 for (int i = 0; i < dim; ++ i)
1571 counters [i] = 0;
1572 }
1573 return;
1574} /* tNeighbors::reset */
1575
1576template <class coordtype>
1577void tNeighbors<coordtype>::set (coordtype *_source)
1578{
1579 source = _source;
1580 return;
1581} /* tNeighbors::set */
1582
1583template <class coordtype>
1585{
1586 // if the initialization was incorrect, return NULL
1587 if (!dim || !counters || !neighbor || !source)
1588 return NULL;
1589
1590 // compute the next set of counters
1591 // and return NULL if this is the end
1592 int cur = 0;
1593 while ((cur < dim) && (counters [cur] == -1))
1594 counters [cur ++] = 0;
1595 if (cur >= dim)
1596 return NULL;
1597 counters [cur] = counters [cur] ?
1598 (signed char) -1 : (signed char) 1;
1599
1600 // compute the neighbor corresponding to these counters
1601 for (int i = 0; i < dim; ++ i)
1602 neighbor [i] = (coordtype) (source [i] + counters [i]);
1603
1604 // wrap the neighbor's coordinates if required
1605 if (wrap)
1606 wrapcoord (neighbor, neighbor, wrap, dim);
1607
1608 // return the neighbor's coordinates
1609 return neighbor;
1610
1611} /* tNeighbors::get */
1612
1613
1614// --------------------------------------------------
1615// ------------------- RECTANGLE --------------------
1616// --------------------------------------------------
1617
1625template <class coordtype>
1627{
1628public:
1630 tRectangle (const coordtype *_left = NULL,
1631 const coordtype *_right = NULL, int _dim = 0);
1632
1635
1638
1641
1644 const coordtype *get ();
1645
1647 void reset ();
1648
1649private:
1651 int dim;
1652
1654 const coordtype *left;
1655
1657 const coordtype *right;
1658
1660 coordtype *point;
1661
1664
1666 void initialize (const coordtype *_left = NULL,
1667 const coordtype *_right = NULL, int _dim = 0);
1668
1670 void deallocate ();
1671
1672}; /* class tRectangle */
1673
1674// --------------------------------------------------
1675
1676template <class coordtype>
1677void tRectangle<coordtype>::initialize (const coordtype *_left,
1678 const coordtype *_right, int _dim)
1679{
1680 firstpoint = 0;
1681 left = _left;
1682 right = _right;
1683 dim = _dim;
1684 if (dim <= 0)
1685 {
1686 dim = 0;
1687 point = NULL;
1688 return;
1689 }
1690 point = new coordtype [dim];
1691 if (!point)
1692 throw "Can't allocate memory for a rectangle.";
1693 reset ();
1694
1695 return;
1696} /* tRectangle::initialize */
1697
1698template <class coordtype>
1699tRectangle<coordtype>::tRectangle (const coordtype *_left, const coordtype *_right,
1700 int _dim)
1701{
1702 initialize (_left, _right, _dim);
1703 return;
1704} /* tRectangle::tRectangle */
1705
1706template <class coordtype>
1708{
1709 initialize (r. left, r. right, r. dim);
1710 return;
1711} /* tRectangle::tRectangle */
1712
1713template <class coordtype>
1715{
1716 deallocate ();
1717 initialize (r. left, r. right, r. dim);
1718 return *this;
1719} /* tRectangle::operator = */
1720
1721template <class coordtype>
1723{
1724 if (point)
1725 delete [] point;
1726 return;
1727} /* tRectangle::deallocate */
1728
1729template <class coordtype>
1731{
1732 deallocate ();
1733 return;
1734} /* tRectangle::~tRectangle */
1735
1736template <class coordtype>
1738{
1739 for (int i = 0; i < dim; ++ i)
1740 point [i] = left [i];
1741 firstpoint = 1;
1742 return;
1743} /* tRectangle::reset */
1744
1745template <class coordtype>
1747{
1748 // if this is the first point, check if the rectangle is nonempty
1749 if (firstpoint)
1750 {
1751 firstpoint = 0;
1752 for (int i = 0; i < dim; ++ i)
1753 if (left [i] >= right [i])
1754 return NULL;
1755 return point;
1756 }
1757
1758 // compute the next point of the rectangle
1759 int cur = 0;
1760 while ((cur < dim) && (++ (point [cur]) >= right [cur]))
1761 {
1762 point [cur] = left [cur];
1763 ++ cur;
1764 }
1765
1766 // if the iterator has run out of points, return NULL
1767 if (cur >= dim)
1768 {
1769 firstpoint = 1;
1770 return NULL;
1771 }
1772
1773 // return the point's coordinates
1774 return point;
1775
1776} /* tRectangle::get */
1777
1778
1779// --------------------------------------------------
1780// ---------------- various functions ---------------
1781// --------------------------------------------------
1782
1784template <class coordtype>
1785int countneighbors (const tPointset<coordtype> &p, const coordtype *c,
1786 int which, int maxcount)
1787{
1788 if (p. empty ())
1789 {
1790 if (which == INSIDE)
1791 return 0;
1792 else
1793 return maxcount;
1794 }
1795
1796 int count = 0;
1797 tNeighbors<coordtype> neigh (c, p. dimension ());
1798 while ((c = neigh. get ()) != NULL)
1799 {
1800 if (which == INSIDE)
1801 {
1802 if (p. check (c))
1803 ++ count;
1804 }
1805 else if (which == OUTSIDE)
1806 {
1807 if (!p. check (c))
1808 ++ count;
1809 }
1810
1811 if (maxcount && (count >= maxcount))
1812 return count;
1813 }
1814
1815 return count;
1816} /* countneighbors */
1817
1818template <class coordtype>
1820 const tPointset<coordtype> &q, coordtype *c,
1821 int which, int maxcount)
1822{
1823 if ((q. empty ()) || (p. dimension () != q. dimension ()))
1824 return countneighbors (p, c, which, maxcount);
1825 else if (p. empty ())
1826 return countneighbors (q, c, which, maxcount);
1827
1828 int count = 0;
1829 tNeighbors<coordtype> neigh (c, p. dimension ());
1830 while ((c = neigh. get ()) != NULL)
1831 {
1832 if (which == INSIDE)
1833 {
1834 if (p. check (c) || q. check (c))
1835 ++ count;
1836 }
1837 else if (which == OUTSIDE)
1838 {
1839 if (!p. check (c) && !q. check (c))
1840 ++ count;
1841 }
1842
1843 if (maxcount && (count >= maxcount))
1844 return count;
1845 }
1846
1847 return count;
1848} /* countneighbors */
1849
1850template <class coordtype>
1851int attheborder (const tPointset<coordtype> &p, const coordtype *c)
1852{
1853 return (countneighbors (p, c, OUTSIDE, 1));
1854
1855} /* attheborder */
1856
1857template <class coordtype>
1859{
1860 if (direction >= 0)
1861 {
1862 if (n >= p. size ())
1863 return -1;
1864 if (n < 0)
1865 n = 0;
1866 int_t size = p. size ();
1867 while (n < size)
1868 {
1869 if (attheborder (p, p [n]))
1870 return n;
1871 else
1872 ++ n;
1873 }
1874 return -1;
1875 }
1876 else
1877 {
1878 if (n < 0)
1879 return -1;
1880 if (n >= p. size ())
1881 n = p. size () - 1;
1882 while (n >= 0)
1883 {
1884 if (attheborder (p, p [n]))
1885 return n;
1886 else
1887 -- n;
1888 }
1889 return -1;
1890 }
1891} /* findboundarypoint */
1892
1893template <class coordtype>
1895 int_t n, int direction)
1896{
1897 if (direction >= 0)
1898 {
1899 if (n >= p. size ())
1900 return -1;
1901 if (n < 0)
1902 n = 0;
1903 while (n < p. size ())
1904 {
1905 if (countneighbors (p, q, p [n], OUTSIDE, 1))
1906 return n;
1907 else
1908 ++ n;
1909 }
1910 return -1;
1911 }
1912 else
1913 {
1914 if (n < 0)
1915 return -1;
1916 if (n >= p. size ())
1917 n = p. size () - 1;
1918 while (n >= 0)
1919 {
1920 if (countneighbors (p, q, p [n], OUTSIDE, 1))
1921 return n;
1922 else
1923 -- n;
1924 }
1925 return -1;
1926 }
1927} /* findboundarypoint */
1928
1929template <class coordtype>
1931{
1932 // add all the points which are at the border
1933 int_t size = p. size ();
1934 for (int_t i = 0; i < size; ++ i)
1935 {
1936 coordtype *c = p [i];
1937 if (attheborder (p, c))
1938 b. add (c);
1939 }
1940 return;
1941} /* computeboundary */
1942
1943template <class coordtype>
1945{
1946 // create a new set of points
1948
1949 // if cannot allocate memory for it, return nothing
1950 if (!boundary)
1951 return NULL;
1952
1953 // copy the global parameters (the defaults may be different)
1954 boundary -> dimension (p. dimension ());
1955 boundary -> gridsize (p. gridsize ());
1956 boundary -> wrapspace (p. wrapspace ());
1957
1958 // compute the boundary
1959 computeboundary (p, *boundary);
1960
1961 return boundary;
1962} /* computeboundary */
1963
1964template <class coordtype>
1965void enhancepoint (tPointset<coordtype> &p, coordtype *c)
1966{
1967 tNeighbors<coordtype> neigh (c, p. dimension ());
1968
1969 while ((c = neigh. get ()) != NULL)
1970 p. add (c);
1971
1972 return;
1973} /* enhancepoint */
1974
1975template <class coordtype>
1977{
1978 enhancepoint (p, p [n]);
1979
1980 return;
1981} /* enhancepoint */
1982
1983template <class coordtype>
1985{
1986 int_t size = p. size ();
1987 for (int_t i = 0; i < size; ++ i)
1988 enhancepoint (p, p [i]);
1989
1990 return;
1991} /* enhance */
1992
1993template <class coordtype>
1994int read (textfile &f, coordtype *c, int maxdim)
1995{
1996 // ignore lines until you can find an opening parenthesis,
1997 // brace or bracket and read this character
1998 int ready = 0;
1999 while (!ready)
2000 {
2001 switch (f. checkchar ())
2002 {
2003 case '(':
2004 case '[':
2005 case '{':
2006 case '"':
2007 case '\'':
2008 f. readchar ();
2009 ready = 1;
2010 break;
2011 case '+':
2012 case '-':
2013 break;
2014 case EOF:
2015 return 0;
2016 default:
2017 f. ignoreline ();
2018 break;
2019 }
2020 }
2021
2022 // read the coordinates
2023 int n = 0;
2024 while (1)
2025 {
2026 // read the current coordinate of the point
2027 c [n ++] = (coordtype) f. readnumber ();
2028
2029 // read a comma between the coordinates
2030 // or the closing parenthesis, brace or bracket if any
2031 switch (f. checkchar ())
2032 {
2033 case ')':
2034 case ']':
2035 case '}':
2036 case '"':
2037 case '\'':
2038 f. readchar ();
2039 return n;
2040 case ',':
2041 f. readchar ();
2042 break;
2043 case '-':
2044 case '+':
2045 break;
2046 default:
2047 if ((f. checkchar () < '0') ||
2048 (f. checkchar () > '9'))
2049 return n;
2050 }
2051
2052 // check if the maximal dimension allowed has been reached
2053 if (n >= maxdim)
2054 return n;
2055 }
2056} /* read */
2057
2058template <class coordtype>
2059int read (std::istream &in, coordtype *c, int maxdim)
2060{
2061 textfile f (in);
2062 return read (f, c, maxdim);
2063} /* read */
2064
2072template <class coordtype>
2073inline int readcoordinates (std::istream &in, coordtype *coord, int maxdim,
2074 int closing)
2075{
2076 // read the opening parenthesis
2077 if (closing == EOF)
2078 closing = readparenthesis (in);
2079 if (closing == EOF)
2080 return -1;
2081
2082 int cur = 0;
2083
2084 ignorecomments (in);
2085 while ((in. peek () != closing) && (cur < maxdim))
2086 {
2087 // ignore a plus before the number if necessary
2088 if (in. peek () == '+')
2089 in. get ();
2090
2091 // finish if there is no number at the input
2092 if ((in. peek () != '-') && !std::isdigit (in. peek ()))
2093 break;
2094
2095 // read the number as 'long' (just in case)
2096 long number;
2097 in >> number;
2098 // if (!in)
2099 // return -1;
2100
2101 // transform this number to a coordtype
2102 coord [cur] = (coordtype) number;
2103 if (coord [cur] != number)
2104 return -1;
2105
2106 // move to the next coordtype position
2107 ++ cur;
2108 if (closing == '\n')
2109 {
2110 while ((in. peek () == ' ') ||
2111 (in. peek () == '\t') ||
2112 (in. peek () == '\r'))
2113 in. get ();
2114 }
2115 else
2116 ignorecomments (in);
2117
2118 // one more thing: read the following comma if any
2119 if (in. peek () == ',')
2120 {
2121 in. get ();
2122 ignorecomments (in);
2123 }
2124 }
2125
2126 // verify that the coordinates were read successfully
2127// if (!in)
2128// return -1;
2129
2130 // read the closing parenthesis
2131 if (in. peek () == closing)
2132 in. get ();
2133 else if ((closing == '\n') && (in. peek () == EOF))
2134 ;
2135 else
2136 return -1;
2137
2138 return cur;
2139} /* readcoordinates */
2140
2141template <class coordtype>
2142inline int readcoordinates (std::istream &in, coordtype *coord, int maxdim)
2143{
2144 return readcoordinates (in, coord, maxdim, EOF);
2145} /* readcoordinates */
2146
2147template <class coordtype>
2148int write (std::ostream &out, const coordtype *c, int dim, char parenthesis,
2149 char closing)
2150{
2151 // write the opening parenthesis, brace or bracket
2152 if (parenthesis != 0)
2153 out << parenthesis;
2154
2155 // output the point's coordinates
2156 for (int i = 0; i < dim; ++ i)
2157 {
2158 if (i)
2159 out << ",";
2160 out << c [i];
2161 }
2162
2163 // write an appropriate closing parenthesis, brace or bracket
2164 if (closing)
2165 out << closing;
2166 else if (parenthesis)
2167 {
2168 int ch = closingparenthesis (parenthesis);
2169 if (ch == EOF)
2170 closing = parenthesis;
2171 else
2172 closing = (char) ch;
2173 out << closing;
2174 }
2175
2176 return dim;
2177} /* write */
2178
2179template <class coordtype>
2180int readcubeorcell (std::istream &in, coordtype *left, coordtype *right,
2181 int maxdim, int *type)
2182{
2183 // ignore all the texts that appear before the actual cell or cube
2184 int closing;
2185 while ((closing = closingparenthesis (in. peek ())) == EOF)
2186 {
2187 ignoreline (in);
2188 ignorecomments (in);
2189 if (!in)
2190 return 0;
2191 }
2192
2193 // try reading the coordinates of the cube
2194 int dim = readcoordinates (in, left, maxdim);
2195
2196 // if successful, then both parentheses are read
2197 if (dim > 0)
2198 {
2199 // check if this is not a product of intervals
2200 ignorecomments (in);
2201 if (((in. peek () != 'x') && (in. peek () != 'X')) ||
2202 (dim > 2))
2203 {
2204 // set the right coordinates accordingly
2205 for (int i = 0; i < dim; ++ i)
2206 right [i] = (coordtype) (left [i] + 1);
2207 if (type)
2208 *type = CUBE;
2209 return dim;
2210 }
2211
2212 // read the remaining intervals
2213 right [0] = (dim < 2) ? left [0] : left [1];
2214 dim = 1;
2215 coordtype temp [2];
2216 while ((in. peek () == 'x') || (in. peek () == 'X'))
2217 {
2218 if (dim >= maxdim)
2219 throw "Too many intervals in a product.";
2220 in. get ();
2221 ignorecomments (in);
2222 int d = readcoordinates (in, temp, 2);
2223 if ((d <= 0) || !in)
2224 throw "Can't read a product of intervals.";
2225 left [dim] = temp [0];
2226 right [dim] = (d < 2) ? temp [0] : temp [1];
2227 ++ dim;
2228 ignorecomments (in);
2229 }
2230 if (type)
2231 *type = CELL;
2232 return dim;
2233 }
2234
2235 // otherwise, this is a cubical cell
2236 else
2237 {
2238 // if an error is set for the input stream, clear it
2239 in. clear (in. rdstate () & ~std::ios::failbit);
2240 ignorecomments (in);
2241
2242 // read two points for the cell
2243 int leftdim = readcoordinates (in, left, maxdim);
2244 ignorecomments (in);
2245 int rightdim = readcoordinates (in, right, maxdim);
2246 ignorecomments (in);
2247
2248 // compare the dimensions
2249 if (!leftdim || !rightdim)
2250 throw "Can't read a cell.";
2251 else if (leftdim != rightdim)
2252 throw "Different dim of left & right point.";
2253 else
2254 dim = leftdim;
2255
2256 // read the closing bracket of the cell
2257 if (in. get () != closing)
2258 throw "Can't read the closing bracket of a cell.";
2259 ignorecomments (in);
2260 if (type)
2261 *type = CELL;
2262 }
2263 return dim;
2264} /* readcubeorcell */
2265
2266template <class coordtype>
2268 int_t first, int_t howmany,
2269 coordtype *wrap, int maxdim, int quiet,
2270 tPointset<coordtype> *notthese)
2271{
2272 // prepare a temporary point of maximal dimension
2273 if (maxdim <= 0)
2274 {
2275 if (wrap)
2276 wrap = NULL;
2277 maxdim = 100;
2278 }
2279 coordtype *temp = allocatepoint<coordtype> (maxdim + 1);
2280
2281 int_t count = 0;
2282 int dim = p. empty () ? 0 : p. dimension ();
2283
2284 if (notthese && !notthese -> empty ())
2285 {
2286 if (!dim)
2287 dim = notthese -> dimension ();
2288 else if (dim != notthese -> dimension ())
2289 {
2290 if (!quiet)
2291 sout << "Error: Dimensions not the same.\n";
2292 return -1;
2293 }
2294 }
2295
2296 while (1)
2297 {
2298 // stop reading if it is already enough
2299 if ((howmany >= 0) && (count >= howmany))
2300 {
2301 delete [] temp;
2302 return count;
2303 }
2304
2305 // ignore all the lines which do not start
2306 // with an opening parenthesis
2307 while ((f. checkchar () != 40) && (f. checkchar () != 91) &&
2308 (f. checkchar () != 123) && (f. checkchar () != EOF))
2309 f. ignoreline ();
2310
2311 // if this is the end of the file, finish successfully
2312 if (f. checkchar () == EOF)
2313 {
2314 delete [] temp;
2315 return count;
2316 }
2317
2318 // read a point
2319 int n = read (f, temp, maxdim + 1);
2320 if (n > maxdim)
2321 {
2322 if (!quiet)
2323 sout << "Line " << f. linenumber () <<
2324 ": The point has too many " <<
2325 "coordinates.\n";
2326 delete [] temp;
2327 return -1;
2328 }
2329
2330 // check if the number of coordinates is the same
2331 // as the dimension of the points in the set
2332 if (!first && dim && n && (n != dim))
2333 {
2334 if (!quiet)
2335 sout << "Line " << f. linenumber () <<
2336 ": Incorrect point dimension.\n";
2337 delete [] temp;
2338 return -1;
2339 }
2340
2341 // set the dimension to be the number of coordinates
2342 if (!first && !dim)
2343 {
2344 dim = n;
2345 if (p. dimension () != dim)
2346 p. dimension (dim);
2347 }
2348
2349 // add the read point to the set
2350 if (first)
2351 -- first;
2352 else
2353 {
2354 if (wrap)
2355 {
2356 p. wrapspace (wrap);
2357 wrap = NULL;
2358 }
2359 if (!notthese || !notthese -> check (temp))
2360 p. add (temp);
2361 ++ count;
2362 }
2363 }
2364} /* read */
2365
2366template <class coordtype>
2367int_t read (std::istream &in, tPointset<coordtype> &p,
2368 int_t first, int_t howmany, coordtype *wrap, int maxdim,
2369 int quiet, tPointset<coordtype> *notthese)
2370{
2371 textfile f (in);
2372 return read (f, p, first, howmany, wrap, maxdim, quiet, notthese);
2373} /* read */
2374
2375template <class coordtype>
2377 coordtype *wrap, int maxdim,
2378 int quiet, tPointset<coordtype> *notthese)
2379{
2380 return read (f, p, 0, -1, wrap, maxdim, quiet, notthese);
2381} /* read */
2382
2383template <class coordtype>
2384int_t read (std::istream &in, tPointset<coordtype> &p, coordtype *wrap,
2385 int maxdim, int quiet, tPointset<coordtype> *notthese)
2386{
2387 textfile f (in);
2388 return read (f, p, wrap, maxdim, quiet, notthese);
2389} /* read */
2390
2391template <class coordtype>
2393{
2394 read (f, p);
2395 return f;
2396} /* operator >> */
2397
2398template <class coordtype>
2399std::istream &operator >> (std::istream &in, tPointset<coordtype> &p)
2400{
2401 textfile f (in);
2402 read (f, p);
2403 return in;
2404} /* operator >> */
2405
2406template <class coordtype>
2407int_t write (std::ostream &out, tPointset<coordtype> &p,
2408 int_t first, int_t howmany, int)
2409{
2410 int_t count = 0;
2411 int dim = p. dimension ();
2412
2413 // write the number of points in the set
2414 out << "; The set contains " << p. size () << " points.\n";
2415 if (first)
2416 out << "; Not writing first " << first << " points.\n";
2417 if (howmany >= 0)
2418 out << "; Writing at most " << howmany << " points.\n";
2419
2420 // write the size of the grid
2421 if (dim && p. gridsize ())
2422 {
2423 for (int i = 0; i < dim; ++ i)
2424 out << (i ? ", " : "; Grid size: ") <<
2425 p. gridsize () [i];
2426 out << '\n';
2427 }
2428
2429 // write statistical information if it has been gathered
2430 if (p. gethashsize ())
2431 out << "; Hashing table size: " <<
2432 p. gethashsize () << " entries.\n";
2433
2434 if (p. stat -> hashhits)
2435 out << "; Hashing statistics: " <<
2436 ((p. stat -> hashhits + p. stat -> hashmisses) /
2437 p. stat -> hashhits) << '.' <<
2438 ((p. stat -> hashhits + p. stat -> hashmisses) * 10 /
2439 p. stat -> hashhits) % 10 << " trials per point, " <<
2440 p. stat -> rehashcount << " times rehashed.\n";
2441
2442 if (p. minimal && p. maximal)
2443 {
2444 out << "; The coordinates " <<
2445 (p. wereremoved ? "varied" : "vary") << " from ";
2446 write (out, p. minimal, dim);
2447 out << " to ";
2448 write (out, p. maximal, dim);
2449 out << ".\n";
2450 }
2451
2452 std::time_t tm;
2453 std::time (&tm);
2454 out << "; Work time: " << (tm - p. stat -> creationtime) <<
2455 " seconds.\n";
2456
2457 // add a warning if any points were removed
2458 if (p. wereremoved)
2459 out << "; Warning: Points were removed, " <<
2460 "so their original order may be distorted.\n";
2461
2462 // write out the dimension of the points (for compatibility
2463 // with the older versions of 'pointset')
2464 out << "dimension " << p. dimension () << '\n';
2465
2466 // output all the points
2467 int_t size = p. size ();
2468 for (int_t i = first; i < size; ++ i)
2469 {
2470 if ((howmany >= 0) && (count >= howmany))
2471 return count;
2472 write (out, p [i], dim);
2473 out << '\n';
2474 ++ count;
2475 }
2476
2477 return count;
2478} /* write */
2479
2480template <class coordtype>
2481std::ostream &operator << (std::ostream &out, tPointset<coordtype> &p)
2482{
2483 write (out, p);
2484 return out;
2485} /* operator << */
2486
2487
2488} // namespace homology
2489} // namespace chomp
2490
2491#endif // _CHOMP_CUBES_POINTSET_H_
2492
2494
This is a small class used only to collect and display statistics on how successful the hashing proce...
Definition: pointset.h:426
std::time_t creationtime
A variable which stores the creation time of each object.
Definition: pointset.h:432
unsigned long hashmisses
The number of unsuccessful attempts to identify an object in a hashing table.
Definition: pointset.h:440
unsigned long hashhits
The number of successful attempts to identify an object in a hashing table.
Definition: pointset.h:436
psethashstat()
The constructor.
Definition: pointset.h:450
unsigned long rehashcount
The number of times the size of the hashing table was changed and all the elements had to be put in t...
Definition: pointset.h:444
This class can be used for iterating point's neighbors.
Definition: pointset.h:1450
tNeighbors & operator=(const tNeighbors< coordtype > &r)
The assignment operator.
Definition: pointset.h:1541
coordtype * get()
Returns the next neighbor.
Definition: pointset.h:1584
const coordtype * source
A pointer to the source point (not allocated!).
Definition: pointset.h:1480
void set(coordtype *_source)
Redefines the source (and doesn't change other variables).
Definition: pointset.h:1577
const coordtype * wrap
The space wrapping (if needed).
Definition: pointset.h:1489
tNeighbors(const coordtype *_source=NULL, int _dim=0, const coordtype *_wrap=NULL)
The only possible constructor for new objects.
Definition: pointset.h:1525
~tNeighbors()
The destructor.
Definition: pointset.h:1559
signed char * counters
The current counters.
Definition: pointset.h:1486
void reset()
Resets the neighbors to the first one.
Definition: pointset.h:1566
void initialize(const coordtype *_source=NULL, int _dim=0, const coordtype *_wrap=NULL)
Initializes the internal data of an object of this class.
Definition: pointset.h:1503
void deallocate()
Deallocates any memory previously allocated for this object.
Definition: pointset.h:1549
int dim
The dimension of the space.
Definition: pointset.h:1477
coordtype * neighbor
The coordinates of a created neighbor.
Definition: pointset.h:1483
This class represents a set of points in R^n with integer coordinates.
Definition: pointset.h:482
psethashstat * stat
Definition: pointset.h:605
int_t getnumber(const coordtype *c) const
Definition: pointset.h:1295
~tPointset()
The destructor.
Definition: pointset.h:1288
coordtype * getpointRounded(double *c) const
Definition: pointset.h:1351
bool empty() const
Returns true if and only if the set of points is empty.
Definition: pointset.h:903
int quiet
Returns the number of points by simply projecting the set onto an integer number.
Definition: pointset.h:593
double * gridsize(double *g=0)
Gets or sets the size of the grid in R^n.
Definition: pointset.h:775
tPointset(int_t initialsize=0, int bequiet=1)
Default constructor for a set of points with the initial size of the set defined here if an upper bou...
Definition: pointset.h:1223
int_t size() const
Returns the number of points in the set.
Definition: pointset.h:897
int_t add(const coordtype *c)
Definition: pointset.h:1047
int_t hashfindpoint(const coordtype *c, int_t *addposition=NULL, int wrapped=0) const
Definition: pointset.h:949
const coordtype * wrapspace(const coordtype *w=NULL)
Definition: pointset.h:842
int dimension() const
Returns the dimension of points.
Definition: pointset.h:891
static double * defaultgrid
Definition: pointset.h:649
void rehash(int_t newsize=0)
Definition: pointset.h:991
static int defaultdimension(int d=0)
Sets or gets the default dimension of points.
Definition: pointset.h:699
coordtype * operator[](int_t n) const
Definition: pointset.h:940
coordtype CoordType
The type of coordinates.
Definition: pointset.h:485
int_t gethashsize() const
Definition: pointset.h:1435
int check(int_t n) const
Definition: pointset.h:1321
int_t addRounded(double *c)
Definition: pointset.h:1150
void initialize(int_t initialsize, int bequiet)
Definition: pointset.h:1175
int removeRounded(const double *c)
Definition: pointset.h:1420
int_t getnumberRounded(const double *c) const
Definition: pointset.h:1309
coordtype * getpoint(int_t n) const
Definition: pointset.h:1339
tPointset & operator=(const tPointset< coordtype > &p)
The assignment operator.
Definition: pointset.h:1277
static coordtype * defaultwrap
Definition: pointset.h:650
int checkRounded(const double *c) const
Definition: pointset.h:1333
void swap(tPointset< coordtype > &other)
Swaps the data with another object of the same type.
Definition: pointset.h:909
coordtype * getpointMiddle(int_t n, double *c) const
Definition: pointset.h:1357
This class can be used for iterating a rectangular set of points, given its left and right bound.
Definition: pointset.h:1627
void reset()
Resets the current point to the first one in the range.
Definition: pointset.h:1737
int dim
The dimension of the space.
Definition: pointset.h:1651
tRectangle(const coordtype *_left=NULL, const coordtype *_right=NULL, int _dim=0)
The only possible constructor for new objects.
Definition: pointset.h:1699
int firstpoint
Should the 0 pointer be returned after the last point?
Definition: pointset.h:1663
~tRectangle()
The destructor.
Definition: pointset.h:1730
const coordtype * left
A pointer to the left point (not allocated!).
Definition: pointset.h:1654
void initialize(const coordtype *_left=NULL, const coordtype *_right=NULL, int _dim=0)
Initializes the internal data of an object of this class.
Definition: pointset.h:1677
tRectangle(const tRectangle< coordtype > &r)
The copy constructor.
Definition: pointset.h:1707
tRectangle & operator=(const tRectangle< coordtype > &r)
The assignment operator.
Definition: pointset.h:1714
void deallocate()
Deallocates any memory previously allocated for this object.
Definition: pointset.h:1722
const coordtype * get()
Returns the next point in the recatngle.
Definition: pointset.h:1746
const coordtype * right
A pointer to the right point (not allocated!).
Definition: pointset.h:1657
coordtype * point
The coordinates of a created point.
Definition: pointset.h:1660
A class for reading text data from a text file.
Definition: textfile.h:553
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
int readcubeorcell(std::istream &in, coordtype *left, coordtype *right, int maxdim, int *type=NULL)
Reads a cube or a cell from a text file.
Definition: pointset.h:2180
coordtype rounddown(double x)
Rounds down the given real number to an integral type.
Definition: pointset.h:214
void ignoreline(std::istream &in)
Ignores the input characters until the end of a line, including this end of the line.
Definition: textfile.h:376
void cubemiddle(coordtype *c, double *p, double *grid, int dim)
Computes the middle of a cube with its left lower etc.
Definition: pointset.h:245
outputstream sout
A replacement for standard output stream, with optional logging and other features provided by the cl...
int closingparenthesis(int ch)
Returns the matching closing parenthesis for the given opening one or EOF if none.
Definition: textfile.h:411
void enhancepoint(tPointset< coordtype > &p, coordtype *c)
Enhances the set by adding the neighborhood of the point with given coordinates.
Definition: pointset.h:1965
void roundpoint(const double *p, coordtype *c, const double *grid, int dim)
Rounds down the double coordinates of a point to integer ones.
Definition: pointset.h:226
tRectangle< coordinate > rectangle
The rectangle class with the default type of coordinates.
Definition: pointset.h:87
std::ostream & operator<<(std::ostream &out, const bincube< Dim, twoPower > &b)
Definition: bincube.h:907
void wrapcoord(coordtype *destination, const coordtype *source, const coordtype *wrap, int dim)
Wraps coordinates stored in 'c' accordint to the wrap table 'wrap' and store the result in the table ...
Definition: pointset.h:119
int write(std::ostream &out, const coordtype *c, int dim, char parenthesis=40, char closing=0)
Definition: pointset.h:2148
bool numberisprime(unsigned n)
Verifies if the given number is a prime number.
Definition: pointset.h:155
tPointset< coordtype > * computeboundary(tPointset< coordtype > &p)
Creates the set of all the boundary points with the 'new' operator.
Definition: pointset.h:1944
tPointset< coordinate > pointset
The pointset class with the default type of coordinates.
Definition: pointset.h:81
coordtype * allocatepoint(int dim, char *errormessage=NULL)
Allocate a point with 'new'. In case of failure throw an error message.
Definition: pointset.h:262
int readparenthesis(std::istream &in)
Reads an opening parenthesis from the input file.
Definition: textfile.h:432
tNeighbors< coordinate > neighbors
The neighbors class with the default type of coordinates.
Definition: pointset.h:84
int_t findboundarypoint(tPointset< coordtype > &p, int_t n, int direction=1)
Finds a boundary point starting at the given one.
Definition: pointset.h:1858
int thesame(const coordtype *c1, const coordtype *c2, int dim)
Compare two points. Returns true iff they have the same coordinates.
Definition: pointset.h:98
void enhance(tPointset< coordtype > &p)
Enhances the set of points by adding to it all the neighbors of all the points in the set.
Definition: pointset.h:1984
short int coordinate
The default type of coordinates.
Definition: pointset.h:63
int readcoordinates(std::istream &in, coordtype *coord, int maxdim, int closing)
Reads the coordinates of a point.
Definition: pointset.h:2073
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 & operator>>(std::istream &in, bincube< Dim, twoPower > &b)
Definition: bincube.h:914
int attheborder(const tPointset< coordtype > &p, const coordtype *c)
Verifies if the point is at the border of a given set.
Definition: pointset.h:1851
int_t pointhashkey(const coordtype *c, int dim, int_t hashsize)
Generates the main hashing key for points.
Definition: pointset.h:180
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
void copycoord(coordtype *destination, const coordtype *source, int dim)
Copies the coordinates of one point to another.
Definition: pointset.h:108
unsigned ceilprimenumber(unsigned n)
Computes the smallest prime number greater than or equal to the given number.
Definition: pointset.h:170
int countneighbors(const tPointset< coordtype > &p, const coordtype *c, int which=1, int maxcount=0)
Counts how many neighbors of the point there are in the set, depending on 'which': 1 = in the set,...
Definition: pointset.h:1785
int_t pointhashadd(const coordtype *c, int dim, int_t hashsize)
Generates the second hashing key for points.
Definition: pointset.h:198
void wrapcoord< double >(double *destination, const double *source, const double *wrap, int dim)
Wraps coordinates stored in 'c' accordint to the wrap table 'wrap' and store the result in the table ...
Definition: pointset.h:142
void swap(mwWorkerData &data1, mwWorkerData &data2)
Definition: mwcoord.h:108
This namespace contains the entire CHomP library interface.
Definition: bitmaps.h:51
#define INSIDE
Definition: pointset.h:273
#define CUBE
Definition: pointset.h:357
#define OUTSIDE
Definition: pointset.h:274
#define CELL
Definition: pointset.h:356
This file contains some useful functions related to the text input/output procedures.