Changeset 26001
- Timestamp:
- Nov 2, 2009, 10:59:20 AM (17 years ago)
- Location:
- trunk/psLib
- Files:
-
- 3 edited
-
. (modified) (1 prop)
-
src/math/psMatrix.c (modified) (19 diffs)
-
src/math/psMatrix.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib
-
Property svn:mergeinfo
set to (toggle deleted branches)
/branches/czw_branch/cleanup/psLib merged eligible /branches/eam_branches/20090522/psLib merged eligible /branches/eam_branches/20090715/psLib merged eligible /branches/eam_branches/20090820/psLib merged eligible /branches/pap/psLib merged eligible /branches/pap_mops/psLib 25137-25255
-
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/psLib/src/math/psMatrix.c
r24122 r26001 94 94 LHS_NAME.data = RHS_NAME; 95 95 96 97 /*****************************************************************************/ 98 /* FILE STATIC FUNCTIONS */ 99 /*****************************************************************************/ 100 101 static void psVectorToGslVector(gsl_vector *outGslVector, const psVector *inVector); 102 static void gslVectorToPsVector(psVector *outVector, gsl_vector *inGslVector); 103 static void psImageToGslMatrix(gsl_matrix *outGslMatrix, const psImage *inImage); 104 static void gslMatrixToPsImage(psImage *outImage, gsl_matrix *inGslMatrix); 96 //////////////////////////////////////////////////////////////////////////////// 97 // Conversion functions 98 //////////////////////////////////////////////////////////////////////////////// 99 100 // gsl_vector holds *doubles*, so we can directly copy F64, but need to convert F32 105 101 106 102 /** Static function to copy psF32 or psF64 vector data to a GSL vector */ 107 static void psVectorToGslVector(gsl_vector *outGslVector, 108 const psVector *inVector) 109 { 110 psU32 i = 0; 111 psU32 n = 0; 112 113 114 n = inVector->n; 115 for(i=0; i<n; i++) { 116 if(inVector->type.type == PS_TYPE_F32) { 117 outGslVector->data[i] = (psF64)inVector->data.F32[i]; 103 static void vectorPStoGSL(gsl_vector *out, const psVector *in) 104 { 105 psAssert(out->size == in->n, "Sizes don't match!"); 106 107 long n = in->n; // Size of input 108 switch (in->type.type) { 109 case PS_TYPE_F32: 110 for (long i = 0; i < n; i++) { 111 out->data[i] = in->data.F32[i]; 112 } 113 break; 114 case PS_TYPE_F64: 115 memcpy(out->data, in->data.F64, n * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 116 break; 117 default: 118 psAbort("Unsupported vector type: %x\n", in->type.type); 119 } 120 return; 121 } 122 123 /** Static function to copy GSL vector data to a psF32 or psF64 vector */ 124 static void vectorGSLtoPS(psVector *out, const gsl_vector *in) 125 { 126 psAssert(in->size == out->n, "Sizes don't match!"); 127 128 long n = out->n; // Size of output 129 switch (out->type.type) { 130 case PS_TYPE_F32: 131 for (long i = 0; i < n; i++) { 132 out->data.F32[i] = in->data[i]; 133 } 134 break; 135 case PS_TYPE_F64: 136 memcpy(out->data.F64, in->data, n * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 137 break; 138 default: 139 psAbort("Unsupported vector type: %x\n", out->type.type); 140 } 141 return; 142 } 143 144 145 /** Static function to copy psF32 or psF64 image data to a GSL matrix */ 146 static void matrixPStoGSL(gsl_matrix *out, const psImage *in) 147 { 148 psAssert(out->size1 == in->numRows && out->size2 == in->numCols, "Sizes don't match!"); 149 150 int numCols = in->numCols, numRows = in->numRows; // Size of matrix 151 switch (in->type.type) { 152 case PS_TYPE_F32: 153 for (int y = 0, i = 0; y < numRows; y++) { 154 for (int x = 0; x < numCols; x++, i++) { 155 out->data[i] = in->data.F32[y][x]; 156 } 157 } 158 break; 159 case PS_TYPE_F64: 160 if (in->parent|| out->tda != out->size1) { 161 for (int y = 0, i = 0; y < numRows; y++, i += numCols) { 162 memcpy(&out->data[i], in->data.F64[y], numCols * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 163 } 118 164 } else { 119 outGslVector->data[i] = inVector->data.F64[i]; 120 } 121 } 122 } 123 124 /** Static function to copy GSL vector data to a psF32 or psF64 vector */ 125 static void gslVectorToPsVector(psVector *outVector, 126 gsl_vector *inGslVector) 127 { 128 psU32 i = 0; 129 psU32 n = 0; 130 131 132 n = outVector->n; 133 for(i=0; i<n; i++) { 134 if(outVector->type.type == PS_TYPE_F32) { 135 outVector->data.F32[i] = (psF32)inGslVector->data[i]; 165 memcpy(out->data, in->p_rawDataBuffer, numCols * numRows * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 166 } 167 break; 168 default: 169 psAbort("Unsupported vector type: %x\n", in->type.type); 170 } 171 return; 172 } 173 174 /** Static function to copy GSL matrix data to a psF32 or psF64 image */ 175 static void matrixGSLtoPS(psImage *out, const gsl_matrix *in) 176 { 177 psAssert(in->size1 == out->numRows && in->size2 == out->numCols, "Sizes don't match!"); 178 179 int numCols = out->numCols, numRows = out->numRows; // Size of matrix 180 switch (out->type.type) { 181 case PS_TYPE_F32: 182 for (int y = 0, i = 0; y < numRows; y++) { 183 for (int x = 0; x < numCols; x++, i++) { 184 out->data.F32[y][x] = in->data[i]; 185 } 186 } 187 break; 188 case PS_TYPE_F64: 189 if (out->parent || in->tda != in->size1) { 190 for (int y = 0, i = 0; y < numRows; y++, i += numCols) { 191 memcpy(out->data.F64[y], &in->data[i], numCols * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 192 } 136 193 } else { 137 outVector->data.F64[i] = inGslVector->data[i]; 138 } 139 } 140 } 141 142 /** Static function to copy psF32 or psF64 image data to a GSL matrix */ 143 static void psImageToGslMatrix(gsl_matrix *outGslMatrix, 144 const psImage *inImage) 145 { 146 psU32 i = 0; 147 psU32 j = 0; 148 psU32 numRows = 0; 149 psU32 numCols = 0; 150 151 152 numRows = inImage->numRows; 153 numCols = inImage->numCols; 154 if(inImage->type.type == PS_TYPE_F32) { 155 for(i=0; i<numRows; i++) { 156 for(j=0; j<numCols; j++) { 157 outGslMatrix->data[i*numCols+j] = inImage->data.F32[i][j]; 158 } 159 } 160 } else { 161 for(i=0; i<numRows; i++) { 162 for(j=0; j<numCols; j++) { 163 outGslMatrix->data[i*numCols+j] = inImage->data.F64[i][j]; 164 } 165 } 166 } 167 } 168 169 /** Static function to copy GSL matrix data to a psF32 or psF64 image */ 170 static void gslMatrixToPsImage(psImage *outImage, 171 gsl_matrix *inGslMatrix) 172 { 173 psU32 i = 0; 174 psU32 j = 0; 175 psU32 numRows = 0; 176 psU32 numCols = 0; 177 178 179 numRows = outImage->numRows; 180 numCols = outImage->numCols; 181 if(outImage->type.type == PS_TYPE_F32) { 182 for(i=0; i<numRows; i++) { 183 for(j=0; j<numCols; j++) { 184 outImage->data.F32[i][j] = inGslMatrix->data[i*numCols+j]; 185 } 186 } 187 } else { 188 for(i=0; i<numRows; i++) { 189 for(j=0; j<numCols; j++) { 190 outImage->data.F64[i][j] = inGslMatrix->data[i*numCols+j]; 191 } 192 } 193 } 194 memcpy(out->p_rawDataBuffer, in->data, numCols * numRows * PSELEMTYPE_SIZEOF(PS_TYPE_F64)); 195 } 196 break; 197 default: 198 psAbort("Unsupported vector type: %x\n", out->type.type); 199 } 200 return; 194 201 } 195 202 … … 245 252 246 253 // Copy psImage data into GSL matrix data 247 psImageToGslMatrix(lu, in);254 matrixPStoGSL(lu, in); 248 255 249 256 // Calculate LU decomposition … … 251 258 252 259 // Copy GSL matrix data to psImage data 253 gslMatrixToPsImage(out, lu);260 matrixGSLtoPS(out, lu); 254 261 255 262 // Free GSL data … … 293 300 // Initialize GSL data 294 301 lu = gsl_matrix_alloc(numRows, numCols); 295 psImageToGslMatrix(lu, LU);302 matrixPStoGSL(lu, LU); 296 303 b = gsl_vector_alloc(RHS->n); 297 psVectorToGslVector(b, RHS);304 vectorPStoGSL(b, RHS); 298 305 x = gsl_vector_alloc(RHS->n); 299 306 … … 306 313 307 314 // Copy GSL vector data to psVector data 308 gslVectorToPsVector(out, x);315 vectorGSLtoPS(out, x); 309 316 310 317 // Free GSL data … … 341 348 // Initialize GSL data 342 349 lu = gsl_matrix_alloc(numRows, numCols); 343 psImageToGslMatrix(lu, LU);350 matrixPStoGSL(lu, LU); 344 351 345 352 permGSL.size = perm->n; … … 352 359 353 360 // Copy GSL vector data to psVector data 354 gslMatrixToPsImage(out, inverse);361 matrixGSLtoPS(out, inverse); 355 362 356 363 // Free GSL data … … 379 386 switch (a->type.type) { 380 387 case PS_TYPE_F32: { 381 psF32 **values = a->data.F32; /* Dereference */382 int numCols = a->numCols, numRows = a->numRows; /* Size of matrix */383 for (int i = 0; i < numRows; i++) {384 for (int j = 0; j < numCols; j++) {385 if (!isfinite(values[i][j])) {386 // psError(PS_ERR_BAD_PARAMETER_VALUE, 3,387 // "Input matrix contains non-finite elements: matrix[%d][%d] is %.2f\n",388 // i, j, values[i][j]);389 return false;390 }391 }392 }393 break;388 psF32 **values = a->data.F32; /* Dereference */ 389 int numCols = a->numCols, numRows = a->numRows; /* Size of matrix */ 390 for (int i = 0; i < numRows; i++) { 391 for (int j = 0; j < numCols; j++) { 392 if (!isfinite(values[i][j])) { 393 // psError(PS_ERR_BAD_PARAMETER_VALUE, 3, 394 // "Input matrix contains non-finite elements: matrix[%d][%d] is %.2f\n", 395 // i, j, values[i][j]); 396 return false; 397 } 398 } 399 } 400 break; 394 401 } 395 402 case PS_TYPE_F64: { 396 psF64 **values = a->data.F64; /* Dereference */397 int numCols = a->numCols, numRows = a->numRows; /* Size of matrix */398 for (int i = 0; i < numRows; i++) {399 for (int j = 0; j < numCols; j++) {400 if (!isfinite(values[i][j])) {401 // psError(PS_ERR_BAD_PARAMETER_VALUE, 3,402 // "Input matrix contains non-finite elements: matrix[%d][%d] is %.2f\n",403 // i, j, values[i][j]);404 return false;405 }406 }407 }408 break;403 psF64 **values = a->data.F64; /* Dereference */ 404 int numCols = a->numCols, numRows = a->numRows; /* Size of matrix */ 405 for (int i = 0; i < numRows; i++) { 406 for (int j = 0; j < numCols; j++) { 407 if (!isfinite(values[i][j])) { 408 // psError(PS_ERR_BAD_PARAMETER_VALUE, 3, 409 // "Input matrix contains non-finite elements: matrix[%d][%d] is %.2f\n", 410 // i, j, values[i][j]); 411 return false; 412 } 413 } 414 } 415 break; 409 416 } 410 // MATRIX_CHECK_NONFINITE_CASE(F32, a);411 // MATRIX_CHECK_NONFINITE_CASE(F64, a);417 // MATRIX_CHECK_NONFINITE_CASE(F32, a); 418 // MATRIX_CHECK_NONFINITE_CASE(F64, a); 412 419 default: 413 psAbort("Should never get here.");420 psAbort("Should never get here."); 414 421 } 415 422 … … 471 478 switch (a->type.type) { 472 479 case PS_TYPE_F32: { 473 psF32 **values = a->data.F32; /* Dereference */474 int numCols = a->numCols, numRows = a->numRows; /* Size of matrix */475 for (int i = 0; i < numRows; i++) {476 for (int j = 0; j < numCols; j++) {477 if (!isfinite(values[i][j])) {478 return false;479 }480 }481 }482 break;480 psF32 **values = a->data.F32; /* Dereference */ 481 int numCols = a->numCols, numRows = a->numRows; /* Size of matrix */ 482 for (int i = 0; i < numRows; i++) { 483 for (int j = 0; j < numCols; j++) { 484 if (!isfinite(values[i][j])) { 485 return false; 486 } 487 } 488 } 489 break; 483 490 } 484 491 case PS_TYPE_F64: { 485 psF64 **values = a->data.F64; /* Dereference */486 int numCols = a->numCols, numRows = a->numRows; /* Size of matrix */487 for (int i = 0; i < numRows; i++) {488 for (int j = 0; j < numCols; j++) {489 if (!isfinite(values[i][j])) {490 return false;491 }492 }493 }494 break;492 psF64 **values = a->data.F64; /* Dereference */ 493 int numCols = a->numCols, numRows = a->numRows; /* Size of matrix */ 494 for (int i = 0; i < numRows; i++) { 495 for (int j = 0; j < numCols; j++) { 496 if (!isfinite(values[i][j])) { 497 return false; 498 } 499 } 500 } 501 break; 495 502 } 496 503 default: 497 psAbort("Should never get here.");498 } 499 504 psAbort("Should never get here."); 505 } 506 500 507 // Following the algorithm laid out by Press et al., we loop along the matrix diagonal, but 501 508 // we do not operate on the diagonal elements in order. Instead, we are looking for the … … 511 518 512 519 if (a->type.type == PS_TYPE_F32) { 513 psF32 **A = a->data.F32;514 psF32 *B = b->data.F32;515 int *colIndex = colIndexV->data.S32;516 int *rowIndex = rowIndexV->data.S32;517 int *pivot = pivotV->data.S32;518 psF32 growth = 1.0;519 520 for (int diag = 0; diag < nSquare; diag++) {521 522 psF32 maxval = 0.0;523 int maxrow = 0;524 int maxcol = 0;525 526 // search for the next pivot527 for (int row = 0; row < nSquare; row++) {528 if (!isfinite(A[row][diag])) goto escape;529 530 // if we have already operated on this row (pivot[row] is true), skip it531 if (pivot[row]) continue;532 533 // if we have not yet operated on this row (pivot[row] is false), look for pivot for this row534 for (int col = 0; col < nSquare; col++) {535 if (pivot[col]) continue;536 if (fabs (A[row][col]) < maxval) continue;537 maxval = fabs (A[row][col]);538 maxrow = row;539 maxcol = col;540 }541 }542 543 // if pivot[maxcol] is set, we have already done this row: this implies a singular matrix544 if (pivot[maxcol]) goto escape;545 pivot[maxcol] = 1;546 547 // if the selected pivot is off the diagonal, do a row swap548 if (maxrow != maxcol) {549 for (int col = 0; col < nSquare; col++) PS_SWAP (A[maxrow][col], A[maxcol][col]);550 PS_SWAP (B[maxrow], B[maxcol]);551 }552 rowIndex[diag] = maxrow;553 colIndex[diag] = maxcol;554 if (A[maxcol][maxcol] == 0.0) goto escape;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.557 558 /* rescale by pivot reciprocal */559 psF32 tmpval = 1.0 / A[maxcol][maxcol];560 A[maxcol][maxcol] = 1.0;561 for (int col = 0; col < nSquare; col++) A[maxcol][col] *= tmpval;562 B[maxcol] *= tmpval;563 564 // check for ill-conditioned matrix: measure the pivot growth and trigger on over/under flow565 growth *= tmpval;566 psTrace ("psLib.math", 4, "growth : %e\n", growth);567 if (fabs(growth) > MAX_RANGE) goto escape;568 569 /* adjust the elements above the pivot */570 for (int row = 0; row < nSquare; row++) {571 if (row == maxcol) continue;572 tmpval = A[row][maxcol];573 A[row][maxcol] = 0.0;574 for (int col = 0; col < nSquare; col++) A[row][col] -= A[maxcol][col]*tmpval;575 B[row] -= B[maxcol]*tmpval;576 }577 }578 579 // swap back the inverse matrix based on the row swaps above580 for (int col = nSquare - 1; col >= 0; col--) {581 if (rowIndex[col] != colIndex[col]) {582 for (int row = 0; row < nSquare; row++) PS_SWAP (A[row][rowIndex[col]], A[row][colIndex[col]]);583 }584 }520 psF32 **A = a->data.F32; 521 psF32 *B = b->data.F32; 522 int *colIndex = colIndexV->data.S32; 523 int *rowIndex = rowIndexV->data.S32; 524 int *pivot = pivotV->data.S32; 525 psF32 growth = 1.0; 526 527 for (int diag = 0; diag < nSquare; diag++) { 528 529 psF32 maxval = 0.0; 530 int maxrow = 0; 531 int maxcol = 0; 532 533 // search for the next pivot 534 for (int row = 0; row < nSquare; row++) { 535 if (!isfinite(A[row][diag])) goto escape; 536 537 // if we have already operated on this row (pivot[row] is true), skip it 538 if (pivot[row]) continue; 539 540 // if we have not yet operated on this row (pivot[row] is false), look for pivot for this row 541 for (int col = 0; col < nSquare; col++) { 542 if (pivot[col]) continue; 543 if (fabs (A[row][col]) < maxval) continue; 544 maxval = fabs (A[row][col]); 545 maxrow = row; 546 maxcol = col; 547 } 548 } 549 550 // if pivot[maxcol] is set, we have already done this row: this implies a singular matrix 551 if (pivot[maxcol]) goto escape; 552 pivot[maxcol] = 1; 553 554 // if the selected pivot is off the diagonal, do a row swap 555 if (maxrow != maxcol) { 556 for (int col = 0; col < nSquare; col++) PS_SWAP (A[maxrow][col], A[maxcol][col]); 557 PS_SWAP (B[maxrow], B[maxcol]); 558 } 559 rowIndex[diag] = maxrow; 560 colIndex[diag] = maxcol; 561 if (A[maxcol][maxcol] == 0.0) goto escape; 562 // Kahan replaces the 0.0 pivot with epsilon*(largest element in column) + underFlow. 563 // Here we are going to raise an error if the dynamic range is too large. 564 565 /* rescale by pivot reciprocal */ 566 psF32 tmpval = 1.0 / A[maxcol][maxcol]; 567 A[maxcol][maxcol] = 1.0; 568 for (int col = 0; col < nSquare; col++) A[maxcol][col] *= tmpval; 569 B[maxcol] *= tmpval; 570 571 // check for ill-conditioned matrix: measure the pivot growth and trigger on over/under flow 572 growth *= tmpval; 573 psTrace ("psLib.math", 4, "growth : %e\n", growth); 574 if (fabs(growth) > MAX_RANGE) goto escape; 575 576 /* adjust the elements above the pivot */ 577 for (int row = 0; row < nSquare; row++) { 578 if (row == maxcol) continue; 579 tmpval = A[row][maxcol]; 580 A[row][maxcol] = 0.0; 581 for (int col = 0; col < nSquare; col++) A[row][col] -= A[maxcol][col]*tmpval; 582 B[row] -= B[maxcol]*tmpval; 583 } 584 } 585 586 // swap back the inverse matrix based on the row swaps above 587 for (int col = nSquare - 1; col >= 0; col--) { 588 if (rowIndex[col] != colIndex[col]) { 589 for (int row = 0; row < nSquare; row++) PS_SWAP (A[row][rowIndex[col]], A[row][colIndex[col]]); 590 } 591 } 585 592 } else { 586 psF64 **A = a->data.F64;587 psF64 *B = b->data.F64;588 int *colIndex = colIndexV->data.S32;589 int *rowIndex = rowIndexV->data.S32;590 int *pivot = pivotV->data.S32;591 psF64 growth = 1.0;592 593 for (int diag = 0; diag < nSquare; diag++) {594 595 psF64 maxval = 0.0;596 int maxrow = 0;597 int maxcol = 0;598 599 // search for the next pivot600 for (int row = 0; row < nSquare; row++) {601 if (!isfinite(A[row][diag])) goto escape;602 603 // if we have already operated on this row (pivot[row] is true), skip it604 if (pivot[row]) continue;605 606 // if we have not yet operated on this row (pivot[row] is false), look for pivot for this row607 for (int col = 0; col < nSquare; col++) {608 if (pivot[col]) continue;609 if (fabs (A[row][col]) < maxval) continue;610 maxval = fabs (A[row][col]);611 maxrow = row;612 maxcol = col;613 }614 }615 616 // if pivot[maxcol] is set, we have already done this row: this implies a singular matrix617 if (pivot[maxcol]) goto escape;618 pivot[maxcol] = 1;619 620 // if the selected pivot is off the diagonal, do a row swap621 if (maxrow != maxcol) {622 for (int col = 0; col < nSquare; col++) PS_SWAP (A[maxrow][col], A[maxcol][col]);623 PS_SWAP (B[maxrow], B[maxcol]);624 }625 rowIndex[diag] = maxrow;626 colIndex[diag] = maxcol;627 if (A[maxcol][maxcol] == 0.0) goto escape;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.630 631 /* rescale by pivot reciprocal */632 psF64 tmpval = 1.0 / A[maxcol][maxcol];633 A[maxcol][maxcol] = 1.0;634 for (int col = 0; col < nSquare; col++) A[maxcol][col] *= tmpval;635 B[maxcol] *= tmpval;636 637 // check for ill-conditioned matrix: measure the pivot growth and trigger on over/under flow638 growth *= tmpval;639 psTrace ("psLib.math", 4, "growth : %e\n", growth);640 if (fabs(growth) > MAX_RANGE) goto escape;641 642 /* adjust the elements above the pivot */643 for (int row = 0; row < nSquare; row++) {644 if (row == maxcol) continue;645 tmpval = A[row][maxcol];646 A[row][maxcol] = 0.0;647 for (int col = 0; col < nSquare; col++) A[row][col] -= A[maxcol][col]*tmpval;648 B[row] -= B[maxcol]*tmpval;649 }650 }651 652 // swap back the inverse matrix based on the row swaps above653 for (int col = nSquare - 1; col >= 0; col--) {654 if (rowIndex[col] != colIndex[col]) {655 for (int row = 0; row < nSquare; row++) PS_SWAP (A[row][rowIndex[col]], A[row][colIndex[col]]);656 }657 }593 psF64 **A = a->data.F64; 594 psF64 *B = b->data.F64; 595 int *colIndex = colIndexV->data.S32; 596 int *rowIndex = rowIndexV->data.S32; 597 int *pivot = pivotV->data.S32; 598 psF64 growth = 1.0; 599 600 for (int diag = 0; diag < nSquare; diag++) { 601 602 psF64 maxval = 0.0; 603 int maxrow = 0; 604 int maxcol = 0; 605 606 // search for the next pivot 607 for (int row = 0; row < nSquare; row++) { 608 if (!isfinite(A[row][diag])) goto escape; 609 610 // if we have already operated on this row (pivot[row] is true), skip it 611 if (pivot[row]) continue; 612 613 // if we have not yet operated on this row (pivot[row] is false), look for pivot for this row 614 for (int col = 0; col < nSquare; col++) { 615 if (pivot[col]) continue; 616 if (fabs (A[row][col]) < maxval) continue; 617 maxval = fabs (A[row][col]); 618 maxrow = row; 619 maxcol = col; 620 } 621 } 622 623 // if pivot[maxcol] is set, we have already done this row: this implies a singular matrix 624 if (pivot[maxcol]) goto escape; 625 pivot[maxcol] = 1; 626 627 // if the selected pivot is off the diagonal, do a row swap 628 if (maxrow != maxcol) { 629 for (int col = 0; col < nSquare; col++) PS_SWAP (A[maxrow][col], A[maxcol][col]); 630 PS_SWAP (B[maxrow], B[maxcol]); 631 } 632 rowIndex[diag] = maxrow; 633 colIndex[diag] = maxcol; 634 if (A[maxcol][maxcol] == 0.0) goto escape; 635 // Kahan replaces the 0.0 pivot with epsilon*(largest element in column) + underFlow. 636 // Here we are going to raise an error if the dynamic range is too large. 637 638 /* rescale by pivot reciprocal */ 639 psF64 tmpval = 1.0 / A[maxcol][maxcol]; 640 A[maxcol][maxcol] = 1.0; 641 for (int col = 0; col < nSquare; col++) A[maxcol][col] *= tmpval; 642 B[maxcol] *= tmpval; 643 644 // check for ill-conditioned matrix: measure the pivot growth and trigger on over/under flow 645 growth *= tmpval; 646 psTrace ("psLib.math", 4, "growth : %e\n", growth); 647 if (fabs(growth) > MAX_RANGE) goto escape; 648 649 /* adjust the elements above the pivot */ 650 for (int row = 0; row < nSquare; row++) { 651 if (row == maxcol) continue; 652 tmpval = A[row][maxcol]; 653 A[row][maxcol] = 0.0; 654 for (int col = 0; col < nSquare; col++) A[row][col] -= A[maxcol][col]*tmpval; 655 B[row] -= B[maxcol]*tmpval; 656 } 657 } 658 659 // swap back the inverse matrix based on the row swaps above 660 for (int col = nSquare - 1; col >= 0; col--) { 661 if (rowIndex[col] != colIndex[col]) { 662 for (int row = 0; row < nSquare; row++) PS_SWAP (A[row][rowIndex[col]], A[row][colIndex[col]]); 663 } 664 } 658 665 } 659 666 … … 701 708 lu = gsl_matrix_alloc(numRows, numCols); 702 709 inv = gsl_matrix_alloc(numRows, numCols); 703 psImageToGslMatrix(lu, in);710 matrixPStoGSL(lu, in); 704 711 705 712 // Invert data and calculate determinant … … 708 715 if (determinant) { 709 716 // XXX this is getting the wrong value: is it the wrong calculation? 710 // it disagrees with the results of 717 // it disagrees with the results of 711 718 // det = (psF32)gsl_linalg_LU_det(lu, signum); 712 719 // used in psMatrixDeterminatn … … 716 723 717 724 // Copy GSL matrix data to psImage data 718 gslMatrixToPsImage(out, inv);725 matrixGSLtoPS(out, inv); 719 726 720 727 // Free GSL structs … … 749 756 perm = gsl_permutation_alloc(numRows); 750 757 lu = gsl_matrix_alloc(numRows, numCols); 751 psImageToGslMatrix(lu, in);758 matrixPStoGSL(lu, in); 752 759 753 760 // Calculate determinant 754 761 gsl_linalg_LU_decomp(lu, perm, &signum); 755 det = (psF32)gsl_linalg_LU_ det(lu, signum);762 det = (psF32)gsl_linalg_LU_lndet(lu); 756 763 757 764 // Free GSL structs … … 877 884 878 885 inGSL = gsl_matrix_alloc(numRows, numCols); 879 psImageToGslMatrix(inGSL, in);886 matrixPStoGSL(inGSL, in); 880 887 outGSL = gsl_matrix_alloc(numRows, numCols); 881 888 … … 892 899 893 900 // Copy GSL matrix data to psImage data 894 gslMatrixToPsImage(out, outGSL);901 matrixGSLtoPS(out, outGSL); 895 902 896 903 // Free GSL structs … … 1026 1033 } 1027 1034 1035 psVector *psMatrixSolveSVD(psVector *out, const psImage *matrix, const psVector *vector) 1036 { 1037 #define psMatrixSolveSVD_EXIT {psFree(out); return NULL; } 1038 PS_ASSERT_GENERAL_IMAGE_NON_NULL(matrix, psMatrixSolveSVD_EXIT); 1039 PS_CHECK_DIMEN_AND_TYPE(matrix, PS_DIMEN_IMAGE, psMatrixSolveSVD_EXIT); 1040 PS_ASSERT_GENERAL_VECTOR_NON_NULL(vector, psMatrixSolveSVD_EXIT); 1041 PS_CHECK_DIMEN_AND_TYPE(vector, PS_DIMEN_VECTOR, psMatrixSolveSVD_EXIT); 1042 1043 int numCols = matrix->numCols, numRows = matrix->numRows; // Size of matrix 1044 1045 // Decompose matrix: A = U S V^T 1046 gsl_matrix *A = gsl_matrix_alloc(numRows, numCols); // Input matrix in GSL-speak; becomes matrix U 1047 gsl_matrix *V = gsl_matrix_alloc(numCols, numCols); // Untransposed matrix V 1048 gsl_vector *S = gsl_vector_alloc(numCols); // Singular values 1049 gsl_vector *work = gsl_vector_alloc(numCols); // Work space for GSL 1050 1051 matrixPStoGSL(A, matrix); 1052 1053 int gslStatus = 0; // Status of GSL 1054 if ((gslStatus = gsl_linalg_SV_decomp(A, V, S, work))) { 1055 const char *err = gsl_strerror(gslStatus); 1056 psError(PS_ERR_UNKNOWN, true, "Unable to decompose matrix: %s", err); 1057 gsl_matrix_free(A); 1058 gsl_matrix_free(V); 1059 gsl_vector_free(S); 1060 gsl_vector_free(work); 1061 return NULL; 1062 } 1063 gsl_vector_free(work); 1064 1065 // Solve system (or minimise least-squares if overconstrained): Ax = b 1066 gsl_vector *b = gsl_vector_alloc(numCols); // Vector b 1067 gsl_vector *x = gsl_vector_alloc(numCols); // Solution 1068 1069 vectorPStoGSL(b, vector); 1070 1071 if ((gslStatus = gsl_linalg_SV_solve(A, V, S, b, x))) { 1072 const char *err = gsl_strerror(gslStatus); 1073 psError(PS_ERR_UNKNOWN, true, "Unable to solve matrix equation: %s", err); 1074 gsl_matrix_free(A); 1075 gsl_matrix_free(V); 1076 gsl_vector_free(S); 1077 gsl_vector_free(b); 1078 gsl_vector_free(x); 1079 return NULL; 1080 } 1081 1082 gsl_matrix_free(A); 1083 gsl_matrix_free(V); 1084 gsl_vector_free(S); 1085 gsl_vector_free(b); 1086 1087 out = psVectorRecycle(out, numCols, PS_TYPE_F64); 1088 1089 vectorGSLtoPS(out, x); 1090 gsl_vector_free(x); 1091 1092 return out; 1093 } 1094 1095 1096 1028 1097 // This code supplied by Andy Becker (becker@astro.washington.edu) 1029 1098 psImage *psMatrixSVD(psImage* evec, psVector* eval, const psImage* in) … … 1050 1119 1051 1120 // Copy psImage data into GSL matrix data 1052 psImageToGslMatrix(A, in);1121 matrixPStoGSL(A, in); 1053 1122 1054 1123 // Calculate SVD decomposition … … 1056 1125 1057 1126 // Copy GSL matrix data to psImage data 1058 gslMatrixToPsImage(evec, V);1059 gslVectorToPsVector(eval, S);1127 matrixGSLtoPS(evec, V); 1128 vectorGSLtoPS(eval, S); 1060 1129 1061 1130 // Take the square root of eval -
trunk/psLib/src/math/psMatrix.h
r24084 r26001 66 66 */ 67 67 psImage *psMatrixLUInvert( 68 psImage *out, ///< place result here if not NULL69 const psImage* LU, ///< LU-decomposed matrix.70 const psVector* perm ///< Permutation vector resulting from psMatrixLUD function.68 psImage *out, ///< place result here if not NULL 69 const psImage* LU, ///< LU-decomposed matrix. 70 const psVector* perm ///< Permutation vector resulting from psMatrixLUD function. 71 71 ); 72 72 … … 186 186 ); 187 187 188 /// Solve a matrix equation using Singular Value Decomposition 189 /// 190 /// Solves Ax = b for x 191 psVector *psMatrixSolveSVD( 192 psVector *solution, ///< Solution to output, or NULL 193 const psImage *matrix, ///< Matrix to be solved 194 const psVector *vector ///< Vector of values 195 ); 196 197 188 198 /// Single value decomposition, provided by Andy Becker 189 199 psImage *psMatrixSVD(psImage* evec, psVector* eval, const psImage* in);
Note:
See TracChangeset
for help on using the changeset viewer.
