123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- /*
- This file contains a template that can generate compile-time generic
- 2d matrix strucst and functions. To use it, do as follows:
- #define TEMPLATE_T int
- #define TEMPLATE_NAME MyMatrix
- #include tmatrix.h
- Then in some C file, write:
- #define TEMPLATE_T int
- #define TEMPLATE_NAME MyMatrix
- #define TEMPLATE_IMPLEMENT
- #include tmatrix.h
- Optionally the following template parameters may also be defined:
- TEMPLATE_ALLOC(SIZE) : custom malloc-compatible allocation function
- TEMPLATE_FREE(PTR) : custom free-compatible allocation function
- TEMPLATE_PREFIX : prefix for the functions gererated. Default: TEMPLATE_NAME.
- The technique used to implement this kind of ANSI C templates is also known as
- "X-Macro", since it relies on the availability certain macros that are yet
- undefined in this file and must be supplied by the programmer.
- */
- #include <stdlib.h>
- #include <tbegin.h>
- #ifdef TEMPLATE_OK
- #ifndef TEMPLATE_IMPLEMENT
- /** Interface of the TMATRIX. */
- struct TEMPLATE_STRUCT {
- TEMPLATE_T **data;
- int w;
- int h;
- };
- typedef struct TEMPLATE_STRUCT TEMPLATE_NAME;
- /** Allocates a new, uninitialized TMATRIX. */
- TEMPLATE_NAME * TEMPLATE_FUNC(alloc)(void);
- /** Cleans up and deinitializes the TMATRIX self */
- TEMPLATE_NAME * TEMPLATE_FUNC(done) (TEMPLATE_NAME * self);
- /** Calls TEMPLATE_NAME_done, and then frees the TMATRIX self */
- TEMPLATE_NAME * TEMPLATE_FUNC(free) (TEMPLATE_NAME * self);
- /** Returns the width of the TMATRIX. Returns -1 is self isn't propery
- * initialized.
- */
- int TEMPLATE_FUNC(w) (TEMPLATE_NAME * self);
- /** Returns the height of the TMATRIX.
- * Returns -1 if self isn't propery initialized. */
- int TEMPLATE_FUNC(h) (TEMPLATE_NAME * self);
- /** Initializes a TMATRIX to be of the given width and height.
- * Returns NULL on error, or if h or w are less than 1.
- * Returns self on sucess.
- */
- TEMPLATE_NAME * TEMPLATE_FUNC(init) (TEMPLATE_NAME * self, int w, int h);
- /** Allocates a new matrix and initializes it. */
- TEMPLATE_NAME * TEMPLATE_FUNC(new) (int w, int h);
- /**
- * Return true if the arguments x and or y are out of range, or
- * if self itself isn't properly initialized. Return false if OK.
- */
- int TEMPLATE_FUNC(outofrange) (TEMPLATE_NAME * self, int w, int h);
- /** Gets an element from the matrix. Does no checking whatsoever.
- * Use only where the inputs are guaranteed to be valid, where speed is
- * of the essence.
- */
- TEMPLATE_T TEMPLATE_FUNC(getraw) (TEMPLATE_NAME * self, int x, int y);
- /** Gets a row of elements from the matrix. Does no checking whatsoever.
- * Use only where the inputs are guaranteed to be valid, where speed is
- * of the essence.
- */
- TEMPLATE_T * TEMPLATE_FUNC(rowraw) (TEMPLATE_NAME * self, int y);
- /** Gets an element from the matrix self.
- * If all goes well, this function returns 0, and sets the value to
- * (*result).
- * If w and h are out of range, or the matrix isn't correctly initialized,
- * does nothing and returns -1 in stead.
- */
- int TEMPLATE_FUNC(get) (TEMPLATE_NAME * self, int w, int h, TEMPLATE_T * result);
- /** Puts an element in the matrix self. Does no checking whatsoever.
- * Use only where the inputs are guaranteed to be valid, where speed is
- * of the essence.
- */
- void TEMPLATE_FUNC(setraw) (TEMPLATE_NAME * self, int w, int h, TEMPLATE_T el);
- /** Puts and element info the matrix self.
- * If all goes well, this function returns 0.
- * If w and h are out of range, or the matrix isn't correctly initialized,
- * does nothing and returns -1 in stead.
- */
- int TEMPLATE_FUNC(put) (TEMPLATE_NAME * self, int w, int h, TEMPLATE_T el);
- /** Copies the data from one matrix to the other.
- * If the matrixes are of unequal size, copies the smallest of both
- * heights and widths.
- * Returns 0 on succes, -1 on error.
- */
- int TEMPLATE_FUNC(copy) (TEMPLATE_NAME * self, TEMPLATE_NAME * other);
- #else
- /* Implementation of the TMATRIX. */
- /** Allocates a new, uninitialized TMATRIX. */
- TEMPLATE_NAME * TEMPLATE_FUNC(alloc) (void) {
- return TEMPLATE_ALLOC(sizeof(TEMPLATE_NAME));
- }
- /** Cleans up and deinitializes the TMATRIX self */
- TEMPLATE_NAME * TEMPLATE_FUNC(done) (TEMPLATE_NAME * self) {
- int index;
- if(!self) return NULL;
- if(!self->data) return self;
- for (index = 0; index < self->h; index ++) {
- if(self->data[index]) { TEMPLATE_FREE(self->data[index]); }
- }
-
- self->w = -1;
- self->h = -1;
- TEMPLATE_FREE(self->data);
- return self;
- }
- /** Calls TEMPLATE_NAME_done, and then frees the TMATRIX self. Returns NULL. */
- TEMPLATE_NAME * TEMPLATE_FUNC(free) (TEMPLATE_NAME * self) {
- TEMPLATE_FUNC(done)(self);
- TEMPLATE_FREE(self);
- return NULL;
- }
- /** Returns the width of the TMATRIX. Returns -1 is self isn't propery
- * initialized.
- */
- int TEMPLATE_FUNC(w) (TEMPLATE_NAME * self) {
- if(!self) return -1;
- return self->w;
- }
- /** Returns the height of the TMATRIX.
- * Returns -1 is self isn't propery initialized. */
- int TEMPLATE_FUNC(h) (TEMPLATE_NAME * self) {
- if(!self) return -1;
- return self->h;
- }
- /** Initializes a TMATRIX to be of the given width and height.
- * Returns NULL on error, or if h or w are less than 1.
- * Returns self on sucess.
- */
- TEMPLATE_NAME * TEMPLATE_FUNC(init) (TEMPLATE_NAME * self, int w, int h) {
- int index;
- if(!self) return NULL;
- self->w = w;
- self->h = h;
- self->data = NULL;
- if ((self->h <= 0) || (self->w <= 0)) { return NULL; }
- // Allocate y dimension
- self->data = (TEMPLATE_T **) TEMPLATE_ALLOC(sizeof(TEMPLATE_T *) * self->h);
- if(!self->data) return NULL;
- // Now allocate the x dimensions.
- for (index = 0; index < self->h; index ++) {
- self->data[index] = (TEMPLATE_T *) TEMPLATE_ALLOC(sizeof(TEMPLATE_T) * self->w);
- if(!self->data[index]) return TEMPLATE_FUNC(free)(self);
- }
- return self;
- }
- /** Allocates a new matrix and initializes it. */
- TEMPLATE_NAME * TEMPLATE_FUNC(new) (int w, int h) {
- TEMPLATE_NAME * self = TEMPLATE_FUNC(alloc)();
- return TEMPLATE_FUNC(init)(self, w, h);
- }
-
- /**
- * Return true if the arguments x and or y are out of range, or
- * if self itself isn't properly initialized. Return false if OK.
- */
- int TEMPLATE_FUNC(outofrange) (TEMPLATE_NAME * self, int x, int y) {
- if(!self) return TRUE;
- if(!self->data) return TRUE;
- if ((x < 0) || (y < 0)) { return TRUE; }
- if ((y >= self->h) || (x >= self->w)) { return TRUE; }
- return FALSE;
- }
- /** Gets an element from the matrix. Does no checking whatsoever.
- * Use only where the inputs are guaranteed to be valid, where speed is
- * of the essence.
- */
- TEMPLATE_T TEMPLATE_FUNC(getraw) (TEMPLATE_NAME * self, int x, int y) {
- return self->data[y][x];
- }
- /** Gets a row of elements from the matrix. Does no checking whatsoever.
- * Use only where the inputs are guaranteed to be valid, where speed is
- * of the essence.
- */
- TEMPLATE_T * TEMPLATE_FUNC(rowraw) (TEMPLATE_NAME * self, int y) {
- return self->data[y];
- }
- /** Gets an element from the matrix self.
- * If all goes well, this function returns 0, and sets the value to
- * (*result).
- * If w and h are out of range, or the matrix isn't correctly initialized,
- * does nothing and returns -1 in stead.
- */
- int TEMPLATE_FUNC(get) (TEMPLATE_NAME * self, int x, int y, TEMPLATE_T * result) {
- TEMPLATE_T * aid;
- if(TEMPLATE_FUNC(outofrange)(self,x,y)) { return -1; }
- (*result) = TEMPLATE_FUNC(getraw)(self,x,y);
- return 0;
- }
- /** Puts an element in the matrix self. Does no checking whatsoever.
- * Use only where the inputs are guaranteed to be valid, where speed is
- * of the essence.
- */
- void TEMPLATE_FUNC(putraw) (TEMPLATE_NAME * self, int x, int y, TEMPLATE_T el) {
- self->data[y][x] = el;
- }
- /** Puts and element info the matrix self.
- * If all goes well, this function returns 0.
- * If w and h are out of range, or the matrix isn't correctly initialized,
- * does nothing and returns -1 in stead.
- */
- int TEMPLATE_FUNC(put) (TEMPLATE_NAME * self, int x, int y, TEMPLATE_T el) {
- if(TEMPLATE_FUNC(outofrange)(self,x,y)) { return -1; }
- TEMPLATE_FUNC(putraw)(self,x,y,el);
- return 0;
- }
- /** Copies the data from one matrix to the other.
- * If the matrixes are of unequal size, copies the smallest of both
- * heights and widths.
- * Returns 0 on succes, -1 on error.
- */
- int TEMPLATE_FUNC(copy) (TEMPLATE_NAME * self, TEMPLATE_NAME * other) {
- int ws, hs, wo, ho, w, h, x, y;
- if ((!self) || (!other)) return -1;
- if ((!self->data) || (!other->data)) return -1;
- ws = TEMPLATE_FUNC(w)(self);
- hs = TEMPLATE_FUNC(h)(self);
-
- wo = TEMPLATE_FUNC(w)(other);
- ho = TEMPLATE_FUNC(h)(other);
- // Copy only smallest of width and height.
- w = (ws < wo ? ws : wo);
- h = (hs < ho ? hs : ho);
- for(y = 0; y < h ; y++) {
- for(x = 0; x < w ; x++) {
- self->data[y][x] = other->data[y][x];
- }
- }
- return 0;
- }
- #endif
- #endif
- /** Finally clean up by undefining all defined macros. **/
- #include <tend.h>
|