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