/* ----------------------------------------------------------------- */
/* 'ZDVClass.cc'										    */
/* Denavit- Hartenberg- Class 						         */
/* 													    */
/* 	last modified 07/04/2003								    */
/* 	provides functions and data for the calculatings			    */
/* 	for cathesian coordinates according to the theory of		    */
/* 	Denavit and Hartenberg								    */
/* 													    */
/* 													    */
/* 	(C) Jochen Zimmermann								    */
/* ----------------------------------------------------------------- */

#include "ZHeaders.h"
/*
//Headerfile is included by ZHeaders.h
#include "ZDVClass.h"
/**/

//constructor
//initialises members
DenavitHartenberg::DenavitHartenberg():LinearAlgebra()
{
	int i,j;
	for(i=0;i<10;i++)
		trigotable[i]=0;
	
     for(i=0;i<NUMBEROFSERVOS;i++) 
     	servoposition[i]=0;
     
     rows=columns=4;	
/*	for(i=0;i<4;i++)
     	for(j=0;j<4;j++)
     		matrix[i][j]= 0;*/
}

//non-standard constructor for initialisation-during-creation
DenavitHartenberg::DenavitHartenberg(double *bufmatrix, const int * const servopos, bool docalc, bool left):LinearAlgebra()
{
	int i,j;
	
	for(i=0;i<10;i++)
		trigotable[i]=0;
	
	rows=columns=4;
/*	for(i=0;i<4;i++)
         	for(j=0;j<4;j++) 
         		matrix[i][j]= 0;
*/          
     for(i=0;i<NUMBEROFSERVOS;i++) servoposition[i]=servopos[i];
     
	if(docalc) GetDVMatrix(bufmatrix,left);
}


//function to retrieve looked-up sine-value
//(in comments is a recursive algorithm, slower but less memory consumption)
//(the table is adjusted to servo-angles: 72�==128 (Servoangle))
double DenavitHartenberg::ServoSin(int servopos)
{
	/*
	//recursive function for angles from 0-90(0-160) degrees
	//(approx. 102.5�s per call)
	//make all angles positive (not likely to happen in application)
	if(servopos<    0) return  ServoSin(servopos+640); 
	//2*PI- periodicity	
	if(servopos>= 640) return  ServoSin(servopos-640); 
	//PI- symmetry
	if(servopos>= 320) return (ServoSin(servopos-320)*(-1.0));
	//PI/2- symmetry
	if(servopos>  160) return  ServoSin(320-servopos);
	//return from table
	return (double)sinlookup[servopos];*/
	
	//non- recursive function for angles from 0-360(0-640) degrees
	//(approx. 24�s per call)
	servopos=servopos%640;
	if(servopos<0) servopos+=640;
	return (double)sinlookup[servopos];
}


//function to retrieve looked-up cosine-value using sine-function
// 90�==160(Servoangle)
double DenavitHartenberg::ServoCos(int servopos)
{
	return ServoSin(160+servopos);
}


//method 'assembles' thigh-matrix out of trigotable
bool DenavitHartenberg::CalcMatrixThigh(bool left)
{
	//calculates the DV- Matrix out of the given servopositions	
	/*
	MATRIX left:					MATRIX right:
	 _						  _	 _						  _	
	|						   |	|						   | 
	|	ae	-af	b	60ae+35a	   |	|	ae	-af	b	60ae+35a	   | 
	|						   |	|						   | 
	|	be	-bf	-a	60be+35b+28  |	|	be	-bf	-a	60be+35b-28  | 
	|						   |	|						   | 
	|	f	e	0	60f		   |	|	f	e	0	60f		   | 
	|						   |	|						   | 
	|	0	0	 0	1		   |	|	0	0	 0	1		   | 
	|_						  _|	|_						  _| 
	*/
	//first index=line, second index=column
	matrix[0][0]= trigotable[0]       *trigotable[2];
	matrix[0][1]=-trigotable[0]       *trigotable[3];
	matrix[0][2]= trigotable[1];
	matrix[0][3]=60*matrix[0][0]+35*trigotable[0];
	
	matrix[1][0]= trigotable[1]       *trigotable[2];
	matrix[1][1]=-trigotable[1]       *trigotable[3];
	matrix[1][2]=-trigotable[0];                     
	matrix[1][3]=60*matrix[1][0]+35*trigotable[1]+28.0; 
	
	matrix[2][0]=trigotable[3];
	matrix[2][1]=trigotable[2];
	matrix[2][2]=0.0;
	matrix[2][3]=60*trigotable[3];
	
	matrix[3][0]=0.0;
	matrix[3][1]=0.0;
	matrix[3][2]=0.0;
	matrix[3][3]=1.0;
	
	if(!left)
	{
		matrix[1][3]-=56.0;
	}
	
	return(true);
}


//method 'assembles' inverted thigh-matrix out of trigotable
bool DenavitHartenberg::CalcMatrixThighInv(bool left)
{
	//calculates the DV- Matrix out of the given servopositions	
	/*
	MATRIX left:					MATRIX right:
	 _						    _	 _						    _	
	|						   	|	|						   	|     
	|	ae	be	f	-35e-60+28be	|	|	ae	be	f	-35e-60-28be	|     
	|						   	|	|						   	|     
	|	-af	-bf	e	35f+28bf		|	|	-af	-bf	e	35f-28bf		|     
	|						   	|	|						   	|     
	|	b	-a	0	+28a		   	|	|	b	-a	0	-28a		   	|     
	|						   	|	|						   	|     
	|	0	0	 0	1		   	|	|	0	0	 0	1		   	|     
	|_						    _|	|_						    _|     
	*/
	//first index=line, second index=column
	matrix[0][0]= trigotable[0]       *trigotable[2];
	matrix[0][1]=-trigotable[1]       *trigotable[2];
	matrix[0][2]= trigotable[3];
	matrix[0][3]=-35*trigotable[2]-60-28*matrix[0][1];
	
	matrix[1][0]=-trigotable[0]       *trigotable[3];
	matrix[1][1]=-trigotable[1]       *trigotable[3];
	matrix[1][2]= trigotable[2];                     
	matrix[1][3]= 35*trigotable[3]	-28*matrix[1][1]; 
	
	matrix[2][0]= trigotable[1];
	matrix[2][1]=-trigotable[0];
	matrix[2][2]=0.0;
	matrix[2][3]=-28*matrix[2][1];
	
	matrix[3][0]=0.0;
	matrix[3][1]=0.0;
	matrix[3][2]=0.0;
	matrix[3][3]=1.0;
	
	if(!left)
	{
		matrix[0][3]+=56*matrix[0][1];
		matrix[1][3]+=56*matrix[1][1];
		matrix[2][3]+=56*matrix[2][1];
	}
	
	return(true);
}


//method 'assembles' foot-matrix out of trigotable
bool DenavitHartenberg::CalcMatrixFoot(bool left)
{
	//calculates the DV- Matrix out of the given servopositions	
	/*
	MATRIX left:										MATRIX right:
	 _										    _	 _										    _	
	|											|	|											|    
	|	aiu+bh	-ahu+bi	 av	   a(35(u+1)+65o+60e)	|	|	aiu+bh	-ahu+bi	 av	   a(35(u+1)+65o+60e)	|    
	|											|	|											|    
	|	biu-ah	-bhu-ai	 bv	   b(35(u+1)+65o+60e)+28	|	|	biu-ah	-bhu-ai	 bv	   b(35(u+1)+65o+60e)-28	|    
	|											|	|											|    
	|	  iv		 -hv		-u	      35v+65p+60f		|	|	  iv		 -hv		-u	      35v+65p+60f		|    
	|											|	|											|    
	|	  0		  0		 0			1			|	|	  0		  0		 0			1			|    
	|_										    _|	|_										    _|    
	*/
	//first index=line, second index=column

	matrix[0][0]= trigotable[0]       *trigotable[4]    *trigotable[8]   +trigotable[1]*trigotable[5];
	matrix[0][1]=-trigotable[0]       *trigotable[5]    *trigotable[8]   +trigotable[1]*trigotable[4];
	matrix[0][2]= trigotable[0]       *trigotable[9];
	matrix[0][3]= trigotable[0]*(35*(1+trigotable[8])+65*trigotable[6]+60*trigotable[2]);
	
	matrix[1][0]= trigotable[1]        *trigotable[4]   *trigotable[8]   -trigotable[0]*trigotable[5];
	matrix[1][1]=-trigotable[1]        *trigotable[5]   *trigotable[8]   -trigotable[0]*trigotable[4];
	matrix[1][2]= trigotable[1]        *trigotable[9];
	matrix[1][3]= trigotable[1]*(35*(1+trigotable[8])+65*trigotable[6]+60*trigotable[2])+28.0;
	
	matrix[2][0]= trigotable[4]   *trigotable[9];
	matrix[2][1]=-trigotable[5]   *trigotable[9];
	matrix[2][2]=-trigotable[8];
	matrix[2][3]=35*trigotable[9]+65*trigotable[7]+60*trigotable[3];
	
	matrix[3][0]=0.0;
	matrix[3][1]=0.0;
	matrix[3][2]=0.0;
	matrix[3][3]=1.0;
	
	if(!left)
	{
		matrix[1][3]-=56.0;
	}
	
	return(true);
}


//method 'assembles' inverted foot-matrix out of trigotable
bool DenavitHartenberg::CalcMatrixFootInv(bool left)
{
	//calculates the DV- Matrix out of the given servopositions	
	/*
	MATRIX left:										MATRIX right:
	 _										    _	 _										    _	
	|											|	|											|        
	|	aiu+bh	biu-ah	+iv	   -i(35(u+1)+60o+65e)	|	|	aiu+bh	biu-ah	+iv	   -i(35(u+1)+60o+65e)	|        
	|							-28(biu-ah)		|	|							+28(biu-ah)		|        
	|	-ahu+bi	-bhu-ai	-hv	   -h(35(u+1)+65o+60e)	|	|	-ahu+bi	-bhu-ai	-hv	   -h(35(u+1)+65o+60e)	|        
	|							-28(-bhu-ai)		|	|							+28(-bhu-ai)		|        
	|	 av		 bv		-u	      35v+65p+60f		|	|	 av		 bv		-u	      35v+65p+60f		|        
	|								-28bv		|	|								+28bv		|        
	|	  0		  0		 0			1			|	|	  0		  0		 0			1			|        
	|_										    _|	|_										    _|        
	*/
	//first index=line, second index=column
	
	matrix[0][0]= trigotable[0]       *trigotable[4]    *trigotable[8]   +trigotable[1]*trigotable[5];
	matrix[0][1]= trigotable[1]       *trigotable[4]    *trigotable[8]   -trigotable[0]*trigotable[5];
	matrix[0][2]= trigotable[4]       *trigotable[9];
	matrix[0][3]=-trigotable[4]*(35*(1+trigotable[8])+60*trigotable[6]+65*trigotable[2])-28*(matrix[0][1]);
	
	matrix[1][0]=-trigotable[0]        *trigotable[5]   *trigotable[8]   +trigotable[1]*trigotable[4];
	matrix[1][1]=-trigotable[1]        *trigotable[5]   *trigotable[8]   -trigotable[0]*trigotable[4];
	matrix[1][2]=-trigotable[5]        *trigotable[9];
	matrix[1][3]= trigotable[5]*(35*(1+trigotable[8])+60*trigotable[6]+65*trigotable[2])-28*(matrix[1][1]);
	
	matrix[2][0]= trigotable[0]   *trigotable[9];
	matrix[2][1]= trigotable[1]   *trigotable[9];
	matrix[2][2]=-trigotable[8];
	matrix[2][3]=-35*trigotable[9]-60*trigotable[7]-65*trigotable[3]-28*(matrix[2][1]);
	
	matrix[3][0]=0.0;
	matrix[3][1]=0.0;
	matrix[3][2]=0.0;
	matrix[3][3]=1.0;
	
	if(!left)
	{
		matrix[0][3]+=56*(matrix[0][1]);
		matrix[1][3]+=56*(matrix[1][1]);
		matrix[2][3]+=56*(matrix[2][1]);
	}
	
	return(true);
}


//method 'assembles' shank-matrix out of trigotable
bool DenavitHartenberg::CalcMatrixShank(bool left)
{
	//calculates the DV- Matrix out of the given servopositions	
	/*
	MATRIX left:							MATRIX right:
	 _					  		    _	 _					  		    _	
	|					   			|	|					   			|      
	|	ao	-ap	b	a*(65o+60e+35)	  	|	|	ao	-ap	b	a*(65o+60e+35)	  	|      
	|					   			|	|					   			|      
	|	bo	-bp	-a	b*(65o+60e+35)+28	|	|	bo	-bp	-a	b*(65o+60e+35)-28	|      
	|					   			|	|					   			|      
	|	p	o	0	65p+60f  			|	|	p	o	0	65p+60f  			|      
	|					   			|	|					   			|      
	|	0	0	0	1	   			|	|	0	0	0	1	   			|      
	|_					  		    _|	|_					  		    _|      
	*/
	//first index=line, second index=column
	matrix[0][0]= trigotable[0]*trigotable[6];
	matrix[0][1]=-trigotable[0]*trigotable[7];
	matrix[0][2]= trigotable[1];
	matrix[0][3]= trigotable[0]*(65*trigotable[6]+60*trigotable[2]+35);
	
	matrix[1][0]= trigotable[1]*trigotable[6];                         
	matrix[1][1]=-trigotable[1]*trigotable[7];                         
	matrix[1][2]=-trigotable[0];                                                    
	matrix[1][3]= trigotable[1]*(65*trigotable[6]+60*trigotable[2]+35)+28; 
	
	matrix[2][0]= trigotable[7];
	matrix[2][1]= trigotable[6];
	matrix[2][2]= 0.0;
	matrix[2][3]= 65*trigotable[7]+60*trigotable[3];
	
	matrix[3][0]= 0.0;
	matrix[3][1]= 0.0;
	matrix[3][2]= 0.0;
	matrix[3][3]= 1.0;
	
	if(!left)
	{
		matrix[1][3]-=56.0;
	}
	
	return(true);
}


//method 'assembles' inverted shank-matrix out of trigotable
bool DenavitHartenberg::CalcMatrixShankInv(bool left)
{
	//calculates the DV- Matrix out of the given servopositions	
	/*
	MATRIX left:							MATRIX right:
	 _					  		    _	 _					  		    _	
	|					   			|	|					   			|          
	|	 ao	 bo	 p	-35o-60e-65-28bo 	|	|	 ao	 bo	 p	-35o-60e-65+28bo 	|          
	|					   			|	|					   			|          
	|	-ap	-bp	 o	35p+60f+65+28bp	|	|	-ap	-bp	 o	35p+60f+65-28bp	|          
	|					   			|	|					   			|          
	|	  b	 -a	 0	+28a  			|	|	  b	 -a	 0	-28a  			|          
	|					   			|	|					   			|          
	|	0	0	 0	1	   			|	|	0	0	 0	1	   			|          
	|_					  		    _|	|_					  		    _|          
	*/
	//first index=line, second index=column
	matrix[0][0]= trigotable[0]*trigotable[6];
	matrix[0][1]= trigotable[1]*trigotable[6];
	matrix[0][2]= trigotable[7];
	matrix[0][3]=-35*trigotable[6]-60*trigotable[2]-65-28*matrix[0][1];
	
	matrix[1][0]=-trigotable[0]*trigotable[7];                         
	matrix[1][1]=-trigotable[1]*trigotable[7];                         
	matrix[1][2]= trigotable[6];                                                    
	matrix[1][3]= 35*trigotable[7]+60*trigotable[3]-28*matrix[1][1]; 
	
	matrix[2][0]= trigotable[1];
	matrix[2][1]=-trigotable[0];
	matrix[2][2]= 0.0;
	matrix[2][3]= -28*matrix[2][1];
	
	matrix[3][0]= 0.0;
	matrix[3][1]= 0.0;
	matrix[3][2]= 0.0;
	matrix[3][3]= 1.0;
	
	if(!left)
	{
		matrix[0][3]+=56*matrix[0][1];
		matrix[1][3]+=56*matrix[1][1];
		matrix[2][3]+=56*matrix[2][1];
	}
	return(true);
}


//method calculates the trigotable for matrix-assembling
//method is performance optimised
bool DenavitHartenberg::CalcTrigoTable(int whichservo)
{
	//-------control variabels-----------//
	int i,j;
	if(whichservo%2) 	j=1;	//left leg
	else 			j=0;	//right leg
	
	if(whichservo<-1) 	i=1;	//inverted
	else 			i=0;	//not inverted
	
	//--------------------always needed---------------------//
	trigotable[0]=ServoCos(servoposition[RHIPS+j]-128);	//a
	trigotable[1]=ServoSin(servoposition[RHIPS+j]-128);	//b
	
	//--------------casesensitive calculation---------------//
	switch(whichservo)
	{
		case -8:
		case  8:
		case -9:
		case  9:	trigotable[2]=ServoCos(servoposition[RHIPB+j+4*i]-128);//e
				trigotable[3]=ServoSin(servoposition[RHIPB+j+4*i]-128);//f
				
				trigotable[4]=ServoCos(servoposition[RANKS+j]-128);	//i
				trigotable[5]=ServoSin(servoposition[RANKS+j]-128);	//h
				
				trigotable[6]=ServoCos(servoposition[RHIPB+j+2*i]+servoposition[RKNEE+j+2*i]-256);	//o				
				trigotable[7]=ServoSin(servoposition[RHIPB+j+2*i]+servoposition[RKNEE+j+2*i]-256);	//p
				
				trigotable[8]=ServoCos(servoposition[RHIPB+j]+servoposition[RKNEE+j]+servoposition[RANKB+j]-384);	//u
				trigotable[9]=ServoSin(servoposition[RHIPB+j]+servoposition[RKNEE+j]+servoposition[RANKB+j]-384);	//v
				
				break;
		case -4:
		case  4:
		case -5:
		case  5:	trigotable[2]=ServoCos(servoposition[RHIPB+j+2*i]-128);//e
				trigotable[3]=ServoSin(servoposition[RHIPB+j+2*i]-128);//f
				
				trigotable[6]=ServoCos(servoposition[RHIPB+j]+servoposition[RKNEE+j]-256);	//o				
				trigotable[7]=ServoSin(servoposition[RHIPB+j]+servoposition[RKNEE+j]-256);	//p
				
				break;

		case -2:
		case  2:
		case -3:
		case  3:	trigotable[2]=ServoCos(servoposition[RHIPB+j]-128);//e
				trigotable[3]=ServoSin(servoposition[RHIPB+j]-128);//f
				
				break;
		
		default:  return false;	//all other cases not implemented or needed
	}
	return true;
};


//method to retrieve private member 'matrix'
void DenavitHartenberg::GetDVMatrix(double *bufmatrix,int whichservo)
{
	int i,j;
     	
     Calc(whichservo);
		
	for(i=0;i<4;i++)
     	for(j=0;j<4;j++) 
     		bufmatrix[i*4+j]=matrix[i][j];

	return;     		
}


//method to branch calculation enquiry from higer level
//which matrix to calculate is decided by servo-defines
DenavitHartenberg& DenavitHartenberg::Calc(int whichservo)
{
	//this function distributes the calculation
	//negative "whichservos" retrieve the inverted matrix
	//matrix inversion is not performed in code online but externally precalculated
	
	int i,j;
	bool left;
	rows=columns=4;
	//get new values	
	Servo* servo=Servo::GetTheInstance();
	servo->Get(servoposition);
          
     if(whichservo%2) 	left = true;
     else 			left = false;
     
	if(CalcTrigoTable(whichservo))	
		switch(whichservo)
		{
			case  2:	//Thigh matrix
			case  3:CalcMatrixThigh(left);	break;
			case  4:	//Shank matrix
			case  5:CalcMatrixShank(left);	break;
			case  8:	//Foot  matrix
			case  9:CalcMatrixFoot (left);	break;
			
			case -2: 	//inverted Thigh matrix
			case -3:CalcMatrixThighInv(left);	break;
			case -4:	//inverted Shank matrix
			case -5:CalcMatrixShankInv(left);	break;
			case -8:	//inverted Foot  matrix
			case -9:CalcMatrixFootInv (left);	break;
		}
	else	for(i=0;i<4;i++)
			for(j=0;j<4;j++)	//Body matrix is identity matrix for all other cases when whichservo==odd and ZeroMatrix when whichservo==even
				if(i==j) 	matrix[i][j]=(whichservo%2);
				else 	matrix[i][j]=0;
	return *this;
}


//operator '=' had to be re-overloaded after inheriting as it is not passed over
DenavitHartenberg& DenavitHartenberg::operator = (const LinearAlgebra& tocopy)
{
	int i,j;
	for(i=0;i<4;i++)
		for(j=0;j<4;j++)
			matrix[i][j]=tocopy.matrix[i][j];
	rows=tocopy.rows;
	columns=tocopy.columns;
	return *this;
}


//look-up table for servo-sine (consumes 2.5kB memory)
const float DenavitHartenberg::sinlookup[640]={		
			0.000000,0.009817,0.019634,0.029448,0.039260,0.049068,0.058871,0.068668,
			0.078459,0.088242,0.098017,0.107782,0.117537,0.127281,0.137012,0.146730,
			0.156434,0.166123,0.175796,0.185452,0.195090,0.204710,0.214309,0.223888,
			0.233445,0.242980,0.252492,0.261979,0.271440,0.280876,0.290285,0.299665,
			0.309017,0.318339,0.327630,0.336890,0.346117,0.355311,0.364470,0.373595,
			0.382683,0.391735,0.400749,0.409724,0.418660,0.427555,0.436409,0.445221,
			0.453990,0.462716,0.471397,0.480032,0.488621,0.497163,0.505657,0.514103,
			0.522499,0.530844,0.539138,0.547381,0.555570,0.563706,0.571788,0.579815,
			0.587785,0.595699,0.603556,0.611354,0.619094,0.626774,0.634393,0.641952,
			0.649448,0.656882,0.664252,0.671559,0.678801,0.685977,0.693087,0.700131,
			0.707107,0.714015,0.720854,0.727623,0.734323,0.740951,0.747508,0.753993,
			0.760406,0.766745,0.773010,0.779201,0.785317,0.791357,0.797321,0.803208,
			0.809017,0.814748,0.820401,0.825975,0.831470,0.836884,0.842217,0.847470,
			0.852640,0.857729,0.862734,0.867657,0.872496,0.877251,0.881921,0.886507,
			0.891007,0.895421,0.899748,0.903989,0.908143,0.912210,0.916188,0.920078,
			0.923880,0.927592,0.931215,0.934748,0.938191,0.941544,0.944806,0.947977,
			0.951057,0.954044,0.956940,0.959744,0.962455,0.965074,0.967599,0.970031,
			0.972370,0.974615,0.976766,0.978823,0.980785,0.982653,0.984427,0.986105,
			0.987688,0.989177,0.990569,0.991867,0.993068,0.994175,0.995185,0.996099,
			0.996917,0.997640,0.998266,0.998795,0.999229,0.999566,0.999807,0.999952,
			1.000000,0.999952,0.999807,0.999566,0.999229,0.998795,0.998266,0.997640,
			0.996917,0.996099,0.995185,0.994175,0.993068,0.991867,0.990569,0.989177,
			0.987688,0.986105,0.984427,0.982653,0.980785,0.978823,0.976766,0.974615,
			0.972370,0.970031,0.967599,0.965074,0.962455,0.959744,0.956940,0.954044,
			0.951057,0.947977,0.944806,0.941544,0.938191,0.934748,0.931215,0.927592,
			0.923880,0.920078,0.916188,0.912210,0.908143,0.903989,0.899748,0.895421,
			0.891007,0.886507,0.881921,0.877251,0.872496,0.867657,0.862734,0.857729,
			0.852640,0.847470,0.842217,0.836884,0.831470,0.825975,0.820401,0.814748,
			0.809017,0.803208,0.797321,0.791357,0.785317,0.779201,0.773010,0.766745,
			0.760406,0.753993,0.747508,0.740951,0.734323,0.727623,0.720854,0.714015,
			0.707107,0.700131,0.693087,0.685977,0.678801,0.671559,0.664252,0.656882,
			0.649448,0.641952,0.634393,0.626774,0.619094,0.611354,0.603556,0.595699,
			0.587785,0.579815,0.571788,0.563706,0.555570,0.547381,0.539138,0.530844,
			0.522499,0.514103,0.505657,0.497163,0.488621,0.480032,0.471397,0.462716,
			0.453990,0.445221,0.436409,0.427555,0.418660,0.409724,0.400749,0.391735,
			0.382683,0.373595,0.364470,0.355311,0.346117,0.336890,0.327630,0.318339,
			0.309017,0.299665,0.290285,0.280876,0.271440,0.261979,0.252492,0.242980,
			0.233445,0.223888,0.214309,0.204710,0.195090,0.185452,0.175796,0.166123,
			0.156434,0.146730,0.137012,0.127281,0.117537,0.107782,0.098017,0.088242,
			0.078459,0.068668,0.058871,0.049068,0.039260,0.029448,0.019634,0.009817,
			0.000000,-0.009817,-0.019634,-0.029448,-0.039260,-0.049068,-0.058871,-0.068668 ,
			-0.078459,-0.088242,-0.098017,-0.107782,-0.117537,-0.127281,-0.137012,-0.146730,
			-0.156434,-0.166123,-0.175796,-0.185452,-0.195090,-0.204710,-0.214309,-0.223888,
			-0.233445,-0.242980,-0.252492,-0.261979,-0.271440,-0.280876,-0.290285,-0.299665,
			-0.309017,-0.318339,-0.327630,-0.336890,-0.346117,-0.355311,-0.364470,-0.373595,
			-0.382683,-0.391735,-0.400749,-0.409724,-0.418660,-0.427555,-0.436409,-0.445221,
			-0.453990,-0.462716,-0.471397,-0.480032,-0.488621,-0.497163,-0.505657,-0.514103,
			-0.522499,-0.530844,-0.539138,-0.547381,-0.555570,-0.563706,-0.571788,-0.579815,
			-0.587785,-0.595699,-0.603556,-0.611354,-0.619094,-0.626774,-0.634393,-0.641952,
			-0.649448,-0.656882,-0.664252,-0.671559,-0.678801,-0.685977,-0.693087,-0.700131,
			-0.707107,-0.714015,-0.720854,-0.727623,-0.734323,-0.740951,-0.747508,-0.753993,
			-0.760406,-0.766745,-0.773010,-0.779201,-0.785317,-0.791357,-0.797321,-0.803208,
			-0.809017,-0.814748,-0.820401,-0.825975,-0.831470,-0.836884,-0.842217,-0.847470,
			-0.852640,-0.857729,-0.862734,-0.867657,-0.872496,-0.877251,-0.881921,-0.886507,
			-0.891007,-0.895421,-0.899748,-0.903989,-0.908143,-0.912210,-0.916188,-0.920078,
			-0.923880,-0.927592,-0.931215,-0.934748,-0.938191,-0.941544,-0.944806,-0.947977,
			-0.951057,-0.954044,-0.956940,-0.959744,-0.962455,-0.965074,-0.967599,-0.970031,
			-0.972370,-0.974615,-0.976766,-0.978823,-0.980785,-0.982653,-0.984427,-0.986105,
			-0.987688,-0.989177,-0.990569,-0.991867,-0.993068,-0.994175,-0.995185,-0.996099,
			-0.996917,-0.997640,-0.998266,-0.998795,-0.999229,-0.999566,-0.999807,-0.999952,
			-1.000000,-0.999952,-0.999807,-0.999566,-0.999229,-0.998795,-0.998266,-0.997640,
			-0.996917,-0.996099,-0.995185,-0.994175,-0.993068,-0.991867,-0.990569,-0.989177,
			-0.987688,-0.986105,-0.984427,-0.982653,-0.980785,-0.978823,-0.976766,-0.974615,
			-0.972370,-0.970031,-0.967599,-0.965074,-0.962455,-0.959744,-0.956940,-0.954044,
			-0.951057,-0.947977,-0.944806,-0.941544,-0.938191,-0.934748,-0.931215,-0.927592,
			-0.923880,-0.920078,-0.916188,-0.912210,-0.908143,-0.903989,-0.899748,-0.895421,
			-0.891007,-0.886507,-0.881921,-0.877251,-0.872496,-0.867657,-0.862734,-0.857729,
			-0.852640,-0.847470,-0.842217,-0.836884,-0.831470,-0.825975,-0.820401,-0.814748,
			-0.809017,-0.803208,-0.797321,-0.791357,-0.785317,-0.779201,-0.773010,-0.766745,
			-0.760406,-0.753993,-0.747508,-0.740951,-0.734323,-0.727623,-0.720854,-0.714015,
			-0.707107,-0.700131,-0.693087,-0.685977,-0.678801,-0.671559,-0.664252,-0.656882,
			-0.649448,-0.641952,-0.634393,-0.626774,-0.619094,-0.611354,-0.603556,-0.595699,
			-0.587785,-0.579815,-0.571788,-0.563706,-0.555570,-0.547381,-0.539138,-0.530844,
			-0.522499,-0.514103,-0.505657,-0.497163,-0.488621,-0.480032,-0.471397,-0.462716,
			-0.453990,-0.445221,-0.436409,-0.427555,-0.418660,-0.409724,-0.400749,-0.391735,
			-0.382683,-0.373595,-0.364470,-0.355311,-0.346117,-0.336890,-0.327630,-0.318339,
			-0.309017,-0.299665,-0.290285,-0.280876,-0.271440,-0.261979,-0.252492,-0.242980,
			-0.233445,-0.223888,-0.214309,-0.204710,-0.195090,-0.185452,-0.175796,-0.166123,
			-0.156434,-0.146730,-0.137012,-0.127281,-0.117537,-0.107782,-0.098017,-0.088242,
			-0.078459,-0.068668,-0.058871,-0.049068,-0.039260,-0.029448,-0.019634,-0.009817};