package hep.aida.ref.optimizer.uncmin;
import java.text.NumberFormat;
class Matrix
{
public static double[][] create(int size)
{
double[][] result = new double[size][];
for (int i=0; i<size; i++) result[i] = new double[size];
return result;
}
public static double[][] clone(double[][] in)
{
double[][] result = (double[][]) in.clone();
for (int i=0; i<result.length; i++)
result[i] = (double[]) result[i].clone();
return result;
}
public static void print(double[][] in)
{
NumberFormat nf = NumberFormat.getInstance();
for (int i=0; i<in.length; i++)
{
for (int j=0; j<in[i].length; j++)
{
System.out.print(nf.format(in[i][j])+" ");
}
System.out.println();
}
}
public static double[][] multiply(double[][] in1, double[][] in2) throws IncompatibleMatrices
{
double[][] out = new double[in1.length][];
for (int i=0; i<in1.length; i++)
{
if (in1[i].length != in2.length) throw new IncompatibleMatrices();
out[i] = new double[in2[i].length];
for (int j=0; j<in2[i].length; j++)
{
out[i][j] = 0;
for (int k=0; k<in1[i].length; k++)
{
out[i][j] += in1[i][k]*in2[k][j];
}
}
}
return out;
}
public static double invert(double[][] array) throws IndeterminateMatrix
{
double det = 1;
int order = array.length;
int[] ik = new int[order];
int[] jk = new int[order];
for (int k=0; k<order; k++)
{
// Find largest element array[i][k] in rest of matrix
double amax = 0;
for (int i=k; i<order; i++)
{
for (int j=k; j<order; j++)
{
if (Math.abs(array[i][j]) > Math.abs(amax))
{
amax = array[i][j];
ik[k] = i;
jk[k] = j;
}
}
}
// Interchange rows and columns to put max in array[k][k]
if (amax == 0) throw new IndeterminateMatrix();
{
int i = ik[k];
if (k > i) throw new MatrixBug();
if (i > k)
{
for (int j=0; j<order; j++)
{
double save = array[k][j];
array[k][j] = array[i][j];
array[i][j] = -save;
}
}
}
{
int j = jk[k];
if (k > j) throw new MatrixBug();
if (j > k)
{
for (int i=0; i<order; i++)
{
double save = array[i][k];
array[i][k] = array[i][j];
array[i][j] = -save;
}
}
}
// Accumulate elements of inverse matrix
for (int i=0; i<order; i++)
{
if (i == k) continue;
array[i][k] = -array[i][k]/amax;
}
for (int i=0; i<order; i++)
{
if (i == k) continue;
for (int j=0; j<order; j++)
{
if (j == k) continue;
array[i][j] += array[i][k]*array[k][j];
}
}
for (int j=0; j<order; j++)
{
if (j == k) continue;
array[k][j] = array[k][j]/amax;
}
array[k][k] = 1/amax;
det *= amax;
}
// restore ordering of matrix
for (int l=0; l<order; l++)
{
int k = order - l - 1;
{
int j = ik[k];
if (j>k)
{
for (int i=0; i<order; i++)
{
double save = array[i][k];
array[i][k] = -array[i][j];
array[i][j] = save;
}
}
}
{
int i = jk[k];
if (i>k)
{
for (int j=0; j<order; j++)
{
double save = array[k][j];
array[k][j] = -array[i][j];
array[i][j] = save;
}
}
}
}
return det;
}
}