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; }