Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
range.h
Go to the documentation of this file.
1/** @file range.h
2 */
3/**
4# Multi-dimensional arrays with arbitrary bounds
5
6This file implements low-level memory allocation for multi-dimensional
7arrays with arbitrary starting and ending indices. This is used to
8implement more memory-efficient tree structures.
9
10The `Memalloc` data structure represents the one-dimensional array
11which is defined by a generic pointer `p` and the size of its elements
12`size` in bytes.
13
14The range of indices of the array is defined by the `Memrange` data
15structure. */
16
17typedef struct {
18 void ** p;
19 int size;
20} Memalloc;
21
22typedef struct {
23 int start, end;
24} Memrange;
25
26/**
27## Memory allocation for one-dimensional arrays
28
29The `memrange_alloc()` function allocates the memory of the arrays
30defined by `mem` and updates the corresponding index range `r` for a
31(new) element of index `i`.
32
33The `mem` argument is an array of `Memalloc` structures ending with a
34NULL pointer for element `p`. */
35
36void memrange_alloc (Memrange * r, Memalloc * mem, int i)
37{
38 if (r->start == r->end) {
39 r->start = i;
40 r->end = i + 1;
41 for (Memalloc * m = mem; m->p; m++) {
42 *m->p = calloc (1, m->size);
43 *m->p = (char *)(*m->p) - i*m->size;
44 }
45 }
46 else if (i >= r->end) {
47 for (Memalloc * m = mem; m->p; m++) {
48 *m->p = realloc ((char *)(*m->p) + r->start*m->size,
49 m->size*(i + 1 - r->start));
50 *m->p = (char *)(*m->p) - r->start*m->size;
51 memset ((char *)(*m->p) + r->end*m->size, 0, (i - r->end + 1)*m->size);
52 }
53 r->end = i + 1;
54 }
55 else if (i < r->start) {
56 for (Memalloc * m = mem; m->p; m++) {
57 *m->p = realloc ((char *)(*m->p) + r->start*m->size, m->size*(r->end - i));
58 memmove ((char *)(*m->p) + (r->start - i)*m->size, *m->p,
59 m->size*(r->end - r->start));
60 memset ((char *)(*m->p), 0, (r->start - i)*m->size);
61 *m->p = (char *)(*m->p) - i*m->size;
62 }
63 r->start = i;
64 }
65}
66
67/**
68## Memory deallocation for one-dimensional arrays
69
70The `memrange_free()` function takes the same arguments as
71`memrange_alloc()` but performs the inverse operation. It returns
72`true` if the arrays are empty after deallocation (i.e. the range of
73indices is empty). */
74
75bool memrange_free (Memrange * r, Memalloc * mem, int i)
76{
77 if (i == r->start) {
78 if (i == r->end - 1) {
79 for (Memalloc * m = mem; m->p; m++) {
80 free ((char *)(*m->p) + r->start*m->size);
81 *m->p = NULL;
82 }
83 r->start = r->end = 0;
84 return true;
85 }
86 else {
87 for (i = i + 1; i < r->end &&
88 !*(void **)((char *)(*mem->p) + i*mem->size); i++);
89 for (Memalloc * m = mem; m->p; m++) {
90 memmove ((char *)(*m->p) + r->start*m->size,
91 (char *)(*m->p) + i*m->size, m->size*(r->end - i));
92 *m->p = realloc ((char *)(*m->p) + r->start*m->size,
93 m->size*(r->end - i));
94 *m->p = (char *)(*m->p) - i*m->size;
95 }
96 r->start = i;
97 }
98 }
99 else if (i == r->end - 1) {
100 for (i = i - 1; i >= r->start &&
101 !*(void **)((char *)(*mem->p) + i*mem->size); i--);
102 r->end = i + 1;
103 for (Memalloc * m = mem; m->p; m++) {
104 *m->p = realloc ((char *)(*m->p) + r->start*m->size,
105 m->size*(r->end - r->start));
106 *m->p = (char *)(*m->p) - r->start*m->size;
107 }
108 }
109 else {
110 assert (i > r->start && i < r->end);
111 for (Memalloc * m = mem; m->p; m++)
112 memset ((char *)(*m->p) + i*m->size, 0, m->size);
113 }
114 return false;
115}
116
117/**
118## Multidimensional arrays
119
120The `Memindex` structure defines multi-dimensional arrays with
121variable bounds. The interface is that used by [/src/grid/tree.h](). */
122
123struct _Memindex {
125#if dimension >= 2
127# if dimension >= 3
128 Memrange ** r3;
129# endif
130#endif
131#if dimension == 1
132 char ** b;
133#elif dimension == 2
134 char *** b;
135#else
136 char **** b;
137#endif
138};
139
140#define Memindex struct _Memindex *
141
142/**
143The `mem_data()` macros return the data stored at a specific
144(multidimensional) index. It assumes that the index is allocated. This
145can be checked with `mem_allocated()`. */
146
147#if dimension == 1
148# define mem_allocated(m,i) \
149 ((i) >= (m)->r1.start && (i) < (m->r1.end) && \
150 (m)->b[i])
151# define mem_data(m,i) ((m)->b[i])
152#elif dimension == 2
153# define mem_allocated(m,i,j) \
154 ((i) >= (m)->r1.start && (i) < (m->r1.end) && \
155 (m)->b[i] && \
156 (j) >= (m)->r2[i].start && (j) < (m)->r2[i].end && \
157 (m)->b[i][j])
158# define mem_data(m,i,j) ((m)->b[i][j])
159#else // dimension == 3
160# define mem_allocated(m,i,j,k) \
161 ((i) >= (m)->r1.start && (i) < (m->r1.end) && \
162 (m)->b[i] && \
163 (j) >= (m)->r2[i].start && (j) < (m)->r2[i].end && \
164 (m)->b[i][j] && \
165 (k) >= (m)->r3[i][j].start && (k) < (m)->r3[i][j].end && \
166 (m)->b[i][j][k])
167# define mem_data(m,i,j,k) ((m)->b[i][j][k])
168#endif // dimension == 3
169
170/**
171The `mem_new()` function returns a new (empty) `Memindex`. */
172
174{
175 Memindex m = calloc (1, sizeof (struct _Memindex));
176 return m;
177}
178
179/**
180The `mem_destroy()` function frees all the memory allocated by a given
181`Memindex`. */
182
183void mem_destroy (Memindex m, int len)
184{
185#if dimension >= 2
186 for (int i = m->r1.start; i < m->r1.end; i++)
187 if (m->b[i]) {
188#if dimension >= 3
189 for (int j = m->r2[i].start; j < m->r2[i].end; j++)
190 if (m->b[i][j])
191 free (m->b[i][j] + m->r3[i][j].start);
192 free (m->r3[i] + m->r2[i].start);
193#endif // dimension >= 3
194 free (m->b[i] + m->r2[i].start);
195 }
196 if (m->b) {
197 free (m->r2 + m->r1.start);
198#if dimension >= 3
199 free (m->r3 + m->r1.start);
200#endif
201 }
202#endif // dimension >= 2
203 if (m->b)
204 free (m->b + m->r1.start);
205 free (m);
206}
207
208/**
209The `mem_assign()` function assigns a (pointer) value to a given index. */
210
211#if dimension == 1
212void mem_assign (Memindex m, int i, int len, void * b)
213{
214 Memalloc mem[] = {{(void **)&m->b, sizeof(char *)},
215 {NULL}};
216 memrange_alloc (&m->r1, mem, i);
217 mem_data(m,i) = b;
218}
219#elif dimension == 2
220void mem_assign (Memindex m, int i, int j, int len, void * b)
221{
222 Memalloc mem[] = {{(void **)&m->b, sizeof(char **)},
223 {(void **)&m->r2, sizeof(Memrange)},
224 {NULL}};
225 memrange_alloc (&m->r1, mem, i);
226 Memalloc mem1[] = {{(void **)&m->b[i], sizeof(char *)},
227 {NULL}};
228 memrange_alloc (&m->r2[i], mem1, j);
229 mem_data(m,i,j) = b;
230}
231#else // dimension == 3
232void mem_assign (Memindex m, int i, int j, int k, int len, void * b)
233{
234 Memalloc mem[] = {{(void **)&m->b, sizeof(char ***)},
235 {(void **)&m->r2, sizeof(Memrange)},
236 {(void **)&m->r3, sizeof(Memrange *)},
237 {NULL}};
238 memrange_alloc (&m->r1, mem, i);
239 Memalloc mem1[] = {{(void **)&m->b[i], sizeof(char **)},
240 {(void **)&m->r3[i], sizeof(Memrange)},
241 {NULL}};
242 memrange_alloc (&m->r2[i], mem1, j);
243 Memalloc mem2[] = {{(void **)&m->b[i][j], sizeof(char *)},
244 {NULL}};
245 memrange_alloc (&m->r3[i][j], mem2, k);
246 mem_data(m,i,j,k) = b;
247}
248#endif // dimension == 3
249
250/**
251The `mem_free()` function frees a given index. */
252
253#if dimension == 1
254void mem_free (Memindex m, int i, int len, void * b)
255{
256 Memalloc mem[] = {{(void **)&m->b, sizeof(char *)},
257 {NULL}};
258 memrange_free (&m->r1, mem, i);
259}
260#elif dimension == 2
261void mem_free (Memindex m, int i, int j, int len, void * b)
262{
263 Memalloc mem[] = {{(void **)&m->b[i], sizeof(char *)},
264 {NULL}};
265 if (memrange_free (&m->r2[i], mem, j)) {
266 Memalloc mem[] = {{(void **)&m->b, sizeof(char **)},
267 {(void **)&m->r2, sizeof(Memrange)},
268 {NULL}};
269 memrange_free (&m->r1, mem, i);
270 }
271}
272#else // dimension == 3
273void mem_free (Memindex m, int i, int j, int k, int len, void * b)
274{
275 Memalloc mem[] = {{(void **)&m->b[i][j], sizeof(char *)},
276 {NULL}};
277 if (memrange_free (&m->r3[i][j], mem, k)) {
278 Memalloc mem[] = {{(void **)&m->b[i], sizeof(char **)},
279 {(void **)&m->r3[i], sizeof(Memrange)},
280 {NULL}};
281 if (memrange_free (&m->r2[i], mem, j)) {
282 Memalloc mem[] = {{(void **)&m->b, sizeof(char ***)},
283 {(void **)&m->r2, sizeof(Memrange)},
284 {(void **)&m->r3, sizeof(Memrange *)},
285 {NULL}};
286 memrange_free (&m->r1, mem, i);
287 }
288 }
289}
290#endif // dimension == 3
291
292/**
293The `foreach_mem()` macro traverses every `_i` allocated elements of
294array `_m` taking into account a periodicity of `_len` (and ghost
295cells). */
296
297#if dimension == 1
298macro foreach_mem (struct _Memindex * index, int len, int _i) {
299 struct _Memindex * _m = index;
300 int _len = len;
301 Point point = {0};
302 for (point.i = max(Period.x*GHOSTS, _m->r1.start);
303 point.i < min(_len - Period.x*GHOSTS, _m->r1.end);
304 point.i += _i)
305 if (_m->b[point.i])
306 {...}
307}
308#elif dimension == 2
309macro foreach_mem (struct _Memindex * index, int len, int _i) {
310 struct _Memindex * _m = index;
311 int _len = len;
312 Point point = {0};
313 for (point.i = max(Period.x*GHOSTS, _m->r1.start);
314 point.i < min(_len - Period.x*GHOSTS, _m->r1.end);
315 point.i += _i)
316 if (_m->b[point.i])
317 for (point.j = max(Period.y*GHOSTS, _m->r2[point.i].start);
318 point.j < min(_len - Period.y*GHOSTS, _m->r2[point.i].end);
319 point.j += _i)
320 if (_m->b[point.i][point.j])
321 {...}
322}
323#else // dimension == 3
324macro foreach_mem (struct _Memindex * index, int len, int _i) {
325 struct _Memindex * _m = index;
326 int _len = len;
327 Point point = {0};
328 for (point.i = max(Period.x*GHOSTS, _m->r1.start);
329 point.i < min(_len - Period.x*GHOSTS, _m->r1.end);
330 point.i += _i)
331 if (_m->b[point.i])
332 for (point.j = max(Period.y*GHOSTS, _m->r2[point.i].start);
333 point.j < min(_len - Period.y*GHOSTS, _m->r2[point.i].end);
334 point.j += _i)
335 if (_m->b[point.i][point.j])
336 for (point.k = max(Period.z*GHOSTS, _m->r3[point.i][point.j].start);
337 point.k < min(_len - Period.z*GHOSTS, _m->r3[point.i][point.j].end);
338 point.k += _i)
339 if (_m->b[point.i][point.j][point.k])
340 {...}
341}
342#endif // dimension == 3
int min
Definition balance.h:192
define k
define m((k)==0 &&(l)==0 &&(m)==0) macro2 foreach_point(double _x=0.
#define GHOSTS
Definition cartesian.h:13
free(list1)
int x
Definition common.h:76
struct @0 Period
define sysmalloc malloc define syscalloc calloc define sysrealloc realloc define sysfree free define systrdup strdup define line calloc(n, s) @ define prealloc(p
#define assert(a)
Definition config.h:107
define sysmalloc malloc define syscalloc calloc define sysrealloc realloc define sysfree free define systrdup strdup define line line realloc(p, s) @ define pfree(p
Point point
Definition conserving.h:86
*cs[i, 0, 0] a *[i -1, 0, 0] j
Definition embed.h:88
scalar int i
Definition embed.h:74
macro
We also redefine the "per field" (inner) traversal.
Definition layers.h:18
size_t max
Definition mtrace.h:8
size *double * b
struct _Memindex * mem_new(int len)
The mem_new() function returns a new (empty) Memindex.
Definition range.h:173
bool memrange_free(Memrange *r, Memalloc *mem, int i)
Definition range.h:75
void memrange_alloc(Memrange *r, Memalloc *mem, int i)
Definition range.h:36
macro foreach_mem(struct _Memindex *index, int len, int _i)
The foreach_mem() macro traverses every _i allocated elements of array _m taking into account a perio...
Definition range.h:309
void mem_free(struct _Memindex *m, int i, int j, int len, void *b)
The mem_free() function frees a given index.
Definition range.h:261
#define Memindex
Definition range.h:140
void mem_assign(struct _Memindex *m, int i, int j, int len, void *b)
The mem_assign() function assigns a (pointer) value to a given index.
Definition range.h:220
#define mem_data(m, i, j)
Definition range.h:158
void mem_destroy(struct _Memindex *m, int len)
The mem_destroy() function frees all the memory allocated by a given Memindex.
Definition range.h:183
def _i
Definition stencils.h:405
void ** p
Definition range.h:18
int size
Definition range.h:19
int end
Definition range.h:23
int start
Definition range.h:23
Definition linear.h:21
int i
Definition linear.h:23
int len
Definition simple.h:16
Memrange * r2
Definition range.h:126
Memrange r1
Definition range.h:124
char *** b
Definition range.h:134
Array * index