/**
 * This class writes a Suzuki approximant of order 2k. 
 * It calls functions from the abstract class SuzFunctions.
 */
public class SuzWriter {

	private static double[] _a;
	private static double[] _aProd;


/**
 *
 */
public SuzWriter(){

    _a = new double[10];     
    _aProd = new double[10];
    _a[0] = 1;
    _aProd[0] = 1;
    for(int k=1; k<10; k++){
    	_a[k] = 1.0/(4 - Math.pow(4, 1.0/(2*k+1)));
    	_aProd[k] = _a[k]*_aProd[k-1];
    }
	
}
/**
 *
 */
    public static void writeSuzuki2(
    	double t, 
    	boolean withCaps,
    	SuzFunctions funs)
    {
    	if(withCaps){
    		funs.writeExpAtimes(t/2);
    	}
		
    	funs.writeExpBtimes(t);
		
		if(withCaps){
			funs.writeExpAtimes(t/2);
    	}
	}
/**
 *
 */
    public static void writeSuzuki2k(
    	int k,//suzukiHalfOrder 
    	double t, 
    	boolean withCaps,
    	SuzFunctions funs)
    {
    	if(k==1){
    		writeSuzuki2(t, withCaps, funs);
    	}else{
    		double a = _a[k-1];
    		double aProd = _aProd[k-2];
    		if(withCaps){
    			funs.writeExpAtimes(a*aProd*t/2);
        	}
    		writeSuzuki2k(k-1, a*t, false, funs);
    			funs.writeExpAtimes(a*aProd*t);
    		writeSuzuki2k(k-1, a*t, false, funs);
    			funs.writeExpAtimes((1 - 3*a)*aProd*t/2);
    		writeSuzuki2k(k-1, (1 - 4*a)*t, false, funs);
    			funs.writeExpAtimes((1 - 3*a)*aProd*t/2);
	        writeSuzuki2k(k-1, a*t, false, funs);
	        	funs.writeExpAtimes(a*aProd*t);
    		writeSuzuki2k(k-1, a*t, false, funs);
    		if(withCaps){
    			funs.writeExpAtimes(a*aProd*t/2);
        	}
    	}
    }

}
