/*
  
Solve a set of simultaneous equations of arbitrary number of vars

For example, for 3 vars:

n11 x +  n12 y + n13 z = n14
n21 x +  n22 y + n23 z = n24
n31 x +  n32 y + n33 z = n34

Enter numbers, when asked by the program, like this:
n11 n12 n13 n14 <enter>
n21 n22 n23 n24 <enter>
n31 n32 n33 n34 <enter>

By: Gaurang Khetan(http://gaurang.org)
Date: 4/26/2004

*/

#include <stdio.h>
#include <assert.h>

float** mat;
float** mat2;
int num;

float calc_determinant(int* on);
int colnum(int* on, int numcol);
float elem_at_colnum(int* on, int numcol);


int main()
{
    float* rhs;

    printf("Enter number of variables: ");
    scanf("%d", &num);

    mat = new (float*)[num];
    for (int i = 0; i<num; i++)
	mat[i] = new float[num];

    mat2 = new (float*)[num];
    for (int i = 0; i<num; i++)
	mat2[i] = new float[num];

    rhs = new float[num];
    
    for (int i = 0; i<num; i++)
	{
	    for (int j = 0; j<num; j++)
		scanf("%f", &(mat[i][j]));
	    scanf("%f", &(rhs[i]));
	}
    
    //setup on array
    int* on = new int[num];
    for (int i = 0; i<num; i++)
	on[i] = 1;
    
    //setup mat2
    for (int i = 0; i<num; i++)
	for (int j = 0; j<num; j++)
	    mat2[i][j] = mat[i][j];

    //basic determinant
    float deter = calc_determinant(on);
  
    //calculation of variables
    for (int i = 0; i<num; i++)
	{
	    // calculation of variable number i
	    
	    // copy rhs onto column number i
	    for (int j = 0; j<num; j++)
		mat2[j][i] = rhs[j];

	    float deter2 = calc_determinant(on);

	    printf("Variable %d = (%f) / (%f) = (%f) \n", i, deter2, deter, deter2/deter);

	    // make it clean again
	    for (int j = 0; j<num; j++)
		mat2[j][i] = mat[j][i];

	}
    return 0;
}

//recursive function to find determinant
float calc_determinant(int* on)
{
    int dimen;

    //calculate dimension
    dimen = 0;
    for (int i = 0; i<num; i++)
	dimen += on[i];

    assert(dimen != 0);

    if (dimen == 1)
	return elem_at_colnum(on, 0);

    float tot = 0;
    int mult = 1;
    for (int i = 0; i<dimen; i++)
	{
	    int ncol = colnum(on, i);

	    on[ncol] = 0;
	    float calc_deter = calc_determinant(on);
	    on[ncol] = 1;
	    
	    tot += (mult*calc_deter*elem_at_colnum(on, i));
	    mult = -mult;
	}

    return tot;
}

//get element at numcol'th column of the current row
float elem_at_colnum(int* on, int numcol)
{
    //calculate dimension
    int dimen = 0;
    for (int i = 0; i<num; i++)
	dimen += on[i];

    //calculate row based on dimension
    int row = num-dimen;

    return mat2[row][colnum(on, numcol)];
}
	
//get numcol'th element of the "on" array
int colnum(int* on, int numcol)
{
    int t=-1;
    int i=0;
    while (i<num)
	{
	    if (on[i] == 1)
		t++;
	    if (t==numcol)
		return i;
	    i++;
	}
    assert(0);
}

    
