bincube.h

Go to the documentation of this file.
00001 
00002 
00003 
00017 
00018 // Copyright (C) 1997-2010 by Pawel Pilarczyk.
00019 //
00020 // This file is part of the Homology Library.  This library is free software;
00021 // you can redistribute it and/or modify it under the terms of the GNU
00022 // General Public License as published by the Free Software Foundation;
00023 // either version 2 of the License, or (at your option) any later version.
00024 //
00025 // This library is distributed in the hope that it will be useful,
00026 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00027 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00028 // GNU General Public License for more details.
00029 //
00030 // You should have received a copy of the GNU General Public License along
00031 // with this software; see the file "license.txt".  If not, write to the
00032 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00033 // MA 02111-1307, USA.
00034 
00035 // Started on November 17, 2005. Last revision: November 22, 2005.
00036 
00037 
00038 #ifndef _CHOMP_CUBES_BINCUBE_H_
00039 #define _CHOMP_CUBES_BINCUBE_H_
00040 
00041 #include "chomp/system/config.h"
00042 #include "chomp/struct/bitcount.h"
00043 #include "chomp/struct/hashsets.h"
00044 
00045 #include <iostream>
00046 #include <fstream>
00047 #include <ctime>
00048 #include <cstdlib>
00049 #include <cstring>
00050 #include <queue>
00051 
00052 namespace chomp {
00053 namespace homology {
00054 
00055 
00056 // --------------------------------------------------
00057 // ---------------------- n^k -----------------------
00058 // --------------------------------------------------
00059 
00062 template <int number, int power>
00063 class Power
00064 {
00065 public:
00066         static const int value = Power<number,power-1>::value * number;
00067 }; /* Power */
00068 
00071 template <int number>
00072 class Power<number,0>
00073 {
00074 public:
00075         static const int value = 1;
00076 }; /* Power */
00077 
00078 
00079 // --------------------------------------------------
00080 // --------------- SET OF FULL CUBES ----------------
00081 // --------------------------------------------------
00082 
00085 class SetOfFullCubes
00086 {
00087 public:
00091         class OutOfRange
00092         {
00093         };
00094 };
00095 
00096 
00097 // --------------------------------------------------
00098 // --------------------- BITMAP ---------------------
00099 // --------------------------------------------------
00100 
00105 template <int Dim, int twoPower>
00106 class FixDimBitmap
00107 {
00108 public:
00109 protected:
00110 }; /* class FixDimBitmap */
00111 
00112 
00113 // --------------------------------------------------
00114 // -------------------- BINCUBE ---------------------
00115 // --------------------------------------------------
00116 
00119 template <int Dim, int twoPower>
00120 class bincube: public FixDimBitmap<Dim,twoPower>, public SetOfFullCubes
00121 {
00122 public:
00124         bincube ();
00125         
00128         bincube (char *buffer);
00129         
00131         bincube (const bincube<Dim,twoPower> &b);
00132 
00134         bincube<Dim,twoPower> &operator = (const bincube<Dim,twoPower> &b);
00135 
00137         ~bincube ();
00138 
00140         static int dimension ();
00141         static const int MaxDim;
00142 
00146         int findcube (int start = 0) const;
00147 
00149         class iterator
00150         {
00151                 friend class bincube<Dim,twoPower>;
00152         public:
00154                 typedef int CoordType;
00155 
00157                 iterator (bincube<Dim,twoPower> *bcub = 0, int num = -1);
00158 
00161                 iterator &operator ++ ();
00162 
00164                 iterator &operator ++ (int);
00165 
00167                 operator int () const;
00168 
00170                 static const int MaxDim;
00171                 
00173                 static int dim ();
00174 
00176                 const int *coord () const;
00177 
00179                 template <class intType>
00180                 intType *coord (intType *tab) const;
00181 
00182 //      protected:
00184                 bincube<Dim,twoPower> *b;
00185 
00187                 int n;
00188 
00189         }; /* class iterator */
00190 
00192         iterator begin ();
00193         
00195         iterator end ();
00196 
00198         static const int max_neighbors;
00199 
00201         class neighborhood_iterator: public iterator
00202         {
00203         public:
00205                 neighborhood_iterator (bincube<Dim,twoPower> *bcub = 0,
00206                         int n = -1, int inicur = -1);
00207 
00210                 neighborhood_iterator &operator ++ ();
00211 
00213                 neighborhood_iterator &operator ++ (int);
00214 
00216                 operator int () const;
00217 
00219         //      operator iterator () const;
00220 
00222 //              friend bool operator ==
00223 //                      (const bincube<Dim,twoPower>::neighborhood_iterator &x1,
00224 //                      const bincube<Dim,twoPower>::neighborhood_iterator &x2);
00225 
00226         protected:
00228                 bincube<Dim,twoPower> *b;
00229 
00231                 int coord [Dim];
00232 
00234                 int ncoord [Dim];
00235 
00237                 int curnum;
00238 
00240                 int cur;
00241 
00242         }; /* class neighborhood_iterator */
00243 
00246         neighborhood_iterator neighborhood_begin (int number) const;
00247 
00249         neighborhood_iterator neighborhood_end (int number) const;
00250 
00253         void add (int number);
00254 
00257         template <class intType>
00258         void add (const intType *coord);
00259 
00262         bool check (int number) const;
00263 
00266         template <class intType>
00267         bool check (const intType *coord) const;
00268 
00271         void remove (int number);
00272 
00275         template <class intType>
00276         void remove (const intType *coord);
00277 
00279         const char *getbuffer () const;
00280 
00282         operator const char * () const;
00283 
00285         static int getbufsize ();
00286 
00288         std::istream &read (std::istream &in);
00289 
00291         static bool wrapped (int dir);
00292 
00294         static void wrap (int dir);
00295 
00297         static void dontwrap (int dir);
00298 
00300         template <class intType>
00301         static intType wrap (intType coord, int dir);
00302 
00305         template <class intType>
00306         static int coord2num (const intType *coord);
00307 
00309         template <class intType>
00310         static intType *num2coord (int number, intType *coord);
00311 
00315         template <class intType>
00316         static const intType *num2coord (int number);
00317 
00319         int count () const;
00320         operator int () const;
00321 
00323         bool empty () const;
00324 
00326         void clear ();
00327 
00329         static const int maxcount;
00330 
00331 protected:
00333         char *buf;
00334         
00336         bool allocated;
00337         
00339         mutable int cardinality;
00340 
00342         static const int bufsize;
00343         
00345         static const int twoMask;
00346 
00348         static const int width;
00349 
00351         static int wrapping;
00352 
00353 }; /* class bincube */
00354 
00355 template <int Dim, int twoPower>
00356 const int bincube<Dim,twoPower>::bufsize = 1 << (Dim * twoPower - 3);
00357 
00358 template <int Dim, int twoPower>
00359 const int bincube<Dim,twoPower>::maxcount = 1 << (Dim * twoPower);
00360 
00361 template <int Dim, int twoPower>
00362 const int bincube<Dim,twoPower>::twoMask = ~0u >> (32 - twoPower);
00363 
00364 template <int Dim, int twoPower>
00365 const int bincube<Dim,twoPower>::width = 1 << twoPower;
00366 
00367 template <int Dim, int twoPower>
00368 int bincube<Dim,twoPower>::wrapping = 0;
00369 
00370 template <int Dim, int twoPower>
00371 const int bincube<Dim,twoPower>::MaxDim = Dim;
00372 
00373 template <int Dim, int twoPower>
00374 const int bincube<Dim,twoPower>::iterator::MaxDim = Dim;
00375 
00376 template <int Dim, int twoPower>
00377 const int bincube<Dim,twoPower>::max_neighbors = Power<3,Dim>::value - 1;
00378 
00379 
00380 // --------------------------------------------------
00381 
00382 template <int Dim, int twoPower>
00383 inline bincube<Dim,twoPower>::bincube ()
00384 {
00385         buf = new char [bufsize];
00386         allocated = true;
00387         memset (buf, 0, bufsize);
00388         cardinality = 0;
00389         return;
00390 } /* bincube::bincube */
00391 
00392 template <int Dim, int twoPower>
00393 inline bincube<Dim,twoPower>::bincube (char *buffer)
00394 {
00395         buf = buffer;
00396         allocated = false;
00397         cardinality = -1;
00398         return;
00399 } /* bincube::bincube */
00400 
00401 template <int Dim, int twoPower>
00402 inline bincube<Dim,twoPower>::bincube (const bincube<Dim,twoPower> &b)
00403 {
00404         buf = new char [bufsize];
00405         allocated = true;
00406         memcpy (buf, b. buf, bufsize);
00407         cardinality = b. cardinality;
00408         return;
00409 } /* bincube::bincube */
00410 
00411 template <int Dim, int twoPower>
00412 inline bincube<Dim,twoPower> &
00413         bincube<Dim,twoPower>::operator = (const bincube<Dim,twoPower> &b)
00414 {
00415         memcpy (buf, b. buf, bufsize);
00416         cardinality = b. cardinality;
00417         return;
00418 } /* bincube::bincube */
00419 
00420 template <int Dim, int twoPower>
00421 inline bincube<Dim,twoPower>::~bincube ()
00422 {
00423         if (allocated)
00424                 delete [] buf;
00425         return;
00426 } /* bincube::~bincube */
00427 
00428 // --------------------------------------------------
00429 
00430 template <int Dim, int twoPower>
00431 inline int bincube<Dim,twoPower>::dimension ()
00432 {
00433         return Dim;
00434 } /* bincube::dimension */
00435 
00436 template <int Dim, int twoPower>
00437 inline bool bincube<Dim,twoPower>::wrapped (int dir)
00438 {
00439         return bincube<Dim,twoPower>::wrapping & (1 << dir);
00440 } /* bincube::wrapped */
00441 
00442 template <int Dim, int twoPower>
00443 inline void bincube<Dim,twoPower>::wrap (int dir)
00444 {
00445         bincube<Dim,twoPower>::wrapping |= (1 << dir);
00446         return;
00447 } /* bincube::wrap */
00448 
00449 template <int Dim, int twoPower>
00450 inline void bincube<Dim,twoPower>::dontwrap (int dir)
00451 {
00452         bincube<Dim,twoPower>::wrapping &= ~(1 << dir);
00453         return;
00454 } /* bincube::dontwrap */
00455 
00456 template <int Dim, int twoPower>
00457 template <class intType>
00458 inline intType bincube<Dim,twoPower>::wrap (intType coord, int dir)
00459 {
00460         if (wrapped (dir))
00461         {
00462                 // this is fast but can be very slow if the
00463                 // coordinates are far from the actual binary cube
00464                 while (coord < 0)
00465                         coord += width;
00466                 while (coord >= width)
00467                         coord -= width;
00468         }
00469         return coord;
00470 } /* bincube::wrap */
00471 
00472 // --------------------------------------------------
00473 
00474 template <int Dim, int twoPower>
00475 template <class intType>
00476 inline int bincube<Dim,twoPower>::coord2num (const intType *coord)
00477 {
00478         int number = 0;
00479         for (int i = Dim - 1; i >= 0; -- i)
00480         {
00481                 int c = coord [i];
00482                 if (wrapped (i))
00483                 {
00484                         // this is fast but can be very slow if the
00485                         // coordinates are far from the actual binary cube
00486                         while (c < 0)
00487                                 c += width;
00488                         while (c >= width)
00489                                 c -= width;
00490                 }
00491                 else if ((c < 0) || (c >= width))
00492                         throw SetOfFullCubes::OutOfRange ();
00493                 number <<= twoPower;
00494                 number |= c;
00495         }
00496         return number;
00497 } /* bincube::coord2num */
00498 
00499 template <int Dim, int twoPower>
00500 template <class intType>
00501 inline intType *bincube<Dim,twoPower>::num2coord (int number, intType *coord)
00502 {
00503         for (int i = 0; i < Dim; ++ i)
00504         {
00505                 coord [i] = number & bincube<Dim,twoPower>::twoMask;
00506                 number >>= twoPower;
00507         }
00508         return coord;
00509 } /* bincube::num2coord */
00510 
00511 template <int Dim, int twoPower>
00512 template <class intType>
00513 inline const intType *bincube<Dim,twoPower>::num2coord (int /*number*/)
00514 {
00515         return 0;
00516 } /* bincube::num2coord */
00517 
00518 // --------------------------------------------------
00519 
00520 template <int Dim, int twoPower>
00521 inline int bincube<Dim,twoPower>::findcube (int start) const
00522 {
00523         // determine the offset of the byte containing the cube
00524         int offset = start >> 3;
00525 
00526         // don't look for cubes outside the valid range
00527         if (offset >= bufsize)
00528                 return maxcount;
00529 
00530         // look for a cube within this byte
00531         if (buf [offset])
00532         {
00533                 int bitnumber = start & 7;
00534                 while (bitnumber < 8)
00535                 {
00536                         if (buf [offset] & (1 << bitnumber))
00537                                 return (offset << 3) + bitnumber;
00538                         ++ bitnumber;
00539                 }
00540         }
00541 
00542         // search for a non-zero byte
00543         while (1)
00544         {
00545                 ++ offset;
00546                 if (offset >= bufsize)
00547                         return maxcount;
00548                 if (buf [offset])
00549                         break;
00550         }
00551 
00552         // retrieve the cube with the non-zero bit within this byte
00553         int bitnumber = 0;
00554         while (1)
00555         {
00556                 if (buf [offset] & (1 << bitnumber))
00557                         return (offset << 3) + bitnumber;
00558                 ++ bitnumber;
00559         }
00560 } /* bincube::findcube */
00561 
00562 // --------------------------------------------------
00563 
00564 template <int Dim, int twoPower>
00565 inline bool bincube<Dim,twoPower>::check (int number) const
00566 {
00567         return buf [number >> 3] & (1 << (number & 7));
00568 } /* bincube::check */
00569 
00570 template <int Dim, int twoPower>
00571 template <class intType>
00572 inline bool bincube<Dim,twoPower>::check (const intType *coord) const
00573 {
00574         return check (coord2num (coord));
00575 } /* bincube::check */
00576 
00577 template <int Dim, int twoPower>
00578 inline void bincube<Dim,twoPower>::add (int number)
00579 {
00580         if ((cardinality >= 0) && !check (number))
00581                 ++ cardinality;
00582         buf [number >> 3] |= (char) (1 << (number & 7));
00583         return;
00584 } /* bincube::add */
00585 
00586 template <int Dim, int twoPower>
00587 template <class intType>
00588 inline void bincube<Dim,twoPower>::add (const intType *coord)
00589 {
00590         return add (coord2num (coord));
00591 } /* bincube::add */
00592 
00593 template <int Dim, int twoPower>
00594 inline void bincube<Dim,twoPower>::remove (int number)
00595 {
00596         if ((cardinality > 0) && check (number))
00597                 -- cardinality;
00598         buf [number >> 3] &= (char) (~(1 << (number & 7)));
00599         return;
00600 } /* bincube::remove */
00601 
00602 template <int Dim, int twoPower>
00603 template <class intType>
00604 inline void bincube<Dim,twoPower>::remove (const intType *coord)
00605 {
00606         return remove (coord2num (coord));
00607 } /* bincube::remove */
00608 
00609 // --------------------------------------------------
00610 
00611 template <int Dim, int twoPower>
00612 inline bincube<Dim,twoPower>::iterator::iterator
00613         (bincube<Dim,twoPower> *bcub, int num): b (bcub), n (num)
00614 {
00615         return;
00616 } /* bincube::iterator::iterator */
00617 
00618 template <int Dim, int twoPower>
00619 inline typename bincube<Dim,twoPower>::iterator &
00620         bincube<Dim,twoPower>::iterator::operator ++ ()
00621 {
00622         if (!b || (n >= bincube<Dim,twoPower>::maxcount))
00623                 return *this;
00624         n = b -> findcube (n + 1);
00625         return *this;
00626 } /* bincube::iterator::operator ++ */
00627 
00628 template <int Dim, int twoPower>
00629 inline typename bincube<Dim,twoPower>::iterator &
00630         bincube<Dim,twoPower>::iterator::operator ++ (int)
00631 {
00632         iterator prev = *this;
00633         ++ *this;
00634         return prev;
00635 } /* bincube::iterator::operator ++ */
00636 
00637 template <int Dim, int twoPower>
00638 inline bincube<Dim,twoPower>::iterator::operator int () const
00639 {
00640         return n;
00641 } /* bincube::iterator::operator int */
00642 
00643 template <int Dim, int twoPower>
00644 inline int bincube<Dim,twoPower>::iterator::dim ()
00645 {
00646         return Dim;
00647 } /* bincube::iterator::dim */
00648 
00649 template <int Dim, int twoPower>
00650 inline const int *bincube<Dim,twoPower>::iterator::coord () const
00651 {
00652         return 0;
00653 } /* bincube::coord */
00654 
00655 template <int Dim, int twoPower>
00656 template <class intType>
00657 inline intType *bincube<Dim,twoPower>::iterator::coord (intType *tab) const
00658 {
00659         return bincube<Dim,twoPower>::num2coord (n, tab);
00660 } /* bincube::coord */
00661 
00662 // --------------------------------------------------
00663 
00664 template <class coordinate>
00665 inline void bit2neighborAlg (int number, const coordinate *src,
00666         coordinate *dest, int Dim)
00667 {
00668         ++ number;
00669         for (int i = Dim - 1; i >= 0; -- i)
00670         {
00671                 dest [i] = src [i];
00672                 switch (number % 3)
00673                 {
00674                         case 2:
00675                                 -- (dest [i]);
00676                                 break;
00677                         case 1:
00678                                 ++ (dest [i]);
00679                                 break;
00680                         case 0:
00681                                 break;
00682                         default:
00683                                 throw "Erratic neighbor.";
00684                 }
00685                 number /= 3;
00686         }
00687 
00688         return;
00689 } /* bit2neighborAlg */
00690 
00691 template <class settype>
00692 typename settype::iterator bit2neighborAlg
00693         (const typename settype::iterator &q, int n)
00694 {
00695         const int Dim = settype::MaxDim;
00696         int coord [Dim];
00697         q. b -> num2coord (q, coord);
00698         bit2neighborAlg (n, coord, coord, Dim);
00699         try
00700         {
00701                 return typename settype::iterator (q. b,
00702                         q. b -> coord2num (coord));
00703         }
00704         catch (...)
00705         {
00706         }
00707         return q;
00708 } /* bit2neighborAlg */
00709 
00710 // --------------------------------------------------
00711 
00712 template <int Dim, int twoPower>
00713 inline bincube<Dim,twoPower>::neighborhood_iterator::neighborhood_iterator
00714         (bincube<Dim,twoPower> *bcub, int num, int inicur):
00715         b (bcub), curnum (-1), cur (inicur)
00716 {
00717         if (b && (num >= 0))
00718                 b -> num2coord (num, coord);
00719         if (num == bincube<Dim,twoPower>::max_neighbors)
00720         {
00721                 for (int i = 0; i < Dim; ++ i)
00722                         ncoord [i] = 0;
00723         }
00724         return;
00725 } /* bincube::neighborhood_iterator::neighborhood_iterator */
00726 
00727 template <int Dim, int twoPower>
00728 inline typename bincube<Dim,twoPower>::neighborhood_iterator &
00729         bincube<Dim,twoPower>::neighborhood_iterator::operator ++ ()
00730 {
00731         if (!b || (cur >= bincube<Dim,twoPower>::max_neighbors))
00732                 return *this;
00733         while (1)
00734         {
00735                 ++ cur;
00736                 if (cur >= bincube<Dim,twoPower>::max_neighbors)
00737                 {
00738                         for (int i = 0; i < Dim; ++ i)
00739                                 ncoord [i] = 0;
00740                         curnum = -1;
00741                         return *this;
00742                 }
00743                 bit2neighborAlg (cur, coord, ncoord, Dim);
00744                 try
00745                 {
00746                         curnum = b -> coord2num (ncoord);
00747                         if (b -> check (curnum))
00748                                 return *this;
00749                 }
00750                 catch (...)
00751                 {
00752                 }
00753         }
00754         return *this;
00755 } /* bincube::iterator::operator ++ */
00756 
00757 template <int Dim, int twoPower>
00758 inline typename bincube<Dim,twoPower>::neighborhood_iterator &
00759         bincube<Dim,twoPower>::neighborhood_iterator::operator ++ (int)
00760 {
00761         if (!b || (cur >= bincube<Dim,twoPower>::maxcount))
00762                 return *this;
00763         neighborhood_iterator prev = *this;
00764         ++ (*this);
00765         return prev;
00766 } /* bincube::neighborhood_iterator::operator ++ */
00767 
00768 template <int Dim, int twoPower>
00769 inline bincube<Dim,twoPower>::neighborhood_iterator::operator int () const
00770 {
00771         return curnum;
00772 } /* bincube::neighborhood_iterator::operator int */
00773 
00774 template <int Dim, int twoPower>
00775 inline bool operator ==
00776         (const typename bincube<Dim,twoPower>::neighborhood_iterator &x1,
00777         const typename bincube<Dim,twoPower>::neighborhood_iterator &x2)
00778 {
00779 //      sout << "DEBUG ==\n";
00780         return ((x1. b == x2. b) && (x1. cur == x2. cur));
00781 } /* bincube::neighborhood_iterator::operator == */
00782 
00783 template <int Dim, int twoPower>
00784 inline bool operator !=
00785         (const typename bincube<Dim,twoPower>::neighborhood_iterator &x1,
00786         const typename bincube<Dim,twoPower>::neighborhood_iterator &x2)
00787 {
00788 //      sout << "DEBUG !=\n";
00789         return !(x1 == x2);
00790 } /* bincube::neighborhood_iterator::operator != */
00791 
00792 // --------------------------------------------------
00793 
00794 template <int Dim, int twoPower>
00795 inline typename bincube<Dim,twoPower>::neighborhood_iterator
00796         bincube<Dim,twoPower>::neighborhood_begin (int n) const
00797 {
00798         typename bincube<Dim,twoPower>::neighborhood_iterator iter
00799                 (const_cast<bincube<Dim,twoPower> *> (this), n);
00800         return ++ iter;
00801 } /* bincube::neighborhood_begin */
00802 
00803 template <int Dim, int twoPower>
00804 inline typename bincube<Dim,twoPower>::neighborhood_iterator
00805         bincube<Dim,twoPower>::neighborhood_end (int n) const
00806 {
00807         return neighborhood_iterator
00808                 (const_cast<bincube<Dim,twoPower> *> (this), n,
00809                 max_neighbors);
00810 } /* bincube::neighborhood_end */
00811 
00812 // --------------------------------------------------
00813 
00814 template <int Dim, int twoPower>
00815 inline typename bincube<Dim,twoPower>::iterator
00816         bincube<Dim,twoPower>::begin ()
00817 {
00818         return iterator (this, findcube ());
00819 } /* bincube::begin */
00820 
00821 template <int Dim, int twoPower>
00822 inline typename bincube<Dim,twoPower>::iterator
00823         bincube<Dim,twoPower>::end ()
00824 {
00825         return iterator (this, maxcount);
00826 } /* bincube::end */
00827 
00828 // --------------------------------------------------
00829 
00830 template <int Dim, int twoPower>
00831 inline const char *bincube<Dim,twoPower>::getbuffer () const
00832 {
00833         return buf;
00834 } /* bincube::getbuffer */
00835 
00836 template <int Dim, int twoPower>
00837 inline bincube<Dim,twoPower>::operator const char * () const
00838 {
00839         return buf;
00840 } /* bincube::operator const char * */
00841 
00842 template <int Dim, int twoPower>
00843 inline int bincube<Dim,twoPower>::getbufsize ()
00844 {
00845         return bufsize;
00846 } /* bincube::getbufsize */
00847 
00848 template <int Dim, int twoPower>
00849 inline std::istream &bincube<Dim,twoPower>::read (std::istream &in)
00850 {
00851         in. read (buf, bufsize);
00852         cardinality = -1;
00853         return in;
00854 } /* bincube::read */
00855 
00856 // --------------------------------------------------
00857 
00858 template <int Dim, int twoPower>
00859 inline int bincube<Dim,twoPower>::count () const
00860 {
00861         if (cardinality >= 0)
00862                 return cardinality;
00863         char *byte = buf;
00864         char *end = byte + bufsize;
00865         int c = 0;
00866         while (byte != end)
00867         {
00868                 c += bitcountbyte (*byte);
00869                 ++ byte;
00870         }
00871         cardinality = c;
00872         return cardinality;
00873 } /* bincube::count */
00874 
00875 template <int Dim, int twoPower>
00876 inline bincube<Dim,twoPower>::operator int () const
00877 {
00878         return count ();
00879 } /* bincube::operator int */
00880 
00881 template <int Dim, int twoPower>
00882 inline bool bincube<Dim,twoPower>::empty () const
00883 {
00884         return !count ();
00885 } /* bincube::empty */
00886 
00887 template <int Dim, int twoPower>
00888 inline void bincube<Dim,twoPower>::clear ()
00889 {
00890         memset (buf, 0, bufsize);
00891         cardinality = 0;
00892         return;
00893 } /* bincube::clear */
00894 
00895 // --------------------------------------------------
00896 
00897 template <int Dim, int twoPower>
00898 inline std::ostream &operator << (std::ostream &out,
00899         const bincube<Dim,twoPower> & b)
00900 {
00901         return out. write (static_cast<const char *> (b), b. getbufsize ());
00902 } /* operator << */
00903 
00904 template <int Dim, int twoPower>
00905 inline std::istream &operator >> (std::istream &in,
00906         bincube<Dim,twoPower> & b)
00907 {
00908         return b. read (in);
00909 } /* operator >> */
00910 
00911 // --------------------------------------------------
00912 
00916 template <class cubetype, class settype>
00917 class NeighborsBdd
00918 {
00919 public:
00920         // the default constructor
00921         NeighborsBdd (const cubetype &middle, const settype &cset):
00922                 q (middle), s (cset) {};
00923 
00924         // the procedure for checking whether the given neighbor exists;
00925         // the number of the neighbor is consistent with the "bit2neighbor"
00926         // and "neighbor2bit" procedures
00927         bool check (int n) const
00928         {
00929                 cubetype neighbor = bit2neighborAlg<settype> (q, n);
00930                 if (neighbor == q)
00931                         return false;
00932                 return (s. check (neighbor));
00933         }
00934 
00935 private:
00936         // the cube whose neighbors are verified
00937         const cubetype &q;
00938 
00939         // the set of cubes in which the neighbors of the cube are sought
00940         const settype &s;
00941 
00942 }; /* class NeighborsBdd */
00943 
00946 template <class SetT>
00947 class Acyclic1d
00948 {
00949 public:
00950         static bool check (typename SetT::iterator q, const SetT &s)
00951         {
00952                 NeighborsBdd<typename SetT::iterator,SetT> n (q, s);
00953                 return acyclic1d (n);
00954         }
00955         static bool check (int n, const SetT &s)
00956         {
00957                 // FIX const cast!
00958                 typename SetT::iterator q (const_cast<SetT *> (&s), n);
00959                 return check (q, s);
00960         }
00961 }; /* Acyclic1d */
00962 
00965 template <class SetT>
00966 class Acyclic2d
00967 {
00968 public:
00969         static bool check (typename SetT::iterator q, const SetT &s)
00970         {
00971                 NeighborsBdd<typename SetT::iterator,SetT> n (q, s);
00972                 return acyclic2d (n);
00973         }
00974         static bool check (int n, const SetT &s)
00975         {
00976                 // FIX const cast!
00977                 typename SetT::iterator q (const_cast<SetT *> (&s), n);
00978                 return check (q, s);
00979         }
00980 }; /* Acyclic2d */
00981 
00984 template <class SetT>
00985 class Acyclic3d
00986 {
00987 public:
00988         static bool check (typename SetT::iterator q, const SetT &s)
00989         {
00990                 NeighborsBdd<typename SetT::iterator,SetT> n (q, s);
00991                 return acyclic3d (n);
00992         }
00993         static bool check (int n, const SetT &s)
00994         {
00995                 // FIX const cast!
00996                 typename SetT::iterator q (const_cast<SetT *> (&s), n);
00997                 return check (q, s);
00998         }
00999 }; /* Acyclic3d */
01000 
01001 // --------------------------------------------------
01002 
01004 template <class Number>
01005 class hashNumber
01006 {
01007 public:
01009         hashNumber (Number n = 0): number (n) {return;}
01010 
01012         operator Number () const {return number;}
01013 
01014 protected:
01015         int number;
01016 }; /* hashNumber */
01017 
01019 template <class Number>
01020 inline int_t hashkey1 (const hashNumber<Number> &n)
01021 {
01022         return static_cast<int_t> (static_cast<Number> (n));
01023 } /* hashkey1 */
01024 
01026 template <class Number>
01027 inline int_t hashkey2 (const hashNumber<Number> &n)
01028 {
01029         return static_cast<int_t> (static_cast<Number> (n) ^
01030                 0xFA5A75A7ul) << 5;
01031 } /* hashkey2 */
01032 
01033 typedef hashedset<hashNumber<int> > hashIntQueue;
01034 
01035 // --------------------------------------------------
01036 
01038 template <class SetT, class QueueT>
01039 void addneighbors (const int &c, const SetT &s, QueueT &q)
01040 {
01041         typename SetT::neighborhood_iterator cur = s. neighborhood_begin (c),
01042                 end = s. neighborhood_end (c);
01043         while (cur != end)
01044         {
01045                 q. add (hashNumber<int> (cur));
01046                 ++ cur;
01047         }
01048         return;
01049 } /* addneighbors */
01050 
01055 template <typename SetT, typename Acyclic, typename QueueT>
01056 int reduceFullCubesAlg (SetT &X, bool quiet)
01057 {
01058         // prepare the set of cubes to consider next time
01059         QueueT Q;
01060 
01061         // scan the entire set until very few cubes are removed
01062         int count = 0;
01063         bool exitloop = false;
01064         bool lastrun = false;
01065         while (!exitloop)
01066         {
01067                 // remember to exit the loop after the last run
01068                 if (lastrun)
01069                         exitloop = true;
01070 
01071                 int countremoved = 0, countleft = 0;
01072                 typename SetT::iterator cur = X. begin (), end = X. end ();
01073                 while (cur != end)
01074                 {
01075                         if (Acyclic::check (cur, X))
01076                         {
01077                                 X. remove (cur);
01078                                 ++ countremoved;
01079                                 if (lastrun)
01080                                         addneighbors (cur, X, Q);
01081                         }
01082                         else
01083                                 ++ countleft;
01084                         ++ cur;
01085         
01086                         // show progress indicator
01087                         if (!quiet && !(count % 5273))
01088                                 scon << std::setw (10) << count <<
01089                                         "\b\b\b\b\b\b\b\b\b\b";
01090                         ++ count;
01091                 }
01092                 if (!quiet)
01093                         sout << ".";
01094 
01095                 if (!lastrun && (countremoved - 10 < (countleft >> 2)))
01096                         lastrun = true;
01097         }
01098         
01099         if (!quiet)
01100                 sout << " ";
01101         count = 0;
01102         while (!Q. empty ())
01103         {
01104                 typename QueueT::value_type elem = Q. front ();
01105                 Q. pop ();
01106                 if (Acyclic::check (elem, X))
01107                 {
01108                         X. remove (elem);
01109                         addneighbors (elem, X, Q);
01110                 }
01111 
01112                 // show progress indicator
01113                 if (!quiet && !(count % 5273))
01114                         scon << std::setw (10) << count <<
01115                                 "\b\b\b\b\b\b\b\b\b\b";
01116                 count ++;
01117         }
01118 
01119         return 0;
01120 } /* reduceFullCubesAlg */
01121 
01122 /*
01124 template <int Dim, int twoPower>
01125 inline int reduceFullCubes (bincube<Dim,twoPower> &X, bool quiet = false)
01126 {
01127         throw "Binary cube reduction not implemented "
01128                 "for dimension > 3.";
01129 }
01130 
01132 template <int twoPower>
01133 inline int reduceFullCubes<3,twoPower> (bincube<3,twoPower> &X, bool quiet = false)
01134 {
01135         return reduceFullCubesAlg<bincube<3,twoPower>,
01136                 Acyclic3d<bincube<3,twoPower> >,hashIntQueue> (X, quiet);
01137 }
01138 
01140 template <int twoPower>
01141 inline int reduceFullCubes<2,twoPower> (bincube<2,twoPower> &X, bool quiet = false)
01142 {
01143         return reduceFullCubesAlg<bincube<2,twoPower>,
01144                 Acyclic2d<bincube<2,twoPower> >,hashIntQueue> (X, quiet);
01145 }
01146 
01148 template <int twoPower>
01149 inline int reduceFullCubes<1,twoPower> (bincube<1,twoPower> &X, bool quiet = false)
01150 {
01151         return reduceFullCubesAlg<bincube<1,twoPower>,
01152                 Acyclic1d<bincube<1,twoPower> >,hashIntQueue> (X, quiet);
01153 }
01154 */
01155 
01157 template <class FullCubSet>
01158 inline int reduceFullCubes (FullCubSet &X, bool quiet = false)
01159 {
01160         switch (X. dimension ())
01161         {
01162                 case 3:
01163                         return reduceFullCubesAlg<FullCubSet,
01164                                 Acyclic3d<FullCubSet>,hashIntQueue> (X, quiet);
01165                 case 2:
01166                         return reduceFullCubesAlg<FullCubSet,
01167                                 Acyclic2d<FullCubSet>,hashIntQueue> (X, quiet);
01168                 case 1:
01169                         return reduceFullCubesAlg<FullCubSet,
01170                                 Acyclic1d<FullCubSet>,hashIntQueue> (X, quiet);
01171                 default:
01172                         throw "Binary cube reduction not implemented "
01173                                 "for dimension > 3.";
01174         }
01175 } /* reduceFullCubes */
01176 
01177 
01178 } // namespace homology
01179 } // namespace chomp
01180 
01181 #endif // _CHOMP_CUBES_BINCUBE_H_
01182 
01184