• Main Page
  • Classes
  • Files
  • File List
  • File Members

chaincon/cubcell.h

Go to the documentation of this file.
00001 /////////////////////////////////////////////////////////////////////////////
00002 ///
00003 /// \file
00004 ///
00005 /// A cubical cell.
00006 ///
00007 /////////////////////////////////////////////////////////////////////////////
00008 
00009 // Copyright (C) 2009-2011 by Pawel Pilarczyk.
00010 //
00011 // This file is part of my research software package. This is free software:
00012 // you can redistribute it and/or modify it under the terms of the GNU
00013 // General Public License as published by the Free Software Foundation,
00014 // either version 3 of the License, or (at your option) any later version.
00015 //
00016 // This software is distributed in the hope that it will be useful,
00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00019 // GNU General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU General Public License
00022 // along with this software; see the file "license.txt". If not,
00023 // please, see <http://www.gnu.org/licenses/>.
00024 
00025 // Started on March 24, 2009. Last revision: March 4, 2011.
00026 
00027 
00028 #ifndef _CHAINCON_CUBCELL_H_
00029 #define _CHAINCON_CUBCELL_H_
00030 
00031 
00032 // include some standard C++ header files
00033 #include <istream>
00034 #include <ostream>
00035 #include <algorithm>
00036 #include <vector>
00037 
00038 // include selected header files from the CHomP library
00039 #include "chomp/system/config.h"
00040 #include "chomp/cubes/pointbas.h"
00041 
00042 // include relevant local header files
00043 #include "chaincon/emptycell.h"
00044 
00045 
00046 // --------------------------------------------------
00047 // ------------------ cubical cell ------------------
00048 // --------------------------------------------------
00049 
00050 /// An elementary cubical cell with vertices of integer type.
00051 template <class CoordT>
00052 class tCubCell
00053 {
00054 public:
00055         /// The type of coordinates.
00056         typedef CoordT CoordType;
00057 
00058         /// The default constructor of an empty cube.
00059         tCubCell ();
00060 
00061         /// The constructor of a full cube from an array of coordinates.
00062         template <class CoordArray>
00063         tCubCell (int dimension, const CoordArray &coordinates);
00064 
00065         /// The constructor of a full cube from two arrays of coordinates.
00066         template <class CoordArray>
00067         tCubCell (int dimension, const CoordArray &left,
00068                 const CoordArray &right);
00069 
00070         /// The copy constructor.
00071         tCubCell (const tCubCell<CoordT> &c);
00072 
00073         /// The constructor of the n-th boundary cube.
00074         tCubCell (const tCubCell<CoordT> &c, int n);
00075 
00076         /// The constructor of the n-th component of the Alexander-Whitney
00077         /// diagonal, either the left one (if side = 0), or the right one
00078         /// (if side = 1).
00079         tCubCell (const tCubCell<CoordT> &c, int n, int side);
00080 
00081         /// The assignment operator.
00082         tCubCell<CoordT> &operator = (const tCubCell<CoordT> &s);
00083 
00084         /// The destructor.
00085         ~tCubCell ();
00086 
00087         /// Returns the dimension of the embedding space.
00088         int spaceDim () const;
00089 
00090         /// Returns the dimension of the elementary cube.
00091         int dim () const;
00092 
00093         /// Returns the n-th left coordinate of the elementary cube.
00094         const CoordT left (int n) const;
00095 
00096         /// Returns the n-th right coordinate of the elementary cube.
00097         const CoordT right (int n) const;
00098 
00099         /// Returns the length of the boundary of the elementary cube.
00100         int boundaryLength () const;
00101 
00102         /// Returns the n-th coefficient in the boundary of the cube.
00103         int boundaryCoef (int n) const;
00104 
00105         /// Returns the number of terms in the Alexander-Whitneney diagonal.
00106         int diagonalLength () const;
00107 
00108         /// The equality operator.
00109         bool operator == (const tCubCell<CoordT> &s) const;
00110 
00111         /// Swaps the data between two cubical cells.
00112         void swap (tCubCell<CoordT> &s);
00113 
00114 private:
00115         /// The number that defines the left corner of the elementary cube.
00116         /// The dimension of the embedding space is stored in high bits
00117         /// of this number.
00118         int_t n1;
00119 
00120         /// The number that defines the right corner of the elementary cube.
00121         /// The dimension of the cubical cell is stored in the high bits
00122         /// of this number.
00123         int_t n2;
00124 
00125 }; /* class tCubCell */
00126 
00127 // --------------------------------------------------
00128 
00129 template <class CoordT>
00130 inline tCubCell<CoordT>::tCubCell (): n1 (0), n2 (0)
00131 {
00132         return;
00133 } /* tCubCell::tCubCell */
00134 
00135 template <class CoordT>
00136 template <class CoordArray>
00137 inline tCubCell<CoordT>::tCubCell (int dimension,
00138         const CoordArray &coordinates): n1 (0), n2 (0)
00139 {
00140         // if the embedding space dimension is not positive
00141         // then create the empty cubical cell
00142         if (dimension <= 0)
00143                 return;
00144 
00145         // compute the number that represents the left corner of the cell
00146         CoordT c [chomp::homology::MaxBasDim];
00147         for (int i = 0; i < dimension; ++ i)
00148                 c [i] = coordinates [i];
00149         n1 = chomp::homology::tPointBase<CoordT>::number (c, dimension);
00150         n1 |= dimension << chomp::homology::NumBits;
00151 
00152         // compute the number that represents the right corner of the cell
00153         for (int i = 0; i < dimension; ++ i)
00154                 ++ (c [i]);
00155         n2 = chomp::homology::tPointBase<CoordT>::number (c, dimension);
00156         n2 |= dimension << chomp::homology::NumBits;
00157 
00158         return;
00159 } /* tCubCell::tCubCell */
00160 
00161 template <class CoordT>
00162 template <class CoordArray>
00163 inline tCubCell<CoordT>::tCubCell (int dimension,
00164         const CoordArray &left, const CoordArray &right): n1 (0), n2 (0)
00165 {
00166         // if the embedding space dimension is not positive
00167         // then create the empty cubical cell
00168         if (dimension <= 0)
00169                 return;
00170 
00171         // compute the dimension of the cell
00172         int cellDimension = 0;
00173         for (int i = 0; i < dimension; ++ i)
00174         {
00175                 if (left [i] != right [i])
00176                         ++ cellDimension;
00177         }
00178 
00179         // compute the number that represents the left corner of the cell
00180         CoordT c [chomp::homology::MaxBasDim];
00181         for (int i = 0; i < dimension; ++ i)
00182                 c [i] = left [i];
00183         n1 = chomp::homology::tPointBase<CoordT>::number (c, dimension);
00184         n1 |= dimension << chomp::homology::NumBits;
00185 
00186         // compute the number that represents the right corner of the cell
00187         for (int i = 0; i < dimension; ++ i)
00188                 c [i] = right [i];
00189         n2 = chomp::homology::tPointBase<CoordT>::number (c, dimension);
00190         n2 |= cellDimension << chomp::homology::NumBits;
00191 
00192         return;
00193 } /* tCubCell::tCubCell */
00194 
00195 template <class CoordT>
00196 inline tCubCell<CoordT>::tCubCell (const tCubCell<CoordT> &c):
00197         n1 (c. n1), n2 (c. n2)
00198 {
00199         return;
00200 } /* tCubCell::tCubCell */
00201 
00202 template <class CoordT>
00203 inline tCubCell<CoordT>::tCubCell (const tCubCell<CoordT> &c, int n)
00204 {
00205         // determine the dimension of the embedding space and of the cell
00206         int spaceDimension = c. spaceDim ();
00207         int cellDimension = c. dim ();
00208 
00209         // prepare arrays for the coordinates of the corners of the cell
00210         CoordT newLeft [chomp::homology::MaxBasDim];
00211         CoordT newRight [chomp::homology::MaxBasDim];
00212         for (int i = 0; i < spaceDimension; ++ i)
00213         {
00214                 newLeft [i] = c. left (i);
00215                 newRight [i] = c. right (i);
00216         }
00217 
00218         // if this is the first set of cells then squeeze rightwards
00219         bool squeezeRight = (n < cellDimension);
00220         if (n >= cellDimension)
00221                 n -= cellDimension;
00222         int counter = 0;
00223         bool squeezed = false;
00224         for (int i = 0; i < spaceDimension; ++ i)
00225         {
00226                 if (newLeft [i] != newRight [i])
00227                 {
00228                         if (n == counter)
00229                         {
00230                                 if (squeezeRight)
00231                                         newLeft [i] = newRight [i];
00232                                 else
00233                                         newRight [i] = newLeft [i];
00234                                 squeezed = true;
00235                                 break;
00236                         }
00237                         ++ counter;
00238                 }
00239         }
00240         if (!squeezed)
00241                 throw "Wrong boundary element requested.";
00242         n1 = chomp::homology::tPointBase<CoordT>::number
00243                 (newLeft, spaceDimension);
00244         n1 |= spaceDimension << chomp::homology::NumBits;
00245         n2 = chomp::homology::tPointBase<CoordT>::number
00246                 (newRight, spaceDimension);
00247         n2 |= (cellDimension - 1) << chomp::homology::NumBits;
00248         return;
00249 } /* tCubCell::tCubCell */
00250 
00251 /// The version of the AW diagonal. For testing only.
00252 static int diagVersion = 0;
00253 
00254 template <class CoordT>
00255 inline tCubCell<CoordT>::tCubCell (const tCubCell<CoordT> &c, int n,
00256         int side)
00257 {
00258         int cellDimension = c. dim ();
00259         if (cellDimension != 2)
00260                 throw "AW diagonal supported for cubes only in dim 2.";
00261         CoordT newLeft [chomp::homology::MaxBasDim];
00262         CoordT newRight [chomp::homology::MaxBasDim];
00263         int spaceDimension = c. spaceDim ();
00264         int indices [2];
00265         int index = 0;
00266         for (int i = 0; i < spaceDimension; ++ i)
00267         {
00268                 newLeft [i] = c. left (i);
00269                 newRight [i] = c. right (i);
00270                 if (newLeft [i] != newRight [i])
00271                         indices [index ++] = i;
00272         }
00273 
00274         if (diagVersion == 1)
00275         {
00276 
00277         if (side == 0)
00278         {
00279                 switch (n)
00280                 {
00281                 case 0:
00282                         newRight [indices [0]] = newLeft [indices [0]];
00283                         newLeft [indices [1]] = newRight [indices [1]];
00284                         break;
00285                 case 1:
00286                         break;
00287                 case 2:
00288                 case 3:
00289                         newLeft [indices [0]] = newRight [indices [0]];
00290                         break;
00291                 case 4:
00292                         newLeft [indices [1]] = newRight [indices [1]];
00293                         break;
00294                 case 5:
00295                         newRight [indices [0]] = newLeft [indices [0]];
00296                         break;
00297                 }
00298         }
00299         else
00300         {
00301                 switch (n)
00302                 {
00303                 case 0:
00304                         break;
00305                 case 1:
00306                         newRight [indices [0]] = newLeft [indices [0]];
00307                         newRight [indices [1]] = newLeft [indices [1]];
00308                         break;
00309                 case 2:
00310                         newLeft [indices [1]] = newRight [indices [1]];
00311                         break;
00312                 default:
00313                         newRight [indices [0]] = newLeft [indices [0]];
00314                         break;
00315                 }
00316         }
00317 
00318         }
00319 
00320         else if (diagVersion == 2)
00321         {
00322 
00323         if (side == 0)
00324         {
00325                 switch (n)
00326                 {
00327                 case 0:
00328                         newRight [indices [1]] = newLeft [indices [1]];
00329                         break;
00330                 case 1:
00331                         newLeft [indices [0]] = newRight [indices [0]];
00332                         break;
00333                 case 2:
00334                         newRight [indices [0]] = newLeft [indices [0]];
00335                         break;
00336                 }
00337         }
00338         else
00339         {
00340                 switch (n)
00341                 {
00342                 case 0:
00343                 case 1:
00344                         newLeft [indices [0]] = newRight [indices [0]];
00345                         break;
00346                 case 2:
00347                         newLeft [indices [1]] = newRight [indices [1]];
00348                         break;
00349                 }
00350         }
00351 
00352         }
00353 
00354         else if (diagVersion == 3)
00355         {
00356 
00357         if (side == 0)
00358         {
00359                 switch (n)
00360                 {
00361                 case 0:
00362                 case 1:
00363                         newRight [indices [1]] = newLeft [indices [1]];
00364                         break;
00365                 case 2:
00366                         newLeft [indices [0]] = newRight [indices [0]];
00367                         break;
00368                 }
00369         }
00370         else
00371         {
00372                 switch (n)
00373                 {
00374                 case 0:
00375                         newLeft [indices [0]] = newRight [indices [0]];
00376                         break;
00377                 case 1:
00378                 case 2:
00379                         newLeft [indices [1]] = newRight [indices [1]];
00380                         break;
00381                 }
00382         }
00383 
00384         }
00385 
00386         else
00387                 throw "Undefined version of A-W diagonal requested.\n";
00388 
00389         int newDimension = 0;
00390         for (int i = 0; i < spaceDimension; ++ i)
00391         {
00392                 if (newLeft [i] != newRight [i])
00393                         ++ newDimension;
00394         }
00395         n1 = chomp::homology::tPointBase<CoordT>::number
00396                 (newLeft, spaceDimension);
00397         n1 |= spaceDimension << chomp::homology::NumBits;
00398         n2 = chomp::homology::tPointBase<CoordT>::number
00399                 (newRight, spaceDimension);
00400         n2 |= newDimension << chomp::homology::NumBits;
00401         return;
00402 } /* tCubCell::tCubCell */
00403 
00404 template <class CoordT>
00405 inline tCubCell<CoordT> &tCubCell<CoordT>::operator =
00406         (const tCubCell<CoordT> &c)
00407 {
00408         n1 = c. n1;
00409         n2 = c. n2;
00410         return *this;
00411 } /* tCubCell::operator = */
00412 
00413 template <class CoordT>
00414 inline tCubCell<CoordT>::~tCubCell ()
00415 {
00416         return;
00417 } /* tCubCell::~tCubCell */
00418 
00419 template <class CoordT>
00420 inline int tCubCell<CoordT>::spaceDim () const
00421 {
00422         return (n1 >> chomp::homology::NumBits);
00423 } /* tCubCell::spaceDim */
00424 
00425 template <class CoordT>
00426 inline int tCubCell<CoordT>::dim () const
00427 {
00428         if ((n1 == 0) && (n2 == 0))
00429                 return -1;
00430         return (n2 >> chomp::homology::NumBits);
00431 } /* tCubCell::dim */
00432 
00433 template <class CoordT>
00434 inline const CoordT tCubCell<CoordT>::left (int n) const
00435 {
00436         return chomp::homology::tPointBase<CoordT>::coord
00437                 (n1 & chomp::homology::NumMask, spaceDim ()) [n];
00438 } /* tCubCell::left */
00439 
00440 template <class CoordT>
00441 inline const CoordT tCubCell<CoordT>::right (int n) const
00442 {
00443         return chomp::homology::tPointBase<CoordT>::coord
00444                 (n2 & chomp::homology::NumMask, spaceDim ()) [n];
00445 } /* tCubCell::right */
00446 
00447 template <class CoordT>
00448 inline int tCubCell<CoordT>::boundaryLength () const
00449 {
00450         int dimension = dim ();
00451 #ifdef NO_EMPTY_CELL
00452         return dimension << 1;
00453 #else
00454         return (dimension > 0) ? (dimension << 1) : 1;
00455 #endif
00456 } /* tCubCell::boundaryLength */
00457 
00458 template <class CoordT>
00459 inline int tCubCell<CoordT>::boundaryCoef (int n) const
00460 {
00461         int dimension = dim ();
00462         if (n >= dimension)
00463                 n -= dimension - 1;
00464         return (n & 1) ? -1 : 1;
00465 } /* tCubCell::boundaryCoef */
00466 
00467 template <class CoordT>
00468 inline int tCubCell<CoordT>::diagonalLength () const
00469 {
00470         if (dim () != 2)
00471                 throw "A-W diagonal supported only in dim 2.";
00472         return 3; //6;
00473 } /* tCubCell::diagonalLength */
00474 
00475 template <class CoordT>
00476 inline bool tCubCell<CoordT>::operator ==
00477         (const tCubCell<CoordT> &s) const
00478 {
00479         return (n1 == s. n1) && (n2 == s. n2);
00480 } /* tCubCell::operator == */
00481 
00482 template <class CoordT>
00483 inline void tCubCell<CoordT>::swap (tCubCell<CoordT> &s)
00484 {
00485         swap (n1, s. n1);
00486         swap (n2, s. n2);
00487         return;
00488 } /* tCubCell::swap */
00489 
00490 // --------------------------------------------------
00491 
00492 /// Generates a hashing key no. 1 for a cubical cell,
00493 /// composed of hashing keys for the coordinates.
00494 /// This key is to be used in a hashed set.
00495 template <class CoordT>
00496 inline int_t hashkey1 (const tCubCell<CoordT> &c)
00497 {
00498         using chomp::homology::hashkey1;
00499         using ::hashkey1;
00500         int d = c. spaceDim ();
00501         if (d <= 0)
00502                 return 0;
00503         else if (d == 1)
00504                 return hashkey1 (c. left (0)) << 2;
00505         else if (d == 2)
00506         {
00507                 return ((hashkey1 (c. left (0)) & 0x655555u) << 10) ^
00508                         ((hashkey1 (c. right (1)) & 0xAAAAAAu));
00509         }
00510         else
00511         {
00512                 return ((hashkey1 (c. left (0)) & 0x655555u) << 10) ^
00513                         ((hashkey1 (c. right (d >> 1)) & 0xAAAAAAu) << 4) ^
00514                         ((hashkey1 (c. left (d - 1)) & 0xAAAAAAu) >> 6);
00515         }
00516 } /* hashkey1 */
00517 
00518 /// Generates a hashing key no. 2 for a cubical cell,
00519 /// composed of hashing keys for the coordinates.
00520 /// This key is to be used in a hashed set.
00521 template <class CoordT>
00522 inline int_t hashkey2 (const tCubCell<CoordT> &c)
00523 {
00524         using chomp::homology::hashkey2;
00525         using ::hashkey2;
00526         int d = c. spaceDim ();
00527         if (d <= 0)
00528                 return 0;
00529         else if (d == 1)
00530                 return hashkey2 (c. right (0)) << 4;
00531         else if (d == 2)
00532         {
00533                 return ((hashkey2 (c. right (0)) & 0xAAAAAAu) >> 5) ^
00534                         ((hashkey2 (c. left (1)) & 0x555555u) << 7);
00535         }
00536         else
00537         {
00538                 return ((hashkey2 (c. right (d - 1)) & 0x555555u) << 9) ^
00539                         ((hashkey2 (c. right (0)) & 0xAAAAAAu) << 1) ^
00540                         ((hashkey2 (c. left (d >> 1)) & 0xAAAAAAu) >> 5);
00541         }
00542 } /* hashkey2 */
00543 
00544 // --------------------------------------------------
00545 
00546 /// Writes an elementary cube in the text mode to an output stream
00547 /// as the cartesian product of elementary intervals.
00548 template <class CoordT>
00549 std::ostream &operator << (std::ostream &out, const tCubCell<CoordT> &c)
00550 {
00551         int dim = c. spaceDim ();
00552         out << '[';
00553         for (int i = 0; i < dim; ++ i)
00554         {
00555                 if (i)
00556                         out << "]x[";
00557                 int left = c. left (i);
00558                 int right = c. right (i);
00559                 out << left;
00560                 if (left != right)
00561                         out << ',' << right;
00562         }
00563         out << ']';
00564         return out;
00565 } /* operator << */
00566 
00567 /// Reads an elementary cube from the input stream in the text format.
00568 /// Skips all the characters in the input stream until
00569 /// an opening parenthesis is found.
00570 /// Then reads the cartesian product that defines the cube.
00571 /// If no elementary cube is found in the input then the cube
00572 /// is not modified.
00573 template <class CoordT>
00574 std::istream &operator >> (std::istream &in, tCubCell<CoordT> &c)
00575 {
00576         // ignore any comments, spaces, tabs and new-line characters
00577         chomp::homology::ignorecomments (in);
00578 
00579         // check for an opening parenthesis of bracket
00580         if ((in. peek () != '[') && (in. peek () != '('))
00581                 return in;
00582 
00583         // read the opening parenthesis of bracket if found
00584         int ch = in. get ();
00585 
00586         // consider the case of the empty cubical cell or the empty cube
00587         if ((in. peek () == ']') || (in. peek () == ')'))
00588         {
00589                 in. get ();
00590                 const CoordT *null = 0;
00591                 c = tCubCell<CoordT> (-1, null, null);
00592                 return in;
00593         }
00594 
00595         int spaceDim = 0;
00596 
00597         // read a full cube with coordinates in parentheses
00598         if (ch == '(')
00599         {
00600                 CoordT coordinates [chomp::homology::MaxBasDim];
00601                 while (1)
00602                 {
00603                         // read a consecutive coordinate of the cube
00604                         CoordT &coordinate = coordinates [spaceDim];
00605                         coordinate = 0;
00606                         in >> coordinate;
00607                         ++ spaceDim;
00608 
00609                         // read the next character
00610                         ch = in. get ();
00611 
00612                         // if this is a closing parenthesis then finish
00613                         if (ch == ')')
00614                         {
00615                                 c = tCubCell<CoordT> (spaceDim, coordinates);
00616                                 return in;
00617                         }
00618 
00619                         // if this is an invalid separator then complain
00620                         if ((ch != ',') && (ch != ' '))
00621                                 throw "Can't read a full cube.";
00622                 }
00623         }
00624 
00625         CoordT leftArray [chomp::homology::MaxBasDim];
00626         CoordT rightArray [chomp::homology::MaxBasDim];
00627         // read the cartesian product of intervals
00628         while (1)
00629         {
00630                 CoordT &left = leftArray [spaceDim];
00631                 CoordT &right = rightArray [spaceDim];
00632                 left = 0;
00633                 right = 0;
00634                 in >> left;
00635                 if (in. peek () == ']')
00636                         right = left;
00637                 else if (in. get () == ',')
00638                         in >> right;
00639                 else
00640                         throw "Can't read a cubical cell.";
00641                 in. get ();
00642                 ++ spaceDim;
00643                 if (in. peek () != 'x')
00644                         break;
00645                 in. get ();
00646                 if (in. get () != '[')
00647                         throw "An interval expected for a cubical cell.";
00648                 if (spaceDim >= chomp::homology::MaxBasDim)
00649                         throw "Too high dimension of a cubical cell.";
00650         }
00651 
00652         // define the cubical cell
00653         c = tCubCell<CoordT> (spaceDim, leftArray, rightArray);
00654 
00655         return in;
00656 } /* operator >> */
00657 
00658 
00659 #endif // _CHAINCON_CUBCELL_H_
00660 

Generated on Tue Apr 5 2011 00:06:32 for Chain Contraction Software by  doxygen 1.7.2