import java.util.*;

//***********************************************************************************
/** Class to return iterate of Grebogi-Ott-Yorke 2d map function.<br>
*/
//***********************************************************************************
public class Map2DGOYFunction extends Map2DFunction {
      double X,Y;
      double a1,a2;

      private static final double p1=-0.26813663648754;
      private static final double p2= 0.98546084298505;
      private static final double p3=-0.91067559396390;
      private static final double p4= 0.50446045609351;
      private static final double p5= 0.31172026382793;
      private static final double p6= 0.94707472523078;
      private static final double p7=-0.04003977835470;
      private static final double p8= 0.23350105508507;
      
      private static final double q1= 0.08818611671542;
      private static final double q2= 0.99030722865609;
      private static final double q3=-0.56502889980448;
      private static final double q4= 0.33630697012268;
      private static final double q5= 0.16299548727086;
      private static final double q6= 0.29804921230971;
      private static final double q7=-0.80398881978155;
      private static final double q8= 0.15506467277737;      
      private static final double pi2=6.283185307;
      private static final double pre=0.10711;          // 0.673/2Pi
      Random myRandom;

      Map2DGOYFunction() {      

            nParameters=1;    
            a = new double[nParameters];    
            aDefault = new double[nParameters];
            aDefault[0]=1.0;   
            title = "Grebogi-Ott-Yorke Map";
            xminDefault=0;
            xmaxDefault=1;
            yminDefault=0; 
            ymaxDefault=1;
            showWinding=false ;
            myRandom=new Random();
            
      }      
                       

//***********************************************************************************
/** Sets the map paramters 
* @param paramters the array of input paramters
*/
//***********************************************************************************      
      public void setParameters(double[] parameters) {
            for(int i=0; i<nParameters;i++) a[i]=parameters[i];
            a1=myRandom.nextDouble();
            a2=myRandom.nextDouble();

//            System.out.println(a[0]+" "+a[1]+" "+a[2]);
            System.out.println(a1+" "+a2);
      }
      
//***********************************************************************************      
/** iterates the map function
* @param x input value
* @return iterated value
*/
//***********************************************************************************
      public void iterate(double[] x) {                       

            X = x[0];
            Y = x[1];

            x[0] = mod(X+a1+a[0]*pre*(
                 p1*Math.sin(pi2*(Y+p2)) +
                 p3*Math.sin(pi2*(X+p4)) +  
                 p5*Math.sin(pi2*(X+Y+p6)) +
                 p7*Math.sin(pi2*(X-Y+p8)) ));
            x[1] = mod(Y+a2+a[0]*pre*(
                 q1*Math.sin(pi2*(Y+q2)) +
                 q3*Math.sin(pi2*(X+q4)) +  
                 q5*Math.sin(pi2*(X+Y+q6)) +
                 q7*Math.sin(pi2*(X-Y+q8)) ));              
            x[2]=X;
            x[3]=Y;   
      }      

//***********************************************************************************      
/** iterates the tangent space to the map function
* @param x input value and returns updated values
* x[0] and x[1] contain the new values of X and Y
* @param t value of tangent vector (updated by iteration)
*/
//***********************************************************************************
      public void iterateTangent(double[] x, double[] t) {                       

            X = t[0];
            Y = t[1];

            t[0] = X+a[0]*pi2*pre*(
                 p1*Math.cos(pi2*(x[1]+p2))*Y +
                 p3*Math.cos(pi2*(x[0]+p4))*X +  
                 p5*Math.cos(pi2*(x[0]+x[1]+p6))*(X+Y) +
                 p7*Math.cos(pi2*(x[0]-x[1]+p8))*(X-Y) );
            t[1] = Y+a[0]*pi2*pre*(
                 q1*Math.cos(pi2*(x[1]+q2))*Y +
                 q3*Math.cos(pi2*(x[0]+q4))*X +  
                 q5*Math.cos(pi2*(x[0]+x[1]+q6))*(X+Y) +
                 q7*Math.cos(pi2*(x[0]-x[1]+q8))*(X-Y));               
      }      

//***********************************************************************************               
}
