Changeset 15820 for trunk/psLib/src/math/psMatrix.c
- Timestamp:
- Dec 13, 2007, 2:41:17 PM (18 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/math/psMatrix.c (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/math/psMatrix.c
r15785 r15820 22 22 * @author Andy Becker, University of Washington (SVD). 23 23 * 24 * @version $Revision: 1.5 2$ $Name: not supported by cvs2svn $25 * @date $Date: 2007-12-1 1 22:10:13$24 * @version $Revision: 1.53 $ $Name: not supported by cvs2svn $ 25 * @date $Date: 2007-12-14 00:41:17 $ 26 26 * 27 27 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii 28 28 */ 29 30 // XXX Future optimisation: use GSL type appropriate to the psLib type, and use memcpy instead of copying each 31 // value individually. 32 29 33 30 34 #ifdef HAVE_CONFIG_H … … 312 316 } 313 317 314 // This is a temporary gauss-jordan solver based on gene's315 // version based on the Numerical Recipes version318 // 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. 316 320 bool psMatrixGJSolve(psImage *a, 317 321 psVector *b … … 320 324 PS_ASSERT_IMAGE_NON_NULL(a, false); 321 325 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); 324 328 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 408 372 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 519 375 520 376 psImage* psMatrixInvert(psImage* out,
Note:
See TracChangeset
for help on using the changeset viewer.
