Changeset 20728


Ignore:
Timestamp:
06/14/16 00:11:40 (9 years ago)
Author:
agscott1
Message:

CHG TripleMultiply now uses static allocation in most cases, and MatrixInvert functions now multiply by the reciprocal of a determinant instead of dividing by the determinant.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • issm/trunk-jpl/src/c/shared/Matrix/MatrixUtils.cpp

    r19572 r20728  
    2222
    2323        int         idima,idimb,idimc,idimd;
    24         IssmDouble *dtemp;
     24        IssmDouble dtemp_static[600];
    2525        _assert_(a && b && c && d);
    2626
     
    5252                idimd=nrowc;
    5353        }
    54 
     54       
    5555        /*  perform the matrix triple product in the order that minimizes the
    5656                 number of multiplies and the temporary space used, noting that
     
    6161        /*  multiply (a*b)*c+d  */
    6262        if (idima*idimc*(idimb+idimd) <= idimb*idimd*(idima+idimc)) {
    63                 dtemp=xNew<IssmDouble>(idima*idimc);
    64 
    65                 MatrixMultiply(a,nrowa,ncola,itrna,b,nrowb,ncolb,itrnb,dtemp,0);
    66                 MatrixMultiply(dtemp,idima,idimc,0,c,nrowc,ncolc,itrnc,d,iaddd);
    67                 xDelete<IssmDouble>(dtemp);
     63                if(idima*idimc>600) {
     64                        /*Use dynamic allocation instead of dtemp_static*/
     65                        IssmDouble *dtemp;
     66                        dtemp=xNew<IssmDouble>(idima*idimc);
     67
     68                        MatrixMultiply(a,nrowa,ncola,itrna,b,nrowb,ncolb,itrnb,dtemp,0);
     69                        MatrixMultiply(dtemp,idima,idimc,0,c,nrowc,ncolc,itrnc,d,iaddd);
     70                        xDelete<IssmDouble>(dtemp);
     71                        return 1;
     72                }
     73                MatrixMultiply(a,nrowa,ncola,itrna,b,nrowb,ncolb,itrnb,&dtemp_static[0],0);
     74                MatrixMultiply(&dtemp_static[0],idima,idimc,0,c,nrowc,ncolc,itrnc,d,iaddd);
    6875        }
    6976
    7077        /*  multiply a*(b*c)+d  */
    7178        else{
    72                 dtemp=xNew<IssmDouble>(idimb*idimd);
    73 
    74                 MatrixMultiply(b,nrowb,ncolb,itrnb,c,nrowc,ncolc,itrnc,dtemp,0);
    75                 MatrixMultiply(a,nrowa,ncola,itrna,dtemp,idimb,idimd,0,d,iaddd);
    76                 xDelete<IssmDouble>(dtemp);
     79                if(idimb*idimd>600) {
     80                        /*Use dynamic allocation instead of dtemp_static*/
     81                        IssmDouble *dtemp;
     82                        dtemp=xNew<IssmDouble>(idimb*idimd);
     83
     84                        MatrixMultiply(b,nrowb,ncolb,itrnb,c,nrowc,ncolc,itrnc,dtemp,0);
     85                        MatrixMultiply(a,nrowa,ncola,itrna,dtemp,idimb,idimd,0,d,iaddd);
     86                        xDelete<IssmDouble>(dtemp);
     87                        return 1;
     88                }
     89                MatrixMultiply(b,nrowb,ncolb,itrnb,c,nrowc,ncolc,itrnc,&dtemp_static[0],0);
     90                MatrixMultiply(a,nrowa,ncola,itrna,&dtemp_static[0],idimb,idimd,0,d,iaddd);
    7791        }
    7892
     
    324338        /*Intermediaries*/
    325339        IssmDouble det;
     340        IssmDouble det_reciprocal;
    326341
    327342        /*Compute determinant*/
    328343        Matrix2x2Determinant(&det,A);
    329344        if (fabs(det) < DBL_EPSILON) _error_("Determinant smaller than machine epsilon");
     345       
     346        /*Multiplication is faster than divsion, so we multiply by the reciprocal*/
     347        det_reciprocal = 1/det; 
    330348
    331349        /*Compute invert*/
    332         Ainv[0]=   A[3]/det; /* =  d/det */
    333         Ainv[1]= - A[1]/det; /* = -b/det */
    334         Ainv[2]= - A[2]/det; /* = -c/det */
    335         Ainv[3]=   A[0]/det; /* =  a/det */
     350        Ainv[0]=   A[3]*det_reciprocal; /* =  d/det */
     351        Ainv[1]= - A[1]*det_reciprocal; /* = -b/det */
     352        Ainv[2]= - A[2]*det_reciprocal; /* = -c/det */
     353        Ainv[3]=   A[0]*det_reciprocal; /* =  a/det */
    336354
    337355}/*}}}*/
     
    441459        /*Intermediaries*/
    442460        IssmDouble det;
     461        IssmDouble det_reciprocal;
    443462
    444463        /*Compute determinant*/
     
    446465        if (fabs(det) < DBL_EPSILON) _error_("Determinant smaller than machine epsilon");
    447466
     467        /*Multiplication is faster than divsion, so we multiply by the reciprocal*/
     468        det_reciprocal = 1/det; 
     469
    448470        /*Compute invert*/
    449         Ainv[0]=(A[4]*A[8]-A[5]*A[7])/det; /* = (e*i-f*h)/det */
    450         Ainv[1]=(A[2]*A[7]-A[1]*A[8])/det; /* = (c*h-b*i)/det */
    451         Ainv[2]=(A[1]*A[5]-A[2]*A[4])/det; /* = (b*f-c*e)/det */
    452         Ainv[3]=(A[5]*A[6]-A[3]*A[8])/det; /* = (f*g-d*i)/det */
    453         Ainv[4]=(A[0]*A[8]-A[2]*A[6])/det; /* = (a*i-c*g)/det */
    454         Ainv[5]=(A[2]*A[3]-A[0]*A[5])/det; /* = (c*d-a*f)/det */
    455         Ainv[6]=(A[3]*A[7]-A[4]*A[6])/det; /* = (d*h-e*g)/det */
    456         Ainv[7]=(A[1]*A[6]-A[0]*A[7])/det; /* = (b*g-a*h)/det */
    457         Ainv[8]=(A[0]*A[4]-A[1]*A[3])/det; /* = (a*e-b*d)/det */
    458 
     471        Ainv[0]=(A[4]*A[8]-A[5]*A[7])*det_reciprocal; /* = (e*i-f*h)/det */
     472        Ainv[1]=(A[2]*A[7]-A[1]*A[8])*det_reciprocal; /* = (c*h-b*i)/det */
     473        Ainv[2]=(A[1]*A[5]-A[2]*A[4])*det_reciprocal; /* = (b*f-c*e)/det */
     474        Ainv[3]=(A[5]*A[6]-A[3]*A[8])*det_reciprocal; /* = (f*g-d*i)/det */
     475        Ainv[4]=(A[0]*A[8]-A[2]*A[6])*det_reciprocal; /* = (a*i-c*g)/det */
     476        Ainv[5]=(A[2]*A[3]-A[0]*A[5])*det_reciprocal; /* = (c*d-a*f)/det */
     477        Ainv[6]=(A[3]*A[7]-A[4]*A[6])*det_reciprocal; /* = (d*h-e*g)/det */
     478        Ainv[7]=(A[1]*A[6]-A[0]*A[7])*det_reciprocal; /* = (b*g-a*h)/det */
     479        Ainv[8]=(A[0]*A[4]-A[1]*A[3])*det_reciprocal; /* = (a*e-b*d)/det */
    459480}/*}}}*/
    460481void Matrix3x3Solve(IssmDouble* X,IssmDouble* A,IssmDouble* B){/*{{{*/
     
    543564        /*Intermediaries*/
    544565        IssmDouble det;
     566        IssmDouble det_reciprocal;
    545567
    546568        /*Compute determinant*/
     
    548570        //if(fabs(det) < DBL_EPSILON) _error_("Determinant smaller than machine epsilon");
    549571
     572        /*Multiplication is faster than division, so we multiply by the reciprocal*/
     573        det_reciprocal = 1/det;
     574
    550575        /*Compute adjoint matrix*/
    551576        Matrix4x4Adjoint(Ainv,A);
    552577
    553578        /*Scalte adjoint matrix to get inverse*/
    554         for(int i=0;i<4*4;i++) Ainv[i] = Ainv[i]/det;
     579        for(int i=0;i<4*4;i++) Ainv[i] = Ainv[i]*det_reciprocal;
    555580}/*}}}*/
    556581void Matrix4x4Solve(IssmDouble* X,IssmDouble* A,IssmDouble *B){/*{{{*/
Note: See TracChangeset for help on using the changeset viewer.