/**
         * <p>
         * Computes the inner product between a vector and the conjugate of another one.
         * <br>
         * <br>
         * &sum;<sub>k=1:n</sub> x<sub>k</sub> * conj(y<sub>k</sub>)<br>
         * where x and y are vectors with n elements.
         * </p>
         *
         * <p>
         * These functions are often used inside of highly optimized code and therefor sanity checks are
         * kept to a minimum.  It is not recommended that any of these functions be used directly.
         * </p>
         *
         * @param x A vector with n elements. Not modified.
         * @param y A vector with n elements. Not modified.
         * @return The inner product of the two vectors.
         */
        public static Complex_F32 innerProdH(CMatrixRMaj x, CMatrixRMaj y, Complex_F32 output)
        {
            if (output == null)
            {
                output = new Complex_F32();
            }
            else
            {
                output.real = output.imaginary = 0;
            }

            int m = x.getDataLength();

            for (int i = 0; i < m; i += 2)
            {
                float realX = x.data[i];
                float imagX = x.data[i + 1];

                float realY = y.data[i];
                float imagY = -y.data[i + 1];

                output.real      += realX * realY - imagX * imagY;
                output.imaginary += realX * imagY + imagX * realY;
            }

            return(output);
        }
Example #2
0
        /**
         * Computes the householder vector used in QR decomposition.
         *
         * u = x / max(x)
         * u(0) = u(0) + |u|
         * u = u / u(0)
         *
         * @param x Input vector.  Unmodified.
         * @return The found householder reflector vector
         */
        public static CMatrixRMaj householderVector(CMatrixRMaj x)
        {
            CMatrixRMaj u = (CMatrixRMaj)x.copy();

            float max = CommonOps_CDRM.elementMaxAbs(u);

            CommonOps_CDRM.elementDivide(u, max, 0, u);

            float       nx = NormOps_CDRM.normF(u);
            Complex_F32 c  = new Complex_F32();

            u.get(0, 0, c);

            float realTau, imagTau;

            if (c.getMagnitude() == 0)
            {
                realTau = nx;
                imagTau = 0;
            }
            else
            {
                realTau = c.real / c.getMagnitude() * nx;
                imagTau = c.imaginary / c.getMagnitude() * nx;
            }

            u.set(0, 0, c.real + realTau, c.imaginary + imagTau);
            CommonOps_CDRM.elementDivide(u, u.getReal(0, 0), u.getImag(0, 0), u);

            return(u);
        }
Example #3
0
        public static void assertEquals(CMatrix A, CMatrix B, float tol)
        {
            assertShape(A, B);

            Complex_F32 a = new Complex_F32();
            Complex_F32 b = new Complex_F32();

            for (int i = 0; i < A.getNumRows(); i++)
            {
                for (int j = 0; j < A.getNumCols(); j++)
                {
                    A.get(i, j, a);
                    B.get(i, j, b);

                    assertTrue(!float.IsNaN(a.real) && !float.IsNaN(b.real),
                               "Real At (" + i + "," + j + ") A = " + a.real + " B = " + b.real);
                    assertTrue(!float.IsInfinity(a.real) && !float.IsInfinity(b.real),
                               "Real At (" + i + "," + j + ") A = " + a.real + " B = " + b.real);
                    assertTrue(Math.Abs(a.real - b.real) <= tol,
                               "Real At (" + i + "," + j + ") A = " + a.real + " B = " + b.real);

                    assertTrue(!float.IsNaN(a.imaginary) && !float.IsNaN(b.imaginary),
                               "Img At (" + i + "," + j + ") A = " + a.imaginary + " B = " + b.imaginary);
                    assertTrue(!float.IsInfinity(a.imaginary) && !float.IsInfinity(b.imaginary),
                               "Img At (" + i + "," + j + ") A = " + a.imaginary + " B = " + b.imaginary);
                    assertTrue(Math.Abs(a.imaginary - b.imaginary) <= tol,
                               "Img At (" + i + "," + j + ") A = " + a.imaginary + " B = " + b.imaginary);
                }
            }
        }
Example #4
0
        /**
         * <p>
         * Checks to see if the matrix is positive semidefinite:
         * </p>
         * <p>
         * x<sup>T</sup> A x &ge; 0<br>
         * for all x where x is a non-zero vector and A is a symmetric matrix.
         * </p>
         *
         * @param A square symmetric matrix. Not modified.
         *
         * @return True if it is positive semidefinite and false if it is not.
         */
        public static bool isPositiveSemidefinite(FMatrixRMaj A)
        {
            if (!isSquare(A))
            {
                return(false);
            }

            EigenDecomposition_F32 <FMatrixRMaj> eig = DecompositionFactory_FDRM.eig(A.numCols, false);

            if (eig.inputModified())
            {
                A = (FMatrixRMaj)A.copy();
            }
            eig.decompose(A);

            for (int i = 0; i < A.numRows; i++)
            {
                Complex_F32 v = eig.getEigenvalue(i);

                if (v.getReal() < 0)
                {
                    return(false);
                }
            }

            return(true);
        }
Example #5
0
        /**
         * <p>Hermitian matrix is a square matrix with complex entries that are equal to its own conjugate transpose.</p>
         *
         * <p>a[i,j] = conj(a[j,i])</p>
         *
         * @param Q The matrix being tested. Not modified.
         * @param tol Tolerance.
         * @return True if it passes the test.
         */
        public static bool isHermitian(CMatrixRMaj Q, float tol)
        {
            if (Q.numCols != Q.numRows)
            {
                return(false);
            }

            Complex_F32 a = new Complex_F32();
            Complex_F32 b = new Complex_F32();

            for (int i = 0; i < Q.numCols; i++)
            {
                for (int j = i; j < Q.numCols; j++)
                {
                    Q.get(i, j, a);
                    Q.get(j, i, b);

                    if (Math.Abs(a.real - b.real) > tol)
                    {
                        return(false);
                    }
                    if (Math.Abs(a.imaginary + b.imaginary) > tol)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
Example #6
0
        /**
         * <p>
         * Puts all the real eigenvectors into the columns of a matrix.  If an eigenvalue is imaginary
         * then the corresponding eigenvector will have zeros in its column.
         * </p>
         *
         * @param eig An eigenvalue decomposition which has already decomposed a matrix.
         * @return An m by m matrix containing eigenvectors in its columns.
         */
        public static FMatrixRMaj createMatrixV(EigenDecomposition_F32 <FMatrixRMaj> eig)
        {
            int N = eig.getNumberOfEigenvalues();

            FMatrixRMaj V = new FMatrixRMaj(N, N);

            for (int i = 0; i < N; i++)
            {
                Complex_F32 c = eig.getEigenvalue(i);

                if (c.isReal())
                {
                    FMatrixRMaj v = eig.getEigenVector(i);

                    if (v != null)
                    {
                        for (int j = 0; j < N; j++)
                        {
                            V.set(j, i, v.get(j, 0));
                        }
                    }
                }
            }

            return(V);
        }
Example #7
0
        public static void print(Stream output, CMatrix mat, string format)
        {
            string type = "dense32";

            Console.WriteLine("Type = " + type + " complex , numRows = " + mat.getNumRows() + " , numCols = " +
                              mat.getNumCols());

            format += " ";

            Complex_F32 c = new Complex_F32();

            for (int y = 0; y < mat.getNumRows(); y++)
            {
                for (int x = 0; x < mat.getNumCols(); x++)
                {
                    mat.get(y, x, c);
                    Console.Write(format, c.real, c.imaginary);
                    if (x < mat.getNumCols() - 1)
                    {
                        Console.Write(" , ");
                    }
                }
                Console.WriteLine();
            }
        }
        /**
         * Performs the following operations:
         * <pre>
         * x = x / max
         * tau = x0*|x|/|xo|   adjust sign to avoid cancellation
         * u = x; u0 = x0 + tau; u = u/u0  (x is not divided by x0)
         * gamma = 2/|u|^2
         * </pre>
         * Note that u is not explicitly computed here.
         *
         * @param start Element in 'u' that it starts at.
         * @param stop Element in 'u' that it stops at.
         * @param x Array
         * @param max Max value in 'u' that is used to normalize it.
         * @param tau Storage for tau
         * @return Returns gamma
         */
        public static float computeTauGammaAndDivide(int start, int stop,
                                                     float[] x, float max,
                                                     Complex_F32 tau)
        {
            int   index = start * 2;
            float nx    = 0;

            for (int i = start; i < stop; i++)
            {
                float realX = x[index++] /= max;
                float imagX = x[index++] /= max;

                nx += realX * realX + imagX * imagX;
            }

            nx = (float)Math.Sqrt(nx);

            float real_x0 = x[2 * start];
            float imag_x0 = x[2 * start + 1];
            float mag_x0  = (float)Math.Sqrt(real_x0 * real_x0 + imag_x0 * imag_x0);

            // TODO Could stability be improved by computing theta so that this
            // special case doesn't need to be handled?
            if (mag_x0 == 0)
            {
                tau.real      = nx;
                tau.imaginary = 0;
            }
            else
            {
                tau.real      = real_x0 / mag_x0 * nx;
                tau.imaginary = imag_x0 / mag_x0 * nx;
            }

            float top, bottom;

            // if there is a chance they can cancel swap the sign
            // TODO not sure if this is right...
            float m0 = mag(real_x0 + tau.real, imag_x0 + tau.imaginary);
            float m1 = mag(real_x0 - tau.real, imag_x0 - tau.imaginary);

            // if ( real_x0*tau.real<0) { // This is the previous rule until the m0 m1 code came into play
            if (m1 > m0)
            {
                tau.real      = -tau.real;
                tau.imaginary = -tau.imaginary;
                top           = nx * nx - nx * mag_x0;
                bottom        = mag_x0 * mag_x0 - 2.0f * nx * mag_x0 + nx * nx;
            }
            else
            {
                top    = nx * nx + nx * mag_x0;
                bottom = mag_x0 * mag_x0 + 2.0f * nx * mag_x0 + nx * nx;
            }

            return(bottom / top); // gamma
        }
        private void checkSplitPerformImplicit()
        {
            // check for splits
            for (int i = x2; i > x1; i--)
            {
                if (_implicit.isZero(i, i - 1))
                {
                    x1 = i;
                    splits[numSplits++] = i - 1;
                    // reduce the scope of what it is looking at
                    return;
                }
            }
            // first try using known eigenvalues in the same order they were originally found
            if (onscript)
            {
                if (_implicit.steps > _implicit.exceptionalThreshold / 2)
                {
                    onscript = false;
                }
                else
                {
                    Complex_F32 a = origEigenvalues[indexVal];

                    // if no splits are found perform an _implicit step
                    if (a.isReal())
                    {
                        _implicit.performImplicitSingleStep(x1, x2, a.getReal());
                    }
                    else if (x2 - x1 >= 1 && x1 + 2 < N)
                    {
                        _implicit.performImplicitDoubleStep(x1, x2, a.real, a.imaginary);
                    }
                    else
                    {
                        onscript = false;
                    }
                }
            }
            else
            {
                // that didn't work so try a modified order
                if (x2 - x1 >= 1 && x1 + 2 < N)
                {
                    _implicit.implicitDoubleStep(x1, x2);
                }
                else
                {
                    _implicit.performImplicitSingleStep(x1, x2, _implicit.A.get(x2, x2));
                }
            }
        }
Example #10
0
        public static void assertEquals(Complex_F32 a, Complex_F32 b, float tol)
        {
            assertTrue(!float.IsNaN(a.real) && !float.IsNaN(b.real), "real a = " + a.real + " b = " + b.real);
            assertTrue(!float.IsInfinity(a.real) && !float.IsInfinity(b.real), "real a = " + a.real + " b = " + b.real);
            assertTrue(Math.Abs(a.real - b.real) <= tol, "real a = " + a.real + " b = " + b.real);

            assertTrue(!float.IsNaN(a.imaginary) && !float.IsNaN(b.imaginary),
                       "imaginary a = " + a.imaginary + " b = " + b.imaginary);
            assertTrue(!float.IsInfinity(a.imaginary) && !float.IsInfinity(b.imaginary),
                       "imaginary a = " + a.imaginary + " b = " + b.imaginary);
            assertTrue(Math.Abs(a.imaginary - b.imaginary) <= tol,
                       "imaginary a = " + a.imaginary + " b = " + b.imaginary);
        }
Example #11
0
        /**
         * <p>
         * A diagonal matrix where real diagonal element contains a real eigenvalue.  If an eigenvalue
         * is imaginary then zero is stored in its place.
         * </p>
         *
         * @param eig An eigenvalue decomposition which has already decomposed a matrix.
         * @return A diagonal matrix containing the eigenvalues.
         */
        public static FMatrixRMaj createMatrixD(EigenDecomposition_F32 <FMatrixRMaj> eig)
        {
            int N = eig.getNumberOfEigenvalues();

            FMatrixRMaj D = new FMatrixRMaj(N, N);

            for (int i = 0; i < N; i++)
            {
                Complex_F32 c = eig.getEigenvalue(i);

                if (c.isReal())
                {
                    D.set(i, i, c.real);
                }
            }

            return(D);
        }
        public bool extractVectors(FMatrixRMaj Q_h)
        {
            //Arrays.fill(eigenvectorTemp.data, 0);
            Array.Clear(eigenvectorTemp.data, 0, eigenvectorTemp.data.Length);

            // extract eigenvectors from the shur matrix
            // start at the top left corner of the matrix
            bool triangular = true;

            for (int i = 0; i < N; i++)
            {
                Complex_F32 c = _implicit.eigenvalues[N - i - 1];

                if (triangular && !c.isReal())
                {
                    triangular = false;
                }

                if (c.isReal() && eigenvectors[N - i - 1] == null)
                {
                    solveEigenvectorDuplicateEigenvalue(c.real, i, triangular);
                }
            }

            // translate the eigenvectors into the frame of the original matrix
            if (Q_h != null)
            {
                FMatrixRMaj temp = new FMatrixRMaj(N, 1);
                for (int i = 0; i < N; i++)
                {
                    FMatrixRMaj v = eigenvectors[i];

                    if (v != null)
                    {
                        CommonOps_FDRM.mult(Q_h, v, temp);
                        eigenvectors[i] = temp;
                        temp            = v;
                    }
                }
            }

            return(true);
        }
        private void solveEigenvectorDuplicateEigenvalue(float real, int first, bool isTriangle)
        {
            float scale = Math.Abs(real);

            if (scale == 0)
            {
                scale = 1;
            }

            eigenvectorTemp.reshape(N, 1, false);
            eigenvectorTemp.zero();

            if (first > 0)
            {
                if (isTriangle)
                {
                    solveUsingTriangle(real, first, eigenvectorTemp);
                }
                else
                {
                    solveWithLU(real, first, eigenvectorTemp);
                }
            }

            eigenvectorTemp.reshape(N, 1, false);

            for (int i = first; i < N; i++)
            {
                Complex_F32 c = _implicit.eigenvalues[N - i - 1];

                if (c.isReal() && Math.Abs(c.real - real) / scale < 100.0f * UtilEjml.F_EPS)
                {
                    eigenvectorTemp.data[i] = 1;

                    FMatrixRMaj v = new FMatrixRMaj(N, 1);
                    CommonOps_FDRM.multTransA(Q, eigenvectorTemp, v);
                    eigenvectors[N - i - 1] = v;
                    NormOps_FDRM.normalizeF(v);

                    eigenvectorTemp.data[i] = 0;
                }
            }
        }
Example #14
0
        public void setup(FMatrixRMaj A)
        {
            if (A.numRows != A.numCols)
            {
                throw new InvalidOperationException("Must be square");
            }

            if (N != A.numRows)
            {
                N = A.numRows;

                this.A = (FMatrixRMaj)A.copy();
                u      = new FMatrixRMaj(A.numRows, 1);

                _temp        = new FMatrixRMaj(A.numRows, 1);
                numStepsFind = new int[A.numRows];
            }
            else
            {
                this.A.set(A);
                UtilEjml.memset(numStepsFind, 0, numStepsFind.Length);
            }

            // zero all the off numbers that should be zero for a hessenberg matrix
            for (int i = 2; i < N; i++)
            {
                for (int j = 0; j < i - 1; j++)
                {
                    this.A.set(i, j, 0);
                }
            }

            eigenvalues = new Complex_F32[A.numRows];
            for (int i = 0; i < eigenvalues.Length; i++)
            {
                eigenvalues[i] = new Complex_F32();
            }

            numEigen        = 0;
            lastExceptional = 0;
            numExceptional  = 0;
            steps           = 0;
        }
Example #15
0
        /**
         * <p>
         * Unitary matrices have the following properties:<br><br>
         * Q*Q<sup>H</sup> = I
         * </p>
         * <p>
         * This is the complex equivalent of orthogonal matrix.
         * </p>
         * @param Q The matrix being tested. Not modified.
         * @param tol Tolerance.
         * @return True if it passes the test.
         */
        public static bool isUnitary(CMatrixRMaj Q, float tol)
        {
            if (Q.numRows < Q.numCols)
            {
                throw new ArgumentException("The number of rows must be more than or equal to the number of columns");
            }

            Complex_F32 prod = new Complex_F32();

            CMatrixRMaj[] u = CommonOps_CDRM.columnsToVector(Q, null);

            for (int i = 0; i < u.Length; i++)
            {
                CMatrixRMaj a = u[i];

                VectorVectorMult_CDRM.innerProdH(a, a, prod);

                if (Math.Abs(prod.real - 1) > tol)
                {
                    return(false);
                }
                if (Math.Abs(prod.imaginary) > tol)
                {
                    return(false);
                }

                for (int j = i + 1; j < u.Length; j++)
                {
                    VectorVectorMult_CDRM.innerProdH(a, u[j], prod);

                    if (!(prod.getMagnitude2() <= tol * tol))
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
Example #16
0
        /**
         * Checks to see if the provided matrix is within tolerance to an identity matrix.
         *
         * @param mat Matrix being examined.  Not modified.
         * @param tol Tolerance.
         * @return True if it is within tolerance to an identify matrix.
         */
        public static bool isIdentity(CMatrix mat, float tol)
        {
            // see if the result is an identity matrix
            Complex_F32 c = new Complex_F32();

            for (int i = 0; i < mat.getNumRows(); i++)
            {
                for (int j = 0; j < mat.getNumCols(); j++)
                {
                    mat.get(i, j, c);
                    if (i == j)
                    {
                        if (!(Math.Abs(c.real - 1) <= tol))
                        {
                            return(false);
                        }
                        if (!(Math.Abs(c.imaginary) <= tol))
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        if (!(Math.Abs(c.real) <= tol))
                        {
                            return(false);
                        }
                        if (!(Math.Abs(c.imaginary) <= tol))
                        {
                            return(false);
                        }
                    }
                }
            }

            return(true);
        }
Example #17
0
        /**
         * Returns a list of all the eigenvalues
         */
        public List <Complex_F64> getEigenvalues()
        {
            List <Complex_F64> ret = new List <Complex_F64>();

            if (is64)
            {
                var d = (EigenDecomposition_F64 <DMatrixRMaj>)eig;
                for (int i = 0; i < eig.getNumberOfEigenvalues(); i++)
                {
                    ret.Add(d.getEigenvalue(i));
                }
            }
            else
            {
                var d = (EigenDecomposition_F32 <FMatrixRMaj>)eig;
                for (int i = 0; i < eig.getNumberOfEigenvalues(); i++)
                {
                    Complex_F32 c = d.getEigenvalue(i);
                    ret.Add(new Complex_F64(c.real, c.imaginary));
                }
            }

            return(ret);
        }