IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 15820


Ignore:
Timestamp:
Dec 13, 2007, 2:41:17 PM (18 years ago)
Author:
Paul Price
Message:

Removing Numerical Recipes code that was noted to be 'temporary': replaced the Gauss-Jordan solver with our LU Decomposition solver, since I couldn't find a GPL Gauss-Jordan solver code (none in GSL). NR says that the LU solver operation count is a factor of 3 better than GJ (p48 of NR ed 2), but we could be slowed down by converting to GSL vector/matrix representation; this could be sped up by doing something other than copying the elements individually that MHPCC originally implemented.

Location:
trunk/psLib/src/math
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/math/psMatrix.c

    r15785 r15820  
    2222 *  @author Andy Becker, University of Washington (SVD).
    2323 *
    24  *  @version $Revision: 1.52 $ $Name: not supported by cvs2svn $
    25  *  @date $Date: 2007-12-11 22:10:13 $
     24 *  @version $Revision: 1.53 $ $Name: not supported by cvs2svn $
     25 *  @date $Date: 2007-12-14 00:41:17 $
    2626 *
    2727 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
    2828 */
     29
     30// XXX Future optimisation: use GSL type appropriate to the psLib type, and use memcpy instead of copying each
     31// value individually.
     32
    2933
    3034#ifdef HAVE_CONFIG_H
     
    312316}
    313317
    314 // This is a temporary gauss-jordan solver based on gene's
    315 // version based on the Numerical Recipes version
     318// This used to be "a temporary gauss-jordan solver based on gene's version based on the Numerical Recipes
     319// version".  However, it's been removed due to copyright, and replaced with LU Decomposition solving.
    316320bool psMatrixGJSolve(psImage *a,
    317321                     psVector *b
     
    320324    PS_ASSERT_IMAGE_NON_NULL(a, false);
    321325    PS_ASSERT_VECTOR_NON_NULL(b, false);
    322     PS_ASSERT_IMAGE_TYPE(a, PS_TYPE_F64, false);
    323     PS_ASSERT_VECTOR_TYPE(b, PS_TYPE_F64, false);
     326    PS_ASSERT_IMAGE_TYPE_F32_OR_F64(a, false);
     327    PS_ASSERT_VECTOR_TYPE_F32_OR_F64(b, false);
    324328    PS_ASSERT_INT_EQUAL(a->numCols, a->numRows, false);
    325     int Nx = a->numCols;
    326     PS_ASSERT_VECTOR_SIZE(b, (long int)Nx, false);
    327 
    328     psF64 *vector = b->data.F64;
    329     psF64 **matrix = a->data.F64;
    330     int *indxc = psAlloc(Nx*sizeof(int));
    331     int *indxr = psAlloc(Nx*sizeof(int));
    332     int *ipiv  = psAlloc(Nx*sizeof(int));
    333     memset(ipiv, 0, Nx*sizeof(int));
    334 
    335     int irow = 0;
    336     int icol = 0;
    337 
    338     for (int i = 0; i < Nx; i++) {
    339         double big = 0.0;
    340         for (int j = 0; j < Nx; j++) {
    341             if (!isfinite(matrix[i][j])) {
    342                 psError(PS_ERR_BAD_PARAMETER_VALUE, 3,
    343                         "Input matrix contains non-finite elements: matrix[%d][%d] is %.2f\n",
    344                         i, j, matrix[i][j]);
    345                 goto fescape;
    346             }
    347             if (ipiv[j] != 1) {
    348                 for (int k = 0; k < Nx; k++) {
    349                     if (ipiv[k] == 0) {
    350                         if (fabs(matrix[j][k]) >= big) {
    351                             big  = fabs(matrix[j][k]);
    352                             irow = j;
    353                             icol = k;
    354                         }
    355                     } else {
    356                         if (ipiv[k] > 1) {
    357                             // psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Singular Matrix (1).\n");
    358                             psTrace("psLib.math", 4, "Singular Matrix (1).\n");
    359                             goto fescape;
    360                         }
    361                     }
    362                 }
    363             }
    364         }
    365         ipiv[icol]++;
    366         if (irow != icol) {
    367             for (int l = 0; l < Nx; l++) {
    368                 PS_SWAP(matrix[irow][l], matrix[icol][l]);
    369             }
    370             PS_SWAP(vector[irow], vector[icol]);
    371         }
    372         indxr[i] = irow;
    373         indxc[i] = icol;
    374         if (matrix[icol][icol] == 0.0) {
    375             // psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Singular Matrix (2).\n");
    376             psTrace (__func__, 4, "Singular Matrix (2).\n");
    377             goto fescape;
    378         }
    379         double pivinv = 1.0 / matrix[icol][icol];
    380         matrix[icol][icol] = 1.0;
    381         for (int l = 0; l < Nx; l++) {
    382             matrix[icol][l] *= pivinv;
    383         }
    384         vector[icol] *= pivinv;
    385 
    386         for (int ll = 0; ll < Nx; ll++) {
    387             if (ll != icol) {
    388                 double dum = matrix[ll][icol];
    389                 matrix[ll][icol] = 0.0;
    390                 for (int l = 0; l < Nx; l++) {
    391                     matrix[ll][l] -= matrix[icol][l]*dum;
    392                 }
    393                 vector[ll] -= vector[icol]*dum;
    394             }
    395         }
    396     }
    397 
    398     for (int l = Nx - 1; l >= 0; l--) {
    399         if (indxr[l] != indxc[l]) {
    400             for (int k = 0; k < Nx; k++) {
    401                 PS_SWAP(matrix[k][indxr[l]], matrix[k][indxc[l]]);
    402             }
    403         }
    404     }
    405     psFree(ipiv);
    406     psFree(indxr);
    407     psFree(indxc);
     329    PS_ASSERT_VECTOR_SIZE(b, (long int)a->numCols, false);
     330
     331    // Check for non-finite entries
     332#define MATRIX_CHECK_NONFINITE_CASE(TYPE,MATRIX) \
     333  case PS_TYPE_##TYPE: { \
     334      ps##TYPE **values = MATRIX->data.TYPE; /* Dereference */ \
     335      int numCols = (MATRIX)->numCols, numRows = (MATRIX)->numRows; /* Size of matrix */ \
     336      for (int i = 0; i < numRows; i++) { \
     337          for (int j = 0; j < numCols; j++) { \
     338              if (!isfinite(values[i][j])) { \
     339                  psError(PS_ERR_BAD_PARAMETER_VALUE, 3, \
     340                          "Input matrix contains non-finite elements: matrix[%d][%d] is %.2f\n", \
     341                          i, j, values[i][j]); \
     342                  return false; \
     343              } \
     344          } \
     345      } \
     346  }
     347
     348    // Check for non-finite entries in matrix
     349    switch (a->type.type) {
     350        MATRIX_CHECK_NONFINITE_CASE(F32, a);
     351        MATRIX_CHECK_NONFINITE_CASE(F64, a);
     352      default:
     353        psAbort("Should never get here.");
     354    }
     355
     356    // Decompose the matrix and solve
     357    psVector *perm = NULL;              // Permutation vector
     358    psImage *lu = psMatrixLUD(NULL, &perm, a); // LU decomposed matrix
     359    if (!lu) {
     360        psError(PS_ERR_UNKNOWN, false, "Unable to generate LU decomposed matrix");
     361        psFree(perm);
     362        return false;
     363    }
     364    b = psMatrixLUSolve(b, lu, b, perm);
     365    psFree(lu);
     366    psFree(perm);
     367    if (!b) {
     368        psError(PS_ERR_UNKNOWN, false, "Unable to solve matrix equation.");
     369        return false;
     370    }
     371
    408372    return true;
    409 
    410 fescape:
    411     psFree(ipiv);
    412     psFree(indxr);
    413     psFree(indxc);
    414     return false;
    415 }
    416 
    417 // This is a temporary gauss-jordan solver based on gene's
    418 // version based on the Numerical Recipes version
    419 bool psMatrixGJSolveF32(psImage *a,
    420                         psVector *b
    421                        )
    422 {
    423     PS_ASSERT_IMAGE_NON_NULL(a, false);
    424     PS_ASSERT_VECTOR_NON_NULL(b, false);
    425     PS_ASSERT_IMAGE_TYPE(a, PS_TYPE_F32, false);
    426     PS_ASSERT_VECTOR_TYPE(b, PS_TYPE_F32, false);
    427     PS_ASSERT_INT_EQUAL(a->numCols, a->numRows, false);
    428     int Nx = a->numCols;
    429     PS_ASSERT_VECTOR_SIZE(b, (long int)Nx, false);
    430 
    431     psF32 *vector = b->data.F32;
    432     psF32 **matrix = a->data.F32;
    433     int *indxc = psAlloc(Nx*sizeof(int));
    434     int *indxr = psAlloc(Nx*sizeof(int));
    435     int *ipiv  = psAlloc(Nx*sizeof(int));
    436     memset(ipiv, 0, Nx*sizeof(int));
    437 
    438     int irow = 0;
    439     int icol = 0;
    440 
    441     for (int i = 0; i < Nx; i++) {
    442         double big = 0.0;
    443         for (int j = 0; j < Nx; j++) {
    444             if (!isfinite(matrix[i][j])) {
    445                 psError(PS_ERR_BAD_PARAMETER_VALUE, 3,
    446                         "Input matrix contains non-finite elements: matrix[%d][%d] is %.2f\n",
    447                         i, j, matrix[i][j]);
    448                 goto fescape;
    449             }
    450             if (ipiv[j] != 1) {
    451                 for (int k = 0; k < Nx; k++) {
    452                     if (ipiv[k] == 0) {
    453                         if (fabs(matrix[j][k]) >= big) {
    454                             big  = fabs(matrix[j][k]);
    455                             irow = j;
    456                             icol = k;
    457                         }
    458                     } else {
    459                         if (ipiv[k] > 1) {
    460                             // psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Singular Matrix (1).\n");
    461                             psTrace("psLib.math", 4, "Singular Matrix (1).\n");
    462                             goto fescape;
    463                         }
    464                     }
    465                 }
    466             }
    467         }
    468         ipiv[icol]++;
    469         if (irow != icol) {
    470             for (int l = 0; l < Nx; l++) {
    471                 PS_SWAP(matrix[irow][l], matrix[icol][l]);
    472             }
    473             PS_SWAP(vector[irow], vector[icol]);
    474         }
    475         indxr[i] = irow;
    476         indxc[i] = icol;
    477         if (matrix[icol][icol] == 0.0) {
    478             // psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Singular Matrix (2).\n");
    479             psTrace (__func__, 4, "Singular Matrix (2).\n");
    480             goto fescape;
    481         }
    482         double pivinv = 1.0 / matrix[icol][icol];
    483         matrix[icol][icol] = 1.0;
    484         for (int l = 0; l < Nx; l++) {
    485             matrix[icol][l] *= pivinv;
    486         }
    487         vector[icol] *= pivinv;
    488 
    489         for (int ll = 0; ll < Nx; ll++) {
    490             if (ll != icol) {
    491                 double dum = matrix[ll][icol];
    492                 matrix[ll][icol] = 0.0;
    493                 for (int l = 0; l < Nx; l++) {
    494                     matrix[ll][l] -= matrix[icol][l]*dum;
    495                 }
    496                 vector[ll] -= vector[icol]*dum;
    497             }
    498         }
    499     }
    500 
    501     for (int l = Nx - 1; l >= 0; l--) {
    502         if (indxr[l] != indxc[l]) {
    503             for (int k = 0; k < Nx; k++) {
    504                 PS_SWAP(matrix[k][indxr[l]], matrix[k][indxc[l]]);
    505             }
    506         }
    507     }
    508     psFree(ipiv);
    509     psFree(indxr);
    510     psFree(indxc);
    511     return true;
    512 
    513 fescape:
    514     psFree(ipiv);
    515     psFree(indxr);
    516     psFree(indxc);
    517     return false;
    518 }
     373}
     374
    519375
    520376psImage* psMatrixInvert(psImage* out,
  • trunk/psLib/src/math/psMatrix.h

    r12292 r15820  
    1919 * @author Ross Harman, MHPCC
    2020 *
    21  * @version $Revision: 1.27 $ $Name: not supported by cvs2svn $
    22  * @date $Date: 2007-03-07 20:48:55 $
     21 * @version $Revision: 1.28 $ $Name: not supported by cvs2svn $
     22 * @date $Date: 2007-12-14 00:41:17 $
    2323 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
    2424 */
     
    6161);
    6262
    63 /** Gauss-Jordan numerical solver.
     63/** Used to be a Gauss-Jordan numerical solver, but now uses LU decomposition.
    6464 *
    6565 *  @return bool:   True if successful.
     
    7070);
    7171
    72 /** Gauss-Jordan numerical solver for F32 input data
    73  *
    74  *  @return bool:   True if successful.
    75  */
    76 bool psMatrixGJSolveF32(
    77     psImage *A,                   ///< Matrix to be solved
    78     psVector *b                   ///< Vector of values
    79 );
     72/** Gauss-Jordan numerical solver for F32 input data */
     73#define psMatrixGJSolveF32(A,B) psMatrixGJSolve(A,B)
     74
    8075
    8176/** Invert psImage matrix.
Note: See TracChangeset for help on using the changeset viewer.