├── README.md ├── easyMatrix ├── include │ └── easyMatrix.h ├── src │ └── easyMatrix.c └── test │ ├── easyMatrixTest.cpp │ └── matrix.py └── utest ├── CMakeLists.txt └── main.cpp /README.md: -------------------------------------------------------------------------------- 1 | # easyMatrix 2 | A pure C language nano Matrix library with best user experience ever! 3 | 4 | easyMatrix is a lite open source Matrix operating library in C language which will help those who develop on embedded systems even without operating systems. 5 | If you can not use other libraries in C++ such as Eigen, easyMatrix is your best choice. 6 | 7 | easyMatrix is really easy and small . You can configure the data type for the matrix. 8 | 8-bit data such as cols and rows number is used instead of 32-bit integer. 9 | 10 | # How to use 11 | 12 | 13 | float val1[] = {1,2,3,4,5,6,7,8,9}; 14 | float val2[] = {1,1,1,1,1,1,1,1,1}; 15 | CREATE_MATRIX_ONSTACK(3,3,A,val1); 16 | CREATE_MATRIX_ONSTACK(3,3,B,val2); 17 | CREATE_MATRIX_ONSTACK(3,3,C,NULL); 18 | addMatrix(&A,&B,&C); 19 | dumpMatrix(&C); 20 | printf("det is:%f\n",detMatrix(&A)); 21 | int x = A.rows; 22 | int y = A.cols; 23 | printf("element[1,1] is:%f\n",A.element[1*x+1]); 24 | //create matrix on heap and you need to delete the pointer 25 | CREATE_DYNAMIC_MATRIX_ONHEAP(x,y,D,val1); 26 | CREATE_DYNAMIC_MATRIX_ONHEAP(x,y,E,val2); 27 | CREATE_DYNAMIC_MATRIX_ONHEAP(x,y,F,NULL); 28 | multiMatrix(D,E,&C); 29 | multiMatrix(D,E,F); 30 | 31 | DELETE_DYNAMIC_MATRIX(D); 32 | DELETE_DYNAMIC_MATRIX(E); 33 | DELETE_DYNAMIC_MATRIX(F); 34 | 35 | -------------------------------------------------------------------------------- /easyMatrix/include/easyMatrix.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: easyMatrix.h 3 | > Author: Zhang Yuteng 4 | > Mail:fellylanma@aliyun.com 5 | > Created Time: 2019年05月13日 星期一 22时06分13秒 6 | ************************************************************************/ 7 | 8 | #ifndef _MAGRIDE_PLANNING_EASYMATRIX_H_ 9 | #define _MAGRIDE_PLANNING_EASYMATRIX_H_ 10 | 11 | #include 12 | typedef unsigned char uint8; 13 | typedef float DATA_TYPE; 14 | 15 | 16 | #define CREATE_MATRIX_ONSTACK(x,y,matrix,initval) \ 17 | struct easyMatrix matrix;\ 18 | DATA_TYPE val##x##N##y##N##matrix[x*y];\ 19 | matrix.rows = x;\ 20 | matrix.cols = y;\ 21 | matrix.element = val##x##N##y##N##matrix;\ 22 | if(initval!=NULL) setMatrix(initval, &(matrix)) 23 | 24 | #define CREATE_DYNAMIC_MATRIX_ONHEAP(x,y,matrix,initval) \ 25 | struct easyMatrix *matrix = (struct easyMatrix*)malloc(sizeof(struct easyMatrix));\ 26 | matrix->rows = x;\ 27 | matrix->cols = y;\ 28 | matrix->element = (DATA_TYPE*) malloc(sizeof(DATA_TYPE)*(x)*(y));\ 29 | if(initval!=NULL) setMatrix(initval, (matrix)) 30 | 31 | #define DELETE_DYNAMIC_MATRIX(matrix) \ 32 | free((matrix)->element);\ 33 | free(matrix) 34 | 35 | struct easyMatrix {\ 36 | uint8 rows,cols;\ 37 | DATA_TYPE* element; 38 | };\ 39 | 40 | struct easyMatrix* setMatrix(DATA_TYPE* const a,struct easyMatrix* c); 41 | 42 | struct easyMatrix* copyMatrix(struct easyMatrix* const a,struct easyMatrix* c); 43 | 44 | struct easyMatrix* transMatrix(struct easyMatrix* const a,struct easyMatrix* c); 45 | 46 | DATA_TYPE detMatrix(struct easyMatrix* const a); 47 | 48 | DATA_TYPE invMatrix(struct easyMatrix* const a, struct easyMatrix*b); 49 | 50 | struct easyMatrix* scaleMatrix(DATA_TYPE, struct easyMatrix* const a, struct easyMatrix*); 51 | 52 | struct easyMatrix* addMatrix(const struct easyMatrix* const a, const struct easyMatrix *const b, struct easyMatrix * c); 53 | 54 | struct easyMatrix* leftMatrix(uint8, uint8, struct easyMatrix* const a, struct easyMatrix* b); 55 | 56 | struct easyMatrix* subMatrix(struct easyMatrix* const a, struct easyMatrix* const b, struct easyMatrix* c); 57 | 58 | struct easyMatrix* multiMatrix(struct easyMatrix* const a, struct easyMatrix* const b, struct easyMatrix* c); 59 | 60 | struct easyMatrix* zerosMatrix(struct easyMatrix* e); 61 | 62 | struct easyMatrix* eyesMatrix(struct easyMatrix* e); 63 | 64 | void dumpMatrix(struct easyMatrix* const e); 65 | 66 | struct easyMatrix* adjMatrix(struct easyMatrix* const a,struct easyMatrix* c); 67 | 68 | struct easyMatrix* getLUMatrix(struct easyMatrix* const A, struct easyMatrix* L,struct easyMatrix* U) ; 69 | 70 | struct easyMatrix* invLMatrix(struct easyMatrix* const L, struct easyMatrix* L_inv) ; 71 | struct easyMatrix* invUMatrix(struct easyMatrix* const U, struct easyMatrix* U_inv) ; 72 | 73 | struct easyMatrix* solveEquationMatrix(const struct easyMatrix* const A,const struct easyMatrix* const Y, struct easyMatrix* X) ; 74 | 75 | 76 | DATA_TYPE fastDetMatrix(struct easyMatrix* const in) ; 77 | #endif//_MAGRIDE_PLANNING_EASYMATRIX_H_ 78 | -------------------------------------------------------------------------------- /easyMatrix/src/easyMatrix.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: easyMatrix.c 3 | > Author: Zhang Yuteng 4 | > Mail: 5 | > Created Time: 2019年05月23日 星期四 21时57分31秒 6 | ************************************************************************/ 7 | 8 | #include 9 | #include 10 | #include "easyMatrix.h" 11 | 12 | int isFiniteNumber(double d) { 13 | return (d<=DBL_MAX&&d>=-DBL_MAX); 14 | } 15 | struct easyMatrix* setMatrix(DATA_TYPE * const a,struct easyMatrix* c) { 16 | uint8 x = c->rows; 17 | uint8 y = c->cols; 18 | int t = x*y; 19 | for(int i=0;ielement[i] = a[i]; 21 | } 22 | return c; 23 | } 24 | 25 | struct easyMatrix* copyMatrix(struct easyMatrix* const a, 26 | struct easyMatrix* c) { 27 | if(a->rows != c->rows) return NULL; 28 | if(a->cols != c->cols) return NULL; 29 | int t = a->rows*a->cols; 30 | for(int i=0;ielement[i] = a->element[i]; 32 | } 33 | return c; 34 | } 35 | 36 | struct easyMatrix* transMatrix(struct easyMatrix* const a, 37 | struct easyMatrix* c) { 38 | if(a->rows != c->cols) return NULL; 39 | if(a->cols != c->rows) return NULL; 40 | int index = 0; 41 | int index_src = 0; 42 | for(uint8 ii=0;iicols;++ii) { 43 | index_src=ii; 44 | for(uint8 jj=0;jjrows;++jj) { 45 | //c->element[index] = a->element[jj*a->cols+ii]; 46 | c->element[index] = a->element[index_src]; 47 | index++; 48 | index_src+=a->cols; 49 | } 50 | } 51 | return c; 52 | } 53 | 54 | struct easyMatrix* leftMatrix(uint8 x_i,uint8 y_i, struct easyMatrix* const in, 55 | struct easyMatrix* out) { 56 | if(in->rows != in->cols) return NULL; 57 | if(out->rows != out->cols) return NULL; 58 | if(in->rows != (out->rows+1)) return NULL; 59 | int index = 0; 60 | int index_src = 0; 61 | uint8 x =in->rows; 62 | uint8 y =in->cols; 63 | for(uint8 kk=0;kkelement[index] = in->element[kk*y+ww]; 67 | out->element[index] = in->element[index_src]; 68 | index++; 69 | } 70 | index_src++; 71 | } 72 | } 73 | return out; 74 | } 75 | struct easyMatrix* adjMatrix(struct easyMatrix* const in, 76 | struct easyMatrix* out) { 77 | if(in->rows != out->cols) return NULL; 78 | if(in->cols != out->rows) return NULL; 79 | int index = 0; 80 | uint8 x = in->rows; 81 | uint8 y = in->cols; 82 | CREATE_DYNAMIC_MATRIX_ONHEAP(x-1,y-1,ret,NULL); 83 | signed char sign1 = 1; 84 | signed char sign2 = 1; 85 | for(uint8 ii=0;iielement[jj*y+ii] = sign2*detMatrix(ret); 91 | out->element[index] = sign2*detMatrix(ret); 92 | sign2 = - sign2; 93 | index+=y; 94 | } 95 | 96 | sign1 = - sign1; 97 | } 98 | DELETE_DYNAMIC_MATRIX(ret); 99 | return out; 100 | } 101 | 102 | DATA_TYPE invMatrix(struct easyMatrix *const in , 103 | struct easyMatrix * out) { 104 | if(in->cols!=in->rows) { 105 | printf("ERROR:invMatrix cols and rows not equal!\n"); 106 | return 0; 107 | }; 108 | if(in->rows != out->cols||in->cols != out->rows) { 109 | printf("ERROR:input matrix and output matrix does not match!\n"); 110 | return 0; 111 | }; 112 | uint8 N = in->cols; 113 | CREATE_DYNAMIC_MATRIX_ONHEAP(N,N,L,NULL); 114 | CREATE_DYNAMIC_MATRIX_ONHEAP(N,N,LINV,NULL); 115 | CREATE_DYNAMIC_MATRIX_ONHEAP(N,N,U,NULL); 116 | CREATE_DYNAMIC_MATRIX_ONHEAP(N,N,UINV,NULL); 117 | getLUMatrix(in,L,U); 118 | invLMatrix(L,LINV); 119 | invUMatrix(U,UINV); 120 | multiMatrix(UINV,LINV,out); 121 | double s = 1; 122 | for(int i = 0;ielement[i*N+i]; 124 | /* 125 | adjMatrix(in,out); 126 | DATA_TYPE scale = detMatrix(in); 127 | if(scale<1e-5&&scale>-1e-5) return 0.0; 128 | scale = 1/scale; 129 | scaleMatrix(scale,out,out); 130 | */ 131 | DELETE_DYNAMIC_MATRIX(L); 132 | DELETE_DYNAMIC_MATRIX(U); 133 | DELETE_DYNAMIC_MATRIX(LINV); 134 | DELETE_DYNAMIC_MATRIX(UINV); 135 | return isFiniteNumber(s); 136 | } 137 | 138 | struct easyMatrix* getLUMatrix(struct easyMatrix* const A, 139 | struct easyMatrix* L, 140 | struct easyMatrix* U) { 141 | int row=0; 142 | DATA_TYPE s = 0; 143 | uint8 N = A->cols; 144 | int t = N*N; 145 | for(int i =0;ielement[i] = 1e-20; 147 | U->element[i] = 1e-20; 148 | } 149 | for(int i=0;ielement[i*N+i] = 1.0; 151 | } 152 | for(int i=0;ielement[i*N+k]*U->element[k*N+j]; 157 | } 158 | U->element[i*N+j]= A->element[i*N+j] - s; 159 | } 160 | for (int j = i + 1;j < N;j++) { 161 | s = 0.0; 162 | for (int k = 0; k < i; k++) 163 | { 164 | s += L->element[j*N+k] * U->element[k*N+i]; 165 | } 166 | L->element[j*N+i] = (A->element[j*N+i] - s) / U->element[i*N+i]; //按列计算l值 167 | } 168 | } 169 | return L; 170 | } 171 | 172 | struct easyMatrix* invLMatrix(struct easyMatrix* const L, 173 | struct easyMatrix* L_inv) { 174 | uint8 N = L->cols; 175 | if(N!=L->rows) { 176 | printf("L matrix is not a sqare matrix!\n"); 177 | return NULL; 178 | } 179 | DATA_TYPE s; 180 | int t = N*N; 181 | for(int i =0;ielement[i] = 1e-13; 183 | } 184 | for (uint8 i = 0;i < N;i++) { 185 | L_inv->element[i*N+i] = 1; 186 | } 187 | for (uint8 i= 1;i < N;i++) { 188 | for (uint8 j = 0;j < i;j++) { 189 | s = 0; 190 | for (uint8 k = 0;k < i;k++) { 191 | s += L->element[i*N+k] * L_inv->element[k*N+j]; 192 | } 193 | L_inv->element[i*N+j] = -s; 194 | } 195 | } 196 | return L_inv; 197 | } 198 | struct easyMatrix* invUMatrix(struct easyMatrix* const U, 199 | struct easyMatrix* U_inv) { 200 | uint8 N = U->cols; 201 | DATA_TYPE s; 202 | int t = N*N; 203 | for(int i =0;ielement[i] = 1e-13; 205 | } 206 | for (uint8 i = 0;i < N;i++) //按列序,列内按照从下到上,计算u的逆矩阵 207 | { 208 | U_inv->element[i*N+i] = 1 / U->element[i*N+i]; 209 | } 210 | for (uint8 i = 1;i < N;i++) { 211 | for (int j = i - 1;j >=0;j--) { 212 | s = 0; 213 | for (uint8 k = j + 1;k <= i;k++) { 214 | s += U->element[j*N+k] * U_inv->element[k*N+i]; 215 | } 216 | U_inv->element[j*N+i] = -s / U->element[j*N+j]; 217 | } 218 | } 219 | return U_inv; 220 | } 221 | DATA_TYPE fastDetMatrix(struct easyMatrix* const in) { 222 | uint8 x = in->rows; 223 | uint8 y = in->cols; 224 | if(x!=y) return 0; 225 | if(x==0 ) return 0; 226 | if(x==1 ) return in->element[0]; 227 | DATA_TYPE *a =in->element; 228 | if(x==2) return(a[0]*a[3]-a[1]*a[2]); 229 | int N = x; 230 | CREATE_DYNAMIC_MATRIX_ONHEAP(N,N,L,NULL); 231 | CREATE_DYNAMIC_MATRIX_ONHEAP(N,N,U,NULL); 232 | getLUMatrix(in,L,U); 233 | double s = 1; 234 | for(int i = 0;ielement[i*N+i]; 236 | DELETE_DYNAMIC_MATRIX(L); 237 | DELETE_DYNAMIC_MATRIX(U); 238 | return s; 239 | } 240 | 241 | DATA_TYPE detMatrix(struct easyMatrix* const in) { 242 | uint8 x = in->rows; 243 | uint8 y = in->cols; 244 | if(x!=y) { 245 | printf("ERROR:Det Matrix input is not sqare matrix!"); 246 | return 0; 247 | } 248 | if(x==0 ) { 249 | printf("ERROR:Det Matrix input is zero!"); 250 | return 0; 251 | } 252 | if(x==1 ) return in->element[0]; 253 | DATA_TYPE *a =in->element; 254 | if(x==2) return(a[0]*a[3]-a[1]*a[2]); 255 | 256 | DATA_TYPE result = 0; 257 | signed char sign = 1; 258 | CREATE_DYNAMIC_MATRIX_ONHEAP(x-1,y-1,ret,NULL); 259 | for(uint8 i=0;icols != b->cols) return NULL; 270 | if(a->rows != b->rows) return NULL; 271 | struct easyMatrix* obj = (struct easyMatrix*)a; 272 | int t = obj->rows*obj->cols; 273 | for(int i=0;ielement[i] = obj->element[i]+b->element[i]; 275 | } 276 | return c; 277 | } 278 | 279 | struct easyMatrix* subMatrix(struct easyMatrix* const a, 280 | struct easyMatrix* const b, 281 | struct easyMatrix* c) { 282 | if(a->cols != b->cols) return NULL; 283 | if(a->rows != b->rows) return NULL; 284 | struct easyMatrix* obj = (struct easyMatrix*)a; 285 | int t = obj->rows*obj->cols; 286 | for(int i=0;ielement[i] = obj->element[i]-b->element[i]; 288 | } 289 | return c; 290 | } 291 | 292 | struct easyMatrix* scaleMatrix(DATA_TYPE scale, struct easyMatrix* const a, struct easyMatrix* b) { 293 | int t = a->cols*a->rows; 294 | for (int i = 0;ielement[i] = a->element[i]*scale; 296 | } 297 | return b; 298 | } 299 | 300 | struct easyMatrix* multiMatrix(struct easyMatrix* const a, 301 | struct easyMatrix* const b, 302 | struct easyMatrix* c) { 303 | if(NULL==c) return NULL; 304 | if(c == a || c == b) return NULL; 305 | if(a->cols != b->rows) return NULL; 306 | int count = 0; 307 | int t_cnt = 0; 308 | int z_cnt = 0; 309 | uint8 x = a->rows; 310 | uint8 y = a->cols; 311 | uint8 z = b->cols; 312 | for(uint8 i = 0;ielement[count] = 0; 315 | z_cnt = 0; 316 | for(uint8 j = 0;jelement[count] += a->element[t_cnt+j]*b->element[z_cnt+k]; 318 | z_cnt += z; 319 | } 320 | count++; 321 | } 322 | t_cnt+=y; 323 | } 324 | return c; 325 | } 326 | 327 | struct easyMatrix* zerosMatrix(struct easyMatrix* e) { 328 | int t = e->cols*e->rows; 329 | for(int i=0;ielement[i] = 0; 331 | } 332 | return e; 333 | } 334 | 335 | struct easyMatrix* eyesMatrix(struct easyMatrix* e) { 336 | if(e->rows != e->cols) return NULL; 337 | zerosMatrix(e); 338 | int index = 0; 339 | for(uint8 i=0;irows;++i) { 340 | e->element[index] = 1.0; 341 | index+=(e->cols); 342 | ++index; 343 | } 344 | return e; 345 | } 346 | 347 | struct easyMatrix* solveEquationMatrix(const struct easyMatrix* const A, 348 | const struct easyMatrix* const Y, 349 | struct easyMatrix* X) { 350 | CREATE_DYNAMIC_MATRIX_ONHEAP(A->rows,A->cols,AINV,NULL); 351 | invMatrix(A,AINV); 352 | multiMatrix(AINV,Y,X); 353 | DELETE_DYNAMIC_MATRIX(AINV); 354 | return X; 355 | } 356 | void dumpMatrix(struct easyMatrix* const e) { 357 | int count = 0; 358 | int x = e->rows; 359 | int y = e->cols; 360 | printf("cols is:%d, rows is:%d\n",x,y); 361 | for(uint8 i = 0;ielement[count]); 364 | ++count; 365 | } 366 | printf("\n"); 367 | } 368 | return; 369 | } 370 | 371 | -------------------------------------------------------------------------------- /easyMatrix/test/easyMatrixTest.cpp: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | > File Name: easyMatrix.c 3 | > Author: Zhang Yuteng 4 | > Mail: 5 | > Created Time: 2019年05月13日 星期一 22时15分52秒 6 | ************************************************************************/ 7 | 8 | #include 9 | extern "C" { 10 | #include "easyMatrix.h" 11 | } 12 | #include "gtest/gtest.h" 13 | 14 | DATA_TYPE val[] = {1,2,3,4,5,6,7,8,9}; 15 | void expect(int i, int j,DATA_TYPE* a, DATA_TYPE* b) { 16 | int t = i*j; 17 | for(int ii=0;iicols*a->rows; 24 | for(int ii=0;iielement[ii],b->element[ii],1e-5); 26 | } 27 | } 28 | 29 | void expect(int i, int j,DATA_TYPE* a, DATA_TYPE val) { 30 | int t = i*j; 31 | for(int ii=0;ii File Name: main.cpp 3 | > Author: Zhang Yuteng 4 | > Mail: 5 | > Created Time: 2019年05月22日 星期三 21时09分54秒 6 | ************************************************************************/ 7 | #include "gtest/gtest.h" 8 | 9 | int main(int argc, char** argv) { 10 | testing::InitGoogleTest(&argc,argv); 11 | return RUN_ALL_TESTS() ; 12 | } 13 | --------------------------------------------------------------------------------