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