Changeset 24085
- Timestamp:
- May 6, 2009, 2:18:42 PM (17 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/math/psMatrix.c (modified) (16 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/math/psMatrix.c
r23983 r24085 199 199 /*****************************************************************************/ 200 200 201 psImage* psMatrixLUD (psImage* out,201 psImage* psMatrixLUDecomposition(psImage* out, 202 202 psVector** perm, 203 203 const psImage* in) … … 210 210 211 211 212 #define psMatrixLUD _EXIT {psFree(out); return NULL;}212 #define psMatrixLUDecomposition_EXIT {psFree(out); return NULL;} 213 213 214 214 // Error checks 215 PS_ASSERT_GENERAL_IMAGE_NON_NULL(in, psMatrixLUD _EXIT);216 PS_CHECK_POINTERS(in, out, psMatrixLUD _EXIT);217 PS_CHECK_DIMEN_AND_TYPE(in, PS_DIMEN_IMAGE, psMatrixLUD _EXIT);218 PS_ASSERT_GENERAL_PTR_NON_NULL(perm, psMatrixLUD _EXIT);215 PS_ASSERT_GENERAL_IMAGE_NON_NULL(in, psMatrixLUDecomposition_EXIT); 216 PS_CHECK_POINTERS(in, out, psMatrixLUDecomposition_EXIT); 217 PS_CHECK_DIMEN_AND_TYPE(in, PS_DIMEN_IMAGE, psMatrixLUDecomposition_EXIT); 218 PS_ASSERT_GENERAL_PTR_NON_NULL(perm, psMatrixLUDecomposition_EXIT); 219 219 220 220 out = psImageRecycle(out, in->numCols, in->numRows, in->type.type); 221 221 222 PS_CHECK_SQUARE(in, psMatrixLUD _EXIT); // gsl_linalg_LU_decomp would fail on non-square input.223 PS_CHECK_SQUARE(out, psMatrixLUD _EXIT);222 PS_CHECK_SQUARE(in, psMatrixLUDecomposition_EXIT); // gsl_linalg_LU_decomp would fail on non-square input. 223 PS_CHECK_SQUARE(out, psMatrixLUDecomposition_EXIT); 224 224 225 225 // Initialize data … … 237 237 "Failed to allocate the permutation vector; " 238 238 "could not determine the cooresponding data type."); 239 psMatrixLUD _EXIT;239 psMatrixLUDecomposition_EXIT; 240 240 } 241 241 … … 259 259 } 260 260 261 psVector* psMatrixLUSol ve(psVector* out,261 psVector* psMatrixLUSolution(psVector* out, 262 262 const psImage* LU, 263 263 const psVector* RHS, … … 316 316 } 317 317 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. 320 # if (0) 321 bool psMatrixGJSolve(psImage *a, 318 psImage *psMatrixLUInvert(psImage *out, 319 const psImage* LU, 320 const psVector* perm) 321 { 322 psS32 numRows = 0; 323 psS32 numCols = 0; 324 gsl_matrix *lu, *inverse; 325 gsl_permutation permGSL; 326 327 #define LUSOLVE_CLEANUP {psFree(out); return NULL;} 328 329 // Error checks 330 PS_ASSERT_GENERAL_IMAGE_NON_NULL(LU, LUSOLVE_CLEANUP); 331 PS_CHECK_DIMEN_AND_TYPE(LU, PS_DIMEN_IMAGE, LUSOLVE_CLEANUP); 332 PS_ASSERT_GENERAL_IMAGE_NON_EMPTY(LU, LUSOLVE_CLEANUP); 333 PS_ASSERT_GENERAL_VECTOR_NON_NULL(perm, LUSOLVE_CLEANUP); 334 335 out = psImageRecycle(out, LU->numCols, LU->numRows, LU->type.type); 336 337 // Initialize data 338 numRows = LU->numRows; 339 numCols = LU->numCols; 340 341 // Initialize GSL data 342 lu = gsl_matrix_alloc(numRows, numCols); 343 psImageToGslMatrix(lu, LU); 344 345 permGSL.size = perm->n; 346 permGSL.data = (psPtr)(perm->data.U8); 347 348 inverse = gsl_matrix_alloc(numRows, numCols); 349 350 // Solve for {x} in equation: {b} = [A]{x} 351 gsl_linalg_LU_invert(lu, &permGSL, inverse); 352 353 // Copy GSL vector data to psVector data 354 gslMatrixToPsImage(out, inverse); 355 356 // Free GSL data 357 gsl_matrix_free(lu); 358 gsl_matrix_free(inverse); 359 360 return out; 361 } 362 363 // This is the LU Decomposition version of the matrix equation solver. It solves the equation 364 // Ax = B, where A is a square matrix (NxN) and B is a vector of length N. This solver only 365 // yields the solution for x, which is returned to the vector B. This now DOES calculate the 366 // inverse of A. A and B may be F32 or F64 XXX can they differ? 367 bool psMatrixLUSolve(psImage *a, 322 368 psVector *b 323 369 ) … … 370 416 // Decompose the matrix and solve 371 417 psVector *perm = NULL; // Permutation vector 372 psImage *lu = psMatrixLUD (NULL, &perm, a); // LU decomposed matrix418 psImage *lu = psMatrixLUDecomposition(NULL, &perm, a); // LU decomposed matrix 373 419 if (!lu) { 374 420 psError(PS_ERR_UNKNOWN, false, "Unable to generate LU decomposed matrix"); … … 376 422 return false; 377 423 } 378 psVector *ans = psMatrixLUSolve(NULL, lu, b, perm); // Answer 424 psVector *ans = psMatrixLUSolution(NULL, lu, b, perm); // Answer 425 426 // invert the matrix : check here for an ill-conditioned matrix? 427 psMatrixLUInvert (a, lu, perm); 428 379 429 psFree(lu); 380 430 psFree(perm); … … 390 440 } 391 441 392 # else 393 394 // Gauss-Jordan elimination using full pivots based on Press et al's description. Substantially 395 // reworked for psLib style: major modifications to conform to C indexing, use a boolean to track the 396 // completed pivot rows and catch the singular matrix early on. Also, much cleaner control loops 397 // than their implementation. XXX this really needs to check on round-off errors (see version by 398 // William Kahan 442 // This is the Gauss-Jordan elimination version of the matrix equation solver. It solves the 443 // equation Ax = B, where A is a square matrix (NxN) and B is a vector of length N. This 444 // solver calculates both the solution for x, which is returned to the vector B and the inverse 445 // of A (returned in A). A and B may be F32 or F64, but must match. 446 447 // Gauss-Jordan elimination using full pivots based on William Kahan's BASIC example and Press 448 // et al's description. Substantially reworked for psLib style: major modifications to conform 449 // to C indexing, use a boolean to track the completed pivot rows and catch the singular matrix 450 // early on. Also, much cleaner control loops than the Press implementation. 451 452 // (based on version by William Kahan -- see Ohana/src/libohana/doc/kahan-gji.pdf) 453 454 # define MAX_RANGE 1.0e7 455 // MAX_RANGE is used to test for ill-conditioned input matrices. For an ill-conditioned 456 // matrix, one or more of the pivots trends towards zero, and growth goes to infinity. Rather 457 // than allow this to go to the numerical precision, I am raising an error if |growth| > MAX_RANGE 399 458 bool psMatrixGJSolve(psImage *a, 400 459 psVector *b … … 439 498 } 440 499 441 // Following the algorithm laid out by Press et al., we loop along the matrix diagonal, 442 // but we do not operate on the diagonal elements in order instead, we are looking for443 // the current max element and operating on that diagonal element. this is effectively444 // column pivoting. row pivoting is perfomed explicitly.500 // Following the algorithm laid out by Press et al., we loop along the matrix diagonal, but 501 // we do not operate on the diagonal elements in order. Instead, we are looking for the 502 // current max element and operating on that diagonal element. This is effectively column 503 // pivoting. Row pivoting is perfomed explicitly. 445 504 446 505 int nSquare = a->numCols; … … 457 516 int *rowIndex = rowIndexV->data.S32; 458 517 int *pivot = pivotV->data.S32; 518 psF32 growth = 1.0; 459 519 460 520 for (int diag = 0; diag < nSquare; diag++) { … … 493 553 colIndex[diag] = maxcol; 494 554 if (A[maxcol][maxcol] == 0.0) goto escape; 495 // XXX Kahan replaces the 0.0 pivot with epsilon*(largest element in column) + underFlow 555 // Kahan replaces the 0.0 pivot with epsilon*(largest element in column) + underFlow. 556 // Here we are going to raise an error if the dynamic range is too large. 496 557 497 558 /* rescale by pivot reciprocal */ … … 500 561 for (int col = 0; col < nSquare; col++) A[maxcol][col] *= tmpval; 501 562 B[maxcol] *= tmpval; 502 // XXX measure the pivot growth and trigger on over/under flow 503 // growth *= tmpval; 504 // fprintf (stderr, "column: %d, growth: %e, epsilon: %e\n", maxcol, growth, epsilon); 563 564 // check for ill-conditioned matrix: measure the pivot growth and trigger on over/under flow 565 growth *= tmpval; 566 psTrace ("psLib.math", 4, "growth : %e\n", growth); 567 if (fabs(growth) > MAX_RANGE) goto escape; 505 568 506 569 /* adjust the elements above the pivot */ … … 526 589 int *rowIndex = rowIndexV->data.S32; 527 590 int *pivot = pivotV->data.S32; 591 psF64 growth = 1.0; 528 592 529 593 for (int diag = 0; diag < nSquare; diag++) { … … 562 626 colIndex[diag] = maxcol; 563 627 if (A[maxcol][maxcol] == 0.0) goto escape; 564 // XXX Kahan replaces the 0.0 pivot with epsilon*(largest element in column) + underFlow 628 // Kahan replaces the 0.0 pivot with epsilon*(largest element in column) + underFlow. 629 // Here we are going to raise an error if the dynamic range is too large. 565 630 566 631 /* rescale by pivot reciprocal */ … … 569 634 for (int col = 0; col < nSquare; col++) A[maxcol][col] *= tmpval; 570 635 B[maxcol] *= tmpval; 571 // XXX measure the pivot growth and trigger on over/under flow 572 // growth *= tmpval; 573 // fprintf (stderr, "column: %d, growth: %e, epsilon: %e\n", maxcol, growth, epsilon); 636 637 // check for ill-conditioned matrix: measure the pivot growth and trigger on over/under flow 638 growth *= tmpval; 639 psTrace ("psLib.math", 4, "growth : %e\n", growth); 640 if (fabs(growth) > MAX_RANGE) goto escape; 574 641 575 642 /* adjust the elements above the pivot */ … … 602 669 return false; 603 670 } 604 605 # endif606 671 607 672 psImage* psMatrixInvert(psImage* out,
Note:
See TracChangeset
for help on using the changeset viewer.
