All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ejml.alg.dense.decomposition.eig.EigenvalueSmall Maven / Gradle / Ivy

Go to download

A fast and easy to use dense matrix linear algebra library written in Java.

There is a newer version: 0.25
Show newest version
/*
 * Copyright (c) 2009-2011, Peter Abeles. All Rights Reserved.
 *
 * This file is part of Efficient Java Matrix Library (EJML).
 *
 * EJML is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3
 * of the License, or (at your option) any later version.
 *
 * EJML is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with EJML.  If not, see .
 */

package org.ejml.alg.dense.decomposition.eig;

import org.ejml.data.Complex64F;


/**
 * @author Peter Abeles
 */
public class EigenvalueSmall {

    public Complex64F value0 = new Complex64F();
    public Complex64F value1 = new Complex64F();

    // if |a11-a22| >> |a12+a21| there might be a better way.  see pg371
    public void value2x2( double a11 , double a12, double a21 , double a22 )
    {
        // apply a rotators such that th a11 and a22 elements are the same
        double c,s;

        if( a12 + a21 == 0 ) { // is this pointless since
            c = s = 1.0/Math.sqrt(2);
        } else {
            double aa = (a11-a22);
            double bb = (a12+a21);

            double t_hat = aa/bb;
            double t = t_hat/(1.0+Math.sqrt(1.0+t_hat*t_hat));

            c = 1.0/Math.sqrt(1.0+t*t);
            s = c*t;
        }

        double c2 = c*c;
        double s2 = s*s;
        double cs = c*s;

        double b11 = c2*a11 + s2*a22 - cs*(a12+a21);
        double b12 = c2*a12 - s2*a21 + cs*(a11-a22);
        double b21 = c2*a21 - s2*a12 + cs*(a11-a22);
//        double b22 = c2*a22 + s2*a11 + cs*(a12+a21);

        // apply second rotator to make A upper triangular if real eigenvalues
        if( b21*b12 >= 0 ) {
            if( b12 == 0 ) {
                c = 0;
                s = 1;
            } else {
                s = Math.sqrt(b21/(b12+b21));
                c = Math.sqrt(b12/(b12+b21));
            }

//            c2 = b12;//c*c;
//            s2 = b21;//s*s;
            cs = c*s;

            a11 = b11 - cs*(b12 + b21);
//            a12 = c2*b12 - s2*b21;
//            a21 = c2*b21 - s2*b12;
            a22 = b11 + cs*(b12 + b21);

            value0.real = a11;
            value1.real = a22;

            value0.imaginary = value1.imaginary = 0;

        } else {
            value0.real = value1.real = b11;
            value0.imaginary = Math.sqrt(-b21*b12);
            value1.imaginary = -value0.imaginary;
        }
    }

    /**
     * Computes the eigenvalues of a 2 by 2 matrix using a faster but more prone to errors method.  This
     * is the typical method.
     */
    public void value2x2_fast( double a11 , double a12, double a21 , double a22 )
    {
        double left = (a11+a22)/2.0;
        double inside = 4.0*a12*a21 + (a11-a22)*(a11-a22);

        if( inside < 0 ) {
            value0.real = value1.real = left;
            value0.imaginary = Math.sqrt(-inside)/2.0;
            value1.imaginary = -value0.imaginary;
        } else {
            double right = Math.sqrt(inside)/2.0;
            value0.real = (left+right);
            value1.real = (left-right);
            value0.imaginary = value1.imaginary = 0.0;
        }
    }

    /**
     * Compute the symmetric eigenvalue using a slightly safer technique
     */
    // See page 385 of Fundamentals of Matrix Computations 2nd
    public void symm2x2_fast( double a11 , double a12, double a22 )
    {
//        double p = (a11 - a22)*0.5;
//        double r = Math.sqrt(p*p + a12*a12);
//
//        value0.real = a22 + a12*a12/(r-p);
//        value1.real = a22 - a12*a12/(r+p);
//    }
//
//    public void symm2x2_std( double a11 , double a12, double a22 )
//    {
        double left  = (a11+a22)*0.5;
        double b     = (a11-a22)*0.5;
        double right = Math.sqrt(b*b+a12*a12);
        value0.real = left + right;
        value1.real = left - right;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy