/// <summary>
        /// Constructor. Menghitung LSE dari persamaan regresi dalam matriks
        /// Y = X B + E
        /// </summary>
        /// <param name="X">Matrix. Matriks berisi data variabel independen X</param>
        /// <param name="Y">Vector. Vektor berisi data variabel dependen Y</param>
        public LeastSquareEstimator(Matrix X, Vector Y)
        {
            this.x = X;
            this.y = Y;
            int n = Y.Tuples;
            int p = X.Cols;

            Matrix xtx = x.GetTranspose() * x;
            Vector xty = x.GetTranspose() * y;

            b = xtx.Solve(xty);

            ycap = x * b;
            e = y - ycap;
            eSquare = e.GetDataSquare();

            Matrix j = new Matrix(n, n);
            j.InitializeAllValue(1.0);

            double yty =Vector.DoubleMultiply(Y.GetTranspose(), Y);
            Vector jy = j * y;
            ssto = yty - Vector.DoubleMultiply(Y.GetTranspose(), jy) / n;
            sse = yty - Vector.DoubleMultiply(b.GetTranspose(), xty);
            ssr = ssto - sse;

            msr = ssr / (p - 1);
            mse = sse / (n - p);
            rSquare = ssr / ssto;
            r = Math.Sqrt(rSquare);

            sbSquare = mse * xtx.GetInverse();
        }
        /// <summary>
        /// Menghitung nilai indeks musiman
        /// </summary>
        /// <param name="y">Vector. data aktual</param>
        /// <param name="seasonalLength">Integer. panjang musiman</param>
        /// <param name="isMultiplicative">Boolean. tipe model yang digunakan</param>
        public SeasonalIndex(Vector y, int seasonalLength, bool isMultiplicative)
        {
            this.y = y;
            this.includedObservation = this.y.Tuples;
            this.seasonalLength = seasonalLength;
            this.isMultiplicative = isMultiplicative;

            sMov1 = new double[includedObservation];
            sMov2 = new double[includedObservation];
            median = new double[seasonalLength];
            seasonal = new double[seasonalLength];

            term = new double[this.includedObservation];
            for (int i = 0; i < this.includedObservation; )
            {
                for (int j = 0; j < this.seasonalLength; ++j)
                {
                    if (i + j != this.includedObservation)
                        term[i + j] = j;
                    else
                        break;
                }
                i += this.seasonalLength;
            }

            this.CalcSeasonalIndex();
        }
        /// <summary>
        /// Metode dekomposisi klasik dengan rasio pada rata-rata bergerak
        /// </summary>
        /// <param name="variable">SeriesVariable. variabel yang akan dianalisis</param>
        /// <param name="seasonalLength">Integer. panjang satu siklus musiman</param>
        /// <param name="isMultiplikatif">Bool. apakah menggunakan metode multiplikatif?</param>
        /// <param name="initialTrend">Integer. Inisial model tren yang digunakan, 1-Linear, 2-Quadratic, 3-Cubic, 4-Exponential</param>
        public DecompositionClassic(SeriesVariable variable, int seasonalLength, bool isMultiplicative, int initialTrend)
        {
            this.variable = variable;
            Vector var = new Vector(this.variable.SeriesValuesNoNaN.ToArray());
            this.y = new Vector(var.Tuples);
            for (int i = 0; i < y.Tuples; i++)
                this.y[i] = var[i];

            this.n = y.Tuples;
            this.seasonalLength = seasonalLength;

            this.trend = new double[this.n];
            this.detrend = new double[this.n];
            this.seasonal = new double[this.n];
            this.deseasonal = new double[this.n];
            this.predicted = new double[this.n];
            this.residual = new double[this.n];

            this.isMultiplicative = isMultiplicative;
            this.initialTrend = initialTrend;

            if (this.isMultiplicative)
                this.Multiplicative();
            else
                this.Additive();

            this.ForecastingError();
        }
        /// <summary>
        /// Constructor. Menghitung nilai keakuratan peramalan
        /// </summary>
        /// <param name="dataY">Vector. data actual</param>
        /// <param name="residual">ArrayDouble. residual</param>
        /// <param name="startIdx">Integer. data awal mulai penghitungan</param>
        /// <param name="endIdx">Integer. banyaknya jumlah observasi</param>
        public MeasuringForecastingError(Vector dataY, double[] residual, int startIdx, int endIdx)
        {
            this.y = dataY;
            this.e = residual;
            this.startIdx = startIdx;
            this.endIdx = endIdx;
            this.n = endIdx - startIdx;

            this.CalcSSE();
            this.CalcMSE();
            this.CalcMAE();
            this.CalcMPE();
            this.CalcMAPE();
        }
        /// <summary>
        /// Fungsi Virtual unutk mendapatkan turunan pertama pada fungsi 
        /// </summary>
        /// <param name="input">Vector. Vector parameter yang dimasukkan</param>
        /// <returns>double. hasil penghitungan fungsi sesuai nilai masukkannya</returns>
        public virtual Vector Gradient(Vector input)
        {
            Vector result = new Vector(input.Tuples);
            Vector vh = new Vector(input.Tuples);
            double h = 0.000001;

            for (int i = 0; i < input.Tuples; i++)
            {
                vh.InitializeAllValue(0);
                vh[i] = h;

                result[i] = (this.Function(input + vh) - this.Function(input)) / h;
            }

            return result;
        }
        /// <summary>
        /// Constructor. Pemulusan dengan metode Rata-Rata Bergerak Tunggal
        /// </summary>
        /// <param name="variable">SeriesVariable. variable</param>
        /// <param name="maLength">Integer. MA Length</param>
        public SingleMovingAverage(SeriesVariable variable, int maLength)
        {
            this.variable = variable;
            Vector var = new Vector(this.variable.SeriesValuesNoNaN.ToArray());
            this.Y = new Vector(var.Tuples);
            for (int i = 0; i < Y.Tuples; i++)
                this.Y[i] = var[i];

            this.n = Y.Tuples;
            this.t = maLength;

            this.smoothing1 = new double[this.n];
            this.predicted = new double[this.n];
            this.residual = new double[this.n];

            this.Smoothing();
            this.ForecastingError();
        }
        /// <summary>
        /// Constructor. Menghitung Pemulusan Eksponensial Tripel
        /// </summary>
        /// <param name="variable">SeriesVariable. variabel</param>
        /// <param name="alpha">Double. Smoothing constant for data</param>
        /// <param name="gamma">Double. Smoothing constant for trend</param>
        /// <param name="beta">Double. Smoothing constant for seasonal</param>
        /// <param name="seasonalLength">Integer. Panjang seasonal</param>
        public TripleExponentialSmoothingWinter(SeriesVariable variable, double alpha, double gamma, double beta, int seasonalLength, bool isMultiplicative)
        {
            this.variable = variable;
            Vector var = new Vector(this.variable.SeriesValuesNoNaN.ToArray());
            this.y = new Vector(var.Tuples);
            for (int i = 0; i < y.Tuples; i++)
                this.y[i] = var[i];

            this.n = this.y.Tuples;
            this.alpha = alpha;
            this.gamma = gamma;
            this.beta = beta;
            this.l = seasonalLength;

            this.isMultiplicative = isMultiplicative;

            this.smoothing = new double[this.n];
            this.trend = new double[this.n];
            this.seasonal = new double[this.n];
            this.predicted= new double[this.n];
            this.residual = new double[this.n];

            //term
            term = new int[this.n];
            for (int i = 0; i < this.n; )
            {
                for (int j = 0; j < this.l; ++j)
                {
                    if (i + j != this.n)
                        term[i + j] = j;
                    else
                        break;
                }
                i += this.l;
            }

            if(this.isMultiplicative)
                SmoothingMultiplicative();
            else
                SmoothingAdditive();

            ForecastingError();
        }
        /// <summary>
        /// Constructor. Pemulusan Eksponensial Ganda dengan metode Holt
        /// </summary>
        /// <param name="variable">SeriesVariable. variabel</param>
        /// <param name="alpha">Double. Smoothing constanta for data</param>
        /// <param name="gamma">Double. Smoothing constanta for trend</param>
        public DoubleExponentialSmoothingHolt(SeriesVariable variable, double alpha, double gamma)
        {
            this.variable = variable;
            Vector var = new Vector(this.variable.SeriesValuesNoNaN.ToArray());
            this.y = new Vector(var.Tuples);
            for (int i = 0; i < y.Tuples; i++)
                this.y[i] = var[i];

            this.n = this.y.Tuples;
            this.a = alpha;
            this.g = gamma;

            this.smoothing = new double[this.n];
            this.trend = new double[this.n];
            this.predicted = new double[this.n];
            this.residual = new double[this.n];

            this.Smoothing();
            this.ForecastingError();
        }
        /// <summary>
        /// Pemulusan dengan metode Rata-Rata Bergerak ganda
        /// </summary>
        /// <param name="variable">SeriesVariable. variabel yang akan dianalisis</param>
        /// <param name="maLength">Integer. MA Length</param>
        public DoubleMovingAverage(SeriesVariable variable, int maLength)
        {
            this.variable = variable;
            Vector var = new Vector(this.variable.SeriesValuesNoNaN.ToArray());
            this.y = new Vector(var.Tuples);
            for (int i = 0; i < y.Tuples; i++)
                y[i] = var[i];

            this.n = y.Tuples;
            this.t = maLength;

            this.smoothing1 = new double[n];
            this.smoothing2 = new double[n];
            this.at = new double[n];
            this.bt = new double[n];
            this.predicted = new double[n];
            this.residual = new double[n];

            Smoothing();
            ForecastingError();
        }
        /// <summary>
        /// Mendapatkan vektor proyeksi antara Vektor X dan Vektor Y
        /// </summary>
        /// <param name="X">Vector. Vektor X</param>
        /// <param name="Y">Vector. Vektor Y</param>
        /// <returns>Vector. Vektor proyeksi</returns>
        public static Vector ProjectionXonY(Vector X, Vector Y)
        {
            Vector result;

            if (X.Type == VectorType.ColumnVector && Y.Type == VectorType.ColumnVector)
            {
                Vector XT = X.GetTranspose();
                double proj = Vector.DoubleMultiply(XT, Y)/(Math.Pow(Y.Length,2));

                result = proj * Y;
            }
            else
            {
                throw new WrongVectorTypeException("Only Column Vector valid");
            }

            return result;
        }
        /// <summary>
        /// Melakukan perkalian matriks terhadap dua vektor
        /// </summary>
        /// <param name="a">Vector. vektor pertama</param>
        /// <param name="b">Vector. vektor kedua</param>
        /// <returns>Matrix. hasil perkalian matriks dua vektor</returns>
        public static Matrix MatrixMultiply(Vector a, Vector b)
        {
            Matrix result = new Matrix(a.Tuples, b.Tuples);

            if (CanMatrixMultiply(a, b))
            {
                for (int i = 0; i < a.Tuples; i++)
                    for (int j = 0; j < b.Tuples; j++)
                        result[i,j] = a[i] * b[j];
            }
            else
            {
                throw new WrongVectorSizeOrTypeException("Vector can't be matrix Multiplied");
            }

            return result;
        }
 /// <summary>
 /// Mengecek apakah dua vektor bertipe sama
 /// </summary>
 /// <param name="a">Vector. vektor pertama</param>
 /// <param name="b">Vector. vektor kedua</param>
 /// <returns>Boolean. Apakah dua vektor bertipe sama?</returns>
 public static bool IsSameType(Vector a, Vector b)
 {
     return (a.Type == b.Type);
 }
 /// <summary>
 /// Mengecek apakah dua vektor berukuran dan bertipe sama
 /// </summary>
 /// <param name="a">Vector. vektor pertama</param>
 /// <param name="b">Vector. vektor kedua</param>
 /// <returns>Boolean. Apakah dua vektor berukuran dan bertipe sama?</returns>
 public static bool IsSameSizeType(Vector a, Vector b)
 {
     return IsSameSize(a,b) && IsSameType(a,b) ;
 }
        /// <summary>
        /// Operator overloading. Operasi perkalian skalar
        /// (perkalian vektor dengan konstanta)
        /// </summary>
        /// <param name="constant">Double. konstanta</param>
        /// <param name="a">Vector. vektor</param>
        /// <returns>Vector. vektor hasil perkalian skalar</returns>
        public static Vector operator *(double constant, Vector a)
        {
            Vector result = new Vector(a.Tuples, a.Type);

            for (int i = 0; i < a.Tuples; i++)
                result[i] = constant * a[i];

            return result;
        }
 /// <summary>
 /// Fungsi Abstrak yang akan digunkakan pada setiap kelas turunannya sesuai fungsi masing-masing
 /// </summary>
 /// <param name="input">Vector. Vektor parameter yang dimasukkan</param>
 /// <returns>double. hasil penghitungan fungsi sesuai nilai masukkannya</returns>
 public abstract double Function(Vector input);
        /// <summary>
        /// Mendapatkan vektor transpose
        /// </summary>
        /// <returns>Vector. Vektor transpose</returns>
        /// <remarks>Vektor transpose didapat dengan mengganti tipe vektor
        /// dari baris menjadi kolom atau sebaliknya</remarks>
        public Vector GetTranspose()
        {
            VectorType newType;

            if (this.type == VectorType.ColumnVector)
                newType = VectorType.RowVector;
            else
                newType = VectorType.ColumnVector;

            Vector result = new Vector(this.tuples, newType);

            for (int i = 0; i < this.tuples; i++)
                result[i] = this.data[i];

            return result;
        }
 /// <summary>
 /// Mengecek apakah sebuah vektor dapat dikalikan dengan sebuah matriks
 /// </summary>
 /// <param name="a">Vector. Vektor</param>
 /// <param name="b">Matrix. Matriks</param>
 /// <returns>Boolean. apakah sebuah vektor dapat dikalikan
 /// dengan sebuah matriks?</returns>
 public static bool CanMultiply(Vector a, Matrix b)
 {
     return (a.Tuples == b.Rows) && (a.Type == VectorType.RowVector);
 }
        /// <summary>
        /// Mendapatkan sudut (dalam radian) antara dua vektor
        /// </summary>
        /// <param name="a">Vector. Vektor pertama</param>
        /// <param name="b">Vector. Vektor kedua</param>
        /// <returns>Double. Sudut antara dua vektor dalam radian</returns>
        public static double Angle(Vector a, Vector b)
        {
            double result;

            if (a.Type == VectorType.ColumnVector && b.Type == VectorType.ColumnVector)
            {
                Vector aT = a.GetTranspose();
                result = Vector.DoubleMultiply(aT, b);
                result /= a.Length * b.Length;
                result = Math.Acos(result);
            }
            else
            {
                throw new WrongVectorTypeException("Only Column Vector valid");
            }

            return result;
        }
 /// <summary>
 /// Mengecek apakah dua vektor dapat dilakukan perkalian matriks.
 /// Perkalian matriks adalah perkalian vektor kolom dengan vektor baris
 /// dimana menghasilkan sebuah matriks persegi.
 /// </summary>
 /// <param name="a">Vector. vektor pertama</param>
 /// <param name="b">Vector. vektor kedua</param>
 /// <returns>Boolean. apakah dua vektor dapat dilakukan perkalian matriks?</returns>
 public static bool CanMatrixMultiply(Vector a, Vector b)
 {
     return IsSameSize(a,b) && (a.Type == VectorType.ColumnVector)
         && (b.Type == VectorType.RowVector);
 }
        /// <summary>
        /// Operator overloading. Operasi pengurangan vektor
        /// </summary>
        /// <param name="a">Vector. Vektor pertama</param>
        /// <param name="b">Vector. Vektor kedua</param>
        /// <returns>Vector. Vektor hasil pengurangan</returns>
        public static Vector operator -(Vector a, Vector b)
        {
            Vector result = new Vector(a.Tuples, a.Type);

            if (IsSameSizeType(a, b))
            {
                for (int i = 0; i < a.Tuples; i++)
                    result[i] = a[i] - b[i];
            }
            else
            {
                throw new NotSameSizeVectorException();
            }

            return result;
        }
        /// <summary>
        /// Operator overloading. Operasi perkalian vektor dengan matriks
        /// </summary>
        /// <param name="a">Vector. Vektor</param>
        /// <param name="b">Matrix. Matriks</param>
        /// <returns>Vector. vektor hasil perkalian vektor dengan matriks.
        /// Berupa vektor baris</returns>
        public static Vector operator *(Vector a, Matrix b)
        {
            Vector result = new Vector(b.Cols, VectorType.RowVector);

            if (CanMultiply(a, b))
            {
                for (int i = 0; i < b.Cols; i++)
                {
                    result[i] = 0.0;
                    for (int j = 0; j < b.Rows; j++)
                    {
                        result[i] += a[j] * b[j, i];
                    }
                }
            }
            else
            {
                throw new WrongVectorSizeOrTypeException("Can't be multiplied");
            }

            return result;
        }
        /// <summary>
        /// Operator overloading. Operasi perkalian matriks dengan vektor
        /// </summary>
        /// <param name="a">Matrix. Matriks</param>
        /// <param name="b">Vector. Vektor</param>
        /// <returns>Vector. vektor hasil perkalian matriks dengan vektor.
        /// Berupa vektor kolom</returns>
        public static Vector operator *(Matrix a, Vector b)
        {
            Vector result = new Vector(a.Rows,VectorType.ColumnVector);

            if (CanMultiply(a, b))
            {
                for (int i = 0; i < a.Rows; i++)
                {
                    result[i] = 0.0;
                    for (int j = 0; j < a.Cols; j++)
                    {
                        result[i] += a[i, j] * b[j];
                    }
                }
            }
            else
            {
                throw new WrongVectorSizeOrTypeException("Can't be multiplied");
            }

            return result;
        }
        /// <summary>
        /// Mendapatkan copy dari vektor
        /// </summary>
        /// <returns>Vector. Copy dari vektor</returns>
        public Vector Copy()
        {
            Vector result = new Vector(this.tuples, this.type);

            for (int i = 0; i < this.tuples; i++)
                result[i] = this.data[i];

            return result;
        }
        /// <summary>
        /// Melakukan perkalian double terhadap dua vektor
        /// </summary>
        /// <param name="a">Vector. vektor pertama</param>
        /// <param name="b">Vector. vektor kedua</param>
        /// <returns>Double. hasil perkalian double dua vektor</returns>
        public static double DoubleMultiply(Vector a, Vector b)
        {
            double result=0.0;

            if (CanDoubleMultiply(a, b))
            {
                for (int i = 0; i < a.Tuples; i++)
                    result += a[i] * b[i];
            }
            else
            {
                throw new WrongVectorSizeOrTypeException("Vector can't be double Multiplied");
            }

            return result;
        }
 /// <summary>
 /// Mendapatkan vector data kuadrat vektor
 /// </summary>
 /// <returns>Vector. Vector data kuadrat</returns>
 public Vector GetDataSquare()
 {
     Vector result = new Vector(this.tuples);
     for (int i = 0; i < this.tuples; i++)
     {
         result[i] = this.data[i] * this.data[i]; ;
     }
     return result;
 }
        /// <summary>
        /// Mengecek apakah dua buah vektor perpendicular.
        /// Dua buah vektor perpendicular jika hasil perkalian doublenya 0
        /// </summary>
        /// <param name="a">Vector. Vektor pertama</param>
        /// <param name="b">Vector. Vektor kedua</param>
        /// <returns>Boolean. Apakah dua buah vektor perpendicular?</returns>
        public static bool IsPerpendicular(Vector a, Vector b)
        {
            bool result;

            if (a.Type == VectorType.ColumnVector && b.Type == VectorType.ColumnVector)
            {
                Vector aT = a.GetTranspose();
                result = Vector.DoubleMultiply(aT, b) == 0.0;
            }
            else
            {
                throw new WrongVectorTypeException("Only Column Vector valid");
            }

            return result;
        }
 //r = Cov(x,y)/(StandardDeviation(x)*StandardDeviation(y))
 private double computePearsonCorr(Vector x, Vector y)
 {
     int n = x.Tuples;
     Vector xy = new Vector(n);
     for (int i = 0; i < n; i++)
         xy[i] = x[i] * y[i];
     double sumxy = xy.GetSumData();
     double xbar = x.GetSumData() / (double)n;
     double ybar = y.GetSumData() / (double)n;
     double covxy = (sumxy - n * xbar * ybar) / (double)(n - 1);
     Vector x2 = x.GetDataSquare();
     Vector y2 = y.GetDataSquare();
     double varx = (n * x2.GetSumData() - Math.Pow(x.GetSumData(), 2.0)) / (double)(n * (n - 1));
     double vary = (n * y2.GetSumData() - Math.Pow(y.GetSumData(), 2.0)) / (double)(n * (n - 1));
     return covxy / Math.Sqrt(varx * vary);
 }
 /// <summary>
 /// Mengecek apakah dua vektor berukuran sama
 /// </summary>
 /// <param name="a">Vector. vektor pertama</param>
 /// <param name="b">Vector. vektor kedua</param>
 /// <returns>Boolean. Apakah dua vektor berukuran sama?</returns>
 public static bool IsSameSize(Vector a, Vector b)
 {
     return (a.Tuples == b.Tuples);
 }
 /// <summary>
 /// Mengecek apakah sebuah matriks dapat dikalikan dengan sebuah vektor
 /// </summary>
 /// <param name="a">Matrix. Matriks</param>
 /// <param name="b">Vector. Vektor</param>
 /// <returns>Boolean. apakah sebuah matriks dapat dikalikan
 /// dengan sebuah vektor?</returns>
 public static bool CanMultiply(Matrix a, Vector b)
 {
     return (a.Cols == b.Tuples) && (b.Type == VectorType.ColumnVector);
 }
        /// <summary>
        /// Linear regression with Y and one or more independent variables
        /// equation: y = b0 + b1x1 + b2x2 + ... + b(p-1)x(p-1) + e
        /// equation in matrix form: Y = XB + E
        /// </summary>
        /// <param name="dependent">SeriesVariable. dependent variable</param>
        /// <param name="independents">SeriesVariables. independent variable</param>
        public LinearRegressionModel(SeriesVariable dependent, SeriesVariables independents)
        {
            //Vector vY = new Vector(dependent.SeriesValuesNoNaN.ToArray());
            //int n = vY.Tuples;
            //int p = independents.Count + 1;
            //Matrix mX = new Matrix(n, p);
            //for (int i = 0; i < p; i++) //kolom
            //{
            //    for (int j = 0; j < n; j++) //baris
            //    {
            //        if (i == 0)
            //            mX[j, i] = 1.0;
            //        else
            //            mX[j, i] = independents[i - 1][j];
            //    }
            //}

            // changed to deal with missing values
            Vector vY = new Vector(dependent.SeriesValuesNoNaN.ToArray());
            int n = vY.Tuples;
            int p = independents.Count + 1;
            Matrix mX = new Matrix(n, p);
            for (int i = 0; i < p; i++) //kolom
            {
                for (int j = 0; j < n; j++) //baris
                {
                    if (i == 0)
                        mX[j, i] = 1.0;
                    else
                        mX[j, i] = independents[i - 1].SeriesValuesNoNaN[j];
                }
            }

            this.lse = new LeastSquareEstimator(mX, vY);

            this.f = this.lse.MSR / this.lse.MSE;
            this.sigOfF = Distribution.F.PValue(this.f, p - 1, n - p);

            double sumOfEtMinusEt_1Square = 0;
            double sumOfESquare = this.lse.ESquare[0];
            for (int i = 1; i < n; i++)
            {
                sumOfEtMinusEt_1Square += Math.Pow(this.lse.E[i] - this.lse.E[i - 1],2.0);
                sumOfESquare += this.lse.ESquare[i];
            }
            this.durbinWatson = sumOfEtMinusEt_1Square / sumOfESquare;

            this.stdErrorOfParameters = new double[p];
            this.t = new double[p];
            this.sigOfT = new double[p];
            this.lbOfParameters = new double[p];
            this.ubOfParameters = new double[p];
            for (int i = 0; i < p; i++)
            {
                this.stdErrorOfParameters[i] = Math.Sqrt(this.lse.SbSquare[i, i]);
                this.t[i] = this.lse.B[i] / this.stdErrorOfParameters[i];
                this.sigOfT[i] = Distribution.T.PValue(this.t[i], n - p, Distribution.T.TestType.TwoSided);
                double error = Distribution.T.InversCDF(0.975, n - p);
                this.ubOfParameters[i] = this.lse.B[i] + error * this.stdErrorOfParameters[i];
                this.lbOfParameters[i] = this.lse.B[i] - error * this.stdErrorOfParameters[i];
            }

            this.vifForPredictors = new double[p - 1];
            this.partialCorr = new double[p - 1];
            this.corr = new double[p - 1];
            for (int i = 1; i < p; i++)
            {
                Vector y = new Vector(mX.GetColData(i));
                Matrix x = new Matrix(n, p - 1);
                int col = 0;
                for (int j = 0; j < p; j++)
                {
                    if (j != i)
                    {
                        for (int k = 0; k < n; k++)
                        {
                            x[k, col] = mX[k, j];
                        }
                        col++;
                    }
                }
                Matrix xtx = x.GetTranspose() * x;
                Vector xty = x.GetTranspose() * y;
                Vector b = xtx.Solve(xty);
                Matrix mJ = new Matrix(n, n);
                mJ.InitializeAllValue(1.0);
                double yty = Vector.DoubleMultiply(y.GetTranspose(), y);
                Vector jy = mJ * y;
                double ssto = yty - Vector.DoubleMultiply(y.GetTranspose(), jy) / n;
                double sse = yty - Vector.DoubleMultiply(b.GetTranspose(), xty);
                double ssr = ssto - sse;
                double rSquare = ssr / ssto;
                this.vifForPredictors[i - 1] = 1 / (1 - rSquare);
                this.corr[i - 1] = computePearsonCorr(vY,y);

                Vector xty2 = x.GetTranspose() * vY;
                Vector b2 = xtx.Solve(xty2);
                double yty2 = Vector.DoubleMultiply(vY.GetTranspose(), vY);
                double sse2 = yty2 - Vector.DoubleMultiply(b2.GetTranspose(), xty2);
                double partDetermination = (sse2 - this.lse.SSE) / sse2;
                this.partialCorr[i - 1] = Math.Sqrt(partDetermination);

            }

            this.expectedResidual = new double[n];
            for (int k = 1; k <= n; k++)
            {
                this.expectedResidual[k - 1] = this.lse.StandardError * Distribution.Normal.InversCDF((k - 0.375) / (n + 0.25));
            }
        }