![]() |
Forum Index : Microcontroller and PC projects : Future Matrix Commands>
Page 1 of 2 ![]() ![]() |
|||||
Author | Message | ||||
toml_12953 Guru ![]() Joined: 13/02/2015 Location: United StatesPosts: 442 |
Are there any plans to add the matrix commands for inverting a square matrix and a function to return the determinant? How about MATH READ a() to read a matrix in from DATA statements? I know I can write these functions myself but they'd be a lot faster if built into the language. |
||||
jirsoft![]() Guru ![]() Joined: 18/09/2020 Location: Czech RepublicPosts: 533 |
I think read matrix from DATA is one-time operation and you will no save too much... Jiri Napoleon Commander and SimplEd for CMM2 (GitHub), CMM2.fun |
||||
Mixtel90![]() Guru ![]() Joined: 05/10/2019 Location: United KingdomPosts: 7937 |
I don't like long lists of DATA statements. I always feel "cheated" somehow, as that data is having to take up twice as much memory. It's usually of no real use on its own and has to be read into something. :( Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
toml_12953 Guru ![]() Joined: 13/02/2015 Location: United StatesPosts: 442 |
Yeah but what are the alternatives? Either type all the data in each time the program is run using INPUT or use an editor to prepare a separate sequential file of data. We have hundreds of DATA statements in our programs so INPUT isn't feasible and the idea having two files that could get separated from each other or get out of sync isn't attractive either. At least DATA keeps all the data right in the file itself. |
||||
Mixtel90![]() Guru ![]() Joined: 05/10/2019 Location: United KingdomPosts: 7937 |
No-one took me up on RESTORE <variable> :) which might have made DATA more useful by being able to select the start of data to be read anywhere by changing the value of a variable. It could be the start of a DATA block or by using RESTORE <variable> : READ x any individual data statement. Actually, as I pointed out at the time, in theory all you really need is the address of the DATA pointer in MMBasic. Once you have that you can start by doing a scan of the data statements and PEEK it at recognizable points. Then you can POKE it with the DATA statement number that you want and you have RESTOREd to where you want to be. This was done on the old TRS-80. You can also use a CSUB as a data store. PEEK its address + an offset and you have the data that you want. Ok when you want numbers, but strings have to be all the same length. Edited 2021-07-16 20:09 by Mixtel90 Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4311 |
Actually I told you how to do it, on the CMM2, the problem is at the time you were asking how to do it on the Picomite (which doesn't have the EXECUTE command). EXECUTE "RESTORE " + v$ Best wishes, Tom MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
jirsoft![]() Guru ![]() Joined: 18/09/2020 Location: Czech RepublicPosts: 533 |
You can add information about length to the strings... Jiri Napoleon Commander and SimplEd for CMM2 (GitHub), CMM2.fun |
||||
Mixtel90![]() Guru ![]() Joined: 05/10/2019 Location: United KingdomPosts: 7937 |
EXECUTE is cheating, Tom. ;) Yep, I was looking for a way to select the different test programs for the PIO assembler (still ongoing). It's no use typing them in as you need them as sometimes things break and you have to check again on another. It's a load of hassle. RESTORE <label> is the best I can manage but it's a bit messy if you want to put a little menu system together (one of my original ideas that got abandoned because I lost interest in it!). No point in writing the assembler on the CMM2 really. It would test run, but development is very easy on the Pico when you can store stuff in flash. Also handy when I can take the PicoMite with me and work on it while I'm looking after my mum three days a week. True, Jiri. :) Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
William Leue Guru ![]() Joined: 03/07/2020 Location: United StatesPosts: 405 |
Note that I posted a matrix inversion program some time back. It also includes a determinant. There are several reasons why my BASIC program is not a good substitute for a robust, C-language version in the firmware, however; including speed and the poor numerical stability of the Gaussian Elimination method I use. -Bill |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10310 |
Point me at some C source and I might include it. NB this must include proper handling of matrices where inversion is impossible Edited 2021-07-17 02:40 by matherp |
||||
William Leue Guru ![]() Joined: 03/07/2020 Location: United StatesPosts: 405 |
There are a ton of them on the web. Take a look at www.sanfoundry.com/c-program-find-inverse-matrix/ -Bill |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10310 |
If you want it then you are going to have to do the spade work to qualify the algorithms, prove they work and that they handle edge cases properly. Anyone can google but that doesn't prove anything |
||||
William Leue Guru ![]() Joined: 03/07/2020 Location: United StatesPosts: 405 |
Of course, Peter, but you didn't ask for that in your previous post. I am not an expert in numerical methods, so I will defer to someone else better qualified. -Bill |
||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4311 |
I got down my copy of "Numerical Recipes in C - The Art of Scientific Computing" (the FORTRAN version is I believe the definitive work on the subject) and had a look at matrix inversion ... either they never intended this book to be read of I am not the intellect I was 25 years ago ![]() Best wishes, Tom Edited 2021-07-17 08:32 by thwill MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
toml_12953 Guru ![]() Joined: 13/02/2015 Location: United StatesPosts: 442 |
Here's a robust version: #include<stdio.h> #include<math.h> #include<conio.h> float determinant(float[25][25],float); void cofactor(float[25][25],float); void transpose(float[25][25],float[25][25],float); int main() { float matrix[25][25],size,d; int i,j; printf("\n\n 1 - Size of Matrix : "); scanf("%f",&size); printf("\n 2 - Enter the elements of the Matrix : \n"); for (i=0;i<size;i++)> { for (j=0;j<size;j++)> { printf("\n\t[ %d , %d ] = ",i,j); scanf("%f",&matrix[i][j]); } printf("\n"); } d=determinant(matrix,size); printf("\n\n\tDeterminant of the Matrix = %6.2f",d); if (d==0) { printf("\n\tInverse does not exsist\n\n"); } else cofactor(matrix,size); getch(); } /*For calculating Determinant of the Matrix . this function is recursive*/ float determinant(float matrix[25][25],float size) { float s=1,det=0,m_minor[25][25]; int i,j,m,n,c; if (size==1) { return (matrix[0][0]); } else { det=0; for (c=0;c<size;c++)> { m=0; n=0; for (i=0;i<size;i++)> { for (j=0;j<size;j++)> { m_minor[i][j]=0; if (i != 0 && j != c) { m_minor[m][n]=matrix[i][j]; if (n<(size-2)) n++; else { n=0; m++; } } } } det=det + s * (matrix[0][c] * determinant(m_minor,size-1)); s=-1 * s; } } return (det); } /*calculate cofactor of matrix*/ void cofactor(float matrix[25][25],float size) { float m_cofactor[25][25],matrix_cofactor[25][25]; int p,q,m,n,i,j; for (q=0;q<size;q++)> { for (p=0;p<size;p++)> { m=0; n=0; for (i=0;i<size;i++)> { for (j=0;j<size;j++)> { if (i != q && j != p) { m_cofactor[m][n]=matrix[i][j]; if (n<(size-2)) n++; else { n=0; m++; } } } } matrix_cofactor[q][p]=pow(-1,q + p) * determinant(m_cofactor,size-1); } } transpose(matrix,matrix_cofactor,size); } /*Finding transpose of cofactor of matrix*/ void transpose(float matrix[25][25],float matrix_cofactor[25][25],float size) { int i,j; float m_transpose[25][25],m_inverse[25][25],d; for (i=0;i<size;i++)> { for (j=0;j<size;j++)> { m_transpose[i][j]=matrix_cofactor[j][i]; } } d=determinant(matrix,size); for (i=0;i<size;i++)> { for (j=0;j<size;j++)> { m_inverse[i][j]=m_transpose[i][j] / d; } } printf("\n\n\tThe inverse of matrix is : \n\n"); for (i=0;i<size;i++)> { for (j=0;j<size;j++)> { printf("\t%3.2f",m_inverse[i][j]); } printf("\n\n"); } } |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10310 |
That code would need significant re-work. Using 25x25 arrays in functions will try and pull c3Kbytes off the stack at each level which will kill the stack on the CMM2 and any other MMBasic variant. Also, using an arbitrary size array is symptomatic of poor programming which doesn't inspire confidence in the rest Edited 2021-07-19 17:46 by matherp |
||||
jirsoft![]() Guru ![]() Joined: 18/09/2020 Location: Czech RepublicPosts: 533 |
I don't remember matrix calculation exactly, but for example determinant is simple iterative operation and here is recursive... Jiri Napoleon Commander and SimplEd for CMM2 (GitHub), CMM2.fun |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10310 |
Note: I will also need test data and results if I am to include anything |
||||
toml_12953 Guru ![]() Joined: 13/02/2015 Location: United StatesPosts: 442 |
Here is an even better version with some test data: #include<stdio.h> #include<math.h> float determinant(float [][25], float); void cofactor(float [][25], float); void transpose(float [][25], float [][25], float); int main() { float a[25][25], k, d; int i, j; printf("Enter the order of the Matrix : "); scanf("%f", &k); printf("Enter the elements of %.0fX%.0f Matrix : \n", k, k); for (i = 0;i < k; i++) { for (j = 0;j < k; j++) { scanf("%f", &a[i][j]); } } d = determinant(a, k); if (d == 0) printf("\nInverse of Entered Matrix is not possible\n"); else{ printf("\nDeterminant of Matrix is %4f : ",d); cofactor(a, k);} } /*For calculating Determinant of the Matrix */ float determinant(float a[25][25], float k) { float s = 1, det = 0, b[25][25]; int i, j, m, n, c; if (k == 1) { return (a[0][0]); } else { det = 0; for (c = 0; c < k; c++) { m = 0; n = 0; for (i = 0;i < k; i++) { for (j = 0 ;j < k; j++) { b[i][j] = 0; if (i != 0 && j != c) { b[m][n] = a[i][j]; if (n < (k - 2)) n++; else { n = 0; m++; } } } } det = det + s * (a[0][c] * determinant(b, k - 1)); s = -1 * s; } } return (det); } void cofactor(float num[25][25], float f) { float b[25][25], fac[25][25]; int p, q, m, n, i, j; for (q = 0;q < f; q++) { for (p = 0;p < f; p++) { m = 0; n = 0; for (i = 0;i < f; i++) { for (j = 0;j < f; j++) { if (i != q && j != p) { b[m][n] = num[i][j]; if (n < (f - 2)) n++; else { n = 0; m++; } } } } fac[q][p] = pow(-1, q + p) * determinant(b, f - 1); } } transpose(num, fac, f); } /*Finding transpose of matrix*/ void transpose(float num[25][25], float fac[25][25], float r) { int i, j; float b[25][25], inverse[25][25], d; for (i = 0;i < r; i++) { for (j = 0;j < r; j++) { b[i][j] = fac[j][i]; } } d = determinant(num, r); for (i = 0;i < r; i++) { for (j = 0;j < r; j++) { inverse[i][j] = b[i][j] / d; } } printf("\n\n\nThe inverse of matrix is : \n"); for (i = 0;i < r; i++) { for (j = 0;j < r; j++) { printf("\t%f", inverse[i][j]); } printf("\n"); } } Test 1: 3 x 3 Enter the elements of 3X3 Matrix : 4 5 1 6 7 2 8 0 4 Determinant of Matrix is 16.000000 : The inverse of matrix is : 1.750000 -1.250000 0.187500 -0.500000 0.500000 -0.125000 -3.500000 2.500000 -0.125000 Test 2: 3 x 3 Enter the order of the Matrix : 3 Enter the elements of 3X3 Matrix : 0,0,1,1,0,0,0,1,0 Inverse of Entered Matrix is not possible Test 3: 2 x 2 Enter the order of the Matrix : 2 Enter the elements of 2X2 Matrix : 1,1,1,1 Determinant of Matrix is 0.000000 : The inverse of matrix is : 1.000000 -0.000000 -0.000000 inf <<< I don't know how you'd want to handle that in BASIC. Test 4: 1 x 1 Enter the order of the Matrix : 1 Enter the elements of 1X1 Matrix : 5 Determinant of Matrix is 5.000000 : The inverse of matrix is : 0.000000 Test 5: 4 x 4 Enter the order of the Matrix : 4 Enter the elements of 4X4 Matrix : 7 9 2 5 0 0 1 1 3 4 -99 .5 12 16 8 -1 Determinant of Matrix is 407.000000 : The inverse of matrix is : 4.000000 -22.012285 -0.316953 -2.170762 -3.000000 16.567568 0.243243 1.689189 0.000000 0.007371 -0.009828 0.002457 -0.000000 0.992629 0.009828 -0.002457 What other types of examples would you like to see? |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10310 |
See the latest PicoMite post. Your code is still horrid with pre-allocated arrays. Here is how I do it. static MMFLOAT* alloc1df (int n) { // int i; MMFLOAT* array; if ((array = (MMFLOAT*) GetMemory(n * sizeof(MMFLOAT))) == NULL) { error("Unable to allocate memory for 1D float array...\n"); exit(0); } // for (i = 0; i < n; i++) { // array[i] = 0.0; // } return array; } static MMFLOAT** alloc2df (int m, int n) { int i; MMFLOAT** array; if ((array = (MMFLOAT **) GetMemory(m * sizeof(MMFLOAT*))) == NULL) { error("Unable to allocate memory for 2D float array...\n"); exit(0); } for (i = 0; i < m; i++) { array[i] = alloc1df(n); } return array; } static void dealloc2df (MMFLOAT** array, int m, int n) { int i; for (i = 0; i < m; i++) { FreeMemorySafe((void *)&array[i]); } FreeMemorySafe((void *)&array); } /*Finding transpose of cofactor of matrix*/ void transpose(MMFLOAT **matrix,MMFLOAT **matrix_cofactor,MMFLOAT **newmatrix, int size) { int i,j; MMFLOAT d; MMFLOAT **m_transpose=alloc2df(size,size); for (i=0;i<size;i++) { for (j=0;j<size;j++) { m_transpose[i][j]=matrix_cofactor[j][i]; } } d=determinant(matrix,size); for (i=0;i<size;i++) { for (j=0;j<size;j++) { newmatrix[i][j]=m_transpose[i][j] / d; } } dealloc2df(m_transpose,size,size); } /*calculate cofactor of matrix*/ void cofactor(MMFLOAT **matrix,MMFLOAT **newmatrix,int size) { MMFLOAT **m_cofactor=alloc2df(size,size); MMFLOAT **matrix_cofactor=alloc2df(size,size); int p,q,m,n,i,j; for (q=0;q<size;q++) { for (p=0;p<size;p++) { m=0; n=0; for (i=0;i<size;i++) { for (j=0;j<size;j++) { if (i != q && j != p) { m_cofactor[m][n]=matrix[i][j]; if (n<(size-2)) n++; else { n=0; m++; } } } } matrix_cofactor[q][p]=pow(-1,q + p) * determinant(m_cofactor,size-1); } } transpose(matrix, matrix_cofactor, newmatrix, size); dealloc2df(m_cofactor,size,size); dealloc2df(matrix_cofactor,size,size); } /*For calculating Determinant of the Matrix . this function is recursive*/ MMFLOAT determinant(MMFLOAT **matrix,int size) { MMFLOAT s=1,det=0; MMFLOAT **m_minor=alloc2df(size,size); int i,j,m,n,c; if (size==1) { return (matrix[0][0]); } else { det=0; for (c=0;c<size;c++) { m=0; n=0; for (i=0;i<size;i++) { for (j=0;j<size;j++) { m_minor[i][j]=0; if (i != 0 && j != c) { m_minor[m][n]=matrix[i][j]; if (n<(size-2)) n++; else { n=0; m++; } } } } det=det + s * (matrix[0][c] * determinant(m_minor,size-1)); s=-1 * s; } } dealloc2df(m_minor,size,size); return (det); } tp = checkstring(cmdline, "M_INVERSE"); if(tp){ void *ptr1 = NULL; void *ptr2 = NULL; int i, j, n, numcols=0, numrows=0; MMFLOAT *a1float=NULL, *a2float=NULL,det; getargs(&tp, 3,","); if(!(argc == 3)) error("Argument count"); ptr1 = findvar(argv[0], V_FIND | V_EMPTY_OK | V_NOFIND_ERR); if(vartbl[VarIndex].type & T_NBR) { if(vartbl[VarIndex].dims[2] != 0) error("Invalid variable"); if(vartbl[VarIndex].dims[1] <= 0) { // Not an array error("Argument 1 must be a numerical 2D array"); } if(vartbl[VarIndex].dims[0] <= 0) { // Not an array error("Argument 1 must be a numerical 2D array"); } numcols=vartbl[VarIndex].dims[0] - OptionBase; numrows=vartbl[VarIndex].dims[1] - OptionBase; a1float = (MMFLOAT *)ptr1; if((uint32_t)ptr1!=(uint32_t)vartbl[VarIndex].val.s)error("Syntax"); } else error("Argument 1 must be a numerical 2D array"); ptr2 = findvar(argv[2], V_FIND | V_EMPTY_OK | V_NOFIND_ERR); if(vartbl[VarIndex].type & T_NBR) { if(vartbl[VarIndex].dims[2] != 0) error("Invalid variable"); if(vartbl[VarIndex].dims[1] <= 0) { // Not an array error("Argument 2 must be a numerical 2D array"); } if(vartbl[VarIndex].dims[0] <= 0) { // Not an array error("Argument 2 must be a numerical 2D array"); } if(numcols!=vartbl[VarIndex].dims[0] - OptionBase)error("array size mismatch"); if(numrows!=vartbl[VarIndex].dims[1] - OptionBase)error("array size mismatch"); a2float = (MMFLOAT *)ptr2; if((uint32_t)ptr2!=(uint32_t)vartbl[VarIndex].val.s)error("Syntax"); } else error("Argument 2 must be a numerical 2D array"); if(numcols!=numrows)error("Array must be square"); n=numrows+1; MMFLOAT **matrix=alloc2df(n,n); for(i=0;i<n;i++){ //load the matrix for(j=0;j<n;j++){ matrix[j][i]=*a1float++; } } det=determinant(matrix,n); if(det==0.0){ dealloc2df(matrix,numcols,numrows); error("Determinant of array is zero"); } MMFLOAT **matrix1=alloc2df(n,n); cofactor(matrix, matrix1, n); for(i=0;i<n;i++){ //load the matrix for(j=0;j<n;j++){ *a2float++=matrix1[j][i]; } } dealloc2df(matrix,numcols,numrows); dealloc2df(matrix1,numcols,numrows); return; } Edited 2021-07-20 01:46 by matherp |
||||
Page 1 of 2 ![]() ![]() |
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |