public void Test02()
        {
            const double angle = Math.PI / 6;
            Matrix X = new Matrix(new RowVector(Math.Cos(angle), -Math.Sin(angle), 0),
                                    new RowVector(Math.Sin(angle), Math.Cos(angle), 0),
                                    new RowVector(0, 0, 1));

            EigenvalueDecomposition evd = new EigenvalueDecomposition(X);
            evd.Sort(EigenvalueDecomposition.SortOrder.Descending);

            Assert.IsTrue(evd.HasComplexValue);

            List<Complex> cv = new List<Complex>();
            int count = evd.RealEigenvalues.Size;
            for (int i = 0; i < count; ++i)
            {
                cv.Add(new Complex(evd.RealEigenvalues[i], evd.ImaginaryEigenvalues[i]));
            }

            Assert.AreEqual(1, (cv[0] * cv[1] * cv[2]).Size, LisysConfig.CalculationLowerLimit);

            Assert.AreEqual(new Complex(1, 0), cv[0]);
            Assert.AreEqual(new Complex(Math.Cos(angle), -Math.Sin(angle)), cv[1]);
            Assert.AreEqual(new Complex(Math.Cos(angle),  Math.Sin(angle)), cv[2]);
        }
        /// <summary>
        /// �s�� X �Ɏ听�����͂�K�p����D
        /// </summary>
        /// <param name="X">
        /// <para>[n, d]�̍s��i�����������邱�Ƃ͂Ȃ��j</para>
        /// <para>�f�[�^���Fn�C�������Fd�Ƃ����Ƃ��C�s�� X �̌`���� n�~d �łȂ���΂Ȃ�Ȃ��D</para>
        /// </param>
        /// <param name="varType">���U�̎��</param>
        public PrincipalComponentAnalysis(Matrix X, VarianceType varType)
        {
            Matrix _X = new Matrix(X);

            // �e�ϐ��̕��ϒl��0�ɂ���
            Vector colAvg = _X.ColumnAverages;
            _X.Columns.ForEach(delegate(int i, IVector v)
            {
                v.ForEach(delegate(ref double val)
                {
                    val -= colAvg[i];
                });
            });

            // ���U�E�����U�s��
            Matrix S = Matrix.Transpose(_X) * _X;
            if (varType == VarianceType.DivN)
            {
                S /= _X.RowSize;
            }
            else
            {
                S /= (_X.RowSize - 1);
            }

            // �ŗL�l����
            EigenvalueDecomposition evd = new EigenvalueDecomposition(S);
            evd.Sort(EigenvalueDecomposition.SortOrder.Descending);

            this.eigenvalues = evd.RealEigenvalues;
            this.eigenvectors = evd.RealEigenvectors;
        }
        /// <summary>
        /// ���ʊ֐��i�W���x�N�g���j����߂�D
        /// </summary>
        /// <param name="Xs">
        /// <para>�e�S��Matrix�I�u�W�F�N�g�i�e�s�̓f�[�^�ɁC�e��͊e�ϐ��ɑΉ�����j�̔z��</para>
        /// <para>
        /// 1�‚̌Q�f�[�^�́C1�‚�<see cref="Matrix"/>�I�u�W�F�N�g�ł���킳��Ă���C
        /// �{�����ɂ�菑���������邱�Ƃ͂Ȃ��iread-only�j�D
        /// </para>
        /// </param>
        public MultipleDiscriminantAnalysis(Matrix[] Xs)
        {
            int C = Xs.Length;          // �Q��
            int[] ns = new int[C];      // �e�Q�̃f�[�^��
            int p = Xs[0].ColumnSize;   // ������

            // �e�S�̃f�[�^����擾
            for (int k = 0; k < C; ++k)
            {
                ns[k] = Xs[k].RowSize;
            }

            Vector tAvg = new Vector(p);    // �S�f�[�^�ɂ�����e�����̕��ϒl
            tAvg.Zero();

            int tN = 0; // �S�f�[�^��

            Vector[] avgs = new Vector[C];  // �e�Q�ɂ�����e�����̕��ϒl
            for (int k = 0; k < C; ++k)
            {
                tN += Xs[k].RowSize;
                avgs[k] = Xs[k].ColumnAverages;

                tAvg.ForEach(delegate(int i, ref double val)
                {
                    val += Xs[k].Columns[i].Sum;
                });
            }
            tAvg /= tN;

            Matrix B = new Matrix(p, p);
            for (int k = 0; k < C; ++k)
            {
                IVector dv = avgs[k] - tAvg;
                B += (ns[k] * new ColumnVector(dv) * new RowVector(dv));
            }

            Matrix W = new Matrix(p, p);
            for (int k = 0; k < C; ++k)
            {
                for (int i = 0; i < ns[k]; ++i)
                {
                    IVector dv = Xs[k].Rows[i] - avgs[k];
                    W += (new ColumnVector(dv) * new RowVector(dv));
                }
            }

            EigenvalueDecomposition evd = new EigenvalueDecomposition(Matrix.Inverse(W) * B);
            evd.Sort(EigenvalueDecomposition.SortOrder.Descending);

            this.eigenvalues = evd.RealEigenvalues;
            this.eigenvectors = evd.RealEigenvectors;
        }
        public void Test01()
        {
            Matrix X = new Matrix(  new RowVector(1, 0, 2),
                                    new RowVector(0, 1, 0),
                                    new RowVector(2, 0, 1));

            Assert.IsTrue(X.IsSymmetric);

            EigenvalueDecomposition evd = new EigenvalueDecomposition(X);
            evd.Sort(EigenvalueDecomposition.SortOrder.Descending);

            Assert.AreEqual( 3, evd.RealEigenvalues[0], LisysConfig.CalculationLowerLimit);
            Assert.AreEqual( 1, evd.RealEigenvalues[1], LisysConfig.CalculationLowerLimit);
            Assert.AreEqual(-1, evd.RealEigenvalues[2], LisysConfig.CalculationLowerLimit);

            Assert.AreEqual(new Vector(1 / Math.Sqrt(2), 0, 1 / Math.Sqrt(2)), evd.RealEigenvectors[0]);
            Assert.AreEqual(new Vector(0, 1, 0), evd.RealEigenvectors[1]);
            Assert.AreEqual(new Vector(-1 / Math.Sqrt(2), 0, 1 / Math.Sqrt(2)), evd.RealEigenvectors[2]);
        }