Last active
October 17, 2025 08:22
-
-
Save MurageKibicho/d81e3cf01c54a47278d2062c00db0720 to your computer and use it in GitHub Desktop.
Using LU Decomposition in C to find the matrix determinant
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //Full walkthrough: https://leetarxiv.substack.com/p/sinkhorn-knopp-algorithm | |
| void PrintMatrix(int rows, int cols, double *matrix) | |
| { | |
| for(int i = 0; i < rows; i++) | |
| { | |
| for(int j = 0; j < cols; j++) | |
| { | |
| double element = matrix[INDEX(i,j, cols)]; | |
| printf("%.3f,",element); | |
| } | |
| printf("\n"); | |
| } | |
| printf("\n"); | |
| } | |
| double LUDecomposition(int n, double *inputMatrix, double *L, double *U, int *P) | |
| { | |
| double det = 1.0; | |
| double *A = (double *)malloc(n * n * sizeof(double)); | |
| memcpy(A, inputMatrix, n * n * sizeof(double)); | |
| //Initialize L and U | |
| for(int i = 0; i < n; i++){for(int j = 0; j < n; j++){L[i * n + j] = (i == j) ? 1.0 : 0.0;U[i * n + j] = 0.0;}} | |
| //Initialize P to identity | |
| for(int i = 0; i < n; i++){P[i] = i;} | |
| for(int i = 0; i < n; i++) | |
| { | |
| //Partial pivoting | |
| double max = fabs(A[i * n + i]); | |
| int pivot = i; | |
| for(int k = i + 1; k < n; k++){double val = fabs(A[k * n + i]);if(val > max){max = val;pivot = k;}} | |
| if(max < 1e-12) | |
| { | |
| printf("WARNING: Singular or near-singular matrix at step %d\n", i); | |
| printf("Max pivot value: %e\n", max); | |
| free(A); | |
| return 0.0; | |
| } | |
| if(pivot != i) | |
| { | |
| //Swap rows in A | |
| for(int j = 0; j < n; j++){double temp = A[i * n + j];A[i * n + j] = A[pivot * n + j];A[pivot * n + j] = temp;} | |
| //Swap rows in L | |
| for(int j = 0; j < i; j++){double temp = L[i * n + j];L[i * n + j] = L[pivot * n + j];L[pivot * n + j] = temp;} | |
| int temp = P[i]; | |
| P[i] = P[pivot]; | |
| P[pivot] = temp; | |
| det = -det; | |
| } | |
| //Compute U[i][j] with NaN check | |
| for(int j = i; j < n; j++) | |
| { | |
| double sum = 0.0; | |
| for(int k = 0; k < i; k++){sum += L[i * n + k] * U[k * n + j];} | |
| U[i * n + j] = A[i * n + j] - sum; | |
| //CHECK FOR NaN/Inf | |
| if(!isfinite(U[i * n + j])) | |
| { | |
| printf("ERROR: Non-finite U[%d][%d] = %f\n", i, j, U[i * n + j]); | |
| printf("A[%d][%d] = %f, sum = %f\n", i, j, A[i * n + j], sum); | |
| free(A); | |
| return NAN; | |
| } | |
| } | |
| // Compute L[j][i] with robustness check | |
| double divisor = U[i * n + i]; | |
| if (fabs(divisor) < 1e-12) | |
| { | |
| printf("\nWARNING: Very small divisor at step %d: %e\n", i, divisor); | |
| free(A); | |
| return 0.0; | |
| } | |
| for(int j = i + 1; j < n; j++) | |
| { | |
| double sum = 0.0; | |
| for(int k = 0; k < i; k++){sum += L[j * n + k] * U[k * n + i];} | |
| L[j * n + i] = (A[j * n + i] - sum) / divisor; | |
| //CHECK FOR NaN/Inf | |
| if(!isfinite(L[j * n + i])) | |
| { | |
| printf("\nERROR: Non-finite L[%d][%d] = %f\n", j, i, L[j * n + i]); | |
| printf("A[%d][%d] = %f, sum = %f, divisor = %f\n", j, i, A[j * n + i], sum, divisor); | |
| free(A); | |
| return NAN; | |
| } | |
| } | |
| det *= U[i * n + i]; | |
| //CHECK DETERMINANT | |
| if(!isfinite(det)) | |
| { | |
| printf("\nERROR: Non-finite determinant at step %d: %f\n", i, det); | |
| printf("U[%d][%d] = %f\n", i, i, U[i * n + i]); | |
| free(A); | |
| return det; | |
| } | |
| } | |
| free(A); | |
| return det; | |
| } | |
| void NaiveMatmul(int rowA, int colA, int colB,double *A, double *B, double *C) | |
| { | |
| for(int i = 0; i < rowA; i++) | |
| { | |
| for(int j = 0; j < colB; j++) | |
| { | |
| double sum = 0.0; | |
| for(int k = 0; k < colA; k++) | |
| { | |
| sum += A[INDEX(i, k, colA)] * B[INDEX(k, j, colB)]; | |
| } | |
| C[INDEX(i, j, colB)] = sum; | |
| } | |
| } | |
| } | |
| void FindPAMatrix(int n, int *P, double *PA, double *A) | |
| { | |
| for (int i = 0; i < n; i++) | |
| { | |
| int srcRow = P[i]; // Row in original A that became row i in the LU step | |
| for (int j = 0; j < n; j++) | |
| { | |
| PA[i * n + j] = A[srcRow * n + j]; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment