Allocate.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2008-2017 Imperial College London
5  * Copyright 2013-2017 Andreas Schuh
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_Allocate_H
21 #define MIRTK_Allocate_H
22 
23 #include "mirtk/Exception.h"
24 
25 
26 namespace mirtk {
27 
28 
29 // Usage:
30 // \code
31 // // Allocate an array of 10 pointers to a grey image and initialize them to 0
32 // GreyImage **images1;
33 // PAllocate(images1, 10);
34 // GreyImage **images2 = PAllocate<irtkGreyImage>(10);
35 // // Allocate an array of 5 integer values without initialization
36 // int *values1;
37 // Allocate(values1, 6);
38 // // Allocate a multi-dimensional array using existing 1D memory
39 // int **values2 = Allocate<int>(2, 3, values1);
40 // // Free memory again
41 // Deallocate(images1);
42 // Deallocate(images2);
43 // // Deallocate multi-dimensional array either as follows
44 // Deallocate(values2, values1);
45 // Deallocate(values1);
46 // // or only the multi-dimensional array, but no separate deallocation of the
47 // // 1D memory which is as well freed already by the following Deallocate call
48 // // Deallocate(values2);
49 // \endcode
50 
51 
52 using std::nothrow;
53 
54 
55 // =============================================================================
56 // 1D array
57 // =============================================================================
58 
59 // -----------------------------------------------------------------------------
60 /// Allocate 1D array
61 template <class Type>
62 inline void Allocate(Type *&matrix, int n)
63 {
64  // Set pointer to nullptr if memory size is not positive
65  if (n <= 0) {
66  matrix = nullptr;
67  return;
68  }
69  // Allocate data memory
70  if ((matrix = new (nothrow) Type[n]) == nullptr) {
71  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", n * sizeof(Type), " bytes");
72  }
73 }
74 
75 // -----------------------------------------------------------------------------
76 /// Allocate 1D array
77 template <class Type>
78 inline Type *Allocate(int n)
79 {
80  Type *matrix;
81  Allocate(matrix, n);
82  return matrix;
83 }
84 
85 // -----------------------------------------------------------------------------
86 /// Allocate 1D array and initialize it
87 template <class Type>
88 inline void CAllocate(Type *&matrix, int n, const Type &init = Type())
89 {
90  // Allocate data memory
91  Allocate(matrix, n);
92  // Initialize data memory
93  if (matrix) {
94  for (int i = 0; i < n; i++) matrix[i] = init;
95  }
96 }
97 
98 // -----------------------------------------------------------------------------
99 /// Allocate 1D array and initialize it
100 template <class Type>
101 inline Type *CAllocate(int n, const Type *init = nullptr)
102 {
103  Type *matrix;
104  const Type default_value = Type();
105  if (!init) init = &default_value;
106  CAllocate(matrix, n, *init);
107  return matrix;
108 }
109 
110 // -----------------------------------------------------------------------------
111 /// Allocate 1D array of pointers initialized to nullptr
112 template <typename Type>
113 inline void PAllocate(Type **&matrix, int n)
114 {
115  // Allocate data memory
116  Allocate(matrix, n);
117  // Initialize data memory
118  if (matrix) memset(matrix, 0, n * sizeof(Type *));
119 }
120 
121 // -----------------------------------------------------------------------------
122 /// Allocate 1D array of pointers initialized to nullptr
123 template <typename Type>
124 inline Type **PAllocate(int n)
125 {
126  Type **matrix;
127  PAllocate(matrix, n);
128  return matrix;
129 }
130 
131 // =============================================================================
132 // 2D array
133 // =============================================================================
134 
135 // -----------------------------------------------------------------------------
136 /// Allocate 2D array stored in contiguous memory block
137 template <class Type>
138 inline void CAllocate(Type **&matrix, int x, int y, const Type &init = Type())
139 {
140  const size_t n = static_cast<size_t>(x) * static_cast<size_t>(y);
141  // Set pointer to nullptr if memory size is not positive
142  if (n <= 0u) {
143  matrix = nullptr;
144  return;
145  }
146  // Allocate pointers
147  if ((matrix = new (nothrow) Type *[y]) == nullptr) {
148  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", y * sizeof(Type *), " bytes");
149  }
150  // Allocate data memory
151  if ((matrix[0] = new (nothrow) Type[n]) == nullptr) {
152  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", n * sizeof(Type), " bytes");
153  }
154  // Initialize data memory
155  for (size_t i = 0; i < n; ++i) matrix[0][i] = init;
156  // Initialize pointers
157  for (int j = 1; j < y; ++j) {
158  matrix[j] = matrix[j-1] + x;
159  }
160 }
161 
162 // -----------------------------------------------------------------------------
163 /// Allocate 2D array stored in contiguous memory block and initialize it
164 template <typename Type>
165 inline Type **CAllocate(int x, int y, const Type *init = nullptr)
166 {
167  Type **matrix;
168  const Type default_value = Type();
169  if (!init) init = &default_value;
170  CAllocate(matrix, x, y, *init);
171  return matrix;
172 }
173 
174 // -----------------------------------------------------------------------------
175 /// Allocate 2D array stored in contiguous memory block
176 template <class Type>
177 inline void Allocate(Type **&matrix, int x, int y, Type *data = nullptr)
178 {
179  const size_t n = static_cast<size_t>(x) * static_cast<size_t>(y);
180  // Set pointer to nullptr if memory size is not positive
181  if (n <= 0u) {
182  matrix = nullptr;
183  return;
184  }
185  // Allocate pointers
186  if ((matrix = new (nothrow) Type *[y]) == nullptr) {
187  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", y * sizeof(Type *), " bytes");
188  }
189  // Allocate data memory
190  if (data) matrix[0] = data;
191  else if ((matrix[0] = new (nothrow) Type[n]) == nullptr) {
192  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", n * sizeof(Type), " bytes");
193  }
194  // Initialize pointers
195  for (int j = 1; j < y; ++j) {
196  matrix[j] = matrix[j-1] + x;
197  }
198 }
199 
200 // -----------------------------------------------------------------------------
201 /// Allocate 2D array stored in contiguous memory block
202 template <typename Type>
203 inline Type **Allocate(int x, int y, Type *data = nullptr)
204 {
205  Type **matrix;
206  Allocate(matrix, x, y, data);
207  return matrix;
208 }
209 
210 // -----------------------------------------------------------------------------
211 /// Reshape 2D array stored in contiguous memory block
212 template <class Type>
213 inline Type **Reshape(Type **matrix, int x, int y)
214 {
215  // Keep data memory
216  Type * const data = matrix[0];
217  // Deallocate old pointers
218  delete[] matrix;
219  // Allocate new pointers
220  if ((matrix = new (nothrow) Type *[y]) == nullptr) {
221  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", y * sizeof(Type *), " bytes");
222  }
223  // Restore data memory
224  matrix[0] = data;
225  // Initialize new pointers
226  for (int j = 1; j < y; ++j) {
227  matrix[j] = matrix[j-1] + x;
228  }
229  return matrix;
230 }
231 
232 // =============================================================================
233 // 3D array
234 // =============================================================================
235 
236 // -----------------------------------------------------------------------------
237 /// Allocate 3D array stored in contiguous memory block
238 template <class Type>
239 inline void CAllocate(Type ***&matrix, int x, int y, int z, const Type &init = Type())
240 {
241  const size_t n = static_cast<size_t>(x)
242  * static_cast<size_t>(y)
243  * static_cast<size_t>(z);
244  // Set pointer to nullptr if memory size is not positive
245  if (n <= 0u) {
246  matrix = nullptr;
247  return;
248  }
249  // Allocate pointers
250  if ((matrix = new (nothrow) Type **[z]) == nullptr) {
251  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", z * sizeof(Type **), " bytes");
252  }
253  if ((matrix[0] = new (nothrow) Type *[z*y]) == nullptr) {
254  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", z * y * sizeof(Type *), " bytes");
255  }
256  // Allocate data memory
257  if ((matrix[0][0] = new (nothrow) Type[n]) == nullptr) {
258  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", n * sizeof(Type), " bytes");
259  }
260  // Initialize data memory
261  for (size_t i = 0; i < n; ++i) matrix[0][0][i] = init;
262  // Initialize pointers
263  for (int k = 0; k < z; ++k) {
264  if (k > 0) matrix[k] = matrix[k-1] + y;
265  for (int j = 0; j < y; ++j) {
266  matrix[k][j] = matrix[0][0] + (k*y + j) * x;
267  }
268  }
269 }
270 
271 // -----------------------------------------------------------------------------
272 /// Allocate 3D array stored in contiguous memory block and initialize it
273 template <typename Type>
274 inline Type ***CAllocate(int x, int y, int z, const Type *init = nullptr)
275 {
276  Type ***matrix;
277  const Type default_value = Type();
278  if (!init) init = &default_value;
279  CAllocate(matrix, x, y, z, *init);
280  return matrix;
281 }
282 
283 // -----------------------------------------------------------------------------
284 /// Allocate 3D array stored in contiguous memory block
285 template <class Type>
286 inline void Allocate(Type ***&matrix, int x, int y, int z, Type *data = nullptr)
287 {
288  const size_t n = static_cast<size_t>(x)
289  * static_cast<size_t>(y)
290  * static_cast<size_t>(z);
291  // Set pointer to nullptr if memory size is not positive
292  if (n <= 0u) {
293  matrix = nullptr;
294  return;
295  }
296  // Allocate pointers
297  if ((matrix = new (nothrow) Type **[z]) == nullptr) {
298  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", z * sizeof(Type **), " bytes");
299  }
300  if ((matrix[0] = new (nothrow) Type *[z*y]) == nullptr) {
301  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", z * y * sizeof(Type *), " bytes");
302  }
303  // Allocate data memory
304  if (data) matrix[0][0] = data;
305  else if ((matrix[0][0] = new (nothrow) Type[n]) == nullptr) {
306  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", n * sizeof(Type), " bytes");
307  }
308  // Initialize pointers
309  for (int k = 0; k < z; ++k) {
310  if (k > 0) matrix[k] = matrix[k-1] + y;
311  for (int j = 0; j < y; ++j) {
312  matrix[k][j] = matrix[0][0] + (k * y + j) * x;
313  }
314  }
315 }
316 
317 // -----------------------------------------------------------------------------
318 /// Allocate 3D array stored in contiguous memory block
319 template <typename Type>
320 inline Type ***Allocate(int x, int y, int z, Type *data = nullptr)
321 {
322  Type ***matrix;
323  Allocate(matrix, x, y, z, data);
324  return matrix;
325 }
326 
327 // -----------------------------------------------------------------------------
328 /// Reshape 3D array stored in contiguous memory block
329 template <class Type>
330 inline Type ***Reshape(Type ***matrix, int x, int y, int z)
331 {
332  // Keep data memory
333  Type * const data = matrix[0][0];
334  // Deallocate old pointers
335  delete[] matrix[0];
336  delete[] matrix;
337  // Allocate new pointers
338  if ((matrix = new (nothrow) Type **[z]) == nullptr) {
339  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", z * sizeof(Type **), " bytes");
340  }
341  if ((matrix[0] = new (nothrow) Type *[z*y]) == nullptr) {
342  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", z * y * sizeof(Type *), " bytes");
343  }
344  // Restore data memory
345  matrix[0][0] = data;
346  // Initialize new pointers
347  for (int k = 0; k < z; ++k) {
348  if (k > 0) matrix[k] = matrix[k-1] + y;
349  for (int j = 0; j < y; ++j) {
350  matrix[k][j] = matrix[0][0] + (k * y + j) * x;
351  }
352  }
353  return matrix;
354 }
355 
356 // =============================================================================
357 // 4D array
358 // =============================================================================
359 
360 // -----------------------------------------------------------------------------
361 /// Allocate 4D array stored in contiguous memory block and initialize it
362 template <class Type>
363 inline void CAllocate(Type ****&matrix, int x, int y, int z, int t, const Type &init = Type())
364 {
365  const size_t n = static_cast<size_t>(x)
366  * static_cast<size_t>(y)
367  * static_cast<size_t>(z)
368  * static_cast<size_t>(t);
369  // Set pointer to nullptr if memory size is not positive
370  if (n <= 0u) {
371  matrix = nullptr;
372  return;
373  }
374  // Allocate pointers
375  if ((matrix = new (nothrow) Type ***[t]) == nullptr) {
376  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", t * sizeof(Type ***), " bytes");
377  }
378  if ((matrix[0] = new (nothrow) Type **[t*z]) == nullptr) {
379  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", t * z * sizeof(Type **), " bytes");
380  }
381  if ((matrix[0][0] = new (nothrow) Type *[t*z*y]) == nullptr) {
382  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", t * z * y * sizeof(Type *), " bytes");
383  }
384  // Allocate data memory
385  if ((matrix[0][0][0] = new (nothrow) Type[n]) == nullptr) {
386  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", n * sizeof(Type), " bytes");
387  }
388  // Initialize data memory
389  for (size_t i = 0; i < n; ++i) matrix[0][0][0][i] = init;
390  // Initialize pointers
391  for (int l = 0; l < t; ++l) {
392  if (l > 0) matrix[l] = matrix[l-1] + z;
393  for (int k = 0; k < z; ++k) {
394  matrix[l][k] = matrix[0][0] + (l * z + k) * y;
395  for (int j = 0; j < y; ++j) {
396  matrix[l][k][j] = matrix[0][0][0] + ((l * z + k) * y + j) * x;
397  }
398  }
399  }
400 }
401 
402 // -----------------------------------------------------------------------------
403 /// Allocate 4D array stored in contiguous memory block and initialize it
404 template <typename Type>
405 inline Type ****CAllocate(int x, int y, int z, int t, const Type *init = nullptr)
406 {
407  Type ****matrix;
408  const Type default_value = Type();
409  if (!init) init = &default_value;
410  CAllocate(matrix, x, y, z, t, *init);
411  return matrix;
412 }
413 
414 // -----------------------------------------------------------------------------
415 /// Allocate 4D array stored in contiguous memory block
416 template <class Type>
417 inline void Allocate(Type ****&matrix, int x, int y, int z, int t, Type *data = nullptr)
418 {
419  const size_t n = static_cast<size_t>(x)
420  * static_cast<size_t>(y)
421  * static_cast<size_t>(z)
422  * static_cast<size_t>(t);
423  // Set pointer to nullptr if memory size is not positive
424  if (n <= 0u) {
425  matrix = nullptr;
426  return;
427  }
428  // Allocate pointers
429  if ((matrix = new (nothrow) Type ***[t]) == nullptr) {
430  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", t * sizeof(Type ***), " bytes");
431  }
432  if ((matrix[0] = new (nothrow) Type ** [t*z]) == nullptr) {
433  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", t * z * sizeof(Type **), " bytes");
434  }
435  if ((matrix[0][0] = new (nothrow) Type * [t*z*y]) == nullptr) {
436  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", t * z * y * sizeof(Type *), " bytes");
437  }
438  // Allocate data memory
439  if (data) matrix[0][0][0] = data;
440  else if ((matrix[0][0][0] = new (nothrow) Type[n]) == nullptr) {
441  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", n * sizeof(Type), " bytes");
442  }
443  // Initialize pointers
444  for (int l = 0; l < t; ++l) {
445  if (l > 0) matrix[l] = matrix[l-1] + z;
446  for (int k = 0; k < z; ++k) {
447  matrix[l][k] = matrix[0][0] + (l * z + k) * y;
448  for (int j = 0; j < y; ++j) {
449  matrix[l][k][j] = matrix[0][0][0] + ((l * z + k) * y + j) * x;
450  }
451  }
452  }
453 }
454 
455 // -----------------------------------------------------------------------------
456 /// Allocate 4D array stored in contiguous memory block
457 template <typename Type>
458 inline Type ****Allocate(int x, int y, int z, int t, Type *data = nullptr)
459 {
460  Type ****matrix;
461  Allocate(matrix, x, y, z, t, data);
462  return matrix;
463 }
464 
465 // -----------------------------------------------------------------------------
466 /// Reshape 4D array stored in contiguous memory block
467 template <class Type>
468 inline Type ****Reshape(Type ****matrix, int x, int y, int z, int t)
469 {
470  // Keep data memory
471  Type * const data = matrix[0][0][0];
472  // Deallocate old pointers
473  delete[] matrix[0][0];
474  delete[] matrix[0];
475  delete[] matrix;
476  // Allocate new pointers
477  if ((matrix = new (nothrow) Type ***[t]) == nullptr) {
478  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", t * sizeof(Type ***), " bytes");
479  }
480  if ((matrix[0] = new (nothrow) Type **[t*z]) == nullptr) {
481  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", t * z * sizeof(Type **), " bytes");
482  }
483  if ((matrix[0][0] = new (nothrow) Type *[t*z*y]) == nullptr) {
484  Throw(ERR_Memory, __FUNCTION__, "Failed to allocate ", t * z * y * sizeof(Type *), " bytes");
485  }
486  // Restore data memory
487  matrix[0][0][0] = data;
488  // Initialize new pointers
489  for (int l = 0; l < t; ++l) {
490  if (l > 0) matrix[l] = matrix[l-1] + z;
491  for (int k = 0; k < z; ++k) {
492  matrix[l][k] = matrix[0][0] + (l * z + k) * y;
493  for (int j = 0; j < y; ++j) {
494  matrix[l][k][j] = matrix[0][0][0] + ((l * z + k) * y + j) * x;
495  }
496  }
497  }
498  return matrix;
499 }
500 
501 
502 } // namespace mirtk
503 
504 #endif // MIRTK_Allocate_H
void PAllocate(Type **&matrix, int n)
Allocate 1D array of pointers initialized to nullptr.
Definition: Allocate.h:113
void Allocate(Type *&matrix, int n)
Allocate 1D array.
Definition: Allocate.h:62
void CAllocate(Type *&matrix, int n, const Type &init=Type())
Allocate 1D array and initialize it.
Definition: Allocate.h:88
Definition: IOConfig.h:41
Type ** Reshape(Type **matrix, int x, int y)
Reshape 2D array stored in contiguous memory block.
Definition: Allocate.h:213
void Throw(ErrorType err, const char *func, Args... args)
Definition: Exception.h:74