// ************************************************************************** //
//                                                                            //
//    eses                   eses                                             //
//   eses                     eses                                            //
//  eses    eseses  esesese    eses   Embedded Systems Group                  //
//  ese    ese  ese ese         ese                                           //
//  ese    eseseses eseseses    ese   Department of Computer Science          //
//  eses   eses          ese   eses                                           //
//   eses   eseses  eseseses  eses    University of Kaiserslautern            //
//    eses                   eses                                             //
//                                                                            //
// ************************************************************************** //
// Optimized Discrete Cosine Transformation by Arai, Agui and Nakajiama       //
// (AAN_DCT)                                                                  //
// Gets along with signed integers             								  //
// Note that array c[k] is defined by c_k = cos(k*(pi/16)), which was 		  //
// computed externally and scaled by 2^13								      //
// Note that AbacusSimulator need following specification: 				      //
//     #const MemSize      96  // size of physical main memory in bytes		  //
// Caution: Doesn't work for any numbers. This AAN_DCT is implemented for 	  //
// test purposes only.														  //
// The AAN DCT is related to the original DCT by the following scaling        //
// equations: u0 = 2*sqrt(2y0) and ui = 4ciyi for i = 1,...,7.		          //
// reference: http://es.cs.uni-kl.de/publications/datarsg/HSKL99.pdf		  //
// ************************************************************************** //


bool tp;
[8]int u; //result
[8]int x; //input


function AAN_DCT(): nat{
	
	int l0_0,l0_1,l0_2,l0_3,l0_4,l0_5,l0_6,l0_7;
	int l1_0,l1_1,l1_2,l1_3,l1_4,l1_5,l1_6;
	int q0,q1;
	int l2_0,l2_2,l2_3,l2_4,l2_5,l3_1,l3_3;

	[9]int c;

//initialize c_k 

	c[1] = +8034;
	c[2] = +7568;
	c[3] = +6811;
	c[4] = +5792;
	c[5] = +4551;
	c[6] = +3134;
	c[7] = +1598;

//phase 1 
	l0_0 = x[0] + x[7];
	l0_1 = x[1] + x[6];
	l0_2 = x[2] + x[5];
	l0_3 = x[3] + x[4];
	l0_4 = x[3] - x[4];
	l0_5 = x[2] - x[5];
	l0_6 = x[1] - x[6];
	l0_7 = x[0] - x[7];

// phase 2 

	l1_0 = l0_0 + l0_3;
	l1_1 = l0_1 + l0_2;
	l1_2 = l0_1 - l0_2;
	l1_3 = l0_0 - l0_3;
	l1_4 = l0_4 + l0_5;
	l1_5 = l0_5 + l0_6;
	l1_6 = l0_6 + l0_7;

	q0 = c[2] - c[6]; 
	q1 = c[2] + c[6];

//phase 3
	l2_5= c[6]*(l1_4-l1_6); 
	l2_0 = c[4]*(l1_2+l1_3); 
    l2_2 = q0*l1_4+l2_5;   
	l2_3 = c[4]*l1_5; 
	l2_4 = q1*l1_6+l2_5;    
	l3_1 = l0_7 + l2_3;
	l3_3 = l0_7 - l2_3;

//phase 4; computing the result
	u[0] = l1_0 + l1_1;
	u[1] = l3_1 + l2_4; 
	u[2] = l2_0 + l1_3; 
	u[3] = l3_3 - l2_2; 
	u[4] = l1_0 - l1_1; 
	u[5] = l3_3 - l2_2; 
	u[6] = l1_3 - l2_0; 
	u[7] = l3_1 - l2_4; 


//dummy return
	return 1;
}

thread test{ 

	nat test;

	x[0] =+2;
	x[1] =+3;
	x[2] =+1;
	x[3] =+1;
	x[4] =+1;
	x[5] =+2;
	x[6] =+2;
	x[7] =+2;

	test = AAN_DCT();

	if((u[0] == +14)&(u[1] == +4434)&(u[2] == +23170)&(u[3] == +10702)&(u[4] == -2)&(u[5] == +10702)&(u[6] == -23166)&(u[7] == -4434))

	{
  		tp = true;
    }

}