* Compute the inverse of a matrix using LU decomposition with partial pivoting. * The return value is the sum of norms of the off-diagonal terms of the * product of a and inv. (A measure of the error.) */
| 2526 | * product of a and inv. (A measure of the error.) |
| 2527 | */ |
| 2528 | double InvertMatrix(const float* input, int size, float* inv) { |
| 2529 | // Allocate memory for the 2D arrays. |
| 2530 | GENERIC_2D_ARRAY<double> U(size, size, 0.0); |
| 2531 | GENERIC_2D_ARRAY<double> U_inv(size, size, 0.0); |
| 2532 | GENERIC_2D_ARRAY<double> L(size, size, 0.0); |
| 2533 | |
| 2534 | // Initialize the working matrices. U starts as input, L as I and U_inv as O. |
| 2535 | int row; |
| 2536 | int col; |
| 2537 | for (row = 0; row < size; row++) { |
| 2538 | for (col = 0; col < size; col++) { |
| 2539 | U[row][col] = input[row*size + col]; |
| 2540 | L[row][col] = row == col ? 1.0 : 0.0; |
| 2541 | U_inv[row][col] = 0.0; |
| 2542 | } |
| 2543 | } |
| 2544 | |
| 2545 | // Compute forward matrix by inversion by LU decomposition of input. |
| 2546 | for (col = 0; col < size; ++col) { |
| 2547 | // Find best pivot |
| 2548 | int best_row = 0; |
| 2549 | double best_pivot = -1.0; |
| 2550 | for (row = col; row < size; ++row) { |
| 2551 | if (Abs(U[row][col]) > best_pivot) { |
| 2552 | best_pivot = Abs(U[row][col]); |
| 2553 | best_row = row; |
| 2554 | } |
| 2555 | } |
| 2556 | // Exchange pivot rows. |
| 2557 | if (best_row != col) { |
| 2558 | for (int k = 0; k < size; ++k) { |
| 2559 | double tmp = U[best_row][k]; |
| 2560 | U[best_row][k] = U[col][k]; |
| 2561 | U[col][k] = tmp; |
| 2562 | tmp = L[best_row][k]; |
| 2563 | L[best_row][k] = L[col][k]; |
| 2564 | L[col][k] = tmp; |
| 2565 | } |
| 2566 | } |
| 2567 | // Now do the pivot itself. |
| 2568 | for (row = col + 1; row < size; ++row) { |
| 2569 | double ratio = -U[row][col] / U[col][col]; |
| 2570 | for (int j = col; j < size; ++j) { |
| 2571 | U[row][j] += U[col][j] * ratio; |
| 2572 | } |
| 2573 | for (int k = 0; k < size; ++k) { |
| 2574 | L[row][k] += L[col][k] * ratio; |
| 2575 | } |
| 2576 | } |
| 2577 | } |
| 2578 | // Next invert U. |
| 2579 | for (col = 0; col < size; ++col) { |
| 2580 | U_inv[col][col] = 1.0 / U[col][col]; |
| 2581 | for (row = col - 1; row >= 0; --row) { |
| 2582 | double total = 0.0; |
| 2583 | for (int k = col; k > row; --k) { |
| 2584 | total += U[row][k] * U_inv[k][col]; |
| 2585 | } |
no outgoing calls