/*Copyright (C) 1992, 1995 by Thomas Glen Smith. All Rights Reserved.*/ /* mdivide APL2 V1.0.0 ************************************************* * mdivide does matrix division with LEFT being the numerator and RIGHT * * the denominator. Arguments of rank greater than two are rejected. * * A scalar is treated as a 1-by-1 matrix, and a vector as a one-column * * matrix. * ***********************************************************************/ #define INCLUDES APLCB+APLMEM #include "includes.h" Aplcb mdivide(left,rite) Aplcb left,rite; { Errinit; Errstop; Getcb; Invert; Matchok; Matmult; Regress; Mdivarg; extern int aplerr; int datacnt,*dimptr,i,lcols,lrows,rank,rcols,rrows; double *dataptr,f,*inv; Aplcb out=NULL; if (errinit()) return(errstop(0,left,rite,out)); if (ERR == mdivarg(rite,&rrows,&rcols)) return(errstop(0,left,rite,out)); if (rrows < rcols) return(errstop(6,left,rite,out)); if (ERR == mdivarg(left,&lrows,&lcols)) return(errstop(0,left,rite,out)); if (lrows != rrows) return(errstop(7,left,rite,out)); if ((left->aplflags & APLCPLX) || (rite->aplflags & APLCPLX)) return(errstop(995,left,rite,out)); /* Can't do complex numbers. */ if (!matchok(&left,&rite,APLNUMB)) return(out); if (rrows == rcols) { /* square matrix? */ inv = invert(rite->aplptr.apldata,rrows); if (NULL == inv) return(errstop(8,left,rite,out)); /* not invertible */ dataptr = matmult(inv,left->aplptr.apldata,rrows,rcols,lcols); free(inv); } else { /* non-square matrix */ dataptr = regress(left,rite,lrows,lcols,rrows,rcols); if (aplerr) return(out); } rank = 0; if (left->aplrank>1) rank++; if (rite->aplrank>1) rank++; datacnt = lcols*rcols; out = getcb(dataptr,datacnt,APLTEMP+APLNUMB,rank,NULL); if (rank > 1) { /* Build new dimensions? */ dimptr = out->apldim; if (rite->aplrank > 1) *dimptr++ = *(rite->apldim+1); if (left->aplrank > 1) *dimptr = *(left->apldim+1); } return(errstop(0,left,rite,out)); }