I have a function in a generic class that calculates a determinant of a matrix. The function works for some inputs with any type, and for others it gives the wrong answer (based on the type).
Here is the function:
public T Determinant()
{
checked
{
int n = dimension;
Matrix<T> a = new Matrix<T>(baseArray);
int i, j, k;
T det = (dynamic)0;
for (i = 0; i < n - 1; i++)
{
for (j = i + 1; j < n; j++)
{
det = (dynamic)a[j, i] / a[i, i];
for (k = i; k < n; k++)
a[j, k] = a[j, k] - (dynamic)det * a[i, k];
}
}
det = (dynamic)1;
for (i = 0; i < n; i++)
det = (dynamic)det * a[i, i];
return det;
}
}
I added the checked block to see if there was an overflow taking place, but apparently, there is no overflow happening.
A sample input is if the baseArray is new double[,] {{11, 11, 12, 17, 21, 29}, {16, 9, 25, 30, 29, 33}, {3, 13, 9, 24, 21, it will give the right answer (very close to -942755), but if baseArray is instead
24}, {23, 6, 29, 21, 23, 23}, {22, 19, 14, 30, 21, 24}, {22, 28,
20, 17, 25, 28}};new int[,] {{11, 11, 12, 17, 21, 29}, {16, 9, 25, 30, 29, 33}, {3, 13, 9, 24, 21, it gives 15934050 as the answer (not even close).
24}, {23, 6, 29, 21, 23, 23}, {22, 19, 14, 30, 21, 24}, {22, 28,
20, 17, 25, 28}};
The indexer on the matrix just returns the i-th j-th elements of the matrix, so they are not the issue.
I’m baffled as to what the issue could be since it is not an overflow. Any ideas?
Code to reproduce:
public class Matrix<T>
where T : IConvertible
{
private int dimension;
private T[][] baseArray;
public Matrix(int dimensions, T[,] baseArray)
{
this.dimension = dimensions;
this.baseArray = new T[dimension][];
for (int i = 0; i < dimension; i++)
{
this.baseArray[i] = new T[dimension];
for (int j = 0; j < dimension; j++)
{
this[i, j] = baseArray[i, j];
}
}
}
public T this[int a, int b]
{
get
{
return baseArray[a][b];
}
set
{
baseArray[a][b] = value;
}
}
public T Determinant()
{
checked
{
int n = dimension;
Matrix<T> a = new Matrix<T>(baseArray);
int i, j, k;
T det = (dynamic)0;
for (i = 0; i < n - 1; i++)
{
for (j = i + 1; j < n; j++)
{
det = (dynamic)a[j, i] / a[i, i];
for (k = i; k < n; k++)
a[j, k] = a[j, k] - (dynamic)det * a[i, k];
}
}
det = (dynamic)1;
for (i = 0; i < n; i++)
det = (dynamic)det * a[i, i];
return det;
}
}
}
When the values are
intvalues, it performs integer arithmetic.When the values are
doublevalues, it performs floating point arithmetic – it’s as simple as that. Simpler example: