//***********************************************************************************
/** Class to return nf'th iterate of map function.<br>
* To be subclassed by specific functions, which must provide:
* <UL><LI> a method evaluateFunction(double x) to return the function which must map the
* interval 0<x<1 into itself.
* <LI> a method evaluateDerivative(double x) to return the derivative at x
* <LI> an int variable nParameters giving the number of map parameters (1 or 2)
* <LI> the initialization of a[nParamters] and aDefault[nParameters]</UL>
* Optional parameters are:<UL>
* <LI> double aMinimum giving a constant minimum value of a
* <LI> double aMaximum giving a constant maximum value of a
* <LI> boolean enforceARange  true if the range is to be enforced (i.e. user 
* cannot override it
* <LI> double bMinimum giving a constant minimum value of b (if nParameters=2)
* <LI> double bMaximum giving a constant maximum value of b
* <LI> boolean enforceBRange  true if the range is to be enforced
* <LI> double x0Default giving the default value of the initial value of x
* <LI> String title giving the name of the function to use as a graph title
* <LI> double[] aDefault(nParameters] giving default values for the map parameters
* </UL>
* Optional methods area:<UL>
* <LI> getAMainmum(double d) gives the minimum value allowed for a (default returns
* aMinimum, but may be overridden.
* <LI> getAMaximum(double d) gives the maximum value allowed for a (default returns
* aMaximum, but may be overridden.
* <LI> boolean showWinding set to true if winding number to be displayed
*/
//***********************************************************************************

public class Map1DFunction {


/** number of map parameters (1 or 2) */
      int nParameters;
/** array giving map paramters */      
      double[] a;
/** array giving default values of map parameters */      
      double[] aDefault;      
/** minimum value of a */      
      double aMinimum=0.;
/** maximum value of a */      
      double aMaximum=4.;
/** true if the maximum is to be enforced      */
      boolean enforceARange=false;      
/** minimum value of b */      
      double bMinimum;
/** maximum value of b */      
      double bMaximum=4.;      
/** true if the minimum is to be enforced       */
      boolean enforceBRange=false;
/** the default value of the initial value of x */
      double x0Default=0.2;
/** the name of the function to use as a graph title */
      String title = "Function";
/** the composition number: i.e. how many times the map is iterated each call */      
      private int nf=1;
/** accumulates the product of the slopes at the nf iteration points */      
      public double slope;
/** winding number for circle map  */      
      public int winding; 
/** set to zero in transients so winding number not updated  */
      public int windingAdd=1;  
/** number of iterations contributing to winding */      
      public int total=0;
/** true if winding number to be shown */
      public boolean showWinding=false;       
      
//***********************************************************************************
/** Sets the map paramters 
* @param paramters the array of input paramters
*/
//***********************************************************************************      
      public void setParameters(double[] parameters) {
            if(parameters.length < nParameters)
                  System.out.println("Incorrect number of parameters");
            for(int i=0; i<nParameters;i++) a[i]=parameters[i];
      }

//***********************************************************************************      
/** iterates the map function nf times: calls evaluateFunction
* @param x input value
* @return iterated value
*/
//***********************************************************************************
      public double iterate(double x) {            
            for(int i=1;i<=nf;i++) x=evaluateFunction(x);
            return x;
      }
//***********************************************************************************      
/** iterates the map function nf times: calls evaluateDerivative and
* evaluates the product of the slopes
* @param x input value
* @return iterated value
*/
//***********************************************************************************
      public double evaluateSlope(double x) {
            slope=1.;            
            for(int i=1;i<=nf;i++) {
                  x=evaluateFunction(x);
                  slope=slope*evaluateDerivative(x);
            }      
            return x;
      }      
//***********************************************************************************
/** evaluates map function
* @param x input value
* @treturn output value
*/
//***********************************************************************************
      public double evaluateFunction(double x) {            
            return x;
      }      

//***********************************************************************************
/** evaluates the derivative of the map function at x
* @param x input value
* @treturn derivative value
*/
//***********************************************************************************
      public double evaluateDerivative(double x) {            
            return x;
      }      
//***********************************************************************************      
/** Sets the compose value nf
* @param inNf the input value of nf
*/
//***********************************************************************************
     public void setCompose(int inNf) {      
            nf=inNf;
     }
     
//***********************************************************************************
/** Returnd the number of paraemters defining the map
* @return number of parameters
*/
//***********************************************************************************
     public int getNParameters() {
            return nParameters;
     } 
     
//***********************************************************************************
/** Returns the maximum value of a allowed (may depend on parameter d, usually the 
* second map parameter).
* @param d
* @return maximum value of a
*/
//***********************************************************************************
     public double getAMaximum(double d) {
        return aMaximum;
     }     

//***********************************************************************************
/** Returns the minimum value of a allowed (may depend on parameter d, usually the 
* second map parameter).
* @param d
* @return minimum value of a
*/
//***********************************************************************************
     public double getAMinimum(double d) {
        return aMinimum;
     }
     
//*********************************************************************************** 
/**
* Shifts x to 0<x<1
* @param x input value
* @return value shifted to between 0 and 1
*/
//**********************************************************************      
      double mod(double x) {
         while (x>1.) {
            winding=winding+windingAdd;
            x=x-1.;
         }   
         while (x<0.) {
            winding=winding-windingAdd;
            x=x+1.;
         }
         total=total+windingAdd;
         return x;
      }
//**********************************************************************               
}
