IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Changeset 12337


Ignore:
Timestamp:
Mar 8, 2007, 1:21:39 PM (19 years ago)
Author:
rhl
Message:

Use GSL LU decomposition for psMatrixGJSolve

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/rel-1_0/psLib/src/math/psMatrix.c

    r12313 r12337  
    2222 *  @author Andy Becker, University of Washington (SVD).
    2323 *
    24  *  @version $Revision: 1.47.2.1 $ $Name: not supported by cvs2svn $
    25  *  @date $Date: 2007-03-08 13:15:49 $
     24 *  @version $Revision: 1.47.2.2 $ $Name: not supported by cvs2svn $
     25 *  @date $Date: 2007-03-08 23:21:39 $
    2626 *
    2727 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
     
    4141#include <gsl/gsl_permutation.h>
    4242#include <gsl/gsl_eigen.h>
     43#include <gsl/gsl_math.h>
    4344
    4445#include "psMemory.h"
     
    322323    PS_ASSERT_VECTOR_TYPE(b, PS_TYPE_F64, false);
    323324    PS_ASSERT_INT_EQUAL(a->numCols, a->numRows, false);
     325#if 1                                   // Use a more robust LU decomposition from GSL
     326    // Initialize GSL data from a and b
     327    gsl_matrix *a_gsl = gsl_matrix_alloc(a->numRows, a->numCols);
     328    psImageToGslMatrix(a_gsl, a);
     329    gsl_vector *b_gsl = gsl_vector_alloc(b->n);
     330    psVectorToGslVector(b_gsl, b);
     331   
     332    gsl_permutation *perm_gsl = gsl_permutation_alloc(b->n);
     333
     334    // Solve for {x} in equation: {b} = [A]{x}
     335    int signum = 0;
     336    if (gsl_linalg_LU_decomp(a_gsl, perm_gsl, &signum) != 0) {
     337        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Singular Matrix.\n");
     338        psTrace("psLib.math", 4, "LU decomposition failed.\n");
     339
     340        gsl_matrix_free(a_gsl);
     341        gsl_vector_free(b_gsl);
     342        gsl_permutation_free(perm_gsl);
     343
     344        return false;
     345    }
     346
     347    gsl_vector *x_gsl = gsl_vector_alloc(b->n);
     348    int solver_failed = gsl_linalg_LU_solve(a_gsl, perm_gsl, b_gsl, x_gsl);
     349
     350    for (int i = 0; i < b->n && !solver_failed; i++) { // gsl_linalg_LU_solve doesn't always catch errors
     351        if (!gsl_finite(b_gsl->data[i])) {
     352            solver_failed = 1;
     353        }
     354    }
     355   
     356    if (solver_failed != 0) {
     357        psError(PS_ERR_BAD_PARAMETER_VALUE, true, "LU solver failed.\n");
     358        psTrace("psLib.math", 4, "LU solver failed.\n");
     359
     360        gsl_matrix_free(a_gsl);
     361        gsl_vector_free(x_gsl);
     362        gsl_vector_free(b_gsl);
     363        gsl_permutation_free (perm_gsl);
     364
     365        return false;
     366    }
     367   
     368    gslVectorToPsVector(b, x_gsl);      // copy answer back to b
     369    gsl_vector_free(b_gsl);
     370    gsl_vector_free(x_gsl);
     371
     372    // Invert A as we may want to use it for a covariance
     373    gsl_matrix *ia_gsl = gsl_matrix_alloc(a->numRows, a->numCols); // inverse matrix if it exists
     374    if (a->numRows == a->numCols) {
     375        if (gsl_linalg_LU_invert(a_gsl, perm_gsl, ia_gsl) != 0) {
     376            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Singular Matrix.\n");
     377            psTrace("psLib.math", 4, "Singular Matrix (1).\n");
     378           
     379            gsl_matrix_free(a_gsl);
     380            gsl_matrix_free(ia_gsl);
     381            gsl_permutation_free (perm_gsl);
     382           
     383            return false;
     384        }
     385       
     386        // Copy a^{-1} back to a
     387        gslMatrixToPsImage(a, ia_gsl);
     388    }
     389
     390    // Free GSL data
     391    gsl_matrix_free(a_gsl);
     392    gsl_matrix_free(ia_gsl);
     393    gsl_permutation_free (perm_gsl);
     394
     395    return true;
     396#else
    324397    int Nx = a->numCols;
    325398    PS_ASSERT_VECTOR_SIZE(b, (long int)Nx, false);
     
    327400    psF64 *vector = b->data.F64;
    328401    psF64 **matrix = a->data.F64;
     402
     403    int *indxc = psAlloc(Nx*sizeof(int));
     404    int *indxr = psAlloc(Nx*sizeof(int));
     405    int *ipiv  = psAlloc(Nx*sizeof(int));
     406    memset(ipiv, 0, Nx*sizeof(int));
     407
     408    int irow = 0;
     409    int icol = 0;
     410
     411    for (int i = 0; i < Nx; i++) {
     412        double big = 0.0;
     413        for (int j = 0; j < Nx; j++) {
     414            if (!isfinite(matrix[i][j])) {
     415                psError(PS_ERR_BAD_PARAMETER_VALUE, 3,
     416                        "Input matrix contains non-finite elements: matrix[%d][%d] is %.2f\n",
     417                        i, j, matrix[i][j]);
     418                goto fescape;
     419            }
     420            if (ipiv[j] != 1) {
     421                for (int k = 0; k < Nx; k++) {
     422                    if (ipiv[k] == 0) {
     423                        if (fabs(matrix[j][k]) >= big) {
     424                            big  = fabs(matrix[j][k]);
     425                            irow = j;
     426                            icol = k;
     427                        }
     428                    } else {
     429                        if (ipiv[k] > 1) {
     430                            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Singular Matrix (1).\n");
     431                            psTrace("psLib.math", 4, "Singular Matrix (1).\n");
     432                            goto fescape;
     433                        }
     434                    }
     435                }
     436            }
     437        }
     438        ipiv[icol]++;
     439        if (irow != icol) {
     440            for (int l = 0; l < Nx; l++) {
     441                PS_SWAP(matrix[irow][l], matrix[icol][l]);
     442            }
     443            PS_SWAP(vector[irow], vector[icol]);
     444        }
     445        indxr[i] = irow;
     446        indxc[i] = icol;
     447        if (matrix[icol][icol] > -FLT_EPSILON && matrix[icol][icol] < FLT_EPSILON) {
     448            psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Singular Matrix (2).\n");
     449            psTrace (__func__, 4, "Singular Matrix (2).\n");
     450            goto fescape;
     451        }
     452        double pivinv = 1.0 / matrix[icol][icol];
     453        matrix[icol][icol] = 1.0;
     454        for (int l = 0; l < Nx; l++) {
     455            matrix[icol][l] *= pivinv;
     456        }
     457        vector[icol] *= pivinv;
     458
     459        for (int ll = 0; ll < Nx; ll++) {
     460            if (ll != icol) {
     461                double dum = matrix[ll][icol];
     462                matrix[ll][icol] = 0.0;
     463                for (int l = 0; l < Nx; l++) {
     464                    matrix[ll][l] -= matrix[icol][l]*dum;
     465                }
     466                vector[ll] -= vector[icol]*dum;
     467            }
     468        }
     469    }
     470
     471    for (int l = Nx - 1; l >= 0; l--) {
     472        if (indxr[l] != indxc[l]) {
     473            for (int k = 0; k < Nx; k++) {
     474                PS_SWAP(matrix[k][indxr[l]], matrix[k][indxc[l]]);
     475            }
     476        }
     477    }
     478    psFree(ipiv);
     479    psFree(indxr);
     480    psFree(indxc);
     481    return true;
     482
     483fescape:
     484    psFree(ipiv);
     485    psFree(indxr);
     486    psFree(indxc);
     487    return false;
     488#endif
     489}
     490
     491// This is a temporary gauss-jordan solver based on gene's
     492// version based on the Numerical Recipes version
     493bool psMatrixGJSolveF32(psImage *a,
     494                        psVector *b
     495                       )
     496{
     497    PS_ASSERT_IMAGE_NON_NULL(a, false);
     498    PS_ASSERT_VECTOR_NON_NULL(b, false);
     499    PS_ASSERT_IMAGE_TYPE(a, PS_TYPE_F32, false);
     500    PS_ASSERT_VECTOR_TYPE(b, PS_TYPE_F32, false);
     501    PS_ASSERT_INT_EQUAL(a->numCols, a->numRows, false);
     502    int Nx = a->numCols;
     503    PS_ASSERT_VECTOR_SIZE(b, (long int)Nx, false);
     504
     505    psF32 *vector = b->data.F32;
     506    psF32 **matrix = a->data.F32;
    329507    int *indxc = psAlloc(Nx*sizeof(int));
    330508    int *indxr = psAlloc(Nx*sizeof(int));
     
    414592}
    415593
    416 // This is a temporary gauss-jordan solver based on gene's
    417 // version based on the Numerical Recipes version
    418 bool psMatrixGJSolveF32(psImage *a,
    419                         psVector *b
    420                        )
    421 {
    422     PS_ASSERT_IMAGE_NON_NULL(a, false);
    423     PS_ASSERT_VECTOR_NON_NULL(b, false);
    424     PS_ASSERT_IMAGE_TYPE(a, PS_TYPE_F32, false);
    425     PS_ASSERT_VECTOR_TYPE(b, PS_TYPE_F32, false);
    426     PS_ASSERT_INT_EQUAL(a->numCols, a->numRows, false);
    427     int Nx = a->numCols;
    428     PS_ASSERT_VECTOR_SIZE(b, (long int)Nx, false);
    429 
    430     psF32 *vector = b->data.F32;
    431     psF32 **matrix = a->data.F32;
    432     int *indxc = psAlloc(Nx*sizeof(int));
    433     int *indxr = psAlloc(Nx*sizeof(int));
    434     int *ipiv  = psAlloc(Nx*sizeof(int));
    435     memset(ipiv, 0, Nx*sizeof(int));
    436 
    437     int irow = 0;
    438     int icol = 0;
    439 
    440     for (int i = 0; i < Nx; i++) {
    441         double big = 0.0;
    442         for (int j = 0; j < Nx; j++) {
    443             if (!isfinite(matrix[i][j])) {
    444                 psError(PS_ERR_BAD_PARAMETER_VALUE, 3,
    445                         "Input matrix contains non-finite elements: matrix[%d][%d] is %.2f\n",
    446                         i, j, matrix[i][j]);
    447                 goto fescape;
    448             }
    449             if (ipiv[j] != 1) {
    450                 for (int k = 0; k < Nx; k++) {
    451                     if (ipiv[k] == 0) {
    452                         if (fabs(matrix[j][k]) >= big) {
    453                             big  = fabs(matrix[j][k]);
    454                             irow = j;
    455                             icol = k;
    456                         }
    457                     } else {
    458                         if (ipiv[k] > 1) {
    459                             // psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Singular Matrix (1).\n");
    460                             psTrace("psLib.math", 4, "Singular Matrix (1).\n");
    461                             goto fescape;
    462                         }
    463                     }
    464                 }
    465             }
    466         }
    467         ipiv[icol]++;
    468         if (irow != icol) {
    469             for (int l = 0; l < Nx; l++) {
    470                 PS_SWAP(matrix[irow][l], matrix[icol][l]);
    471             }
    472             PS_SWAP(vector[irow], vector[icol]);
    473         }
    474         indxr[i] = irow;
    475         indxc[i] = icol;
    476         if (matrix[icol][icol] == 0.0) {
    477             // psError(PS_ERR_BAD_PARAMETER_VALUE, true, "Singular Matrix (2).\n");
    478             psTrace (__func__, 4, "Singular Matrix (2).\n");
    479             goto fescape;
    480         }
    481         double pivinv = 1.0 / matrix[icol][icol];
    482         matrix[icol][icol] = 1.0;
    483         for (int l = 0; l < Nx; l++) {
    484             matrix[icol][l] *= pivinv;
    485         }
    486         vector[icol] *= pivinv;
    487 
    488         for (int ll = 0; ll < Nx; ll++) {
    489             if (ll != icol) {
    490                 double dum = matrix[ll][icol];
    491                 matrix[ll][icol] = 0.0;
    492                 for (int l = 0; l < Nx; l++) {
    493                     matrix[ll][l] -= matrix[icol][l]*dum;
    494                 }
    495                 vector[ll] -= vector[icol]*dum;
    496             }
    497         }
    498     }
    499 
    500     for (int l = Nx - 1; l >= 0; l--) {
    501         if (indxr[l] != indxc[l]) {
    502             for (int k = 0; k < Nx; k++) {
    503                 PS_SWAP(matrix[k][indxr[l]], matrix[k][indxc[l]]);
    504             }
    505         }
    506     }
    507     psFree(ipiv);
    508     psFree(indxr);
    509     psFree(indxc);
    510     return true;
    511 
    512 fescape:
    513     psFree(ipiv);
    514     psFree(indxr);
    515     psFree(indxc);
    516     return false;
    517 }
    518 
    519594psImage* psMatrixInvert(psImage* out,
    520595                        const psImage* in,
Note: See TracChangeset for help on using the changeset viewer.