/// <summary>
        /// Approximate Wilk's lambda by F statistics
        /// </summary>
        /// <param name="H">Hypothesis Sum of Squares and Cross Products.</param>
        /// <param name="E">Error Sum of Squares and Cross Products</param>
        /// <param name="N">number of data points</param>
        /// <param name="p">number of variables</param>
        /// <param name="g">number of groups</param>
        /// <param name="F_crit">The F critical value</param>
        /// <returns>The p-value</returns>
        public static double GetWilksLambda(double[][] H, double[][] E, int N, int p, int g, out double F_crit)
        {
            double[][] H_plus_E             = Add(H, E);
            double     E_determinant        = MatrixOp.GetDeterminant(E);
            double     H_plus_E_determinant = MatrixOp.GetDeterminant(H_plus_E);
            double     lambda = E_determinant / H_plus_E_determinant;

            double a           = N - g - (p - g + 2) / 2.0;
            int    b_threshold = p * p + (g - 1) * (g - 1) - 5;
            double b           = 1;

            if (b_threshold > 0)
            {
                b = System.Math.Sqrt((p * p * (g - 1) - 4) / b_threshold);
            }

            double c = (p * (g - 1) - 2) / 2.0;

            F_crit = ((1 - System.Math.Pow(lambda, 1 / b)) / (System.Math.Pow(lambda, 1 / b))) * ((a * b - c) / (p * (g - 1)));

            double DF1    = p * (g - 1);
            double DF2    = a * b - c;
            double pValue = 1 - FDistribution.GetPercentile(F_crit, DF1, DF2);

            return(pValue);
        }
        public static void RunExample(double[][] A)
        {
            Console.WriteLine("A = {0}", MatrixOp.Summary(A));

            double[][] C = MatrixOp.GetUpperTriangularMatrix(A);
            Console.WriteLine("C = {0}", MatrixOp.Summary(C));

            double detA = MatrixOp.GetDeterminant(A);

            Console.WriteLine("det(A) = {0}", detA);
        }