fork download
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <assert.h>
  4. #include <string.h>
  5.  
  6. //#include "mmat.h"
  7. #include <stdbool.h>
  8.  
  9. // Matrix.h
  10. typedef struct
  11. {
  12. size_t y_dim, x_dim;
  13. float **cells;
  14. } Matrix;
  15.  
  16. Matrix *matrix_construct(size_t y_dim, size_t x_dim); // constructs zeroed
  17. void matrix_set_values(Matrix *dst, float *row_major_floats);
  18. void matrix_free(Matrix *m); // frees m as well as cells
  19.  
  20. void matrix_assign(Matrix *dst, Matrix const *src); // may re-size dst
  21. bool matrix_is_equal(Matrix const *m1, Matrix const *m2);
  22.  
  23. typedef Matrix *MatrixBinaryOperator(Matrix const *m1, Matrix const *m2);
  24. MatrixBinaryOperator matrix_multiply;
  25. bool matrix_operate_self(MatrixBinaryOperator *op, Matrix *m1, Matrix const *m2);
  26.  
  27. //----- end of mmat.h
  28.  
  29.  
  30. Matrix *matrix_construct(size_t y_dim, size_t x_dim)
  31. {
  32. Matrix *m = malloc( sizeof *m );
  33.  
  34. m->x_dim = x_dim;
  35. m->y_dim = y_dim;
  36.  
  37. // assume IEEE754 floats (all bits zero = 0)
  38. m->cells = malloc( y_dim * sizeof *m->cells );
  39. for ( size_t ii = 0; ii < y_dim; ++ii )
  40. m->cells[ii] = calloc( x_dim, sizeof *m->cells[ii] );
  41.  
  42. return m;
  43. }
  44.  
  45. void matrix_set_values(Matrix *dst, float *row_major_floats)
  46. {
  47. for (size_t y = 0; y < dst->y_dim; ++y)
  48. for (size_t x = 0; x < dst->x_dim; ++x)
  49. dst->cells[y][x] = *row_major_floats++;
  50. }
  51.  
  52. bool matrix_is_equal(Matrix const *m1, Matrix const *m2)
  53. {
  54. if ( m1->y_dim != m2->y_dim ) return false;
  55. if ( m1->x_dim != m2->x_dim ) return false;
  56.  
  57. for (size_t y = 0; y < m1->y_dim; ++y)
  58. if ( memcmp(m1->cells[y], m2->cells[y], m1->x_dim * sizeof m1->cells[0][0]) )
  59. return false;
  60.  
  61. return true;
  62. }
  63.  
  64. bool matrix_operate_self(MatrixBinaryOperator *op, Matrix *m1, Matrix const *m2)
  65. {
  66. Matrix *result = op(m1, m2);
  67. if ( !result ) return true;
  68. matrix_assign(m1, result);
  69. matrix_free(result);
  70. return false;
  71. }
  72.  
  73. static void matrix_deallocate(Matrix *m)
  74. {
  75. for ( size_t y = 0; y < m->y_dim; ++y )
  76. free(m->cells[y]);
  77. free(m->cells);
  78.  
  79. m->x_dim = 0;
  80. m->y_dim = 0;
  81. m->cells = 0;
  82. }
  83.  
  84. void matrix_free(Matrix *m)
  85. {
  86. matrix_deallocate(m);
  87. free(m);
  88. }
  89.  
  90. void matrix_assign(Matrix *dst, Matrix const *src)
  91. {
  92. // note: could optimize this to not allocate if dims the same
  93. matrix_deallocate(dst);
  94. Matrix *new = matrix_construct(src->y_dim, src->x_dim);
  95. for (size_t y = 0; y < src->y_dim; ++y)
  96. memcpy(new->cells[y], src->cells[y], src->x_dim * sizeof new->cells[0][0]);
  97.  
  98. if ( !new ) exit(EXIT_FAILURE);
  99. *dst = *new;
  100. free(new);
  101. }
  102.  
  103. Matrix *matrix_multiply(Matrix const *m1, Matrix const *m2)
  104. {
  105. if ( m1->x_dim != m2->y_dim )
  106. return NULL;
  107.  
  108. Matrix *new = matrix_construct(m1->y_dim, m2->x_dim);
  109.  
  110. for (size_t col = 0; col < m2->x_dim; ++col) // Each column of m2
  111. for (size_t row = 0; row < m1->y_dim; ++row) // Each row of m1
  112. {
  113. // do dot-product of those two
  114. float sum = 0;
  115.  
  116. for (size_t ii = 0; ii < m2->y_dim; ++ii)
  117. sum += m2->cells[ii][col] * m1->cells[row][ii];
  118.  
  119. new->cells[row][col] = sum;
  120. }
  121.  
  122. return new;
  123. }
  124.  
  125. static void matrix_printf(char const *prompt, Matrix const *mat)
  126. {
  127. printf("%20.20s:", prompt);
  128. for (size_t y = 0; y < mat->y_dim; ++y)
  129. {
  130. if (y > 0 ) printf("%20.20s ", "");
  131. printf("( ");
  132. for (size_t x = 0; x < mat->x_dim; ++x)
  133. printf("%3.3f ", mat->cells[y][x]);
  134. printf(")\n");
  135. }
  136.  
  137. }
  138. int main()
  139. {
  140.  
  141. float mat1_array[3][2] = {{0, 1}, {3, 4}, {6, 7}};
  142. float mat2_array[2][3] = {{5, 1, 2}, {3, 4, 5}};
  143.  
  144. Matrix *mat1 = matrix_construct(3, 2);
  145. Matrix *mat2 = matrix_construct(2, 3);
  146. matrix_set_values(mat1, (float *)&mat1_array);
  147. matrix_set_values(mat2, (float *)&mat2_array);
  148.  
  149. Matrix *mat3 = matrix_multiply(mat1, mat2);
  150.  
  151. matrix_printf("mat1", mat1);
  152. matrix_printf("mat2", mat2);
  153. matrix_printf("mat3", mat3);
  154.  
  155. matrix_operate_self(matrix_multiply, mat1, mat2);
  156. assert( matrix_is_equal(mat1, mat3) );
  157.  
  158. matrix_free(mat1);
  159. matrix_free(mat2);
  160. matrix_free(mat3);
  161. }
  162.  
Success #stdin #stdout 0s 2380KB
stdin
Standard input is empty
stdout
                mat1:( 0.000 1.000 )
                     ( 3.000 4.000 )
                     ( 6.000 7.000 )
                mat2:( 5.000 1.000 2.000 )
                     ( 3.000 4.000 5.000 )
                mat3:( 3.000 4.000 5.000 )
                     ( 27.000 19.000 26.000 )
                     ( 51.000 34.000 47.000 )