The Original CHomP Software
multitab.h
Go to the documentation of this file.
1
3
15
16// Copyright (C) 1997-2020 by Pawel Pilarczyk.
17//
18// This file is part of my research software package. This is free software:
19// you can redistribute it and/or modify it under the terms of the GNU
20// General Public License as published by the Free Software Foundation,
21// either version 3 of the License, or (at your option) any later version.
22//
23// This software is distributed in the hope that it will be useful,
24// but WITHOUT ANY WARRANTY; without even the implied warranty of
25// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26// GNU General Public License for more details.
27//
28// You should have received a copy of the GNU General Public License
29// along with this software; see the file "license.txt". If not,
30// please, see <https://www.gnu.org/licenses/>.
31
32// Started in January 2002. Last revision: February 21, 2007.
33
34
35#ifndef _CHOMP_STRUCT_MULTITAB_H_
36#define _CHOMP_STRUCT_MULTITAB_H_
37
38#include "chomp/system/config.h"
39//#include "chomp/system/textfile.h"
40//#include "chomp/struct/integer.h"
41
42#include <algorithm>
43//#include <cstdlib>
44//#include <ctime>
45//#include <iostream>
46
47namespace chomp {
48namespace homology {
49
50
51// --------------------------------------------------
52// ------------------ multi table -------------------
53// --------------------------------------------------
54
56#define DEFAULTPIECESIZE 32
57
63template <class element>
65{
66public:
69 multitable (int piecesize = 0);
70
73
76
79
83 element &operator [] (int_t n);
84
87 const element &operator () (int_t n) const;
88
91 const element &operator [] (int_t n) const;
92
95 void allocate (int_t n);
96
99 void fill (const element &e, int_t n);
100
103
104private:
107
111
114
116 element **tab;
117
119 void increase (int_t n);
120
121}; /* class multitable */
122
123// --------------------------------------------------
124
125template <class element>
127{
128 tab = 0;
129 npieces = 0;
130 if (piecesize <= 0)
131 piecesize = DEFAULTPIECESIZE;
132 shiftbits = 1;
133 while ((1 << shiftbits) < piecesize)
134 ++ shiftbits;
135 offsetmask = (1 << shiftbits) - 1;
136 return;
137} /* multitable<element>::multitable */
138
139template <class element>
141 npieces (m. npieces), shiftbits (m. shiftbits),
142 offsetmask (m. offsetmask)
143{
144 int piecesize = 1 << shiftbits;
145 tab = new element * [npieces];
146 if (!tab)
147 throw "Cannot alloc mem in copying constructor of a table.";
148 for (int_t i = 0; i < npieces; ++ i)
149 {
150 if (m. tab [i])
151 {
152 tab [i] = new element [piecesize];
153 if (!tab [i])
154 throw "No memory in copying constr.";
155 for (int j = 0; j < piecesize; ++ j)
156 tab [i] [j] = m. tab [i] [j];
157 }
158 else
159 {
160 tab [i] = 0;
161 }
162 }
163 return;
164} /* multitable<element>::multitable */
165
166template <class element>
168 (const multitable<element> &m)
169{
170 // if this is the same object then do nothing
171 if (this == &m)
172 return *this;
173
174 // have all the tables been deallocated?
175 int deallocated = 0;
176
177 // if the size of pieces does not match, they must be deallocated
178 if (shiftbits != m. shiftbits)
179 {
180 // deallocate all the pieces
181 for (int_t i = 0; i < npieces; ++ i)
182 {
183 if (tab [i])
184 {
185 delete [] tab [i];
186 tab [i] = 0;
187 }
188 }
189 deallocated = 1;
190 shiftbits = m. shiftbits;
191 offsetmask = m. offsetmask;
192 }
193
194 // if the number of pieces is not the same, change the table
195 // and for the moment gather in the new table all the pieces
196 // that are already allocated
197 if (npieces != m. npieces)
198 {
199 // allocate a new table of pieces
200 element **newtab = (m. npieces) ?
201 (new element * [m. npieces]) : 0;
202 if (!newtab && m. npieces)
203 throw "No memory for a table in operator =.";
204
205 // if there may be some not deallocated elements,
206 // gather them at the beginning of the table
207 // and set the rest of the pointers to 0s
208 if (!deallocated)
209 {
210 // 'i' points to the current entry in the new table,
211 // 'j' points to the current entry in the old table
212 int_t i = 0;
213 int_t j = 0;
214 while (i < m. npieces)
215 {
216 // find an allocated piece in the old table
217 while ((j < npieces) && !tab [j])
218 ++ j;
219 // if found, take it to the new table
220 if (j < npieces)
221 newtab [i ++] = tab [j ++];
222 // otherwise zero the rest of the new table
223 else
224 {
225 while (i < m. npieces)
226 newtab [i ++] = 0;
227 }
228 }
229 // if there are some pieces remaining, delete them
230 while (j < npieces)
231 {
232 if (tab [j])
233 delete [] tab [j];
234 ++ j;
235 }
236 }
237 else
238 {
239 for (int_t i = 0; i < m. npieces; ++ i)
240 newtab [i] = 0;
241 }
242
243 if (tab)
244 delete [] tab;
245 tab = newtab;
246 npieces = m. npieces;
247 }
248
249 // if the table is empty, then finish now
250 if (!npieces)
251 return *this;
252
253 // copy the data from 'm' to the current table;
254 // try to use pieces which are already allocated
255 int_t first_nonempty = 0;
256 int_t first_empty = 0;
257 int_t pos = 0;
258 int piecesize = 1 << shiftbits;
259
260 // find the first nonempty piece and the first empty one
261 while ((first_nonempty < npieces) && !tab [first_nonempty])
262 ++ first_nonempty;
263 while ((first_empty < npieces) && tab [first_empty])
264 ++ first_empty;
265
266 // copy all the pieces
267 while (pos < npieces)
268 {
269 if (m. tab [pos])
270 {
271 if (!tab [pos])
272 {
273 if (first_nonempty < npieces)
274 {
275 tab [pos] = tab [first_nonempty];
276 tab [first_nonempty ++] = 0;
277 }
278 else
279 {
280 tab [pos] = new element [piecesize];
281 if (!tab [pos])
282 throw "Error in operator =.";
283 }
284 ++ first_empty;
285 }
286 else
287 {
288 ++ first_nonempty;
289 }
290
291 // copy the source piece to this piece
292 for (int i = 0; i < piecesize; ++ i)
293 tab [pos] [i] = m. tab [pos] [i];
294 }
295 else if (tab [pos])
296 {
297 if (first_empty < npieces)
298 {
299 tab [first_empty] = tab [pos];
300 ++ first_empty;
301 }
302 else
303 delete [] tab [pos];
304 ++ first_nonempty;
305 tab [pos] = 0;
306 }
307 else
308 {
309 ++ first_empty;
310 }
311
312 // move to the next position
313 ++ pos;
314
315 // update pointers to the first available [non]empty piece
316 while ((first_nonempty < npieces) && !tab [first_nonempty])
317 ++ first_nonempty;
318 while ((first_empty < npieces) && tab [first_empty])
319 ++ first_empty;
320 }
321
322 return *this;
323} /* multitable<element>::operator = */
324
325template <class element>
327{
328 if (!tab)
329 return;
330 for (int_t i = 0; i < npieces; ++ i)
331 {
332 if (tab [i])
333 delete [] tab [i];
334 }
335 delete [] tab;
336 return;
337} /* multitable<element>::~multitable */
338
339template <class element>
341{
342 if (n < 0)
343 throw "Negative index of an element in a table used.";
344
345 // calculate the number of piece of interest
346 int_t piece = n >> shiftbits;
347
348 // increase the number of pieces if necessary
349 if (piece >= npieces)
350 {
351 int_t newnpieces = (npieces << 1) + 1;
352 if (newnpieces <= piece)
353 newnpieces = piece + 1;
354 increase (newnpieces);
355 }
356
357 // allocate the piece if necessary
358 if (!tab [piece])
359 {
360 tab [piece] = new element [1 << shiftbits];
361 if (!tab [piece])
362 throw "Cannot allocate a piece of a table";
363 }
364
365 return tab [piece] [n & offsetmask];
366} /* multitable<element>::operator [] */
367
368template <class element>
369inline const element &multitable<element>::operator () (int_t n) const
370{
371 if (n < 0)
372 throw "Negative index of an element in a table used.";
373
374 // calculate the number of piece of interest
375 int_t piece = n >> shiftbits;
376
377 if ((piece >= npieces) || (!tab [piece]))
378 throw "Non-existent table entry requested.";
379
380 return tab [piece] [n & offsetmask];
381} /* multitable<element>::operator () */
382
383template <class element>
384inline const element &multitable<element>::operator [] (int_t n) const
385{
386 return (*this) (n);
387} /* multitable<element>::operator [] const */
388
389template <class element>
391{
392 if (n <= 0)
393 return;
394 int piecesize = 1 << shiftbits;
395 int_t necessarypieces = (n + piecesize - 1) / piecesize;
396
397 // allocate more pieces if needed
398 if (necessarypieces > npieces)
399 increase (necessarypieces);
400
401 // deallocate unnecessary pieces
402 for (int_t i = necessarypieces; i < npieces; ++ i)
403 {
404 if (tab [i])
405 {
406 delete [] tab [i];
407 tab [i] = 0;
408 }
409 }
410 return;
411} /* multitable<element>::allocate */
412
413template <class element>
414void multitable<element>::fill (const element &e, int_t n)
415{
416 if (n <= 0)
417 return;
418 int piecesize = 1 << shiftbits;
419 int_t maxpiece = (n + piecesize - 1) / piecesize;
420 if (maxpiece > npieces)
421 increase (maxpiece);
422 for (int_t piece = 0; piece < maxpiece; ++ piece)
423 {
424 if (!tab [piece])
425 {
426 tab [piece] = new element [piecesize];
427 if (!tab [piece])
428 throw "Too little mem for a piece.";
429
430 }
431 if ((piece == maxpiece - 1) && (n & offsetmask))
432 piecesize = n & offsetmask;
433 for (int i = 0; i < piecesize; ++ i)
434 tab [piece] [i] = e;
435 }
436 return;
437} /* multitable<element>::fill */
438
439template <class element>
441{
442 std::swap (npieces, other. npieces);
443 std::swap (shiftbits, other. shiftbits);
444 std::swap (offsetmask, other. offsetmask);
445 std::swap (tab, other. tab);
446 return;
447} /* multitable<element>::swap */
448
449template <class element>
451{
452 // DEBUG
453// if (n != 1)
454// sbug << "Inc " << n << ".\n";
455 if (n <= npieces)
456 throw "Trying to increase a multitable incorrectly.";
457 element **newtab = new element * [n];
458 if (!newtab)
459 throw "Cannot increase a table.";
460 for (int_t i = 0; i < npieces; ++ i)
461 newtab [i] = tab [i];
462 for (int_t i = npieces; i < n; ++ i)
463 newtab [i] = 0;
464 delete [] tab;
465 tab = newtab;
466 npieces = n;
467 return;
468} /* multitable<element>::increase */
469
470
471} // namespace homology
472} // namespace chomp
473
474#endif // _CHOMP_STRUCT_MULTITAB_H_
475
477
A container for elements placed in a table (like a vector) that is actually built of many smaller tab...
Definition: multitab.h:65
element & operator[](int_t n)
Returns a reference of an element for reading/writing.
Definition: multitab.h:340
void swap(multitable< element > &other)
Swaps data with another multitable object.
Definition: multitab.h:440
void increase(int_t n)
Increases the number of pieces to the desired one.
Definition: multitab.h:450
multitable(const multitable< element > &m)
The copy constructor.
Definition: multitab.h:140
void fill(const element &e, int_t n)
Fills the table from 0 to the given index with the given element.
Definition: multitab.h:414
void allocate(int_t n)
Allocates the table for holding 'n' elements.
Definition: multitab.h:390
int offsetmask
The mask to get the offset of an element in a table piece.
Definition: multitab.h:113
int shiftbits
The number of bits to shift the index of an element in the table.
Definition: multitab.h:110
const element & operator()(int_t n) const
Returns a reference of an element for reading only.
Definition: multitab.h:369
element ** tab
The actual tables.
Definition: multitab.h:116
int_t npieces
The number of pieces ready to allocate.
Definition: multitab.h:106
multitable(int piecesize=0)
The default constructor for a table with the given size of each piece (should be a power of 2 or is r...
Definition: multitab.h:126
multitable< element > & operator=(const multitable< element > &m)
The assignment operator.
Definition: multitab.h:168
~multitable()
The destructor.
Definition: multitab.h:326
This file contains some precompiler definitions which indicate the operating system and/or compiler u...
int int_t
Index type for indexing arrays, counting cubes, etc.
Definition: config.h:115
#define DEFAULTPIECESIZE
The default size of a piece used in the multi-table.
Definition: multitab.h:56
void swap(mwWorkerData &data1, mwWorkerData &data2)
Definition: mwcoord.h:108
This namespace contains the entire CHomP library interface.
Definition: bitmaps.h:51