package jsci.maths.polynomials;

import jsci.maths.AbstractMath;
import jsci.maths.Complex;
import jsci.maths.matrices.AbstractComplexSquareMatrix;
import jsci.maths.matrices.AbstractDoubleSquareMatrix;
import jsci.maths.matrices.ComplexSquareMatrix;
import jsci.maths.matrices.DoubleSquareMatrix;

/**
 *
 * @author  b.dietrich
 */
public final class PolynomialMath extends AbstractMath {
        private PolynomialMath() {}

    /**
     * Returns the companion matrix of a given polynomial.
     * The eigenvalues of the companion matrix are the roots of the polynomial.
     * 
     * @param p the polynomial
     *
     * @return the companion matrix
     * @jsci.planetmath CompanionMatrix
     */
    public static AbstractDoubleSquareMatrix toCompanionMatrix( RealPolynomial p ) {
        RealPolynomial np = normalize(p);

        int n = np.degree();
        if ( n < 1 ) {
            throw new IllegalArgumentException( "Cannot get a companion matrix for a constant factor" );
        }

        AbstractDoubleSquareMatrix dsm = new DoubleSquareMatrix( n );

        for ( int k = 0; k < (n-1); k++ ) {
        // fill subdiagonal
            dsm.setElement( k+1, k, 1.0 );
        // fill lastCol
            dsm.setElement( k, n-1, np.getCoefficientAsDouble( k ) );
        }
        // fill lastRow/lastCol
        dsm.setElement( n-1, n-1, np.getCoefficientAsDouble( n-1 ) );

        return dsm;
    }
    public static AbstractComplexSquareMatrix toCompanionMatrix( ComplexPolynomial p ) {
        ComplexPolynomial np = normalize(p);

        int n = np.degree();
        if ( n < 1 ) {
            throw new IllegalArgumentException( "Cannot get a companion matrix for a constant factor" );
        }

        AbstractComplexSquareMatrix csm = new ComplexSquareMatrix( n );

        for ( int k = 0; k < ( n-1 ); k++ ) {
        // fill subdiagonal
            csm.setElement( k+1, k, 1.0, 0.0 );
        // fill lastCol
            csm.setElement( k, n-1, np.getCoefficientAsComplex( k ) );
        }
        // fill lastRow/lastCol
        csm.setElement( n-1, n-1, np.getCoefficientAsComplex( n-1 ) );

        return csm;
    }

    /**
     * Calculates the roots of a given polynomial by solving the
     * eigenvalue problem for the companion matrix.
     * This is not yet implemented (depends on a QR- decomposition)
     * @param p the polynomial
     *
     * @return (unordered) list of roots.
     */
    public static Complex[] findRoots( RealPolynomial p ) {
        AbstractDoubleSquareMatrix matrix = toCompanionMatrix( p );

        // return solveEigenvalueByQR(c);
        throw new java.lang.UnsupportedOperationException("Not yet implemented.");
    }

    /**
     * Get the maximum degree of two polynomials
     * @param p1
     * @param p2
     */
    public static int maxDegree( Polynomial p1, Polynomial p2 ) {
        return Math.max( p1.degree(), p2.degree() );
    }

    /**
     * Get the minimal degree of two polynomials
     * @param p1
     * @param p2
     */
    public static int minDegree( Polynomial p1, Polynomial p2 ) {
        return Math.min( p1.degree(), p2.degree() );
    }

    /**
     * Evaluates a polynomial by Horner's scheme.
     * @param p
     * @param t
     */
    public static double evalPolynomial( RealPolynomial p, double t ) {
        final int n    = p.degree();
        double r = p.getCoefficientAsDouble(n);
        for ( int i = n-1; i >= 0; i-- ) {
            r = p.getCoefficientAsDouble(i) + ( r * t );
        }

        return r;
    }

    /**
     * Evaluates a polynomial by Horner's scheme.
     * @param p
     * @param t
     */
    public static Complex evalPolynomial( ComplexPolynomial p, Complex t ) {
        final int n     = p.degree();
        Complex r = p.getCoefficientAsComplex(n);
        for ( int i = n-1; i >= 0; i-- ) {
            r = p.getCoefficientAsComplex(i).add( r.multiply( t ) );
        }

        return r;
    }

    /**
     * Interpolates a polynomial.
     * Caveat: this method is brute-force, slow and not very stable.
     * It shouldn't be used for more than approx. 10 points.
     * Remember the strong variations of higher degree polynomials.
     *
     * @param samplingPoints an array[2][n] where array[0] denotes x-values, array[1] y-values
     */
    public static RealPolynomial interpolateLagrange( double[][] samplingPoints ) {
        RealLagrangeBasis r = new RealLagrangeBasis( samplingPoints[0] );
        return ( (RealPolynomial) r.superposition( samplingPoints[1] ) );
    }

    /**    
     * Interpolates a polynomial.
     * Caveat: this method is brute-force, slow and not very stable.
     * It shouldn't be used for more than approx. 10 points.
     * Remember the strong variations of higher degree polynomials.
     *
     * @param samplingPoints an array[2][n] where array[0] denotes x-values, array[1] y-values
     */
    public static ComplexPolynomial interpolateLagrange( Complex[][] samplingPoints ) {
        ComplexLagrangeBasis r = new ComplexLagrangeBasis( samplingPoints[0] );
        return ( (ComplexPolynomial) r.superposition( samplingPoints[1] ) );
    }

    /**
     * Normalizes a given real polynomial, i.e. divide by the leading coefficient.
     * @param p
     */
    public static RealPolynomial normalize( RealPolynomial p ) {
        final int n       = p.degree();
        final double c   = p.getCoefficientAsDouble( n );
        double[] m = new double[n+1];
        m[n]    = 1.0;
        for ( int i = 0; i < n; i++ ) {
            m[i] = p.getCoefficientAsDouble( i ) / c;
        }

        return new RealPolynomial( m );
    }
    /**
     * Normalizes a given complex polynomial, i.e. divide by the leading coefficient.
     * @param p
     */
    public static ComplexPolynomial normalize( ComplexPolynomial p ) {
        final int n       = p.degree();
        final Complex c   = p.getCoefficientAsComplex( n );
        Complex[] m = new Complex[n+1];
        m[n]    = Complex.ONE;
        for ( int i = 0; i < n; i++ ) {
            m[i] = p.getCoefficientAsComplex( i ).divide( c );
        }

        return new ComplexPolynomial( m );
    }

    /**
     *
     * Try to cast a Polynomial to a complex polynomial
     */
    public static ComplexPolynomial toComplex( Polynomial p ) {
        if ( p instanceof ComplexPolynomial ) {
            return (ComplexPolynomial) p;
        } else if ( p instanceof RealPolynomial ) {
            double[] d  = ( (RealPolynomial) p ).getCoefficientsAsDoubles();
            Complex[] c = new Complex[d.length];
            for ( int k = 0; k < d.length; k++ ) {
                c[k] = new Complex( d[k], 0 );
            }

            return new ComplexPolynomial( c );
        } else {
            throw new IllegalArgumentException("Polynomial class not recognised by this method.");
        }
    }
}


 

Ads help maintain this website.