cellvar.h

Go to the documentation of this file.
00001 
00002 
00003 
00015 
00016 // Copyright (C) 1997-2010 by Pawel Pilarczyk.
00017 //
00018 // This file is part of the Homology Library.  This library is free software;
00019 // you can redistribute it and/or modify it under the terms of the GNU
00020 // General Public License as published by the Free Software Foundation;
00021 // either version 2 of the License, or (at your option) any later version.
00022 //
00023 // This library is distributed in the hope that it will be useful,
00024 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00026 // GNU General Public License for more details.
00027 //
00028 // You should have received a copy of the GNU General Public License along
00029 // with this software; see the file "license.txt".  If not, write to the
00030 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00031 // MA 02111-1307, USA.
00032 
00033 // Started in January 2002. Last revision: August 4, 2010.
00034 
00035 
00036 #ifndef _CHOMP_CUBES_CELLVAR_H_
00037 #define _CHOMP_CUBES_CELLVAR_H_
00038 
00039 #include "chomp/system/config.h"
00040 #include "chomp/system/textfile.h"
00041 #include "chomp/cubes/pointset.h"
00042 #include "chomp/homology/chains.h"
00043 #include "chomp/struct/bitfield.h"
00044 #include "chomp/struct/integer.h"
00045 #include "chomp/struct/hashsets.h"
00046 #include "chomp/homology/gcomplex.h"
00047 #include "chomp/cubes/pointbas.h"
00048 #include "chomp/cubes/cubevar.h"
00049 #include "chomp/cubes/cellmain.h"
00050 
00051 #include <iostream>
00052 #include <fstream>
00053 #include <cstdlib>
00054 
00055 namespace chomp {
00056 namespace homology {
00057 
00058 
00059 // --------------------------------------------------
00060 // ------- CubicalCell with allocated memory --------
00061 // --------------------------------------------------
00062 
00067 template <class coordtype>
00068 class tCellVar
00069 {
00070 public:
00072         typedef coordtype CoordType;
00073 
00075         static const int MaxDim = // MaxBasDim;
00076                 (tCubeVar<coordtype>::MaxDim < MaxBasDim) ?
00077                 tCubeVar<coordtype>::MaxDim : MaxBasDim;
00078 
00080         static const int MaxSpaceDim = tCubeVar<coordtype>::MaxDim;
00081 
00083         typedef typename tCubeVar<coordtype>::PointBase PointBase;
00084 
00086         tCellVar ();
00087 
00089         tCellVar (const coordtype *c1, const coordtype *c2,
00090                 int spcdim, int celldim = -1);
00091 
00093         tCellVar (const tCubeVar<coordtype> &q1,
00094                 const tCubeVar<coordtype> &q2);
00095 
00098         tCellVar (const tCubeVar<coordtype> &q, int facedim);
00099 
00101         explicit tCellVar (const tCubeVar<coordtype> &q);
00102 
00105         tCellVar (const tCellVar<coordtype> &q, int offset, int ncoords);
00106 
00108         tCellVar (const tCellVar<coordtype> &c);
00109 
00111         tCellVar<coordtype> &operator = (const tCellVar<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 tCellVar<coordtype> &c1,
00154                 const tCellVar<coordtype> &c2)
00155         {
00156                 return ((c1. n == c2. n) && ((c1. n == 0) ||
00157                         thesame (c1. tab, c2. tab, c1. spacedim ())));
00158         } /* operator == */
00159 
00160 private:
00162         coordtype *tab;
00163 
00167         int_t n;
00168 
00170         void initialize (const coordtype *c1, const coordtype *c2,
00171                 int spcdim, int celldim = -1);
00172 
00173 }; /* class tCellVar */
00174 
00175 // --------------------------------------------------
00176 
00177 template<class coordtype>
00178 int tCellVar<coordtype>::OutputBits = 0;
00179 
00180 // --------------------------------------------------
00181 
00182 template <class coordtype>
00183 inline void tCellVar<coordtype>::initialize (const coordtype *c1,
00184         const coordtype *c2, int spcdim, int)
00185 {
00186         // test the validity of the dimension
00187         if (spcdim <= 0)
00188                 throw "Non-positive dimension of the space.";
00189         else if (spcdim >= MaxDim)
00190                 throw "Too high dimension of a cell.";
00191 
00192         // initialize the internal number with the space dimension
00193         n = static_cast<int_t> (spcdim) << NumBits;
00194 
00195         // prepare a table for coordinates if necessary
00196         tab = new coordtype [spcdim];
00197         if (!tab)
00198                 throw "Not enough memory to create a cell.";
00199 
00200         // copy the left corner coordinates to the cell
00201         PointBase::wrapcopy (tab, c1, spcdim);
00202 
00203         // prepare wrapped right coordinates for the detection of cell bits
00204         coordtype r [MaxDim];
00205         PointBase::wrapcopy (r, c2, spcdim);
00206 
00207         // set the bits of the cell
00208         for (int i = 0; i < spcdim; ++ i)
00209         {
00210                 if (tab [i] != r [i])
00211                         n |= (static_cast<int_t> (1) << i);
00212         }
00213         return;
00214 } /* tCellVar::initialize */
00215 
00216 template <class coordtype>
00217 inline tCellVar<coordtype>::tCellVar ()
00218 : tab (0), n (0)
00219 {
00220         return;
00221 } /* tCellVar::tCellVar */
00222 
00223 template <class coordtype>
00224 inline tCellVar<coordtype>::tCellVar
00225         (const coordtype *c1, const coordtype *c2, int spcdim, int celldim)
00226 {
00227         initialize (c1, c2, spcdim, celldim);
00228         return;
00229 } /* tCellVar::tCellVar */
00230 
00231 template <class coordtype>
00232 inline int tCellVar<coordtype>::dim () const
00233 {
00234         int count = 0;
00235         for (int i = 0; i < NumBits; ++ i)
00236         {
00237                 if (n & (static_cast<int_t> (1) << i))
00238                         ++ count;
00239         }
00240         return count;
00241 } /* tCellVar::dim */
00242 
00243 template <class coordtype>
00244 inline int tCellVar<coordtype>::spacedim () const
00245 {
00246         return static_cast<int> (n >> NumBits);
00247 } /* tCellVar::spacedim */
00248 
00249 template <class coordtype>
00250 inline tCellVar<coordtype>::tCellVar (const tCellVar<coordtype> &q,
00251         int offset, int ncoords)
00252 {
00253         int spcdim = static_cast<int> (q. n >> NumBits);
00254         if ((offset < 0) || (ncoords <= 0) || (offset + ncoords > spcdim))
00255                 throw "Wrong cell projection requested.";
00256         coordtype right [MaxDim];
00257         q. rightcoord (right);
00258         initialize (q. tab + offset, right + offset, ncoords);
00259 //      *** More efficient [unfinished, yet] ***
00260 //      tab = new coordtype [spcdim];
00261 //      if (!tab)
00262 //              throw "Not enough memory to create a projected cell.";
00263 //      for (int i = 0; i < spcdim; ++ i)
00264 //              tab [i] = q. tab [i];
00265 //      [...]
00266         return;
00267 } /* tCellVar::tCellVar */
00268 
00269 template <class coordtype>
00270 inline tCellVar<coordtype>::tCellVar (const tCellVar<coordtype> &q)
00271 {
00272         n = q. n;
00273         tab = new coordtype [spacedim ()];
00274         if (!tab)
00275                 throw "Not enough memory to copy a cubical cell.";
00276         copycoord (tab, q. tab, spacedim ());
00277         return;
00278 } /* tCellVar::tCellVar */
00279 
00280 template <class coordtype>
00281 inline tCellVar<coordtype> &tCellVar<coordtype>::operator =
00282         (const tCellVar<coordtype> &q)
00283 {
00284         // determine the new dimension
00285         int d = q. spacedim ();
00286 
00287         // allocate a new table if the dimension is to be changed
00288         if (d != spacedim ())
00289         {
00290                 if (tab)
00291                         delete [] tab;
00292                 tab = new coordtype [d];
00293                 if (!tab)
00294                         throw "Not enough memory to copy a cubical cell.";
00295         }
00296 
00297         // copy the data of the cubical cell
00298         copycoord (tab, q. tab, d);
00299         n = q. n;
00300 
00301         return *this;
00302 } /* tCellVar::operator = */
00303 
00304 template <class coordtype>
00305 inline coordtype *tCellVar<coordtype>::leftcoord (coordtype *c) const
00306 {
00307         if (!c)
00308                 throw "Null pointer to save left coordinates.";
00309         int d = spacedim ();
00310         for (int i = 0; i < d; ++ i)
00311                 c [i] = tab [i];
00312         return c;
00313 } /* tCellVar::leftcoord */
00314 
00315 template <class coordtype>
00316 inline coordtype *tCellVar<coordtype>::rightcoord (coordtype *c) const
00317 {
00318         if (!c)
00319                 throw "Null pointer to save right coordinates.";
00320         int d = spacedim ();
00321         for (int i = 0; i < d; ++ i)
00322         {
00323                 c [i] = tab [i];
00324                 if (n & (static_cast<int_t> (1) << i))
00325                         ++ (c [i]);
00326         }
00327         PointBase::wrapcoord (c, d);
00328         return c;
00329 } /* tCellVar::rightcoord */
00330 
00331 template <class coordtype>
00332 inline int_t tCellVar<coordtype>::hashkey1 () const
00333 {
00334         switch (spacedim ())
00335         {
00336         case 0:
00337                 return 0;
00338         case 1:
00339                 return (static_cast<int_t> (tab [0]) << 12) ^ n;
00340         case 2:
00341                 return (((static_cast<int_t> (tab [0])) << 18) +
00342                         ((static_cast<int_t> (tab [1])) << 6)) ^ n;
00343         default:
00344                 return (((static_cast<int_t> (tab [0])) << 18) +
00345                         ((static_cast<int_t> (tab [1])) << 6) +
00346                         ((static_cast<int_t> (tab [2])) >> 6)) ^ n;
00347         }
00348 } /* tCellVar::hashkey1 */
00349 
00350 template <class coordtype>
00351 inline int_t tCellVar<coordtype>::hashkey2 () const
00352 {
00353         int d = spacedim ();
00354         switch (d)
00355         {
00356         case 0:
00357                 return 0;
00358         case 1:
00359                 return (static_cast<int_t> (tab [0]) << 3) ^ (n << 5);
00360         case 2:
00361                 return ((static_cast<int_t> (tab [0]) >> 1) +
00362                         (static_cast<int_t> (tab [1]) << 13)) ^ (n << 5);
00363         default:
00364                 return (((static_cast<int_t> (tab [d - 1])) << 20) +
00365                         ((static_cast<int_t> (tab [d - 2])) << 9) +
00366                         ((static_cast<int_t> (tab [d - 3])) >> 1)) ^
00367                         (n << 5);
00368         }
00369 } /* tCellVar::hashkey2 */
00370 
00371 template <class coordtype>
00372 const char *tCellVar<coordtype>::name ()
00373 {
00374         return "cubical cell";
00375 } /* tCellVar::name */
00376 
00377 template <class coordtype>
00378 const char *tCellVar<coordtype>::pluralname ()
00379 {
00380         return "cubical cells";
00381 } /* tCellVar::pluralname */
00382 
00383 // --------------------------------------------------
00384 
00385 template <class coordtype>
00386 inline tCellVar<coordtype>::tCellVar
00387         (const tCubeVar<coordtype> &q1, const tCubeVar<coordtype> &q2)
00388 {
00389         // prepare tables for coordinates of the cubical cell
00390         coordtype left [MaxDim];
00391         coordtype right [MaxDim];
00392 
00393         // get the coordinates of minimal vertices of both cubes
00394         coordtype c1 [MaxDim];
00395         q1. coord (c1);
00396         coordtype c2 [MaxDim];
00397         q2. coord (c2);
00398 
00399         // get the dimension of the space and check for consistency
00400         int spcdim = q1. dim ();
00401         if (spcdim != q2. dim ())
00402                 throw "Trying to intersect cubes of different dimension.";
00403 
00404         // calculate the coordinates of both vertices of the cubical cell
00405         // and the dimension of the cubical cell
00406         int celldim = 0;
00407         const coordtype *wrap = PointBase::getwrapping (spcdim);
00408         for (int i = 0; i < spcdim; ++ i)
00409         {
00410                 if (c1 [i] == c2 [i])
00411                 {
00412                         left [i] = c1 [i];
00413                         right [i] = c1 [i];
00414                         ++ right [i];
00415                         ++ celldim;
00416                 }
00417                 else if ((c1 [i] - c2 [i] == -1) || (wrap && wrap [i] &&
00418                         (c1 [i] - c2 [i] == wrap [i] - 1)))
00419                 {
00420                         left [i] = c2 [i];
00421                         right [i] = c2 [i];
00422                 }
00423                 else if ((c1 [i] - c2 [i] == 1) || (wrap && wrap [i] &&
00424                         (c1 [i] - c2 [i] == -wrap [i] + 1)))
00425                 {
00426                         left [i] = c1 [i];
00427                         right [i] = c1 [i];
00428                 }
00429                 else
00430                         throw "The cubes do not intersect.";
00431         }
00432 
00433         // initialize the data of the cube
00434         initialize (left, right, spcdim, celldim);
00435 
00436         return;
00437 } /* tCellVar::tCellVar */
00438 
00439 template <class coordtype>
00440 inline tCellVar<coordtype>::tCellVar (const tCubeVar<coordtype> &q)
00441 // NOTE: This function is not as efficient as it could be. Instead of using
00442 // the "initialize" function, it should create the data structures itself.
00443 {
00444         // get the coordinates of minimal vertex of the cube
00445         const coordtype *left = q. tab + 1;
00446 
00447         // get the dimension of the space and of the cell
00448         int d = q. dim ();
00449 
00450         // prepare a table for coordinates of the other vertex of the cell
00451         coordtype right [MaxDim];
00452 
00453         // calculate the coordinates of other vertex of the cell
00454         for (int i = 0; i < d; ++ i)
00455                 right [i] = left [i] + 1;
00456 
00457         // initialize the cell
00458         initialize (left, right, d, d);
00459         return;
00460 } /* tCellVar::tCellVar */
00461 
00462 template <class coordtype>
00463 inline tCellVar<coordtype>::tCellVar (const tCubeVar<coordtype> &q,
00464         int facedim)
00465 // NOTE: This function is not as efficient as it could be. Instead of using
00466 // the "initialize" function, it should create the data structures itself.
00467 {
00468         // get the coordinates of minimal vertex of the cube
00469         const coordtype *left = q. tab + 1;
00470 
00471         // prepare a table for coordinates of the other vertex of the cell
00472         coordtype right [MaxDim];
00473 
00474         // get the dimension of the space and of the cell
00475         int d = q. dim ();
00476 
00477         // calculate the coordinates of other vertex of the cell
00478         for (int i = 0; i < d; ++ i)
00479                 right [i] = left [i] + ((i < facedim) ? 1 : 0);
00480 
00481         // initialize the cell
00482         initialize (left, right, d, facedim);
00483         return;
00484 } /* tCellVar::tCellVar */
00485 
00486 // --------------------------------------------------
00487 
00489 template <class coordtype>
00490 inline int operator != (const tCellVar<coordtype> &c1,
00491         const tCellVar<coordtype> &c2)
00492 {
00493         return !(c1 == c2);
00494 } /* operator != */
00495 
00496 // --------------------------------------------------
00497 
00499 template <class coordtype>
00500 inline tCellVar<coordtype> operator *
00501         (const tCellVar<coordtype> &c1,
00502         const tCellVar<coordtype> &c2)
00503 {
00504         // get the underlying space dimensions for both cells
00505         int d1 = c1. spacedim (), d2 = c2. spacedim ();
00506         if (d1 + d2 >= tCellVar<coordtype>::MaxDim)
00507                 throw "Too high dimension of a Cartesian product of cells.";
00508 
00509         // prepare arrays for the coordinates of the cell to create
00510         coordtype left [tCellVar<coordtype>::MaxDim];
00511         coordtype right [tCellVar<coordtype>::MaxDim];
00512 
00513         // extract the coordinates of the first cell
00514         c1. leftcoord (left);
00515         c1. rightcoord (right);
00516 
00517         // extract the coordinates of the second cell
00518         c2. leftcoord (left + d1);
00519         c2. rightcoord (right + d1);
00520 
00521         // create the Cartesian product of the cells
00522         return tCellVar<coordtype> (left, right, d1 + d2,
00523                 c1. dim () + c2. dim ());
00524 } /* operator * */
00525 
00527 template <class coordtype>
00528 inline std::ostream &operator << (std::ostream &out,
00529         const tCellVar<coordtype> &c)
00530 {
00531         return WriteCubicalCell (out, c);
00532 } /* operator << */
00533 
00535 template <class coordtype>
00536 inline std::istream &operator >> (std::istream &in,
00537         tCellVar<coordtype> &c)
00538 {
00539         return ReadCubicalCell (in, c);
00540 } /* operator >> */
00541 
00542 // --------------------------------------------------
00543 
00545 template <class coordtype>
00546 inline tCellVar<coordtype> boundarycell (const tCellVar<coordtype> &q,
00547         int i, bool onlyexisting)
00548 {
00549         return CubicalBoundaryCell (q, i, onlyexisting);
00550 } /* boundarycell */
00551 
00553 template <class coordtype>
00554 inline tCellVar<coordtype> boundarycell (const tCellVar<coordtype> &q,
00555         int i)
00556 {
00557         return CubicalBoundaryCell (q, i);
00558 } /* boundarycell */
00559         
00561 template <class coordtype>
00562 inline int boundarylength (const tCellVar<coordtype> &q)
00563 {
00564         return CubicalBoundaryLength (q);
00565 } /* boundarylength */
00566 
00568 template <class coordtype>
00569 inline int boundarycoef (const tCellVar<coordtype> &q, int i)
00570 {
00571         return CubicalBoundaryCoef (q, i);
00572 } /* boundarycoef */
00573 
00574 
00575 } // namespace homology
00576 } // namespace chomp
00577 
00578 #endif // _CHOMP_CUBES_CELLVAR_H_
00579 
00581