public static IntSquareMatrix I(int n)
    {
        IntSquareMatrix identity = new IntSquareMatrix(n);

        for (int i = 0; i < n; i++)
        {
            identity[i, i] = 1;
        }
        return(identity);
    }
    public static void Main(string[] args)
    {
        int[,] a = new int [3, 3] {
            { 1, 2, 3 },
            { 4, 5, 6 },
            { 7, 8, 9 }
        };
        IntSquareMatrix matrixA = new IntSquareMatrix(a);

        Console.WriteLine(BinaryExponentiation(matrixA, 3));
    }
    public static IntSquareMatrix BinaryExponentiation(IntSquareMatrix a, int n)
    {
        if (n == 0)
        {
            return(IntSquareMatrix.I(a.N));
        }
        IntSquareMatrix half = BinaryExponentiation(a, n >> 1);
        IntSquareMatrix full = half * half;

        if ((n & 1) == 1)
        {
            full *= a;
        }
        return(full);
    }
    public static IntSquareMatrix operator*(IntSquareMatrix m1, IntSquareMatrix m2)
    {
        int n = m1.N;
        int m = m2.N;

        if (n != m)
        {
            throw new Exception($"Can not multiply {n}x{n} and {m}x{m} martix");
        }

        IntSquareMatrix result = new IntSquareMatrix(n);

        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                for (int k = 0; k < n; k++)
                {
                    result[i, j] += (m1[i, k] * m2[k, j]);
                }
            }
        }
        return(result);
    }
 public IntSquareMatrix(IntSquareMatrix other) : this(other._a)
 {
 }