// Arup Guha
// 4/4/2012
// Solves for a determinant using row operations.
// Created by editing eqn-solver3.c.

#include <stdio.h>
#include <math.h>

#define SIZE 10
#define DEBUG 0

double getDet(double matrix[][SIZE], int n);
void print(double matrix[][SIZE], int n);
void swapRows(double matrix[][SIZE], int row1, int row2);

int main() {

    double matrix[SIZE][SIZE];

    // Open the input file.
    FILE* ifp = fopen("matrix.txt", "r");

    // Read in the number of sets of equations to solve.
    int numprobs;
    fscanf(ifp, "%d", &numprobs);

    // Go through each set.
    int loop;
    for (loop=1; loop<=numprobs; loop++) {

        int n;
        fscanf(ifp, "%d", &n);

        // Read in the matrix.
        int i,j;
        for (i=0; i<n; i++) {
            for (j=0; j<n; j++) {
                fscanf(ifp,"%lf", &matrix[i][j]);
            }
        }

        printf("Case %d: Det is %lf\n", loop, getDet(matrix, n));

    }

    return 0;
}

// Prints out matrix.
void print(double matrix[][SIZE], int n) {

    int i,j;
    for (i=0; i<n; i++) {

        for (j=0; j<n; j++)
            printf("%6.2lf", matrix[i][j]);
        printf("\n");
    }
}

// Computes the determinant of matrix via row operations.
double getDet(double matrix[][SIZE], int n) {

    int i,j,k;
    int sign = 1;
    // Using row (i-1) as a pivot.
    for (i=1; i<n; i++) {

        // This is the row we are simplifying.
        for (j=i; j<n; j++) {

            // Make sure that the row we use to pivot has a
            // largest non-zero term in the pivot location.
            int bestrow = i-1, tryrow;
            for (tryrow = i; tryrow<n; tryrow++) {

                if (fabs(matrix[tryrow][i-1]) >
                    fabs(matrix[bestrow][i-1]))
                    bestrow = tryrow;
            }

            // Only swap rows if necessary.
            if (i-1 != bestrow) {
                swapRows(matrix, i-1, bestrow);
                //if ((i-1)%2 != bestrow%2)
                sign = -sign;
            }
            // This is the factor we multiply each term by in equation i-1.
            double mult = matrix[j][i-1]/matrix[i-1][i-1];

            // Update all entries on row j using the multiplicative factor.
            for (k=0; k<n; k++)
                matrix[j][k] -= (mult*matrix[i-1][k]);
        } // end j
    } // end i;

    // The determinant is the product of this diagonal times the sign.
    double prod = 1;
    for (i=0; i<n; i++)
        prod = prod*matrix[i][i];

    return prod*sign;
}

// Swaps rows row1 and row2 in matrix.
void swapRows(double matrix[][SIZE], int row1, int row2) {

    int i;

    for (i=0; i<SIZE; i++) {
        double temp = matrix[row1][i];
        matrix[row1][i] = matrix[row2][i];
        matrix[row2][i] = temp;
    }
}

