Changeset 12337
- Timestamp:
- Mar 8, 2007, 1:21:39 PM (19 years ago)
- File:
-
- 1 edited
-
branches/rel-1_0/psLib/src/math/psMatrix.c (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/rel-1_0/psLib/src/math/psMatrix.c
r12313 r12337 22 22 * @author Andy Becker, University of Washington (SVD). 23 23 * 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 $ 26 26 * 27 27 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 41 41 #include <gsl/gsl_permutation.h> 42 42 #include <gsl/gsl_eigen.h> 43 #include <gsl/gsl_math.h> 43 44 44 45 #include "psMemory.h" … … 322 323 PS_ASSERT_VECTOR_TYPE(b, PS_TYPE_F64, false); 323 324 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 324 397 int Nx = a->numCols; 325 398 PS_ASSERT_VECTOR_SIZE(b, (long int)Nx, false); … … 327 400 psF64 *vector = b->data.F64; 328 401 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 483 fescape: 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 493 bool 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; 329 507 int *indxc = psAlloc(Nx*sizeof(int)); 330 508 int *indxr = psAlloc(Nx*sizeof(int)); … … 414 592 } 415 593 416 // This is a temporary gauss-jordan solver based on gene's417 // version based on the Numerical Recipes version418 bool psMatrixGJSolveF32(psImage *a,419 psVector *b420 )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 519 594 psImage* psMatrixInvert(psImage* out, 520 595 const psImage* in,
Note:
See TracChangeset
for help on using the changeset viewer.
