cellbase.h

Go to the documentation of this file.
00001 
00002 
00003 
00016 
00017 // Copyright (C) 1997-2010 by Pawel Pilarczyk.
00018 //
00019 // This file is part of the Homology Library.  This library is free software;
00020 // you can redistribute it and/or modify it under the terms of the GNU
00021 // General Public License as published by the Free Software Foundation;
00022 // either version 2 of the License, or (at your option) any later version.
00023 //
00024 // This library is distributed in the hope that it will be useful,
00025 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00026 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00027 // GNU General Public License for more details.
00028 //
00029 // You should have received a copy of the GNU General Public License along
00030 // with this software; see the file "license.txt".  If not, write to the
00031 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00032 // MA 02111-1307, USA.
00033 
00034 // Started in January 2002. Last revision: August 4, 2010.
00035 
00036 
00037 #ifndef _CHOMP_CUBES_CELLBASE_H_
00038 #define _CHOMP_CUBES_CELLBASE_H_
00039 
00040 #include "chomp/system/config.h"
00041 #include "chomp/system/textfile.h"
00042 #include "chomp/cubes/pointset.h"
00043 #include "chomp/homology/chains.h"
00044 #include "chomp/struct/bitfield.h"
00045 #include "chomp/struct/integer.h"
00046 #include "chomp/struct/hashsets.h"
00047 #include "chomp/homology/gcomplex.h"
00048 #include "chomp/cubes/pointbas.h"
00049 #include "chomp/cubes/cubebase.h"
00050 #include "chomp/cubes/cellmain.h"
00051 
00052 #include <iostream>
00053 #include <fstream>
00054 #include <cstdlib>
00055 
00056 namespace chomp {
00057 namespace homology {
00058 
00059 
00060 // --------------------------------------------------
00061 // ----------- CubicalCell with PointBase -----------
00062 // --------------------------------------------------
00063 
00068 template <class coordtype>
00069 class tCellBase
00070 {
00071 public:
00073         typedef coordtype CoordType;
00074 
00076         static const int MaxDim = tCubeBase<coordtype>::MaxDim;
00077 
00079         static const int MaxSpaceDim = tCubeBase<coordtype>::MaxDim;
00080 
00082         typedef typename tCubeBase<coordtype>::PointBase PointBase;
00083 
00085         tCellBase ();
00086 
00088         tCellBase (const coordtype *c1, const coordtype *c2,
00089                 int spcdim, int celldim = -1);
00090 
00092         tCellBase (const tCubeBase<coordtype> &q1,
00093                 const tCubeBase<coordtype> &q2);
00094 
00097         tCellBase (const tCubeBase<coordtype> &q, int facedim);
00098 
00100         explicit tCellBase (const tCubeBase<coordtype> &q);
00101 
00104         tCellBase (const tCellBase<coordtype> &q, int offset, int ncoords);
00105 
00107         tCellBase (const tCellBase<coordtype> &c);
00108 
00110         tCellBase<coordtype> &operator =
00111                 (const tCellBase<coordtype> &c);
00112 
00114         int dim () const;
00115 
00117         int spacedim () const;
00118 
00120         coordtype *leftcoord (coordtype *c) const;
00121 
00123         coordtype *rightcoord (coordtype *c) const;
00124 
00126         int_t hashkey1 () const;
00127 
00129         int_t hashkey2 () const;
00130 
00132         static const char *name ();
00133 
00135         static const char *pluralname ();
00136 
00141         enum OutputBitValues
00142         {
00143                 BitProduct = 0x01,      // unset => two vertices
00144                 BitSpace = 0x02
00145         };
00146 
00148         static int OutputBits;
00149 
00150         // --- friends: ---
00151 
00153         friend inline int operator == (const tCellBase<coordtype> &c1,
00154                 const tCellBase<coordtype> &c2)
00155         {
00156                 return (c1. n1 == c2. n1) && (c1. n2 == c2. n2);
00157         } /* operator == */
00158 
00159 private:
00161         int_t num1 () const;
00162 
00164         int_t num2 () const;
00165 
00168         int_t n1;
00169 
00172         int_t n2;
00173 
00175         void initialize (const coordtype *c1, const coordtype *c2,
00176                 int spcdim, int celldim = -1);
00177 
00178 }; /* class tCellBase */
00179 
00180 // --------------------------------------------------
00181 
00182 template<class coordtype>
00183 int tCellBase<coordtype>::OutputBits = 0;
00184 
00185 // --------------------------------------------------
00186 
00187 template <class coordtype>
00188 inline int_t tCellBase<coordtype>::num1 () const
00189 {
00190         return (n1 & NumMask);
00191 } /* tCellBase::num1 */
00192 
00193 template <class coordtype>
00194 inline int_t tCellBase<coordtype>::num2 () const
00195 {
00196         return (n2 & NumMask);
00197 } /* tCellBase::num2 */
00198 
00199 template <class coordtype>
00200 inline void tCellBase<coordtype>::initialize (const coordtype *c1,
00201         const coordtype *c2, int spcdim, int celldim)
00202 {
00203         // test the validity of the dimension
00204         if (spcdim <= 0)
00205                 throw "Non-positive dimension of the space.";
00206         else if (spcdim >= MaxDim)
00207                 throw "Too high dimension of a cell.";
00208 
00209         // get the number of the left vertex
00210         n1 = PointBase::number (c1, spcdim);
00211         if (n1 < 0)
00212                 throw "Negative number of the left vertex.";
00213 
00214         // get the number of the right vertex
00215         n2 = PointBase::number (c2, spcdim);
00216         if (n2 < 0)
00217                 throw "Negative number of the right vertex.";
00218 
00219         // calculate the dimension of the cubical cell if it is unknown
00220         if (celldim < 0)
00221         {
00222                 celldim = 0;
00223                 c1 = PointBase::coord (n1, spcdim);
00224                 c2 = PointBase::coord (n2, spcdim);
00225                 for (int i = 0; i < spcdim; ++ i)
00226                 {
00227                         if (c2 [i] != c1 [i])
00228                                 ++ celldim;
00229                 }
00230         }
00231 
00232         // add the space dimension and the cell dimension to the numbers
00233         n1 |= (static_cast<int_t> (spcdim) << NumBits);
00234         n2 |= (static_cast<int_t> (celldim) << NumBits);
00235         return;
00236 } /* tCellBase::initialize */
00237 
00238 // --------------------------------------------------
00239 
00240 template <class coordtype>
00241 inline tCellBase<coordtype>::tCellBase ()
00242 : n1 (0), n2 (0)
00243 {
00244         return;
00245 } /* tCellBase::tCellBase */
00246 
00247 template <class coordtype>
00248 inline tCellBase<coordtype>::tCellBase
00249         (const coordtype *c1, const coordtype *c2, int spcdim, int celldim)
00250 {
00251         initialize (c1, c2, spcdim, celldim);
00252         return;
00253 } /* tCellBase::tCellBase */
00254 
00255 template <class coordtype>
00256 inline tCellBase<coordtype>::tCellBase
00257         (const tCubeBase<coordtype> &q1, const tCubeBase<coordtype> &q2)
00258 {
00259         // get the dimension of the space and check for consistency
00260         int spcdim = q1. dim ();
00261         if (spcdim != q2. dim ())
00262                 throw "Trying to intersect cubes of different dimension.";
00263 
00264         // get the coordinates of minimal vertices of both cubes
00265         coordtype c1 [MaxDim];
00266         q1. coord (c1);
00267         coordtype c2 [MaxDim];
00268         q2. coord (c2);
00269 
00270         // prepare tables for the new coordinates of the cubical cell
00271         coordtype left [MaxDim];
00272         coordtype right [MaxDim];
00273 
00274         // compute the new coordinates of the cubical cell
00275         int celldim = CommonCell (left, right, c1, c2, spcdim,
00276                 PointBase::getwrapping (spcdim));
00277         
00278         // create the cell as computed
00279         initialize (left, right, spcdim, celldim);
00280 
00281         return;
00282 } /* tCellBase::tCellBase */
00283 
00284 template <class coordtype>
00285 inline tCellBase<coordtype>::tCellBase (const tCubeBase<coordtype> &q,
00286         int facedim)
00287 : n1 (q. n)
00288 {
00289         // check the dimensions
00290         int spcdim = static_cast<int> (n1 >> NumBits);
00291         if (facedim < 0)
00292                 throw "Negative dimension of a face requested.";
00293         if (facedim > spcdim)
00294                 throw "Too high dimension of a face requested.";
00295 
00296         // create the opposite corner of the cell
00297         const coordtype *c1 = PointBase::coord (num1 (), spcdim);
00298         coordtype c2 [MaxDim];
00299         for (int i = 0; i < spcdim; ++ i)
00300                 c2 [i] = c1 [i] + ((i < facedim) ? 1 : 0);
00301 
00302         // determine the number of the opposite corner and add cell dimension
00303         n2 = PointBase::number (c2, spcdim) |
00304                 (static_cast<int_t> (facedim) << NumBits);
00305         return;
00306 } /* tCellBase::tCellBase */
00307 
00308 template <class coordtype>
00309 inline tCellBase<coordtype>::tCellBase (const tCubeBase<coordtype> &q)
00310 : n1 (q. n)
00311 {
00312         // create the opposite corner of the cell
00313         int spcdim = static_cast<int> (n1 >> NumBits);
00314         const coordtype *c1 = PointBase::coord (num1 (), spcdim);
00315         coordtype c2 [MaxDim];
00316         for (int i = 0; i < spcdim; ++ i)
00317                 c2 [i] = c1 [i] + 1;
00318 
00319         // determine the number of the opposite corner and add cell dimension
00320         n2 = PointBase::number (c2, spcdim) |
00321                 (static_cast<int_t> (spcdim) << NumBits);
00322         return;
00323 } /* tCellBase::tCellBase */
00324 
00325 template <class coordtype>
00326 inline tCellBase<coordtype>::tCellBase (const tCellBase<coordtype> &q,
00327         int offset, int ncoords)
00328 {
00329         int spcdim = static_cast<int> (q. n1 >> NumBits);
00330         if ((offset < 0) || (ncoords <= 0) || (offset + ncoords > spcdim))
00331                 throw "Wrong cell projection requested.";
00332         const coordtype *c1 = PointBase::coord (q. n1 & NumMask, spcdim);
00333         const coordtype *c2 = PointBase::coord (q. n2 & NumMask, spcdim);
00334         initialize (c1 + offset, c2 + offset, ncoords);
00335         return;
00336 } /* tCellBase::tCellBase */
00337 
00338 template <class coordtype>
00339 inline tCellBase<coordtype>::tCellBase (const tCellBase<coordtype> &q)
00340 : n1 (q. n1), n2 (q. n2)
00341 {
00342         return;
00343 } /* tCellBase::tCellBase */
00344 
00345 template <class coordtype>
00346 inline tCellBase<coordtype> &tCellBase<coordtype>::operator =
00347         (const tCellBase<coordtype> &q)
00348 {
00349         n1 = q. n1;
00350         n2 = q. n2;
00351         return *this;
00352 } /* tCellBase::operator = */
00353 
00354 template <class coordtype>
00355 inline int tCellBase<coordtype>::dim () const
00356 {
00357         return static_cast<int> (n2 >> NumBits);
00358 } /* tCellBase::dim */
00359 
00360 template <class coordtype>
00361 inline int tCellBase<coordtype>::spacedim () const
00362 {
00363         return (n1 >> NumBits);
00364 } /* tCellBase::spacedim */
00365 
00366 template <class coordtype>
00367 inline coordtype *tCellBase<coordtype>::leftcoord (coordtype *c) const
00368 {
00369         const coordtype *leftc = PointBase::coord (num1 (), spacedim ());
00370         if (!c)
00371                 throw "Null pointer to save left coordinates.";
00372         copycoord (c, leftc, spacedim ());
00373         return c;
00374 } /* tCellBase::leftcoord */
00375 
00376 template <class coordtype>
00377 inline coordtype *tCellBase<coordtype>::rightcoord (coordtype *c) const
00378 {
00379         const coordtype *rightc = PointBase::coord (num2 (), spacedim ());
00380         if (!c)
00381                 throw "Null pointer to save right coordinates.";
00382         copycoord (c, rightc, spacedim ());
00383         return c;
00384 } /* tCellBase::rightcoord */
00385 
00386 template <class coordtype>
00387 inline int_t tCellBase<coordtype>::hashkey1 () const
00388 {
00389         return ((n1 ^ 0x55555555u) << 17) ^ ((n1 ^ 0xAAAAAAAAu) << 7) ^
00390                 ((n2 ^ 0xAAAAAAAAu) >> 7);
00391 } /* tCellBase::hashkey1 */
00392 
00393 template <class coordtype>
00394 inline int_t tCellBase<coordtype>::hashkey2 () const
00395 {
00396         return ((n2 ^ 0xAAAAAAAAu) << 21) ^ ((n2 ^ 0x55555555u) << 10) ^
00397                 ((n1 ^ 0x55555555u) >> 9);
00398 } /* tCellBase::hashkey2 */
00399 
00400 template <class coordtype>
00401 const char *tCellBase<coordtype>::name ()
00402 {
00403         return "cubical cell";
00404 } /* tCellBase::name */
00405 
00406 template <class coordtype>
00407 const char *tCellBase<coordtype>::pluralname ()
00408 {
00409         return "cubical cells";
00410 } /* tCellBase::pluralname */
00411 
00412 // --------------------------------------------------
00413 
00415 template <class coordtype>
00416 inline int operator != (const tCellBase<coordtype> &c1,
00417         const tCellBase<coordtype> &c2)
00418 {
00419         return !(c1 == c2);
00420 } /* operator != */
00421 
00422 // --------------------------------------------------
00423 
00425 template <class coordtype>
00426 inline tCellBase<coordtype> operator *
00427         (const tCellBase<coordtype> &c1,
00428         const tCellBase<coordtype> &c2)
00429 {
00430         // get the underlying space dimensions for both cells
00431         int d1 = c1. spacedim (), d2 = c2. spacedim ();
00432         if (d1 + d2 >= tCellBase<coordtype>::MaxDim)
00433                 throw "Too high dimension of a Cartesian product of cells.";
00434 
00435         // prepare arrays for the coordinates of the cell to create
00436         coordtype left [tCellBase<coordtype>::MaxDim];
00437         coordtype right [tCellBase<coordtype>::MaxDim];
00438 
00439         // extract the coordinates of the first cell
00440         c1. leftcoord (left);
00441         c1. rightcoord (right);
00442 
00443         // extract the coordinates of the second cell
00444         c2. leftcoord (left + d1);
00445         c2. rightcoord (right + d1);
00446 
00447         // create the Cartesian product of the cells
00448         return tCellBase<coordtype> (left, right, d1 + d2,
00449                 c1. dim () + c2. dim ());
00450 } /* operator * */
00451 
00453 template <class coordtype>
00454 inline std::ostream &operator << (std::ostream &out,
00455         const tCellBase<coordtype> &c)
00456 {
00457         return WriteCubicalCell (out, c);
00458 } /* operator << */
00459 
00461 template <class coordtype>
00462 inline std::istream &operator >> (std::istream &in,
00463         tCellBase<coordtype> &c)
00464 {
00465         return ReadCubicalCell (in, c);
00466 } /* operator >> */
00467 
00468 // --------------------------------------------------
00469 
00473 template <class coordtype>
00474 inline tCellBase<coordtype> boundarycell (const tCellBase<coordtype> &q,
00475         int i, bool onlyexisting)
00476 {
00477         return CubicalBoundaryCell (q, i, onlyexisting);
00478 } /* boundarycell */
00479 
00481 template <class coordtype>
00482 inline tCellBase<coordtype> boundarycell (const tCellBase<coordtype> &q,
00483         int i)
00484 {
00485         return CubicalBoundaryCell (q, i);
00486 } /* boundarycell */
00487         
00489 template <class coordtype>
00490 inline int boundarylength (const tCellBase<coordtype> &q)
00491 {
00492         return CubicalBoundaryLength (q);
00493 } /* boundarylength */
00494 
00496 template <class coordtype>
00497 inline int boundarycoef (const tCellBase<coordtype> &q, int i)
00498 {
00499         return CubicalBoundaryCoef (q, i);
00500 } /* boundarycoef */
00501 
00502 
00503 } // namespace homology
00504 } // namespace chomp
00505 
00506 #endif // _CHOMP_CUBES_CELLBASE_H_
00507 
00509