ESP8266 ILI9341 display support code with printf sources, wire-frame viewer and custom fonts  1.0
ESP8266ILI9341DisplayProject
matrix.c
Go to the documentation of this file.
1 
23 #include "user_config.h"
24 
25 #include "matrix.h"
26 
29 
30 
37 int TestSquare(mat_t MatA)
38 {
39  return( (MatA.rows == MatA.cols) ? 1 : 0 );
40 }
41 
48 mat_t MatAlloc(int rows, int cols)
49 {
50  int r;
51  mat_t MatA;
52  float *fptr;
53 
54  if(rows < 1)
55  {
56 #if MATDEBUG & 1
57  //FIXME
58  printf("MatAlloc: rows < 1\n");
59 #endif
60  rows = 1;
61  }
62  if(cols< 1)
63  {
64 #if MATDEBUG & 1
65  //FIXME
66  printf("MatAlloc: cols < 1\n");
67 #endif
68  cols = 1;
69  }
70 
71  MatA.data = safecalloc(rows,sizeof(float *));
72  if(MatA.data == NULL)
73  {
74  MatA.rows = 0;
75  MatA.cols = 0;
76  return(MatA);
77  }
78 
79  for (r=0;r<rows;r++)
80  {
81  fptr = safecalloc(cols,sizeof(float));
82  if(fptr == NULL)
83  {
84  MatFree(MatA);
85  return(MatA);
86  }
87 
88  MatA.data[r] = fptr;
89  }
90  MatA.rows = rows;
91  MatA.cols = cols;
92  if(cols == rows)
93  MatA.size = cols;
94  else
95  MatA.size = 0;
96  return(MatA);
97 }
98 
104 MEMSPACE
105 mat_t MatAllocSQ(int size)
106 {
107  return(MatAlloc(size,size));
108 }
109 
110 
115 MEMSPACE
116 void MatFree(mat_t matF)
117 {
118  int i;
119  if(matF.data)
120  {
121  for (i=0;i<matF.rows;i++)
122  {
123  if(matF.data[i])
124  {
125  safefree(matF.data[i]);
126  matF.data[i] = NULL;
127  }
128  else
129  {
130 #if MATDEBUG & 1
131  printf("MatFree: attempt to free null matF row: %d\n", i);
132 #endif
133  }
134  }
135  safefree(matF.data);
136  matF.data = NULL;
137  }
138  else
139  {
140 #if MATDEBUG & 1
141  printf("MatFree: attempt to free null matF\n");
142 #endif
143  }
144 }
145 
151 MEMSPACE
152 mat_t MatLoad(void *V, int rows, int cols)
153 {
154  mat_t MatA = MatAlloc(rows,cols);
155  float *f = (float *) V;
156 
157  int r,c,k;
158 
159  k = 0;
160  for(r=0;r<rows;++r)
161  {
162  for(c=0;c<cols;++c)
163  {
164  MatA.data[r][c] = f[k++];
165  }
166  }
167  return(MatA);
168 }
169 
175 MEMSPACE
176 mat_t MatLoadSQ(void *V, int size)
177 {
178  return(MatLoad(V,size,size));
179 }
180 
181 
186 MEMSPACE
187 void MatPrint(mat_t matrix)
188 {
189  int r,c;
190 
191  printf("size: rows(%d), cols(%d)\n", matrix.rows,matrix.cols);
192  for(r=0;r<matrix.rows;++r)
193  {
194  for(c=0;c<matrix.cols;++c)
195  {
196  printf("%+e ", (double) matrix.data[r][c]);
197  }
198  printf("\n");
199  }
200  printf("\n");
201 }
202 
211 MEMSPACE
212 mat_t DeleteRowCol(mat_t MatA,int row,int col)
213 {
214  int r,c;
215  int rM, cM;
216  mat_t MatM;
217  int rows = MatA.rows;
218  int cols = MatA.cols;
219  if(cols < 2)
220  {
221  //FIXME user error
222  cols = 2;
223 #if MATDEBUG & 1
224  printf("DeleteRowCol cols:%d < 2 error\n",cols);
225 #endif
226  }
227  if(rows < 2)
228  {
229  //FIXME user error
230  rows = 2;
231 #if MATDEBUG & 1
232  printf("DeleteRowCol rows:%d < 2 error\n",rows);
233 #endif
234  }
235 
236  MatM = MatAlloc(rows-1,cols-1);
237  rM = 0;
238  for(r=0;r<MatA.rows;++r)
239  {
240  // delete row
241  if(r == row)
242  continue;
243  cM = 0;
244  for(c=0;c<MatA.cols;++c)
245  {
246  // delete col
247  if(c == col)
248  continue;
249  MatM.data[rM][cM] = MatA.data[r][c];
250  ++cM;
251  }
252  ++rM;
253  }
254  return(MatM);
255 }
256 
262 MEMSPACE
264 {
265  int c,r;
266  // allocate using transposed rows and columns
267  mat_t MatR = MatAlloc(MatA.cols, MatA.rows);
268  // row
269  for (r = 0; r < MatA.rows; r++)
270  {
271  // col
272  for( c = 0 ; c < MatA.cols ; c++ )
273  {
274  // transposed
275  MatR.data[c][r] = MatA.data[r][c];
276  }
277  }
278  return(MatR);
279 }
280 
290 MEMSPACE
291 float Minor(mat_t MatA, int row, int col)
292 {
293  float D;
294  mat_t SubMat = DeleteRowCol(MatA, row, col);
295  D = Determinant(SubMat);
296  MatFree(SubMat);
297  return(D);
298 }
299 
309 MEMSPACE
310 float Cofactor(mat_t MatA, int row, int col)
311 {
312  float D = Minor(MatA, row, col);;
313  // (-1)exp(row+col) is -1 if (row+col) odd otherwise 1.0 if even
314  D *= ( ((row+col) & 1) ? -1.0 : 1.0);
315  return(D);
316 }
317 
324 MEMSPACE
326 {
327  int r,c;
328  // Since the result is the transpose we allocate switching rows and cols here
329  mat_t MatAdj = MatAlloc(MatA.cols,MatA.rows);
330 
331  for(r = 0; r< MatA.rows;++r)
332  {
333  for(c = 0; c < MatA.cols;++c)
334  {
335  // transpose rows and columns when storing Cofactors to get the Adjugate
336  MatAdj.data[c][r] = Cofactor(MatA,r,c);
337  }
338  }
339  return(MatAdj);
340 }
341 
342 
349 MEMSPACE
350 float Determinant(mat_t MatA)
351 {
352  int r,c,n,cc;
353  float D = 0;
354 
355  if(MatA.cols != MatA.rows)
356  {
357  //FIXME error
358 #if MATDEBUG & 1
359  printf("Determinate: Matrix MUST be square!\n");
360 #endif
361  return(D);
362  }
363 
364  if (MatA.size < 1)
365  {
366 #if MATDEBUG & 1
367  printf("Determinate: Matrix size MUST be > 0!\n");
368 #endif
369  return(D);
370  }
371  // 1 x 1 case
372  if (MatA.size == 1)
373  {
374  D = MatA.data[0][0];
375  return(D);
376  }
377  // 2 x 2 case
378  if (MatA.size == 2)
379  {
380  D = MatA.data[0][0] * MatA.data[1][1] - MatA.data[1][0] * MatA.data[0][1];
381  return(D);
382  }
383  // solve > 2 cases by recursive Cofactor method
384  for (n=0;n<MatA.size;++n)
385  {
386  D += MatA.data[0][n] * Cofactor(MatA, 0, n);
387  }
388  return(D);
389 }
390 
398 MEMSPACE
400 {
401  int r,c;
402  float D;
403 
404  mat_t MatAdj;
405 
406 #if MATDEBUG & 2
407  printf("MatA\n");
408  MatPrint(MatA);
409 #endif
410 
411  D=Determinant(MatA);
412 
413  if(!D)
414  {
415  //FIXME flag error somehow
416 #if MATDEBUG & 1
417  printf("Determinant(MatA) = 0!\n\n");
418 #endif
419  return(MatA);
420  }
421 
422 #if MATDEBUG & 2
423  printf("Determinant(MatA):\n%e\n\n", (double) D);
424 #endif
425 
426  MatAdj = Adjugate(MatA);
427 #if MATDEBUG & 2
428  printf("Adjugate(MatA)\n");
429  MatPrint(MatAdj);
430 #endif
431  // row
432  for (r=0;r<MatAdj.rows;++r)
433  {
434  // col
435  for (c=0;c<MatAdj.cols;++c)
436  {
437  MatAdj.data[r][c] /= D;
438  }
439  }
440 #if MATDEBUG & 2
441  printf("Adjugate(MatA)/Determinant(MatA)\n");
442  MatPrint(MatAdj);
443 #endif
444 
445  return(MatAdj);
446 }
447 
455 MEMSPACE
457 {
458  // AT = Transpose(A)
459  mat_t MatAT = Transpose(MatA);
460 
461  // AT * A
462  mat_t MatR = MatMul(MatAT,MatA);
463 
464  // 1/(AT * A)
465  mat_t MatI = Invert(MatR);
466 
467  // Pseudo Inverse (AT × A)–1 × AT\n
468  mat_t MatPI = MatMul(MatI,MatAT);
469 
470  MatFree(MatR);
471  MatFree(MatI);
472  MatFree(MatAT);
473 
474  return(MatPI);
475 }
476 
477 
489 MEMSPACE
490 mat_t MatMul(mat_t MatA, mat_t MatB)
491 {
492  float sum = 0;
493  mat_t MatR = MatAlloc(MatA.rows,MatB.cols);
494 
495  int rA,cB,rB;
496 
497  if (MatA.cols != MatB.rows)
498 #if MATDEBUG & 1
499  printf("error MatA cols(%d) != MatB rows(%d)\n", MatA.cols, MatB.rows);
500 #endif
501 
502  // A row
503  for (rA = 0; rA < MatA.rows; ++rA)
504  {
505  // col B
506  for (cB = 0; cB < MatB.cols; ++cB)
507  {
508  // row B
509  for (rB = 0; rB < MatB.rows; ++rB)
510  {
511  sum += (MatA.data[rA][rB] * MatB.data[rB][cB]);
512  }
513  MatR.data[rA][cB] = sum;
514  sum = 0;
515  }
516  }
517  return(MatR);
518 }
519 
526 MEMSPACE
527 mat_t MatRead(char *name)
528 {
529 
530  FILE *fp;
531  char *ptr;
532  int r,c;
533  int rows = 0;
534  int cols = 0;
535  int cnt;
536  int lines = 0;
537  mat_t MatR;
538  char tmp[128];
539 
540  MatR.rows = 0;
541  MatR.cols = 0;
542  MatR.data = NULL;
543 
544  fp = fopen(name,"rb");
545  if(fp == NULL)
546  {
547  return(MatR);
548  }
549 
550  // Read Matrix header with rows and columns
551  ptr = fgets(tmp,253,fp);
552  if(ptr == NULL)
553  {
554  fclose(fp);
555  return(MatR);
556  }
557  //printf("line:%d, %s\n", lines, tmp);
558  ++lines;
559  cnt = sscanf(ptr,"Matrix R:%d C:%d", (int *) &rows, (int *) &cols);
560  if(rows < 1 || cols < 1)
561  {
562  printf("sscanf: %d\n",cnt);
563  printf("MatRead expected header: Matrix R:%d C:%d\n",tmp);
564  fclose(fp);
565  return(MatR);
566  }
567 
568  // FIXME set limts or just let alloc fail ???
569  MatR = MatAlloc(rows,cols);
570  if(MatR.data == NULL)
571  {
572  printf("MatRead(%s: &d,&d) could not alloc memory\n", name, rows,cols);
573  fclose(fp);
574  return(MatR);
575  }
576 
577  for(r=0;r<rows;++r)
578  {
579  // Read rows and columns
580  ptr = fgets(tmp,253,fp);
581  //printf("line:%d, %s\n", lines, tmp);
582  ++lines;
583  if(ptr == NULL)
584  {
585  fclose(fp);
586  MatFree(MatR);
587  return(MatR);
588  }
589  for(c=0;c<cols;++c)
590  {
591  MatR.data[r][c] = strtod(ptr,&ptr);
592  }
593  }
594  fclose(fp);
595  return(MatR);
596 }
597 
604 MEMSPACE
605 int MatWrite(char *name, mat_t MatW)
606 {
607 
608  FILE *fp;
609  int r,c;
610 
611  fp = fopen(name,"wb");
612  if(fp == NULL)
613  {
614  return(0);
615  }
616 
617  fprintf(fp,"Matrix R:%d C:%d\n",MatW.rows,MatW.cols);
618  for(r=0;r<MatW.rows;++r)
619  {
620  for(c=0;c<MatW.cols;++c)
621  {
622  fprintf(fp,"%e ", (double) MatW.data[r][c]);
623  }
624  fprintf(fp,"\n");
625  }
626  fclose(fp);
627  return(1);
628 }
629 
630 
631 #ifdef MATTEST
632 // =============================================
633 // test1
634 // compute Adj(AJ)
635 
636 float AJ[3][3] =
637 {
638  { -3, 2, -5 },
639  { -1, 0, -2 },
640  { 3, -4, 1 }
641 };
642 
643 // =============================================
644 // test2
645 // Matrix Multiplication
646 // compute C * D
647 
648 float C[3][3] =
649 {
650  { 1,2,0 },
651  { 0, 1, 1 },
652  { 2, 0, 1 }
653 };
654 float D[3][3] =
655 {
656  { 1, 1, 2 },
657  { 2, 1, 1 },
658  { 1, 2, 1 }
659 };
660 
661 // =============================================
662 // test3
663 // Test functions required for 3 point screen calibration
664 // See: https://www.maximintegrated.com/en/app-notes/index.mvp/id/5296
665 // Calibration in touch-screen systems
666 //
667 // Calculation
668 // 1/A * X
669 // 1/A * Y
670 //
671 // Answer should be
672 // xd = 0.0635 x + 0.0024 y + 18.9116
673 // yd = -0.0227 x + 0.1634 y + 37.8887
674 // Where (x, y) are touch panel coordinates
675 // and (xd, yd) is the adjusted screen coordinate
676 float A3[3][3] = {
677  { 650, 2000, 1 },
678  { 2800, 1350, 1 },
679  { 2640, 3500, 1 }
680 };
681 
682 float X3[3][1] =
683 {
684  {65},
685  {200},
686  {195}
687 };
688 
689 float Y3[3][1] =
690 {
691  {350},
692  {195},
693  {550}
694 };
695 
696 // =============================================
697 // test4
698 // Test functions required for 5 point screen calibration
699 // See: https://www.maximintegrated.com/en/app-notes/index.mvp/id/5296
700 // Calibration in touch-screen systems
701 //
702 // Calculation - note: AT = transpose(A)
703 // (1/(AT * A) * AT) * X
704 // (1/(AT * A) * AT) * Y
705 //
706 // Answer should be
707 // xd = 0.0677 x + 0.0190 y - 33.7973
708 // yd = -0.0347 x + 0.2100 y - 27.4030
709 // Where (x, y) are touch panel coordinates
710 // and (xd, yd) is the adjusted screen coordinate
711 
712 
713 float A5[5][3] = {
714  { 1700, 2250, 1 },
715  { 750, 1200, 1 },
716  { 3000, 1500, 1 },
717  { 2500, 3400, 1 },
718  { 600, 3000, 1 }
719 };
720 
721 float X5[5][1] =
722 {
723  {100},
724  {50},
725  {200},
726  {210},
727  {65}
728 };
729 
730 float Y5[5][1] =
731 {
732  {350},
733  {200},
734  {200},
735  {600},
736  {600}
737 };
738 
739 int main(int argc, char *argv[])
740 {
741  mat_t MatA,MatX,MatY;
742  mat_t MatI;
743  mat_t MatPI;
744  mat_t MatC,MatD;
745  mat_t MatR;
746  mat_t MatAdj;
747 
748 
749  // =============================
750  // test Adjugate
751  printf("==========================================\n");
752  MatA = MatLoad(AJ,3,3);
753  printf("MatA\n");
754  MatPrint(MatA);
755  MatAdj = Adjugate(MatA);
756  printf("Adjugate(MatA)\n");
757  MatPrint(MatAdj);
758  MatFree(MatAdj);
759  MatFree(MatA);
760  printf("==========================================\n");
761  printf("\n");
762 
763  // =============================
764  // test MatMul
765  printf("==========================================\n");
766  MatC = MatLoadSQ(C,3);
767  printf("MatC\n");
768  MatPrint(MatC);
769  MatD = MatLoadSQ(D,3);
770  printf("MatD\n");
771  MatPrint(MatD);
772  MatR = MatMul(MatC,MatD);
773  printf("MatC * MatD\n");
774  MatPrint(MatR);
775  MatFree(MatC);
776  MatFree(MatD);
777  MatFree(MatR);
778  printf("==========================================\n");
779  printf("\n");
780 
781  // ===============================================================
782  // ===============================================================
783  // Test functions required for 3 point screen calibration
784  // See: https://www.maximintegrated.com/en/app-notes/index.mvp/id/5296
785  // Calibration in touch-screen systems
786  printf("==========================================\n");
787  printf("Set of three display positions\n");
788  MatX = MatLoad(X3,3,1);
789  printf("X\n");
790  MatPrint(MatX);
791 
792  MatY = MatLoad(Y3,3,1);
793  printf("Y\n");
794  MatPrint(MatY);
795 
796  printf("Correponding touch screen positions, differing scale and skew\n");
797  MatA = MatLoadSQ(A3,3);
798  printf("A\n");
799  MatPrint(MatA);
800 
801  // 1/A
802  MatI = Invert(MatA);
803  printf("1/(A)\n");
804  MatPrint(MatI);
805  MatFree(MatA);
806 
807  printf("Solution Matrix to translate touch screen to screen positions\n");
808  // MatR = 1/A * X
809  MatR = MatMul(MatI,MatX);
810  printf("1/A * X\n");
811  MatPrint(MatR);
812  MatFree(MatR);
813  MatFree(MatX);
814 
815  // MatR = 1/A * Y
816  MatR = MatMul(MatI,MatY);
817  printf("1/A * Y\n");
818  MatPrint(MatR);
819  MatFree(MatR);
820  MatFree(MatY);
821 
822  MatFree(MatI);
823  printf("==========================================\n");
824  printf("\n");
825 
826  // ===============================================================
827  // ===============================================================
828  // Test functions required for N point screen calibration
829  // Use least square solution by Pseudo Invert method
830  // See: https://www.maximintegrated.com/en/app-notes/index.mvp/id/5296
831  // Calibration in touch-screen systems
832  printf("==========================================\n");
833  printf("Set of five display positions\n");
834  MatX = MatLoad(X5,5,1);
835  printf("X\n");
836  MatPrint(MatX);
837 
838  MatY = MatLoad(Y5,5,1);
839  printf("Y\n");
840  MatPrint(MatY);
841 
842  printf("Correponding touch screen positions, differing scale and skew\n");
843  MatA = MatLoad(A5,5,3);
844  printf("A\n");
845  MatPrint(MatA);
846 
847  printf("Compute pseudo-inverse matrix, 1/(AT × A) × AT\n");
848  MatPI = PseudoInvert(MatA);
849  printf("PI = Pseudo Invert(A)\n");
850  MatPrint(MatPI);
851  MatFree(MatA);
852 
853  printf("Solution Matrix to translate touch screen to screen positions\n");
854  // MatR = PI * X
855  MatR = MatMul(MatPI,MatX);
856  printf("(R = PI * X\n");
857  MatPrint(MatR);
858  MatFree(MatR);
859  MatFree(MatX);
860 
861  // MatR = 1/A * Y
862  MatR = MatMul(MatPI,MatY);
863  printf("R = PI * Y\n");
864  MatPrint(MatR);
865  MatFree(MatR);
866  MatFree(MatY);
867 
868  MatFree(MatPI);
869 
870  printf("==========================================\n");
871  printf("\n");
872 
873 }
874 #endif
875 
876 
float ** data
Definition: matrix.h:28
MEMSPACE int TestSquare(mat_t MatA)
Credits: https://www.cs.rochester.edu/~brown/Crypto/assts/projects/adj.html.
Definition: matrix.c:37
Master include file for project Includes all project includes and defines here.
MEMSPACE void MatPrint(mat_t matrix)
Print a matrix.
Definition: matrix.c:187
MEMSPACE mat_t Transpose(mat_t MatA)
Transpose matrix.
Definition: matrix.c:263
MEMSPACE char * fgets(char *str, int size, FILE *stream)
get a string from stdin See fdevopen() sets stream->put get for TTY devices
Definition: posix.c:420
MEMSPACE FILE * fopen(const char *path, const char *mode)
POSIX Open a file with path name and ascii file mode string.
Definition: posix.c:782
FILE type structure.
Definition: posix.h:156
MEMSPACE int fprintf(FILE *fp, const char *format,...)
fprintf function Example user defined printf function using fputc for I/O This method allows I/O to d...
Definition: posix.c:2484
MEMSPACE float Cofactor(mat_t MatA, int row, int col)
Cofactor is determinate of minor submatrix * (-1)exp(row+col) Minor submatrix has one less row and co...
Definition: matrix.c:310
int cols
Definition: matrix.h:29
MEMSPACE mat_t MatAlloc(int rows, int cols)
Allocate a matrix.
Definition: matrix.c:48
Definition: matrix.h:27
MEMSPACE uint16_t sum(char *name)
sum of a file with 16bit hex and integer results
Definition: posix_tests.c:626
MEMSPACE float Minor(mat_t MatA, int row, int col)
Compute determinate of the minor submatrix Minor submatrix has one less row and column as a result...
Definition: matrix.c:291
#define NULL
Definition: cpu.h:55
MEMSPACE double strtod(const char *nptr, char **endptr)
MEMSPACE mat_t DeleteRowCol(mat_t MatA, int row, int col)
Create smaller matrix by deleatting specified row and colume Used by Minor and Cofactor.
Definition: matrix.c:212
int size
Definition: matrix.h:31
int main(int argc, char *argv[])
Definition: send.c:148
matrix functions
MEMSPACE int fclose(FILE *stream)
POSIX close a file stream.
Definition: posix.c:1239
int sscanf(const char *strp, const char *fmt,...)
int rows
Definition: matrix.h:30
MEMSPACE mat_t MatRead(char *name)
Read a matrix.
Definition: matrix.c:527
MEMSPACE mat_t Adjugate(mat_t MatA)
Adjugate is transpose of cofactor matrix of A.
Definition: matrix.c:325
#define MEMSPACE
Definition: cpu.h:25
MEMSPACE mat_t MatLoad(void *V, int rows, int cols)
Load a matrix.
Definition: matrix.c:152
MEMSPACE void MatFree(mat_t matF)
Free a matrix.
Definition: matrix.c:116
MEMSPACE int printf(const char *format,...)
MEMSPACE mat_t MatMul(mat_t MatA, mat_t MatB)
Multiply two matrix.
Definition: matrix.c:490
MEMSPACE int MatWrite(char *name, mat_t MatW)
Write a matrix.
Definition: matrix.c:605
MEMSPACE mat_t MatLoadSQ(void *V, int size)
Load a square matrix.
Definition: matrix.c:176
MEMSPACE void safefree(void *p)
Safe free - Only free a pointer if it is in malloc memory range. We want to try to catch frees of sta...
Definition: system.c:165
MEMSPACE float Determinant(mat_t MatA)
Determinant by recursion using Cofactors.
Definition: matrix.c:350
MEMSPACE mat_t MatAllocSQ(int size)
Allocate a matrix.
Definition: matrix.c:105
MEMSPACE mat_t Invert(mat_t MatA)
Calculate Matrix Inverse.
Definition: matrix.c:399
MEMSPACE void * safecalloc(size_t nmemb, size_t size)
Safe Calloc - Display Error message if Calloc fails.
Definition: system.c:128
MEMSPACE mat_t PseudoInvert(mat_t MatA)
Calculate Pseudo Matrix Inverse Used for least square fitting of non square matrix with excess soluti...
Definition: matrix.c:456