Code snippets:muldim sim
From C
3 files. You might compile them together with something like:
$ gcc -ansi -pedantic -o muldim_test muldim.c muldim_test.c
The first file is muldim_test.c:
/**** muldim_test.c - Shao Miller, April 4th, 2012 */
#include <stdlib.h>
#include <stdio.h>
#include "muldim.h"
/*** Macros */
#define CountOf(array) (sizeof (array) / sizeof *(array))
int main(void) {
int result;
muldim_t arr;
muldim_t end;
int test[2][3][4];
int i, j, k, * ip;
/* Assume failure */
result = EXIT_FAILURE;
/* Same dimensions as 'test' */
arr = muldim_zalloc(sizeof (int), 3, 2, 3, 4);
if (!arr.ptr) {
goto err_arr;
}
muldim_dmp(arr);
end = muldim_get(arr, 3, 1, 2, 4);
if (!end.ptr) {
goto err_end;
}
muldim_dmp(end);
printf(
"(\n"
" (char *) (test[1][2] + 4) -\n"
" (char *) test[0][0]\n"
" ) == %d\n",
(
(char *) (test[1][2] + 4) -
(char *) test[0][0]
)
);
printf(
"(\n"
" (char *) end.ptr -\n"
" (char *) arr.ptr\n"
" ) == %d\n",
(
(char *) end.ptr -
(char *) arr.ptr
)
);
/* Same dimensions as 'test' */
for (i = 0; i < CountOf(test); ++i) {
for (j = 0; j < CountOf(test[0]); ++j) {
ip = muldim_get(arr, 2, i, j).ptr;
for (k = 0; k < CountOf(test[0][0]); ++k) {
if (ip[k]) {
printf("muldim_zalloc failed!\n");
goto err_nonzero;
}
ip[k] = 42;
continue;
}
continue;
}
continue;
}
/* Success */
printf("Yay\n");
result = EXIT_SUCCESS;
err_nonzero:
err_end:
free(arr.mem);
err_arr:
return result;
}
The next file is the header muldim.h:
/**** muldim.h - Shao Miller, April 4th, 2012 */
#ifndef MULDIM_H_
#include <stddef.h>
/*** Macros */
#define MULDIM_H_
/*** Object types */
typedef struct s_muldim s_muldim, muldim_t;
/*** Struct/union definitions */
struct s_muldim {
void * ptr;
size_t dims;
size_t stride;
size_t * dims_at;
void * mem;
};
/*** Function declarations */
extern muldim_t muldim_alloc(size_t base_sz, size_t dims, ...);
extern muldim_t muldim_zalloc(size_t base_sz, size_t dims, ...);
extern muldim_t muldim_get(muldim_t muldim, size_t dims, ...);
extern void muldim_dmp(muldim_t muldim);
#endif /* MULDIM_H_ */
And lastly we have muldim.c:
/**** muldim.c - Shao Miller, April 4th, 2012 */
#include <stddef.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include "muldim.h"
/*** Function declarations */
static size_t sz_add(size_t x, size_t y);
static size_t sz_mul(size_t x, size_t y);
/*** Struct/union definitions */
struct s_muldim_wrapper {
muldim_t muldim;
size_t dims_hdr[1];
};
/*** Object definitions */
static const muldim_t new_muldim;
/*** Function definitions */
muldim_t muldim_alloc(size_t base_sz, size_t dims, ...) {
register const size_t dims_offset = offsetof(
struct s_muldim_wrapper,
dims_hdr
);
muldim_t result;
size_t dims_sz;
size_t hdr_sz;
va_list vargs;
size_t array_sz;
size_t i;
int dim;
size_t total_sz;
char * ptr;
size_t * dims_at;
result = new_muldim;
if (!base_sz) {
goto err_base_sz;
}
dims_sz = sz_mul(dims, sizeof result.dims_at[0]);
if (!dims_sz) {
goto err_dims_sz;
}
hdr_sz = sz_add(dims_offset, dims_sz);
if (!hdr_sz) {
goto err_hdr_sz;
}
hdr_sz = sz_add(base_sz, hdr_sz);
if (!hdr_sz) {
goto err_hdr_sz;
}
hdr_sz = hdr_sz - 1;
hdr_sz = hdr_sz / base_sz;
hdr_sz = hdr_sz * base_sz;
va_start(vargs, dims);
array_sz = base_sz;
for (i = dims; i; --i) {
dim = va_arg(vargs, int);
if (dim < 1) {
goto err_dim;
}
array_sz = sz_mul(array_sz, (size_t) dim);
if (!array_sz) {
goto err_array_sz;
}
continue;
}
va_end(vargs);
total_sz = sz_add(hdr_sz, array_sz);
if (!total_sz) {
goto err_total_sz;
}
ptr = malloc(total_sz);
if (!ptr) {
goto err_ptr;
}
/* Success */
dims_at = (void *) (ptr + dims_offset);
va_start(vargs, dims);
for (i = 0; i < dims; ++i) {
dim = va_arg(vargs, int);
dims_at[i] = (size_t) dim;
continue;
}
va_end(vargs);
result.ptr = ptr + hdr_sz;
result.dims = dims;
result.stride = array_sz;
result.dims_at = dims_at;
result.mem = ptr;
*(muldim_t *) ptr = result;
return result;
free(ptr);
err_ptr:
err_total_sz:
err_array_sz:
err_dim:
err_hdr_sz:
err_dims_sz:
err_base_sz:
return result;
}
muldim_t muldim_zalloc(size_t base_sz, size_t dims, ...) {
register const size_t dims_offset = offsetof(
struct s_muldim_wrapper,
dims_hdr
);
muldim_t result;
size_t dims_sz;
size_t hdr_sz;
va_list vargs;
size_t array_sz;
size_t i;
int dim;
size_t total_sz;
char * ptr;
size_t * dims_at;
result = new_muldim;
if (!base_sz) {
goto err_base_sz;
}
dims_sz = sz_mul(dims, sizeof result.dims_at[0]);
if (!dims_sz) {
goto err_dims_sz;
}
hdr_sz = sz_add(dims_offset, dims_sz);
if (!hdr_sz) {
goto err_hdr_sz;
}
hdr_sz = sz_add(base_sz, hdr_sz);
if (!hdr_sz) {
goto err_hdr_sz;
}
hdr_sz = hdr_sz - 1;
hdr_sz = hdr_sz / base_sz;
hdr_sz = hdr_sz * base_sz;
va_start(vargs, dims);
array_sz = base_sz;
for (i = dims; i; --i) {
dim = va_arg(vargs, int);
if (dim < 1) {
goto err_dim;
}
array_sz = sz_mul(array_sz, (size_t) dim);
if (!array_sz) {
goto err_array_sz;
}
continue;
}
va_end(vargs);
total_sz = sz_add(hdr_sz, array_sz);
if (!total_sz) {
goto err_total_sz;
}
total_sz = total_sz / base_sz;
ptr = calloc(total_sz, base_sz);
if (!ptr) {
goto err_ptr;
}
/* Success */
dims_at = (void *) (ptr + dims_offset);
va_start(vargs, dims);
for (i = 0; i < dims; ++i) {
dim = va_arg(vargs, int);
dims_at[i] = (size_t) dim;
continue;
}
va_end(vargs);
result.ptr = ptr + hdr_sz;
result.dims = dims;
result.stride = array_sz;
result.dims_at = dims_at;
result.mem = ptr;
*(muldim_t *) ptr = result;
return result;
free(ptr);
err_ptr:
err_total_sz:
err_array_sz:
err_dim:
err_hdr_sz:
err_dims_sz:
err_base_sz:
return result;
}
muldim_t muldim_get(muldim_t muldim, size_t dims, ...) {
char * ptr;
va_list vargs;
int dim;
if (!dims || dims > muldim.dims) {
goto err_dims;
}
ptr = muldim.ptr;
va_start(vargs, dims);
while (dims--) {
dim = va_arg(vargs, int);
if (dim < 0 || dim > muldim.dims_at[0]) {
goto err_dim;
}
muldim.stride = muldim.stride / muldim.dims_at[0];
ptr = ptr + muldim.stride * dim;
--muldim.dims;
++muldim.dims_at;
continue;
}
va_end(vargs);
/* Success */
muldim.ptr = ptr;
return muldim;
err_dim:
err_dims:
return new_muldim;
}
void muldim_dmp(muldim_t muldim) {
printf(
"ptr == %p\n"
"dims == %u\n"
"stride == %u\n"
"dims_at == %p\n"
"mem == %p\n",
muldim.ptr,
(unsigned int) muldim.dims,
(unsigned int) muldim.stride,
(void *) muldim.dims_at,
muldim.mem
);
printf("dimensions: { ");
while (muldim.dims--) {
printf("%u, ", (unsigned int) muldim.dims_at++[0]);
continue;
}
printf("}\n");
return;
}
static size_t sz_add(size_t x, size_t y) {
size_t result;
result = x + y;
if (result <= x || result <= y) {
/* Wrap-around */
return 0;
}
return result;
}
static size_t sz_mul(size_t x, size_t y) {
size_t result;
result = x * y;
if (result <= x || result <= y) {
/* Wrap-around */
return 0;
}
return result;
}
