10 // stride array has length n_dims + 1
11 // stride[0] is size of the data
12 // stride[n_dims] == 1
13 // note that a zero-dimensional array is a scalar (with size 1 byte)
21 // following constructor is geared towards being called from array_dupN()
22 // which already has the strides available, so it doesn't calculate them
23 static inline __attribute__((always_inline)) struct array *array_new(
33 assert(stride[i] == s);
36 assert(stride[i] == s);
41 sizeof(struct array) +
45 n_dims * (2 * sizeof(size_t))
47 struct array *p = aligned_alloc(ALIGN, header + stride[0]);
49 perror("aligned_alloc()");
54 p->data = (char *)p + header;
55 p->stride = p->dim + n_dims;
56 memcpy(p->dim, dim, n_dims * sizeof(size_t));
57 memcpy(p->stride, stride, (n_dims + 1) * sizeof(size_t));
61 static inline __attribute__((always_inline)) void array_free(
67 // following are more optimized constructors for when number of dimensions
68 // is known but strides are not known and must be calculated from dimensions
69 static inline __attribute__((always_inline)) struct array *array_new0(void) {
70 struct array *p = aligned_alloc(
73 (sizeof(struct array) + sizeof(size_t) + ALIGN - 1) & ~(ALIGN - 1)
77 perror("aligned_alloc()");
82 p->data = (char *)p + (
83 (sizeof(struct array) + sizeof(size_t) + ALIGN - 1) & ~(ALIGN - 1)
90 static inline __attribute__((always_inline)) struct array *array_new0_init(
93 struct array *p = array_new0();
94 memcpy(p->data, src, p->stride[0]);
98 static inline __attribute__((always_inline)) struct array *array_new0_zero(void) {
99 struct array *p = array_new0();
100 memset(p->data, 0, p->stride[0]);
104 static inline __attribute__((always_inline)) struct array *array_new1(
107 struct array *p = aligned_alloc(
110 (sizeof(struct array) + 3 * sizeof(size_t) + ALIGN - 1) & ~(ALIGN - 1)
114 perror("aligned_alloc()");
119 p->data = (char *)p + (
120 (sizeof(struct array) + 3 * sizeof(size_t) + ALIGN - 1) & ~(ALIGN - 1)
122 p->stride = p->dim + 1;
129 static inline __attribute__((always_inline)) struct array *array_new1_init(
133 struct array *p = array_new1(dim0);
134 memcpy(p->data, src, p->stride[0]);
138 static inline __attribute__((always_inline)) struct array *array_new1_zero(
141 struct array *p = array_new1(dim0);
142 memset(p->data, 0, p->stride[0]);
146 static inline __attribute__((always_inline)) struct array *array_new2(
150 struct array *p = aligned_alloc(
153 (sizeof(struct array) + 5 * sizeof(size_t) + ALIGN - 1) & ~(ALIGN - 1)
157 perror("aligned_alloc()");
162 p->data = (char *)p + (
163 (sizeof(struct array) + 5 * sizeof(size_t) + ALIGN - 1) & ~(ALIGN - 1)
165 p->stride = p->dim + 2;
170 p->stride[0] = dim0 * dim1;
174 static inline __attribute__((always_inline)) struct array *array_new2_init(
179 struct array *p = array_new2(dim0, dim1);
180 memcpy(p->data, src, p->stride[0]);
184 static inline __attribute__((always_inline)) struct array *array_new2_zero(
188 struct array *p = array_new2(dim0, dim1);
189 memset(p->data, 0, p->stride[0]);
193 static inline __attribute__((always_inline)) struct array *array_new3(
198 struct array *p = aligned_alloc(
201 (sizeof(struct array) + 7 * sizeof(size_t) + ALIGN - 1) & ~(ALIGN - 1)
202 ) + dim0 * dim1 * dim2
205 perror("aligned_alloc()");
210 p->data = (char *)p + (
211 (sizeof(struct array) + 7 * sizeof(size_t) + ALIGN - 1) & ~(ALIGN - 1)
213 p->stride = p->dim + 3;
219 p->stride[1] = dim1 * dim2;
220 p->stride[0] = dim0 * p->stride[1];
224 static inline __attribute__((always_inline)) struct array *array_new3_init(
230 struct array *p = array_new3(dim0, dim1, dim2);
231 memcpy(p->data, src, p->stride[0]);
235 static inline __attribute__((always_inline)) struct array *array_new3_zero(
240 struct array *p = array_new3(dim0, dim1, dim2);
241 memset(p->data, 0, p->stride[0]);
245 static inline __attribute__((always_inline)) struct array *array_new4(
251 struct array *p = aligned_alloc(
254 (sizeof(struct array) + 9 * sizeof(size_t) + ALIGN - 1) & ~(ALIGN - 1)
255 ) + dim0 * dim1 * dim2 * dim3
258 perror("aligned_alloc()");
263 p->data = (char *)p + (
264 (sizeof(struct array) + 9 * sizeof(size_t) + ALIGN - 1) & ~(ALIGN - 1)
266 p->stride = p->dim + 4;
273 p->stride[2] = dim2 * dim3;
274 p->stride[1] = dim1 * p->stride[2];
275 p->stride[0] = dim0 * p->stride[1];
279 static inline __attribute__((always_inline)) struct array *array_new4_init(
286 struct array *p = array_new4(dim0, dim1, dim2, dim3);
287 memcpy(p->data, src, p->stride[0]);
291 static inline __attribute__((always_inline)) struct array *array_new4_zero(
297 struct array *p = array_new4(dim0, dim1, dim2, dim3);
298 memset(p->data, 0, p->stride[0]);
302 static inline __attribute__((always_inline)) void *array_index0(
303 const struct array *self
305 assert(self->n_dims >= 0);
309 static inline __attribute__((always_inline)) void *array_index1(
310 const struct array *self,
313 assert(self->n_dims >= 1);
314 assert(i0 >= 0 && i0 < self->dim[0]);
317 i0 * self->stride[1];
320 static inline __attribute__((always_inline)) void *array_index2(
321 const struct array *self,
325 assert(self->n_dims >= 2);
326 assert(i0 >= 0 && i0 < self->dim[0]);
327 assert(i1 >= 0 && i1 < self->dim[1]);
330 i1 * self->stride[2] +
331 i0 * self->stride[1];
334 static inline __attribute__((always_inline)) void *array_index3(
335 const struct array *self,
340 assert(self->n_dims >= 3);
341 assert(i0 >= 0 && i0 < self->dim[0]);
342 assert(i1 >= 0 && i1 < self->dim[1]);
343 assert(i2 >= 0 && i2 < self->dim[2]);
346 i2 * self->stride[3] +
347 i1 * self->stride[2] +
348 i0 * self->stride[1];
351 static inline __attribute__((always_inline)) void *array_index4(
352 const struct array *self,
358 assert(self->n_dims >= 4);
359 assert(i0 >= 0 && i0 < self->dim[0]);
360 assert(i1 >= 0 && i1 < self->dim[1]);
361 assert(i2 >= 0 && i2 < self->dim[2]);
362 assert(i3 >= 0 && i3 < self->dim[3]);
365 i3 * self->stride[4] +
366 i2 * self->stride[3] +
367 i1 * self->stride[2] +
368 i0 * self->stride[1];
371 static inline __attribute__((always_inline)) void array_get0(
372 const struct array *self,
375 memcpy(dest, array_index0(self), self->stride[0]);
378 static inline __attribute__((always_inline)) void array_get1(
379 const struct array *self,
383 memcpy(dest, array_index1(self, i0), self->stride[1]);
386 static inline __attribute__((always_inline)) void array_get2(
387 const struct array *self,
392 memcpy(dest, array_index2(self, i0, i1), self->stride[2]);
395 static inline __attribute__((always_inline)) void array_get3(
396 const struct array *self,
402 memcpy(dest, array_index3(self, i0, i1, i2), self->stride[3]);
405 static inline __attribute__((always_inline)) void array_get4(
406 const struct array *self,
413 memcpy(dest, array_index4(self, i0, i1, i2, i3), self->stride[4]);
416 static inline __attribute__((always_inline)) void array_set0(
420 memcpy(array_index0(self), src, self->stride[0]);
423 static inline __attribute__((always_inline)) void array_set1(
428 memcpy(array_index1(self, i0), src, self->stride[1]);
431 static inline __attribute__((always_inline)) void array_set2(
437 memcpy(array_index2(self, i0, i1), src, self->stride[2]);
440 static inline __attribute__((always_inline)) void array_set3(
447 memcpy(array_index3(self, i0, i1, i2), src, self->stride[3]);
450 static inline __attribute__((always_inline)) void array_set4(
458 memcpy(array_index4(self, i0, i1, i2, i3), src, self->stride[4]);
461 static inline __attribute__((always_inline)) void array_clear0(
464 memset(array_index0(self), 0, self->stride[0]);
467 static inline __attribute__((always_inline)) void array_clear1(
471 memset(array_index1(self, i0), 0, self->stride[1]);
474 static inline __attribute__((always_inline)) void array_clear2(
479 memset(array_index2(self, i0, i1), 0, self->stride[2]);
482 static inline __attribute__((always_inline)) void array_clear3(
488 memset(array_index3(self, i0, i1, i2), 0, self->stride[3]);
491 static inline __attribute__((always_inline)) void array_clear4(
498 memset(array_index4(self, i0, i1, i2, i3), 0, self->stride[4]);
501 static inline __attribute__((always_inline)) struct array *array_dup0(
502 const struct array *self
504 assert(self->n_dims >= 0);
505 struct array *p = array_new(
510 array_get0(self, p->data);
514 static inline __attribute__((always_inline)) struct array *array_dup1(
515 const struct array *self,
518 assert(self->n_dims >= 1);
519 struct array *p = array_new(
524 array_get1(self, p->data, i0);
528 static inline __attribute__((always_inline)) struct array *array_dup2(
529 const struct array *self,
533 assert(self->n_dims >= 2);
534 struct array *p = array_new(
539 array_get2(self, p->data, i0, i1);
543 static inline __attribute__((always_inline)) struct array *array_dup3(
544 const struct array *self,
549 assert(self->n_dims >= 3);
550 struct array *p = array_new(
555 array_get3(self, p->data, i0, i1, i2);
559 static inline __attribute__((always_inline)) struct array *array_dup4(
560 const struct array *self,
566 assert(self->n_dims >= 4);
567 struct array *p = array_new(
572 array_get4(self, p->data, i0, i1, i2, i3);