Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 #ifndef _CHAINCON_CUBCELL_H_
00029 #define _CHAINCON_CUBCELL_H_
00030 
00031 
00032 
00033 #include <istream>
00034 #include <ostream>
00035 #include <algorithm>
00036 #include <vector>
00037 
00038 
00039 #include "chomp/system/config.h"
00040 #include "chomp/cubes/pointbas.h"
00041 
00042 
00043 #include "chaincon/emptycell.h"
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 template <class CoordT>
00052 class tCubCell
00053 {
00054 public:
00055 
00056         typedef CoordT CoordType;
00057 
00058 
00059         tCubCell ();
00060 
00061 
00062         template <class CoordArray>
00063         tCubCell (int dimension, const CoordArray &coordinates);
00064 
00065 
00066         template <class CoordArray>
00067         tCubCell (int dimension, const CoordArray &left,
00068                 const CoordArray &right);
00069 
00070 
00071         tCubCell (const tCubCell<CoordT> &c);
00072 
00073 
00074         tCubCell (const tCubCell<CoordT> &c, int n);
00075 
00076 
00077 
00078 
00079         tCubCell (const tCubCell<CoordT> &c, int n, int side);
00080 
00081 
00082         tCubCell<CoordT> &operator = (const tCubCell<CoordT> &s);
00083 
00084 
00085         ~tCubCell ();
00086 
00087 
00088         int spaceDim () const;
00089 
00090 
00091         int dim () const;
00092 
00093 
00094         const CoordT left (int n) const;
00095 
00096 
00097         const CoordT right (int n) const;
00098 
00099 
00100         int boundaryLength () const;
00101 
00102 
00103         int boundaryCoef (int n) const;
00104 
00105 
00106         int diagonalLength () const;
00107 
00108 
00109         bool operator == (const tCubCell<CoordT> &s) const;
00110 
00111 
00112         void swap (tCubCell<CoordT> &s);
00113 
00114 private:
00115 
00116 
00117 
00118         int_t n1;
00119 
00120 
00121 
00122 
00123         int_t n2;
00124 
00125 }; 
00126 
00127 
00128 
00129 template <class CoordT>
00130 inline tCubCell<CoordT>::tCubCell (): n1 (0), n2 (0)
00131 {
00132         return;
00133 } 
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         
00141         
00142         if (dimension <= 0)
00143                 return;
00144 
00145         
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         
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 } 
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         
00167         
00168         if (dimension <= 0)
00169                 return;
00170 
00171         
00172         int cellDimension = 0;
00173         for (int i = 0; i < dimension; ++ i)
00174         {
00175                 if (left [i] != right [i])
00176                         ++ cellDimension;
00177         }
00178 
00179         
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         
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 } 
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 } 
00201 
00202 template <class CoordT>
00203 inline tCubCell<CoordT>::tCubCell (const tCubCell<CoordT> &c, int n)
00204 {
00205         
00206         int spaceDimension = c. spaceDim ();
00207         int cellDimension = c. dim ();
00208 
00209         
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         
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 } 
00250 
00251 
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 } 
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 } 
00412 
00413 template <class CoordT>
00414 inline tCubCell<CoordT>::~tCubCell ()
00415 {
00416         return;
00417 } 
00418 
00419 template <class CoordT>
00420 inline int tCubCell<CoordT>::spaceDim () const
00421 {
00422         return (n1 >> chomp::homology::NumBits);
00423 } 
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 } 
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 } 
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 } 
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 } 
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 } 
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; 
00473 } 
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 } 
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 } 
00489 
00490 
00491 
00492 
00493 
00494 
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 } 
00517 
00518 
00519 
00520 
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 } 
00543 
00544 
00545 
00546 
00547 
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 } 
00566 
00567 
00568 
00569 
00570 
00571 
00572 
00573 template <class CoordT>
00574 std::istream &operator >> (std::istream &in, tCubCell<CoordT> &c)
00575 {
00576         
00577         chomp::homology::ignorecomments (in);
00578 
00579         
00580         if ((in. peek () != '[') && (in. peek () != '('))
00581                 return in;
00582 
00583         
00584         int ch = in. get ();
00585 
00586         
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         
00598         if (ch == '(')
00599         {
00600                 CoordT coordinates [chomp::homology::MaxBasDim];
00601                 while (1)
00602                 {
00603                         
00604                         CoordT &coordinate = coordinates [spaceDim];
00605                         coordinate = 0;
00606                         in >> coordinate;
00607                         ++ spaceDim;
00608 
00609                         
00610                         ch = in. get ();
00611 
00612                         
00613                         if (ch == ')')
00614                         {
00615                                 c = tCubCell<CoordT> (spaceDim, coordinates);
00616                                 return in;
00617                         }
00618 
00619                         
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         
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         
00653         c = tCubCell<CoordT> (spaceDim, leftArray, rightArray);
00654 
00655         return in;
00656 } 
00657 
00658 
00659 #endif // _CHAINCON_CUBCELL_H_
00660