Go to the documentation of this file.00001
00002
00003
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifndef _CHOMP_STRUCT_MULTITAB_H_
00037 #define _CHOMP_STRUCT_MULTITAB_H_
00038
00039 #include "chomp/system/config.h"
00040
00041
00042
00043
00044
00045
00046
00047 namespace chomp {
00048 namespace homology {
00049
00050
00051
00052
00053
00054
00055 template <typename T>
00056 inline void my_swap (T &x, T &y)
00057 {
00058 T tmp = x;
00059 x = y;
00060 y = tmp;
00061 return;
00062 }
00063
00064
00065
00066
00067
00068
00070 #define DEFAULTPIECESIZE 32
00071
00077 template <class element>
00078 class multitable
00079 {
00080 public:
00083 multitable (int piecesize = 0);
00084
00086 multitable (const multitable<element> &m);
00087
00089 multitable<element> &operator = (const multitable<element> &m);
00090
00092 ~multitable ();
00093
00097 element &operator [] (int_t n);
00098
00101 const element &operator () (int_t n) const;
00102
00105 const element &operator [] (int_t n) const;
00106
00109 void allocate (int_t n);
00110
00113 void fill (const element &e, int_t n);
00114
00116 void swap (multitable<element> &other);
00117
00118 private:
00120 int_t npieces;
00121
00124 int shiftbits;
00125
00127 int offsetmask;
00128
00130 element **tab;
00131
00133 void increase (int_t n);
00134
00135 };
00136
00137
00138
00139 template <class element>
00140 inline multitable<element>::multitable (int piecesize)
00141 {
00142 tab = 0;
00143 npieces = 0;
00144 if (piecesize <= 0)
00145 piecesize = DEFAULTPIECESIZE;
00146 shiftbits = 1;
00147 while ((1 << shiftbits) < piecesize)
00148 ++ shiftbits;
00149 offsetmask = (1 << shiftbits) - 1;
00150 return;
00151 }
00152
00153 template <class element>
00154 multitable<element>::multitable (const multitable<element> &m):
00155 npieces (m. npieces), shiftbits (m. shiftbits),
00156 offsetmask (m. offsetmask)
00157 {
00158 int piecesize = 1 << shiftbits;
00159 tab = new element * [npieces];
00160 if (!tab)
00161 throw "Cannot alloc mem in copying constructor of a table.";
00162 for (int_t i = 0; i < npieces; ++ i)
00163 {
00164 if (m. tab [i])
00165 {
00166 tab [i] = new element [piecesize];
00167 if (!tab [i])
00168 throw "No memory in copying constr.";
00169 for (int j = 0; j < piecesize; ++ j)
00170 tab [i] [j] = m. tab [i] [j];
00171 }
00172 else
00173 {
00174 tab [i] = 0;
00175 }
00176 }
00177 return;
00178 }
00179
00180 template <class element>
00181 multitable<element> &multitable<element>::operator =
00182 (const multitable<element> &m)
00183 {
00184
00185 if (this == &m)
00186 return *this;
00187
00188
00189 int deallocated = 0;
00190
00191
00192 if (shiftbits != m. shiftbits)
00193 {
00194
00195 for (int_t i = 0; i < npieces; ++ i)
00196 {
00197 if (tab [i])
00198 {
00199 delete [] tab [i];
00200 tab [i] = 0;
00201 }
00202 }
00203 deallocated = 1;
00204 shiftbits = m. shiftbits;
00205 offsetmask = m. offsetmask;
00206 }
00207
00208
00209
00210
00211 if (npieces != m. npieces)
00212 {
00213
00214 element **newtab = (m. npieces) ?
00215 (new element * [m. npieces]) : 0;
00216 if (!newtab && m. npieces)
00217 throw "No memory for a table in operator =.";
00218
00219
00220
00221
00222 if (!deallocated)
00223 {
00224
00225
00226 int_t i = 0;
00227 int_t j = 0;
00228 while (i < m. npieces)
00229 {
00230
00231 while ((j < npieces) && !tab [j])
00232 ++ j;
00233
00234 if (j < npieces)
00235 newtab [i ++] = tab [j ++];
00236
00237 else
00238 {
00239 while (i < m. npieces)
00240 newtab [i ++] = 0;
00241 }
00242 }
00243
00244 while (j < npieces)
00245 {
00246 if (tab [j])
00247 delete [] tab [j];
00248 ++ j;
00249 }
00250 }
00251 else
00252 {
00253 for (int_t i = 0; i < m. npieces; ++ i)
00254 newtab [i] = 0;
00255 }
00256
00257 if (tab)
00258 delete [] tab;
00259 tab = newtab;
00260 npieces = m. npieces;
00261 }
00262
00263
00264 if (!npieces)
00265 return *this;
00266
00267
00268
00269 int_t first_nonempty = 0;
00270 int_t first_empty = 0;
00271 int_t pos = 0;
00272 int piecesize = 1 << shiftbits;
00273
00274
00275 while ((first_nonempty < npieces) && !tab [first_nonempty])
00276 ++ first_nonempty;
00277 while ((first_empty < npieces) && tab [first_empty])
00278 ++ first_empty;
00279
00280
00281 while (pos < npieces)
00282 {
00283 if (m. tab [pos])
00284 {
00285 if (!tab [pos])
00286 {
00287 if (first_nonempty < npieces)
00288 {
00289 tab [pos] = tab [first_nonempty];
00290 tab [first_nonempty ++] = 0;
00291 }
00292 else
00293 {
00294 tab [pos] = new element [piecesize];
00295 if (!tab [pos])
00296 throw "Error in operator =.";
00297 }
00298 ++ first_empty;
00299 }
00300 else
00301 {
00302 ++ first_nonempty;
00303 }
00304
00305
00306 for (int i = 0; i < piecesize; ++ i)
00307 tab [pos] [i] = m. tab [pos] [i];
00308 }
00309 else if (tab [pos])
00310 {
00311 if (first_empty < npieces)
00312 {
00313 tab [first_empty] = tab [pos];
00314 ++ first_empty;
00315 }
00316 else
00317 delete [] tab [pos];
00318 ++ first_nonempty;
00319 tab [pos] = 0;
00320 }
00321 else
00322 {
00323 ++ first_empty;
00324 }
00325
00326
00327 ++ pos;
00328
00329
00330 while ((first_nonempty < npieces) && !tab [first_nonempty])
00331 ++ first_nonempty;
00332 while ((first_empty < npieces) && tab [first_empty])
00333 ++ first_empty;
00334 }
00335
00336 return *this;
00337 }
00338
00339 template <class element>
00340 inline multitable<element>::~multitable ()
00341 {
00342 if (!tab)
00343 return;
00344 for (int_t i = 0; i < npieces; ++ i)
00345 {
00346 if (tab [i])
00347 delete [] tab [i];
00348 }
00349 delete [] tab;
00350 return;
00351 }
00352
00353 template <class element>
00354 inline element &multitable<element>::operator [] (int_t n)
00355 {
00356 if (n < 0)
00357 throw "Negative index of an element in a table used.";
00358
00359
00360 int_t piece = n >> shiftbits;
00361
00362
00363 if (piece >= npieces)
00364 {
00365 int_t newnpieces = (npieces << 1) + 1;
00366 if (newnpieces <= piece)
00367 newnpieces = piece + 1;
00368 increase (newnpieces);
00369 }
00370
00371
00372 if (!tab [piece])
00373 {
00374 tab [piece] = new element [1 << shiftbits];
00375 if (!tab [piece])
00376 throw "Cannot allocate a piece of a table";
00377 }
00378
00379 return tab [piece] [n & offsetmask];
00380 }
00381
00382 template <class element>
00383 inline const element &multitable<element>::operator () (int_t n) const
00384 {
00385 if (n < 0)
00386 throw "Negative index of an element in a table used.";
00387
00388
00389 int_t piece = n >> shiftbits;
00390
00391 if ((piece >= npieces) || (!tab [piece]))
00392 throw "Non-existent table entry requested.";
00393
00394 return tab [piece] [n & offsetmask];
00395 }
00396
00397 template <class element>
00398 inline const element &multitable<element>::operator [] (int_t n) const
00399 {
00400 return (*this) (n);
00401 }
00402
00403 template <class element>
00404 void multitable<element>::allocate (int_t n)
00405 {
00406 if (n <= 0)
00407 return;
00408 int piecesize = 1 << shiftbits;
00409 int_t necessarypieces = (n + piecesize - 1) / piecesize;
00410
00411
00412 if (necessarypieces > npieces)
00413 increase (necessarypieces);
00414
00415
00416 for (int_t i = necessarypieces; i < npieces; ++ i)
00417 {
00418 if (tab [i])
00419 {
00420 delete [] tab [i];
00421 tab [i] = 0;
00422 }
00423 }
00424 return;
00425 }
00426
00427 template <class element>
00428 void multitable<element>::fill (const element &e, int_t n)
00429 {
00430 if (n <= 0)
00431 return;
00432 int piecesize = 1 << shiftbits;
00433 int_t maxpiece = (n + piecesize - 1) / piecesize;
00434 if (maxpiece > npieces)
00435 increase (maxpiece);
00436 for (int_t piece = 0; piece < maxpiece; ++ piece)
00437 {
00438 if (!tab [piece])
00439 {
00440 tab [piece] = new element [piecesize];
00441 if (!tab [piece])
00442 throw "Too little mem for a piece.";
00443
00444 }
00445 if ((piece == maxpiece - 1) && (n & offsetmask))
00446 piecesize = n & offsetmask;
00447 for (int i = 0; i < piecesize; ++ i)
00448 tab [piece] [i] = e;
00449 }
00450 return;
00451 }
00452
00453 template <class element>
00454 inline void multitable<element>::swap (multitable<element> &other)
00455 {
00456 my_swap (npieces, other. npieces);
00457 my_swap (shiftbits, other. shiftbits);
00458 my_swap (offsetmask, other. offsetmask);
00459 my_swap (tab, other. tab);
00460 return;
00461 }
00462
00463 template <class element>
00464 void multitable<element>::increase (int_t n)
00465 {
00466
00467
00468
00469 if (n <= npieces)
00470 throw "Trying to increase a multitable incorrectly.";
00471 element **newtab = new element * [n];
00472 if (!newtab)
00473 throw "Cannot increase a table.";
00474 for (int_t i = 0; i < npieces; ++ i)
00475 newtab [i] = tab [i];
00476 for (int_t i = npieces; i < n; ++ i)
00477 newtab [i] = 0;
00478 delete [] tab;
00479 tab = newtab;
00480 npieces = n;
00481 return;
00482 }
00483
00484
00485 }
00486 }
00487
00488 #endif // _CHOMP_STRUCT_MULTITAB_H_
00489
00491