// Compute a single eigenvector, which amounts to computing column c
        // of matrix Q.  The reflections and rotations are applied incrementally.
        // This is useful when you want only a small number of the eigenvectors.
        public void GetEigenvector(int c, double[] eigenvector)
        {
            if (0 <= c && c < mSize)
            {
                // y = H*x, then x and y are swapped for the next H
                double[] x = eigenvector;
                double[] y = mPVector;

                // Start with the Euclidean basis vector.
                Array.Clear(x, 0, mSize);
                if (mPermutation[c] >= 0)
                {
                    x[mPermutation[c]] = 1;
                }
                else
                {
                    x[c] = 1;
                }

                // Apply the Givens rotations.
                // [RMS] C# doesn't support reverse iterator so I replaced w/ loop...right?
                //typename std::vector < GivensRotation >::const_reverse_iterator givens = mGivens.rbegin();
                //for (/**/; givens != mGivens.rend(); ++givens) {
                for (int i = mGivens.Count - 1; i >= 0; --i)
                {
                    GivensRotation givens = mGivens[i];
                    double         xr     = x[givens.index];
                    double         xrp1   = x[givens.index + 1];
                    double         tmp0   = givens.cs * xr + givens.sn * xrp1;
                    double         tmp1   = -givens.sn * xr + givens.cs * xrp1;
                    x[givens.index]     = tmp0;
                    x[givens.index + 1] = tmp1;
                }

                // Apply the Householder reflections.
                for (int i = mSize - 3; i >= 0; --i)
                {
                    // Get the Householder vector v.
                    //double const* column = &mMatrix[i];
                    ArrayAlias <double> column = new ArrayAlias <double>(mMatrix, i);
                    double twoinvvdv           = column[mSize * (i + 1)];
                    int    r;
                    for (r = 0; r < i + 1; ++r)
                    {
                        y[r] = x[r];
                    }

                    // Compute s = Dot(x,v) * 2/v^T*v.
                    double s = x[r];  // r = i+1, v[i+1] = 1
                    for (int j = r + 1; j < mSize; ++j)
                    {
                        s += x[j] * column[mSize * j];
                    }
                    s *= twoinvvdv;

                    y[r] = x[r] - s;  // v[i+1] = 1

                    // Compute the remaining components of y.
                    for (++r; r < mSize; ++r)
                    {
                        y[r] = x[r] - s * column[mSize * r];
                    }

                    //std::swap(x, y);
                    var tmp = x; x = y; y = tmp;
                }
                // The final product is stored in x.

                if (x != eigenvector)
                {
                    Array.Copy(x, eigenvector, mSize);
                }
            }
        }
        // Accumulate the Householder reflections and Givens rotations to produce
        // the orthogonal matrix Q for which Q^T*A*Q = D.  The input
        // 'eigenvectors' must be NxN and stored in row-major order.
        public void GetEigenvectors(double[] eigenvectors)
        {
            if (eigenvectors != null && mSize > 0)
            {
                // Start with the identity matrix.
                Array.Clear(eigenvectors, 0, mSize * mSize);
                for (int d = 0; d < mSize; ++d)
                {
                    eigenvectors[d + mSize * d] = 1;
                }

                // Multiply the Householder reflections using backward accumulation.
                int r, c;
                for (int i = mSize - 3, rmin = i + 1; i >= 0; --i, --rmin)
                {
                    // Copy the v vector and 2/Dot(v,v) from the matrix.
                    //double const* column = &mMatrix[i];
                    ArrayAlias <double> column = new ArrayAlias <double>(mMatrix, i);
                    double twoinvvdv           = column[mSize * (i + 1)];
                    for (r = 0; r < i + 1; ++r)
                    {
                        mVVector[r] = 0;
                    }
                    mVVector[r] = 1;
                    for (++r; r < mSize; ++r)
                    {
                        mVVector[r] = column[mSize * r];
                    }

                    // Compute the w vector.
                    for (r = 0; r < mSize; ++r)
                    {
                        mWVector[r] = 0;
                        for (c = rmin; c < mSize; ++c)
                        {
                            mWVector[r] += mVVector[c] * eigenvectors[r + mSize * c];
                        }
                        mWVector[r] *= twoinvvdv;
                    }

                    // Update the matrix, Q <- Q - v*w^T.
                    for (r = rmin; r < mSize; ++r)
                    {
                        for (c = 0; c < mSize; ++c)
                        {
                            eigenvectors[c + mSize * r] -= mVVector[r] * mWVector[c];
                        }
                    }
                }

                // Multiply the Givens rotations.
                foreach (GivensRotation givens in mGivens)
                {
                    for (r = 0; r < mSize; ++r)
                    {
                        int    j    = givens.index + mSize * r;
                        double q0   = eigenvectors[j];
                        double q1   = eigenvectors[j + 1];
                        double prd0 = givens.cs * q0 - givens.sn * q1;
                        double prd1 = givens.sn * q0 + givens.cs * q1;
                        eigenvectors[j]     = prd0;
                        eigenvectors[j + 1] = prd1;
                    }
                }

                mIsRotation = 1 - (mSize & 1);
                if (mPermutation[0] >= 0)
                {
                    // Sorting was requested.
                    Array.Clear(mVisited, 0, mVisited.Length);
                    for (int i = 0; i < mSize; ++i)
                    {
                        if (mVisited[i] == 0 && mPermutation[i] != i)
                        {
                            // The item starts a cycle with 2 or more elements.
                            mIsRotation = 1 - mIsRotation;
                            int start = i, current = i, j, next;
                            for (j = 0; j < mSize; ++j)
                            {
                                mPVector[j] = eigenvectors[i + mSize * j];
                            }
                            while ((next = mPermutation[current]) != start)
                            {
                                mVisited[current] = 1;
                                for (j = 0; j < mSize; ++j)
                                {
                                    eigenvectors[current + mSize * j] =
                                        eigenvectors[next + mSize * j];
                                }
                                current = next;
                            }
                            mVisited[current] = 1;
                            for (j = 0; j < mSize; ++j)
                            {
                                eigenvectors[current + mSize * j] = mPVector[j];
                            }
                        }
                    }
                }
            }
        }