using System.Diagnostics.CodeAnalysis;
using System.Drawing.Drawing2D;

namespace Lab6
{
    public class Alg2
    {
        public double Begin(double[,] matrixA, int threadCount)
        {
            int size = matrixA.GetLength(0);

            if (size == 1)
            {
                return matrixA[0, 0];
            }
            else if (size == 2)
            {
                return matrixA[0, 0] * matrixA[1, 1] - matrixA[0, 1] * matrixA[1, 0];
            }
            else
            {
                double determinant = 0;
                object lockObject = new object();

                Parallel.For(0, size, new ParallelOptions { MaxDegreeOfParallelism = threadCount }, i =>
                {
                    double[,] subMatrix = GetSubMatrix(matrixA, i);
                    double subDeterminant = matrixA[0, i] * Determinant(subMatrix);

                    lock (lockObject)
                    {
                        determinant += Math.Pow(-1, i) * subDeterminant;
                    }
                });

                return determinant;
            }
        }

        static double[,] GetSubMatrix(double[,] matrix, int columnIndex)
        {
            int size = matrix.GetLength(0);
            double[,] subMatrix = new double[size - 1, size - 1];

            for (int i = 1; i < size; i++)
            {
                for (int j = 0; j < size; j++)
                {
                    if (j < columnIndex)
                    {
                        subMatrix[i - 1, j] = matrix[i, j];
                    }
                    else if (j > columnIndex)
                    {
                        subMatrix[i - 1, j - 1] = matrix[i, j];
                    }
                }
            }

            return subMatrix;
        }

        static double Determinant(double[,] matrix)
        {
            int size = matrix.GetLength(0);

            if (size == 1)
            {
                return matrix[0, 0];
            }
            else if (size == 2)
            {
                return matrix[0, 0] * matrix[1, 1] - matrix[0, 1] * matrix[1, 0];
            }
            else
            {
                double determinant = 0;

                for (int i = 0; i < size; i++)
                {
                    double[,] subMatrix = GetSubMatrix(matrix, i);

                    determinant += Math.Pow(-1, i) * matrix[0, i] * Determinant(subMatrix);
                }

                return determinant;
            }
        }
    }
}