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
00029
00030
00031
00032
00033
00034
00035 #ifndef _FINRESDYN_COVBOXES_H_
00036 #define _FINRESDYN_COVBOXES_H_
00037
00038
00039
00040 #include <vector>
00041 #include <cmath>
00042
00043
00044 #include "chomp/struct/hashsets.h"
00045 #include "chomp/cubes/pointset.h"
00046 #include "chomp/cubes/cube.h"
00047
00048
00049 #include "rounding.h"
00050 #include "streams.h"
00051
00052
00053
00054
00055
00056
00057
00058 class DummyBoxNumbers
00059 {
00060 public:
00061
00062 void add (int) {};
00063
00064 };
00065
00066
00067
00068
00069
00070
00071
00072 template <class NumType>
00073 class tCoverBoxes
00074 {
00075 public:
00076
00077 typedef NumType NumberType;
00078
00079
00080 tCoverBoxes (const int spaceDim, const NumType *leftCorner,
00081 const NumType *boxWidths, const int *partCounts,
00082 const NumType *overlap = 0);
00083
00084
00085 ~tCoverBoxes ();
00086
00087
00088 int dim () const;
00089
00090
00091 int size () const;
00092
00093
00094
00095 template <class ResultType>
00096 void get (const int n,
00097 ResultType *leftBounds, ResultType *rightBounds) const;
00098
00099
00100 template <class ResultType>
00101 void getLeftCorner (ResultType *leftCorner) const;
00102
00103
00104 template <class ResultType>
00105 void getBoxWidths (ResultType *boxWidths) const;
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 template <class InputType, class BoxNumbers>
00116 void cover (const InputType *leftBounds,
00117 const InputType *rightBounds, BoxNumbers &boxNumbers,
00118 NumType *diameter2 = 0);
00119
00120
00121 template <class InputType>
00122 void cover (const InputType *x);
00123
00124
00125 void forget ();
00126
00127 private:
00128
00129 int spaceDim;
00130
00131
00132 NumType *leftCorner;
00133
00134
00135 NumType *boxWidths;
00136
00137
00138 NumType *rightCorner;
00139
00140
00141
00142 int *partCounts;
00143
00144
00145 NumType *overlap;
00146
00147
00148
00149 typedef int CoordType;
00150
00151
00152 CoordType *buffer;
00153
00154
00155 typedef chomp::homology::tCubeBase<CoordType> CubeType;
00156
00157
00158 chomp::homology::hashedset<CubeType> boxes;
00159
00160
00161
00162 NumType leftBound (int coord, int dir) const;
00163
00164
00165
00166 NumType rightBound (int coord, int dir) const;
00167
00168
00169
00170 CoordType leftCoord (const NumType &bound, int dir) const;
00171
00172
00173
00174 CoordType rightCoord (const NumType &bound, int dir) const;
00175
00176
00177 tCoverBoxes (const tCoverBoxes<NumType> &);
00178
00179
00180 tCoverBoxes<NumType> &operator = (const tCoverBoxes<NumType> &);
00181
00182 };
00183
00184
00185
00186 template <class NumType>
00187 inline tCoverBoxes<NumType>::tCoverBoxes (const int spaceDim,
00188 const NumType *leftCorner, const NumType *boxWidths,
00189 const int *partCounts, const NumType *overlap)
00190 {
00191
00192 if ((spaceDim <= 0) || (spaceDim > 100000))
00193 throw "Wrong space dimension for a box open cover.";
00194 this -> spaceDim = spaceDim;
00195
00196
00197 for (int i = 0; i < spaceDim; ++ i)
00198 {
00199 if (boxWidths [i] <= 0)
00200 throw "Trying to use a non-positive box width.";
00201 if (partCounts [i] <= 0)
00202 throw "Trying to use a non-positive no. of parts.";
00203 if (overlap && (overlap [i] <= 0))
00204 throw "Trying to use a too small overlap.";
00205 if (overlap && (2.00001 * overlap [i] >=
00206 boxWidths [i] / partCounts [i]))
00207 {
00208 throw "Trying to use too large overlap.";
00209 }
00210 }
00211
00212
00213 this -> leftCorner = new NumType [spaceDim];
00214 for (int i = 0; i < spaceDim; ++ i)
00215 this -> leftCorner [i] = leftCorner [i];
00216
00217
00218 this -> boxWidths = new NumType [spaceDim];
00219 for (int i = 0; i < spaceDim; ++ i)
00220 this -> boxWidths [i] = boxWidths [i];
00221
00222
00223 this -> rightCorner = new NumType [spaceDim];
00224 for (int i = 0; i < spaceDim; ++ i)
00225 {
00226 this -> rightCorner [i] = tRounding<NumberType>::add_up
00227 (this -> leftCorner [i], this -> boxWidths [i]);
00228 }
00229
00230
00231 this -> partCounts = new int [spaceDim];
00232 for (int i = 0; i < spaceDim; ++ i)
00233 this -> partCounts [i] = partCounts [i];
00234
00235
00236 this -> overlap = new NumType [spaceDim];
00237 if (!overlap)
00238 {
00239 const NumType min_number =
00240 tRounding<NumType>::min_number ();
00241 for (int i = 0; i < spaceDim; ++ i)
00242 this -> overlap [i] = min_number;
00243 }
00244 else
00245 {
00246 for (int i = 0; i < spaceDim; ++ i)
00247 this -> overlap [i] = overlap [i];
00248 }
00249
00250
00251 this -> buffer = new CoordType [2 * spaceDim];
00252
00253 return;
00254 }
00255
00256 template <class NumType>
00257 inline tCoverBoxes<NumType>::tCoverBoxes (const tCoverBoxes<NumType> &)
00258 {
00259 throw "Trying to use the copy constructor for an open cover.";
00260 return;
00261 }
00262
00263 template <class NumType>
00264 inline tCoverBoxes<NumType> &tCoverBoxes<NumType>::operator =
00265 (const tCoverBoxes<NumType> &)
00266 {
00267 throw "Trying to use the assignment operator for an open cover.";
00268 return;
00269 }
00270
00271 template <class NumType>
00272 inline tCoverBoxes<NumType>::~tCoverBoxes ()
00273 {
00274 delete [] leftCorner;
00275 delete [] boxWidths;
00276 delete [] rightCorner;
00277 delete [] partCounts;
00278 delete [] overlap;
00279 delete [] buffer;
00280 return;
00281 }
00282
00283 template <class NumType>
00284 inline int tCoverBoxes<NumType>::dim () const
00285 {
00286 return spaceDim;
00287 }
00288
00289 template <class NumType>
00290 inline int tCoverBoxes<NumType>::size () const
00291 {
00292 return boxes. size ();
00293 }
00294
00295 template <class NumType>
00296 inline void tCoverBoxes<NumType>::forget ()
00297 {
00298 chomp::homology::hashedset<CubeType> empty;
00299 boxes = empty;
00300 return;
00301 }
00302
00303 template <class NumType>
00304 inline NumType tCoverBoxes<NumType>::leftBound (int coord, int dir) const
00305 {
00306 if (coord == 0)
00307 return leftCorner [dir];
00308 typedef tRounding<NumType> rnd;
00309 NumType left1 = rnd::mul_down (boxWidths [dir], coord);
00310 NumType left2 = rnd::div_down (left1, partCounts [dir]);
00311 return rnd::add_down (leftCorner [dir], left2);
00312 }
00313
00314 template <class NumType>
00315 inline NumType tCoverBoxes<NumType>::rightBound (int coord, int dir) const
00316 {
00317 typedef tRounding<NumType> rnd;
00318 if (coord == partCounts [dir])
00319 return rnd::add_up (leftCorner [dir], boxWidths [dir]);
00320 NumType right1 = rnd::mul_up (boxWidths [dir], coord + 1);
00321 NumType right2 = rnd::div_up (right1, partCounts [dir]);
00322 NumType right3 = rnd::add_up (right2, overlap [dir]);
00323 return rnd::add_up (leftCorner [dir], right3);
00324 }
00325
00326 template <class NumType>
00327 inline typename tCoverBoxes<NumType>::CoordType
00328 tCoverBoxes<NumType>::leftCoord
00329 (const NumType &bound, int dir) const
00330 {
00331
00332 if (bound < leftCorner [dir])
00333 throw "Trying to cover a box that is too large (left).";
00334
00335
00336 if (bound == leftCorner [dir])
00337 return 0;
00338
00339
00340 NumType offset = bound - leftCorner [dir];
00341 int coord = static_cast<CoordType>
00342 (offset * partCounts [dir] / boxWidths [dir]);
00343 if (coord < 0)
00344 return 0;
00345
00346
00347 if ((coord + 1 < partCounts [dir]) &&
00348 (leftBound (coord + 1, dir) <= bound))
00349 {
00350 sbug << "* Left bound inc improve.\n";
00351 ++ coord;
00352 }
00353
00354
00355
00356 if ((coord > 0) && (leftBound (coord, dir) > bound))
00357 {
00358 sbug << "* Left bound dec cover.\n";
00359 -- coord;
00360 }
00361
00362
00363 if ((coord > 0) && (rightBound (coord - 1, dir) > bound))
00364 {
00365 sbug << "* Left bound dec overlap.\n";
00366 -- coord;
00367 }
00368
00369 return coord;
00370 }
00371
00372 template <class NumType>
00373 inline typename tCoverBoxes<NumType>::CoordType
00374 tCoverBoxes<NumType>::rightCoord
00375 (const NumType &bound, int dir) const
00376 {
00377
00378 if (bound > rightCorner [dir])
00379 throw "Trying to cover a box that is too large (right).";
00380
00381
00382 if (bound == rightCorner [dir])
00383 return partCounts [dir];
00384
00385
00386 NumType offset = bound - leftCorner [dir] - overlap [dir];
00387 int coord = (offset > 0) ? (static_cast<CoordType>
00388 (offset * partCounts [dir] / boxWidths [dir]) + 1) : 1;
00389 if (coord >= partCounts [dir])
00390 return partCounts [dir];
00391
00392
00393 if ((coord > 1) && (rightBound (coord - 2, dir) >= bound))
00394 {
00395 sbug << "* Right bound inc improve.\n";
00396 -- coord;
00397 }
00398
00399
00400
00401 if ((coord < partCounts [dir]) &&
00402 (rightBound (coord - 1, dir) < bound))
00403 {
00404 sbug << "* Right bound inc cover.\n";
00405 ++ coord;
00406 }
00407
00408
00409 if ((coord < partCounts [dir]) &&
00410 (leftBound (coord, dir) < bound))
00411 {
00412 sbug << "* Right bound inc overlap.\n";
00413 ++ coord;
00414 }
00415
00416 return coord;
00417 }
00418
00419 template <class NumType>
00420 template <class ResultType>
00421 inline void tCoverBoxes<NumType>::get (const int n,
00422 ResultType *leftBounds, ResultType *rightBounds) const
00423 {
00424
00425 typedef tRounding<ResultType> rnd;
00426
00427
00428 if ((n < 0) || (n >= boxes. size ()))
00429 throw "Wrong cover element requested.";
00430
00431
00432 CoordType *boxCoord = buffer;
00433 boxes [n]. coord (boxCoord);
00434
00435
00436 for (int i = 0; i < spaceDim; ++ i)
00437 {
00438 leftBounds [i] = leftBound (boxCoord [i], i);
00439 rightBounds [i] = rightBound (boxCoord [i], i);
00440 }
00441 return;
00442 }
00443
00444 template <class NumType>
00445 template <class ResultType>
00446 inline void tCoverBoxes<NumType>::getLeftCorner (ResultType *leftCorner)
00447 const
00448 {
00449 for (int i = 0; i < spaceDim; ++ i)
00450 leftCorner [i] = this -> leftCorner [i];
00451 return;
00452 }
00453
00454 template <class NumType>
00455 template <class ResultType>
00456 inline void tCoverBoxes<NumType>::getBoxWidths (ResultType *boxWidths)
00457 const
00458 {
00459 for (int i = 0; i < spaceDim; ++ i)
00460 boxWidths [i] = this -> boxWidths [i];
00461 return;
00462 }
00463
00464 template <class NumType>
00465 template <class InputType, class BoxNumbers>
00466 inline void tCoverBoxes<NumType>::cover (const InputType *leftBounds,
00467 const InputType *rightBounds, BoxNumbers &boxNumbers,
00468 NumType *diameter2)
00469 {
00470
00471 CoordType *left = buffer;
00472 CoordType *right = buffer + spaceDim;
00473
00474
00475 for (int i = 0; i < spaceDim; ++ i)
00476 {
00477 left [i] = leftCoord (leftBounds [i], i);
00478 right [i] = rightCoord (rightBounds [i], i);
00479 }
00480
00481
00482 if (diameter2)
00483 {
00484 NumType squares = 0;
00485 for (int i = 0; i < spaceDim; ++ i)
00486 {
00487 NumType diff = tRounding<NumType>::sub_up
00488 (rightBound (right [i], i),
00489 leftBound (left [i], i));
00490 NumType diff2 = tRounding<NumType>::mul_up
00491 (diff, diff);
00492 squares = tRounding<NumType>::add_up
00493 (squares, diff2);
00494 }
00495
00496 *diameter2 = squares;
00497 }
00498
00499
00500 chomp::homology::tRectangle<CoordType> r (left, right, spaceDim);
00501 const CoordType *c;
00502 while ((c = r. get ()) != 0)
00503 {
00504 CubeType q (c, spaceDim);
00505 int n = boxes. getnumber (q);
00506 if (n >= 0)
00507 boxNumbers. add (n);
00508 else
00509 {
00510 boxNumbers. add (boxes. size ());
00511 boxes. add (q);
00512 }
00513 }
00514
00515 return;
00516 }
00517
00518 template <class NumType>
00519 template <class InputType>
00520 inline void tCoverBoxes<NumType>::cover (const InputType *x)
00521 {
00522
00523 typedef tRounding<NumType> rnd;
00524
00525
00526 NumType *xLeft = new NumType [spaceDim];
00527 NumType *xRight = new NumType [spaceDim];
00528 NumType min_number = rnd::min_number ();
00529 for (int i = 0; i < spaceDim; ++ i)
00530 {
00531 xLeft [i] = rnd::add_down (x [i], min_number);
00532 xRight [i] = rnd::add_up (x [i], min_number);
00533 }
00534
00535
00536 DummyBoxNumbers d;
00537 this -> cover (xLeft, xRight, d);
00538
00539
00540 delete [] xRight;
00541 delete [] xLeft;
00542 return;
00543 }
00544
00545 template <class NumType>
00546 inline std::ostream &operator << (std::ostream &out,
00547 const tCoverBoxes<NumType> &cover)
00548 {
00549 int dim = cover. dim ();
00550 NumType *buffer = new NumType [dim << 1];
00551 NumType *leftBound = buffer;
00552 NumType *rightBound = buffer + dim;
00553 for (int n = 0; n < cover. size (); ++ n)
00554 {
00555 cover. get (n, leftBound, rightBound);
00556 for (int i = 0; i < dim; ++ i)
00557 {
00558 out << (i ? " x [" : "[") << leftBound [i] <<
00559 "," << rightBound [i] << "]";
00560 }
00561 out << "\n";
00562 }
00563 delete [] buffer;
00564 return out;
00565 }
00566
00567
00568 #endif // _FINRESDYN_COVBOXES_H_
00569