tmatrix.h 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /*
  2. This file contains a template that can generate compile-time generic
  3. 2d matrix strucst and functions. To use it, do as follows:
  4. #define TEMPLATE_T int
  5. #define TEMPLATE_NAME MyMatrix
  6. #include tmatrix.h
  7. Then in some C file, write:
  8. #define TEMPLATE_T int
  9. #define TEMPLATE_NAME MyMatrix
  10. #define TEMPLATE_IMPLEMENT
  11. #include tmatrix.h
  12. Optionally the following template parameters may also be defined:
  13. TEMPLATE_ALLOC(SIZE) : custom malloc-compatible allocation function
  14. TEMPLATE_FREE(PTR) : custom free-compatible allocation function
  15. TEMPLATE_PREFIX : prefix for the functions gererated. Default: TEMPLATE_NAME.
  16. The technique used to implement this kind of ANSI C templates is also known as
  17. "X-Macro", since it relies on the availability certain macros that are yet
  18. undefined in this file and must be supplied by the programmer.
  19. */
  20. #include <stdlib.h>
  21. #include <tbegin.h>
  22. #ifdef TEMPLATE_OK
  23. #ifndef TEMPLATE_IMPLEMENT
  24. /** Interface of the TMATRIX. */
  25. struct TEMPLATE_STRUCT {
  26. TEMPLATE_T **data;
  27. int w;
  28. int h;
  29. };
  30. typedef struct TEMPLATE_STRUCT TEMPLATE_NAME;
  31. /** Allocates a new, uninitialized TMATRIX. */
  32. TEMPLATE_NAME * TEMPLATE_FUNC(alloc)(void);
  33. /** Cleans up and deinitializes the TMATRIX self */
  34. TEMPLATE_NAME * TEMPLATE_FUNC(done) (TEMPLATE_NAME * self);
  35. /** Calls TEMPLATE_NAME_done, and then frees the TMATRIX self */
  36. TEMPLATE_NAME * TEMPLATE_FUNC(free) (TEMPLATE_NAME * self);
  37. /** Returns the width of the TMATRIX. Returns -1 is self isn't propery
  38. * initialized.
  39. */
  40. int TEMPLATE_FUNC(w) (TEMPLATE_NAME * self);
  41. /** Returns the height of the TMATRIX.
  42. * Returns -1 if self isn't propery initialized. */
  43. int TEMPLATE_FUNC(h) (TEMPLATE_NAME * self);
  44. /** Initializes a TMATRIX to be of the given width and height.
  45. * Returns NULL on error, or if h or w are less than 1.
  46. * Returns self on sucess.
  47. */
  48. TEMPLATE_NAME * TEMPLATE_FUNC(init) (TEMPLATE_NAME * self, int w, int h);
  49. /** Allocates a new matrix and initializes it. */
  50. TEMPLATE_NAME * TEMPLATE_FUNC(new) (int w, int h);
  51. /**
  52. * Return true if the arguments x and or y are out of range, or
  53. * if self itself isn't properly initialized. Return false if OK.
  54. */
  55. int TEMPLATE_FUNC(outofrange) (TEMPLATE_NAME * self, int w, int h);
  56. /** Gets an element from the matrix. Does no checking whatsoever.
  57. * Use only where the inputs are guaranteed to be valid, where speed is
  58. * of the essence.
  59. */
  60. TEMPLATE_T TEMPLATE_FUNC(getraw) (TEMPLATE_NAME * self, int x, int y);
  61. /** Gets a row of elements from the matrix. Does no checking whatsoever.
  62. * Use only where the inputs are guaranteed to be valid, where speed is
  63. * of the essence.
  64. */
  65. TEMPLATE_T * TEMPLATE_FUNC(rowraw) (TEMPLATE_NAME * self, int y);
  66. /** Gets an element from the matrix self.
  67. * If all goes well, this function returns 0, and sets the value to
  68. * (*result).
  69. * If w and h are out of range, or the matrix isn't correctly initialized,
  70. * does nothing and returns -1 in stead.
  71. */
  72. int TEMPLATE_FUNC(get) (TEMPLATE_NAME * self, int w, int h, TEMPLATE_T * result);
  73. /** Puts an element in the matrix self. Does no checking whatsoever.
  74. * Use only where the inputs are guaranteed to be valid, where speed is
  75. * of the essence.
  76. */
  77. void TEMPLATE_FUNC(setraw) (TEMPLATE_NAME * self, int w, int h, TEMPLATE_T el);
  78. /** Puts and element info the matrix self.
  79. * If all goes well, this function returns 0.
  80. * If w and h are out of range, or the matrix isn't correctly initialized,
  81. * does nothing and returns -1 in stead.
  82. */
  83. int TEMPLATE_FUNC(put) (TEMPLATE_NAME * self, int w, int h, TEMPLATE_T el);
  84. /** Copies the data from one matrix to the other.
  85. * If the matrixes are of unequal size, copies the smallest of both
  86. * heights and widths.
  87. * Returns 0 on succes, -1 on error.
  88. */
  89. int TEMPLATE_FUNC(copy) (TEMPLATE_NAME * self, TEMPLATE_NAME * other);
  90. #else
  91. /* Implementation of the TMATRIX. */
  92. /** Allocates a new, uninitialized TMATRIX. */
  93. TEMPLATE_NAME * TEMPLATE_FUNC(alloc) (void) {
  94. return TEMPLATE_ALLOC(sizeof(TEMPLATE_NAME));
  95. }
  96. /** Cleans up and deinitializes the TMATRIX self */
  97. TEMPLATE_NAME * TEMPLATE_FUNC(done) (TEMPLATE_NAME * self) {
  98. int index;
  99. if(!self) return NULL;
  100. if(!self->data) return self;
  101. for (index = 0; index < self->h; index ++) {
  102. if(self->data[index]) { TEMPLATE_FREE(self->data[index]); }
  103. }
  104. self->w = -1;
  105. self->h = -1;
  106. TEMPLATE_FREE(self->data);
  107. return self;
  108. }
  109. /** Calls TEMPLATE_NAME_done, and then frees the TMATRIX self. Returns NULL. */
  110. TEMPLATE_NAME * TEMPLATE_FUNC(free) (TEMPLATE_NAME * self) {
  111. TEMPLATE_FUNC(done)(self);
  112. TEMPLATE_FREE(self);
  113. return NULL;
  114. }
  115. /** Returns the width of the TMATRIX. Returns -1 is self isn't propery
  116. * initialized.
  117. */
  118. int TEMPLATE_FUNC(w) (TEMPLATE_NAME * self) {
  119. if(!self) return -1;
  120. return self->w;
  121. }
  122. /** Returns the height of the TMATRIX.
  123. * Returns -1 is self isn't propery initialized. */
  124. int TEMPLATE_FUNC(h) (TEMPLATE_NAME * self) {
  125. if(!self) return -1;
  126. return self->h;
  127. }
  128. /** Initializes a TMATRIX to be of the given width and height.
  129. * Returns NULL on error, or if h or w are less than 1.
  130. * Returns self on sucess.
  131. */
  132. TEMPLATE_NAME * TEMPLATE_FUNC(init) (TEMPLATE_NAME * self, int w, int h) {
  133. int index;
  134. if(!self) return NULL;
  135. self->w = w;
  136. self->h = h;
  137. self->data = NULL;
  138. if ((self->h <= 0) || (self->w <= 0)) { return NULL; }
  139. // Allocate y dimension
  140. self->data = (TEMPLATE_T **) TEMPLATE_ALLOC(sizeof(TEMPLATE_T *) * self->h);
  141. if(!self->data) return NULL;
  142. // Now allocate the x dimensions.
  143. for (index = 0; index < self->h; index ++) {
  144. self->data[index] = (TEMPLATE_T *) TEMPLATE_ALLOC(sizeof(TEMPLATE_T) * self->w);
  145. if(!self->data[index]) return TEMPLATE_FUNC(free)(self);
  146. }
  147. return self;
  148. }
  149. /** Allocates a new matrix and initializes it. */
  150. TEMPLATE_NAME * TEMPLATE_FUNC(new) (int w, int h) {
  151. TEMPLATE_NAME * self = TEMPLATE_FUNC(alloc)();
  152. return TEMPLATE_FUNC(init)(self, w, h);
  153. }
  154. /**
  155. * Return true if the arguments x and or y are out of range, or
  156. * if self itself isn't properly initialized. Return false if OK.
  157. */
  158. int TEMPLATE_FUNC(outofrange) (TEMPLATE_NAME * self, int x, int y) {
  159. if(!self) return TRUE;
  160. if(!self->data) return TRUE;
  161. if ((x < 0) || (y < 0)) { return TRUE; }
  162. if ((y >= self->h) || (x >= self->w)) { return TRUE; }
  163. return FALSE;
  164. }
  165. /** Gets an element from the matrix. Does no checking whatsoever.
  166. * Use only where the inputs are guaranteed to be valid, where speed is
  167. * of the essence.
  168. */
  169. TEMPLATE_T TEMPLATE_FUNC(getraw) (TEMPLATE_NAME * self, int x, int y) {
  170. return self->data[y][x];
  171. }
  172. /** Gets a row of elements from the matrix. Does no checking whatsoever.
  173. * Use only where the inputs are guaranteed to be valid, where speed is
  174. * of the essence.
  175. */
  176. TEMPLATE_T * TEMPLATE_FUNC(rowraw) (TEMPLATE_NAME * self, int y) {
  177. return self->data[y];
  178. }
  179. /** Gets an element from the matrix self.
  180. * If all goes well, this function returns 0, and sets the value to
  181. * (*result).
  182. * If w and h are out of range, or the matrix isn't correctly initialized,
  183. * does nothing and returns -1 in stead.
  184. */
  185. int TEMPLATE_FUNC(get) (TEMPLATE_NAME * self, int x, int y, TEMPLATE_T * result) {
  186. TEMPLATE_T * aid;
  187. if(TEMPLATE_FUNC(outofrange)(self,x,y)) { return -1; }
  188. (*result) = TEMPLATE_FUNC(getraw)(self,x,y);
  189. return 0;
  190. }
  191. /** Puts an element in the matrix self. Does no checking whatsoever.
  192. * Use only where the inputs are guaranteed to be valid, where speed is
  193. * of the essence.
  194. */
  195. void TEMPLATE_FUNC(putraw) (TEMPLATE_NAME * self, int x, int y, TEMPLATE_T el) {
  196. self->data[y][x] = el;
  197. }
  198. /** Puts and element info the matrix self.
  199. * If all goes well, this function returns 0.
  200. * If w and h are out of range, or the matrix isn't correctly initialized,
  201. * does nothing and returns -1 in stead.
  202. */
  203. int TEMPLATE_FUNC(put) (TEMPLATE_NAME * self, int x, int y, TEMPLATE_T el) {
  204. if(TEMPLATE_FUNC(outofrange)(self,x,y)) { return -1; }
  205. TEMPLATE_FUNC(putraw)(self,x,y,el);
  206. return 0;
  207. }
  208. /** Copies the data from one matrix to the other.
  209. * If the matrixes are of unequal size, copies the smallest of both
  210. * heights and widths.
  211. * Returns 0 on succes, -1 on error.
  212. */
  213. int TEMPLATE_FUNC(copy) (TEMPLATE_NAME * self, TEMPLATE_NAME * other) {
  214. int ws, hs, wo, ho, w, h, x, y;
  215. if ((!self) || (!other)) return -1;
  216. if ((!self->data) || (!other->data)) return -1;
  217. ws = TEMPLATE_FUNC(w)(self);
  218. hs = TEMPLATE_FUNC(h)(self);
  219. wo = TEMPLATE_FUNC(w)(other);
  220. ho = TEMPLATE_FUNC(h)(other);
  221. // Copy only smallest of width and height.
  222. w = (ws < wo ? ws : wo);
  223. h = (hs < ho ? hs : ho);
  224. for(y = 0; y < h ; y++) {
  225. for(x = 0; x < w ; x++) {
  226. self->data[y][x] = other->data[y][x];
  227. }
  228. }
  229. return 0;
  230. }
  231. #endif
  232. #endif
  233. /** Finally clean up by undefining all defined macros. **/
  234. #include <tend.h>