package fmph.features.util;

import cern.colt.matrix.DoubleMatrix2D;
import cern.colt.matrix.impl.DenseDoubleMatrix2D;

public class Util {
    public static void exponentiate_real_matrix(DoubleMatrix2D X, DoubleMatrix2D Y, int size, int degree)
    // Sets Y to equal exp(X); X is assumed to be real.
    // Y can be expressed as a convergent power series in X:
    // Y = I + X + X*X/2 + X*X*X/6 + X*X*X*X/24 + ...
    // the power series is truncated after the X^(degree) term.
    // Since X is real and each term above is real, Y is also real.
    // An eigenvector of X with eigenvalue lambda is an eigenvector of Y with eigenvalue exp(lambda)
    {
           
            DenseDoubleMatrix2D EYE = new DenseDoubleMatrix2D(size,size);
            EYE.assign(0.0);  for (int i=0; i<size; i++) { EYE.setQuick(i,i,1.0); }  // Intially sets Y to the identity matrix; 
            Y.assign(EYE); 
            DenseDoubleMatrix2D Z = new DenseDoubleMatrix2D(size,size);   Z.assign(EYE);
            DenseDoubleMatrix2D W = new DenseDoubleMatrix2D(size,size);
            for (int j=1; j<=degree; j++) {
                    W.assign(Z);
                    W.zMult(X,Z,1.0/((double) j),0.0,false,false);   // Z = (1/j)*W*X + 0*Z = X^j/j!
                    Z.zMult(EYE,Y,1.0,1.0,false,true);   // Y = Z*I + Y = Z+Y = Y+X^j/j!
            }
            
            
            
            return;
    }
}
