/*MaestroA.java*/
/*
 * Contains numerical utilities
 * authors: Singh T. Junior and Umberto Ravaioli
 * version 1.0 - Copyright: Amanogawa.com - All Rights Reserved
 */

public  class MaestroA{
    MaestroA(){}
    
    public static final double getMin(double x[]){
	double min;
	min = x[0];
	for(int i=1;i<x.length;i++){
	    if(min>x[i]) {min = x[i];}
	}	
	return min;        
    }
    
    public static final double getMax(double x[]){
	double max;
	max = x[0];
	for(int i=1;i<x.length;i++){
	    if(max<x[i]) {max = x[i];}
	}
	return max;
    }
    
    public static final double getMin(double x[][], int M, int N){
	double min;
	min = x[0][0];
	for(int j=0;j<N;j++){
	for(int i=0;i<M;i++){
	    if(min>x[i][j]) {min = x[i][j];}
	}}	
	return min;        
    }
    
    public static final double getMax(double x[][], int M, int N){
	double max;
	max = x[0][0];
	for(int j=0;j<N;j++){
	for(int i=0;i<M;i++){
	    if(max<x[i][j]) {max = x[i][j];}
	}}
	return max;
    }
    
     public static final double getMin(double x[][], int M, int N, int j){
	double min;
	min = x[0][j];
	for(int i=0;i<M;i++){
	    if(min>x[i][j]) {min = x[i][j];}
	}
	return min;        
    }
    
    public static final double getMax(double x[][], int M, int N, int j){
	double max;
	max = x[0][j];
	for(int i=0;i<M;i++){
	    if(max<x[i][j]) {max = x[i][j];}
	}
	return max;
    }
    
    public static double rounder(double x, int res){
	if(Math.abs(x)*Math.pow(10,res)>1.0*Integer.MAX_VALUE){
	    return x;
	}
	if(x>=0.0){
	    return (int)(Math.abs(x)*Math.pow(10,res)+0.5)/Math.pow(10,res);
	}
	else{
	    return -(int)(Math.abs(x)*Math.pow(10,res)+0.5)/Math.pow(10,res);
	}
    }
    
    public static double rounder(double x, int res, boolean roundoff){
	double tmp;
	if(roundoff){ tmp = 0.5; }
	else{ tmp = 0.0; }
	if(Math.abs(x)*Math.pow(10,res)>1.0*Integer.MAX_VALUE){
	    return x;
	}
	if(x>=0.0){
	    return (int)(Math.abs(x)*Math.pow(10,res)+tmp)/Math.pow(10,res);
	}
	else{
	    return -(int)(Math.abs(x)*Math.pow(10,res)+tmp)/Math.pow(10,res);
	}
    }
    
    public static double mapper(double x, double ymax, double ymin, double xmax, double xmin){
	double a, b;
	if(xmax == xmin){return xmin;}
	a = (ymax-ymin)/(xmax-xmin);
	b = ymax - a * xmax;
	return a*x+b;
    }
    
    public static void confiner(double x[], double xmax, double xmin){
	for(int i = 0 ; i < x.length; i++){
	    if(x[i] < xmin){x[i] = xmin; }
	    if(x[i] > xmax){x[i] = xmax; }
	}
    }
    
    public static void confiner(double x[][], int N, int M, double xmax, double xmin){
	for(int j = 0; j < M; j++){
	for(int i = 0 ; i < N; i++){
	    if(x[i][j] < xmin){x[i][j] = xmin; }
	    if(x[i][j] > xmax){x[i][j] = xmax; }
	}}
    }
    
     public static void confiner(double x[][], int N, int M, double xmax, double xmin, int j){
	for(int i = 0 ; i < N; i++){
	    if(x[i][j] < xmin){x[i][j] = xmin; }
	    if(x[i][j] > xmax){x[i][j] = xmax; }
	}
    }
    
    public static void randomizer(double x[], double xmax, double xmin,int tipo){
	switch(tipo){
	    case 1: //totally random
		for(int i = 0; i < x.length; i++){
		    x[i] = xmin+(xmax-xmin)*Math.random();
		}
		break;
	    case 2: //noise sine
		for(int i = 0; i< x.length; i++){
		    x[i] = (xmax-xmin)*(Math.sin(2.0*Math.PI*i/x.length)+0.2*Math.random());
		}
		break;
	}
    }
    
    public static void signal_stir(double x[],double wt, double xmax, double xmin,int tipo){
	switch(tipo){
	    case 1://sin function
		for(int i = 0; i < x.length; i++){
		    x[i] = (xmax - xmin) * Math.sin(wt+2.0*Math.PI*i/x.length);
		}
		break;
	    case 2://noisy sin function
		for(int i = 0; i < x.length; i++){
		    x[i] = (xmax - xmin) * (Math.sin(wt+2.0*Math.PI*i/x.length)+0.2*Math.random());
		}
		break;
	} 
    }
    
    public static double[] rotation(double x[],double theta){
	double tmp[] = new double[2];
	tmp[0] = x[0] * ( Math.cos(theta) ) + x[1] * ( Math.sin(theta) );
	tmp[1] = x[0] * (-Math.sin(theta) ) + x[1] * ( Math.cos(theta) );
	return tmp;
    }
    
    public static double[] inv_rotation(double x[],double theta){
	double tmp[] = new double[2];
	tmp[0] = x[0] * ( Math.cos(theta) ) + x[1] * (-Math.sin(theta) );
	tmp[1] = x[0] * ( Math.sin(theta) ) + x[1] * ( Math.cos(theta) );
	return tmp;
    } 
    
    
}