#include"FullStaticCooleyTukey.h"
#include"StaticCooleyTukeySetup.h"
#include"FFTKernels.h"
#include"Iterators.h"

#ifndef FLOAT_TYPE
#define FLOAT_TYPE double
#endif

typedef FLOAT_TYPE _FloatType;

#ifndef INT_TYPE
#define INT_TYPE int
#endif

typedef INT_TYPE _IntType;

#ifndef DATA_LENGTH_FOR_KERNEL
#define DATA_LENGTH_FOR_KERNEL DATA_LENGTH_FOR_KERNEL_must_be_defined_in_compile_option
#endif

const INT_TYPE _N = DATA_LENGTH_FOR_KERNEL;

export template<>
void FullStaticCooleyTukeyKernel<_FloatType, _IntType, _N>::transform
			(FullStaticCooleyTukeyKernel<_FloatType, _IntType, _N>::Complex* in
			, FullStaticCooleyTukeyKernel<_FloatType, _IntType, _N>::Complex* out)
{
	typedef FullStaticCooleyTukeyKernel<_FloatType, _IntType, _N> SKernelDecl;
	typedef SKernelDecl::Complex Complex;
	typedef SKernelDecl::Int Int;
	
	static const Int N = _N;
	typedef StaticFFTConfig<Normal, Complex*, Complex*, Int, N> Config;
	typedef StaticFFTKernelImpl<Config, FullStaticFFTCalc> Kernel;

	Kernel::exec(in, out);
}

export template<>
void FullStaticCooleyTukeyKernel<_FloatType, _IntType, _N>::transformWithTwiddle
			( FullStaticCooleyTukeyKernel<_FloatType, _IntType, _N>::Complex* in
			, FullStaticCooleyTukeyKernel<_FloatType, _IntType, _N>::Complex* out
			, FullStaticCooleyTukeyKernel<_FloatType, _IntType, _N>::Int stride
			, FullStaticCooleyTukeyKernel<_FloatType, _IntType, _N>::Int offset
			, FullStaticCooleyTukeyKernel<_FloatType, _IntType, _N>::Float mul_r
			, FullStaticCooleyTukeyKernel<_FloatType, _IntType, _N>::Float mul_l)
{
	typedef FullStaticCooleyTukeyKernel<_FloatType, _IntType, _N> SKernelDecl;
	typedef SKernelDecl::Complex Complex;
	typedef SKernelDecl::Int Int;
	
	typedef StrideIterator<Complex*> StIt;
	typedef TwiddleIterator<Complex*> TwIt;
	static const int N = _N;
	typedef StaticFFTConfig<Normal, TwIt, StIt, Int, N> Config;
	typedef StaticFFTKernelImpl<Config, FullStaticFFTCalc> Kernel;

	StIt stin(in, stride, offset);
	StIt stout(out, stride, offset);
	TwIt twin(stin, mul_r, mul_l);
	
	Kernel::exec(twin, stout);
}

template<>
const char *const FullStaticCooleyTukeyKernel<_FloatType, _IntType, _N>::feature = "FullStaticCooleyTukeyKernel";
