// MILOS v2.0 (2020)
// Milne-Eddington inversion code (based on IDL MILOS code by D. Orozco)
// Manuel Cabrera, Juan P. Cobos, Luis Bellot (IAA-CSIC)
// For questions, please contact lbellot@iaa.es
//

/*
;      eta0 = line-to-continuum absorption coefficient ratio
;      B = magnetic field strength       [Gauss]
;      vlos = line-of-sight velocity     [km/s]
;      dopp = Doppler width              [Angstroms]
;      aa = damping parameter
;      gm = magnetic field inclination   [deg]
;      az = magnetic field azimuth       [deg]
;      S0 = source function constant
;      S1 = source function gradient
;      mac = macroturbulent velocity     [km/s]
;      alpha = filling factor of the magnetic component [0->1]

*/

#include <time.h>
#include "defines.h"
#include <string.h>
#include <stdio.h>
#include "/opt/local/cfitsio/cfitsio-3.350/include/fitsio.h" ///opt/local/cfitsio/cfitsio-3.350/include/
#include "utilsFits.h"
#include "milosUtils.h"
#include "lib.h"
#include "readConfig.h"
#include <unistd.h>
#include <complex.h>
#include <fftw3.h> //siempre a continuacion de complex.h
#include <gsl/gsl_spline.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_eigen.h>
#include <libgen.h>

int NTERMS = 11;
Cuantic *cuantic; // Variable global, está hecho así, de momento,para parecerse al original

PRECISION **PUNTEROS_CALCULOS_COMPARTIDOS;
int POSW_PUNTERO_CALCULOS_COMPARTIDOS;
int POSR_PUNTERO_CALCULOS_COMPARTIDOS;

REAL *dtaux, *etai_gp3, *ext1, *ext2, *ext3, *ext4;
REAL *gp1, *gp2, *dt, *dti, *gp3, *gp4, *gp5, *gp6, *etai_2;
REAL *gp4_gp2_rhoq, *gp5_gp2_rhou, *gp6_gp2_rhov;
REAL *dgp1, *dgp2, *dgp3, *dgp4, *dgp5, *dgp6, *d_dt;
REAL *d_ei, *d_eq, *d_eu, *d_ev, *d_rq, *d_ru, *d_rv;
REAL *dfi, *dshi;
REAL CC, CC_2, sin_gm, azi_2, sinis, cosis, cosis_2, cosi, sina, cosa, sinda, cosda, sindi, cosdi, sinis_cosa, sinis_sina;
REAL *fi_p, *fi_b, *fi_r, *shi_p, *shi_b, *shi_r;
REAL *etain, *etaqn, *etaun, *etavn, *rhoqn, *rhoun, *rhovn;
REAL *etai, *etaq, *etau, *etav, *rhoq, *rhou, *rhov;
REAL *parcial1, *parcial2, *parcial3;
REAL *nubB, *nupB, *nurB;
REAL **uuGlobalInicial;
REAL **HGlobalInicial;
REAL **FGlobalInicial;

PRECISION *GMAC,* GMAC_DERIV;
PRECISION * dirConvPar;
REAL *resultConv;
PRECISION * G = NULL;

REAL * opa;
int FGlobal, HGlobal, uuGlobal;

REAL *d_spectra, *spectra, *spectra_mac, *spectra_slight;

// GLOBAL variables to use for FFT calculation
fftw_complex * inSpectraFwPSF, *inSpectraBwPSF, *outSpectraFwPSF, *outSpectraBwPSF;
fftw_complex * inSpectraFwMAC, *inSpectraBwMAC, *outSpectraFwMAC, *outSpectraBwMAC;
fftw_plan planForwardPSF, planBackwardPSF;
fftw_plan planForwardMAC, planBackwardMAC;
fftw_complex * inFilterMAC, * inFilterMAC_DERIV, * outFilterMAC, * outFilterMAC_DERIV;
fftw_plan planFilterMAC, planFilterMAC_DERIV;

fftw_complex * fftw_G_PSF, * fftw_G_MAC_PSF, * fftw_G_MAC_DERIV_PSF;
fftw_complex * inPSF_MAC, * inMulMacPSF, * inPSF_MAC_DERIV, *inMulMacPSFDeriv, *outConvFilters, * outConvFiltersDeriv;
fftw_plan planForwardPSF_MAC, planForwardPSF_MAC_DERIV,planBackwardPSF_MAC, planBackwardPSF_MAC_DERIV;

//Convolutions values
int sizeG = 0;
PRECISION FWHM = 0;

ConfigControl configCrontrolFile;

// fvoigt memory consuption
 _Complex double *z,* zden, * zdiv;

gsl_vector *eval;
gsl_matrix *evec;
gsl_eigen_symmv_workspace * workspace;

int main(int argc, char **argv)
{
	int i; // for indexes
	PRECISION *wlines;
	int nlambda;
	Init_Model *vModels;
	float chisqrf, * vChisqrf;
	int * vNumIter; // to store the number of iterations used to converge for each pixel
	int indexLine, free_params; // index to identify central line to read it

	//*****
	Init_Model INITIAL_MODEL;
	PRECISION * deltaLambda, * PSF;
	PRECISION initialLambda, step, finalLambda;
	int N_SAMPLES_PSF;
	int posWL=0;
	//----------------------------------------------

	float * slight = NULL;
	int nl_straylight, ns_straylight, nx_straylight=0,ny_straylight=0;
	const char  * nameInputFileSpectra ;
	char nameOutputFilePerfiles [4096];
	const char	* nameInputFileLines;
	const char	* nameInputFilePSF ;
    FitsImage * fitsImage;
	PRECISION  dat[7];

	/********************* Read data input from file ******************************/

	/* Read data input from file */

	loadInitialValues(&configCrontrolFile);
	readTrolFile(argv[1],&configCrontrolFile,1);

	nameInputFileSpectra = configCrontrolFile.ObservedProfiles;
	nameInputFileLines = configCrontrolFile.AtomicParametersFile;

	nameInputFilePSF = configCrontrolFile.PSFFile;
	FWHM = configCrontrolFile.FWHM;

	/***************** READ INIT MODEL ********************************/
	if(configCrontrolFile.InitialGuessModel[0]!='\0' && !readInitialModel(&INITIAL_MODEL,configCrontrolFile.InitialGuessModel)){
		printf("\nERROR READING GUESS MODEL 1 FILE\n");
		exit(EXIT_FAILURE);
	}
	checkInitialModel(&INITIAL_MODEL);

	if(INITIAL_MODEL.alfa<1 && access(configCrontrolFile.StrayLightFile,F_OK)){
		printf("\nERROR. Filling factor in Initial model is less than 1 and Stray Light file  %s can not be accessed\n",configCrontrolFile.StrayLightFile);
		exit(EXIT_FAILURE);
	}

	if(configCrontrolFile.fix[10]==0) NTERMS--;
	if(INITIAL_MODEL.mac ==0 && configCrontrolFile.fix[9]==0){
		 NTERMS--;
	}

	// allocate memory for eigen values
	eval = gsl_vector_alloc (NTERMS);
  	evec = gsl_matrix_alloc (NTERMS, NTERMS);
	workspace = gsl_eigen_symmv_alloc (NTERMS);

	/***************** READ WAVELENGHT FROM GRID OR FITS ********************************/
	PRECISION * vLambda, *vOffsetsLambda;

	if(configCrontrolFile.useMallaGrid){ // read lambda from grid file
		printf("\n--------------------------------------------------------------------------------");
		printf("\nMALLA GRID FILE READ: %s",configCrontrolFile.MallaGrid);
		printf("\n--------------------------------------------------------------------------------");
		indexLine = readMallaGrid(configCrontrolFile.MallaGrid, &initialLambda, &step, &finalLambda, 1);
		printf("--------------------------------------------------------------------------------\n");
		nlambda = ((finalLambda-initialLambda)/step)+1;
		vOffsetsLambda = calloc(nlambda,sizeof(PRECISION));
		vOffsetsLambda[0] = initialLambda;
		for(i=1;i<nlambda;i++){
			vOffsetsLambda[i] = vOffsetsLambda[i-1]+step;
		}
		// pass to armstrong
		initialLambda = initialLambda/1000.0;
		step = step/1000.0;
		finalLambda = finalLambda/1000.0;
		vLambda = calloc(nlambda,sizeof(PRECISION));

		printf("Number of wavelengths in the wavelength grid: %d",nlambda);
		printf("\n--------------------------------------------------------------------------------\n");
		printf("\n--------------------------------------------------------------------------------");
		printf("\nATMOSPHERE LINES FILE READ: %s",nameInputFileLines);
		configCrontrolFile.CentralWaveLenght = readFileCuanticLines(nameInputFileLines,dat,indexLine,1);
		if(configCrontrolFile.CentralWaveLenght==0){
			printf("\n QUANTUM LINE NOT FOUND, REVIEW IT. INPUT CENTRAL WAVE LENGHT: %f",configCrontrolFile.CentralWaveLenght);
			exit(1);
		}
		vLambda[0]=configCrontrolFile.CentralWaveLenght+(initialLambda);
		for(i=1;i<nlambda;i++){
			vLambda[i]=vLambda[i-1]+step;
		}
		/******************* CREATE CUANTINC AND INITIALIZE DINAMYC MEMORY*******************/
		cuantic = create_cuantic(dat,1);

	}
	else{ // read lambda from fits file
		printf("\n--------------------------------------------------------------------------------");
		printf("\nWAVELENGTH FILE READ: %s",configCrontrolFile.WavelengthFile);
		vLambda = readFitsLambdaToArray(configCrontrolFile.WavelengthFile,&indexLine,&nlambda);
		if(vLambda==NULL){
			printf("\n FILE WITH WAVELENGHT HAS NOT BEEN READ PROPERLY, please check it.\n");
			free(vLambda);
			exit(EXIT_FAILURE);
		}
		printf("--------------------------------------------------------------------------------\n");
		printf("Number of wavelengths in the wavelength file: %d",nlambda);
		printf("\n--------------------------------------------------------------------------------\n");
		printf("\n--------------------------------------------------------------------------------");
		printf("\nATMOSPHERE LINES FILE READ: %s",nameInputFileLines);
		configCrontrolFile.CentralWaveLenght = readFileCuanticLines(nameInputFileLines,dat,indexLine,1);
		if(configCrontrolFile.CentralWaveLenght==0){
			printf("\n QUANTUM LINE NOT FOUND, REVIEW IT. INPUT CENTRAL WAVE LENGHT: %f",configCrontrolFile.CentralWaveLenght);
			exit(1);
		}
		/******************* CREATE CUANTINC AND INITIALIZE DINAMYC MEMORY*******************/
		cuantic = create_cuantic(dat,1);

	}

	/*********************************************** INITIALIZE VARIABLES  *********************************/
	REAL * vSigma = malloc((nlambda*NPARMS)*sizeof(REAL));
	for(i=0;i<nlambda*NPARMS;i++){
		vSigma[i] = configCrontrolFile.noise;
	}

	CC = PI / 180.0;
	CC_2 = CC * 2;

	wlines = (PRECISION *)calloc(2, sizeof(PRECISION));
	wlines[0] = 1;
	wlines[1] = configCrontrolFile.CentralWaveLenght;

	// count how many free param we have
	free_params=0;
	for(i=0;i<11;i++){
		if(configCrontrolFile.fix[i])
			free_params++;
	}

	/****************************************************************************************************/
	int numln=nlambda;
	// MACROTURBULENCE PLANS
	inFilterMAC = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
	outFilterMAC = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
	planFilterMAC = fftw_plan_dft_1d(numln, inFilterMAC, outFilterMAC, FFT_FORWARD, FFTW_MEASURE );
	inFilterMAC_DERIV = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
	outFilterMAC_DERIV = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
	planFilterMAC_DERIV = fftw_plan_dft_1d(numln, inFilterMAC_DERIV, outFilterMAC_DERIV, FFT_FORWARD, FFTW_MEASURE );

	inSpectraFwMAC = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
	outSpectraFwMAC = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
	planForwardMAC = fftw_plan_dft_1d(numln, inSpectraFwMAC, outSpectraFwMAC, FFT_FORWARD, FFTW_MEASURE );
	inSpectraBwMAC = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
	outSpectraBwMAC = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
	planBackwardMAC = fftw_plan_dft_1d(numln, inSpectraBwMAC, outSpectraBwMAC, FFT_BACKWARD, FFTW_MEASURE );

	// ********************************************* IF PSF HAS BEEN SELECTED IN TROL READ PSF FILE OR CREATE GAUSSIAN FILTER ***********//
	if(configCrontrolFile.ConvolveWithPSF){

		if(configCrontrolFile.FWHM > 0){
			G = fgauss_WL(FWHM,vLambda[1]-vLambda[0],vLambda[0],vLambda[nlambda/2],nlambda,&sizeG);
			//char nameAux [4096];
			//char obsAux [4096];
			//if(configCrontrolFile.ObservedProfiles[0]!='\0'){
			//	strcpy(obsAux,configCrontrolFile.ObservedProfiles);
			//	strcpy(nameAux,dirname(obsAux));
			//}
			//else{
			//	strcpy(obsAux,configCrontrolFile.InitialGuessModel);
			//	strcpy(nameAux,dirname(obsAux));
			//}
			//strcat(nameAux,"/gaussian.psf");
			//FILE *fptr = fopen(nameAux, "w");

			FILE *fptr = fopen("gaussian.psf", "w");

			if(fptr!=NULL){
			        printf("\n Gaussian PSF will be saved to file gaussian.psf");
				int kk;
				for (kk = 0; kk < nlambda; kk++)
				{
					fprintf(fptr,"\t%f\t%e\n", (vLambda[kk]-configCrontrolFile.CentralWaveLenght)*1000, G[kk]);
				}
				fclose(fptr);
			}
			else{
			  //	printf("\n ERROR !!! The output file cannot be opened: %s",nameAux);
				printf("\n ERROR !!! The output file cannot be opened: gaussian.psf");
			}
		}else{
			// read the number of lines
			FILE *fp;
			char ch;
			N_SAMPLES_PSF=0;
			//open file in read more
			fp=fopen(nameInputFilePSF,"r");
			if(fp==NULL)
			{
				printf("File \"%s\" does not exist!!!\n",nameInputFilePSF);
				return 0;
			}

			//read character by character and check for new line
			while((ch=fgetc(fp))!=EOF)
			{
				if(ch=='\n')
					N_SAMPLES_PSF++;
			}

			//close the file
			fclose(fp);
			if(N_SAMPLES_PSF>0){
				deltaLambda = calloc(N_SAMPLES_PSF,sizeof(PRECISION));
				PSF = calloc(N_SAMPLES_PSF,sizeof(PRECISION));
				readPSFFile(deltaLambda,PSF,nameInputFilePSF,configCrontrolFile.CentralWaveLenght);
				// CHECK if values of deltaLambda are in the same range of vLambda. For do that we truncate to 4 decimal places
				if( (trunc(vOffsetsLambda[0])) < (trunc(deltaLambda[0]))  || (trunc(vOffsetsLambda[nlambda-1])) > (trunc(deltaLambda[N_SAMPLES_PSF-1])) ){
					printf("\n\n ERROR: The wavelength range given in the PSF file is smaller than the range in the mesh file [%lf,%lf] [%lf,%lf]  \n\n",deltaLambda[0],vOffsetsLambda[0],deltaLambda[N_SAMPLES_PSF-1],vOffsetsLambda[nlambda-1]);
					exit(EXIT_FAILURE);
				}
				G = malloc(nlambda * sizeof(PRECISION));

				double offset=0;
				for(i=0;i<nlambda && !posWL;i++){
					if( fabs(trunc(vOffsetsLambda[i]))==0)
						posWL = i;
				}
				if(posWL!= (nlambda/2) ){ // move center to the middle of samples
					offset = ((  ((nlambda)/2) - posWL)*step)*1000;
				}

				interpolationLinearPSF(deltaLambda,  PSF, vOffsetsLambda ,N_SAMPLES_PSF, G, nlambda,offset);

				sizeG = nlambda;
			}
			else{
				printf("\n****************** ERROR THE PSF FILE is empty or damaged.******************\n");
				exit(EXIT_FAILURE);
			}
			printf("\n--------------------------------------------------------------------------------");
			printf("\nPSF FILE READ: %s", nameInputFilePSF);
			printf("\n--------------------------------------------------------------------------------\n");
		}

		//PSF FILTER PLANS
		inSpectraFwPSF = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
		outSpectraFwPSF = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
		planForwardPSF = fftw_plan_dft_1d(numln, inSpectraFwPSF, outSpectraFwPSF, FFT_FORWARD, FFTW_MEASURE );
		inSpectraBwPSF = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
		outSpectraBwPSF = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
		planBackwardPSF = fftw_plan_dft_1d(numln, inSpectraBwPSF, outSpectraBwPSF, FFT_BACKWARD, FFTW_MEASURE );

		fftw_complex * in = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * numln);
		int i;
		for (i = 0; i < numln; i++)
		{
			in[i] = G[i] + 0 * _Complex_I;
		}
		fftw_G_PSF = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * numln);
		fftw_plan p = fftw_plan_dft_1d(numln, in, fftw_G_PSF, FFT_FORWARD, FFTW_MEASURE );
		fftw_execute(p);
		for (i = 0; i < numln; i++)
		{
			fftw_G_PSF[i] = fftw_G_PSF[i] / numln;
		}
		fftw_destroy_plan(p);
		fftw_free(in);

		inPSF_MAC = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
		fftw_G_MAC_PSF = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
		planForwardPSF_MAC = fftw_plan_dft_1d(numln, inPSF_MAC, fftw_G_MAC_PSF, FFT_FORWARD, FFTW_MEASURE );
		inMulMacPSF = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
		outConvFilters = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
		planBackwardPSF_MAC = fftw_plan_dft_1d(numln, inMulMacPSF, outConvFilters, FFT_BACKWARD, FFTW_MEASURE );

		inPSF_MAC_DERIV = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
		fftw_G_MAC_DERIV_PSF = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
		planForwardPSF_MAC_DERIV = fftw_plan_dft_1d(numln, inPSF_MAC_DERIV, fftw_G_MAC_DERIV_PSF, FFT_FORWARD, FFTW_MEASURE );
		inMulMacPSFDeriv = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
		outConvFiltersDeriv = (fftw_complex *) fftw_malloc(sizeof(fftw_complex) * numln);
		planBackwardPSF_MAC_DERIV = fftw_plan_dft_1d(numln, inMulMacPSFDeriv, outConvFiltersDeriv, FFT_BACKWARD, FFTW_MEASURE );

	}
	/****************************************************************************************************/
	//  IF NUMBER OF CYCLES IS LES THAN 0 THEN --> WE USE CLASSICAL ESTIMATES
	//  IF NUMBER OF CYCLES IS 0 THEN -->  DO SYNTHESIS FROM THE INIT MODEL
	//  IF NUMBER OF CYCLES IS GREATER THAN 0 --> READ FITS FILE OR PER FILE AND PROCESS DO INVERSION WITH N CYCLES

	if(configCrontrolFile.NumberOfCycles<0){
		// read fits or per

		AllocateMemoryDerivedSynthesis(nlambda);
		if(strcmp(file_ext(configCrontrolFile.ObservedProfiles),PER_FILE)==0){ // invert only per file
			float * spectroPER = calloc(nlambda*NPARMS,sizeof(float));
			FILE * fReadSpectro;
			char * line = NULL;
			size_t len = 0;
			ssize_t read;
			fReadSpectro = fopen(configCrontrolFile.ObservedProfiles, "r");

			int contLine=0;
			if (fReadSpectro == NULL)
			{
				printf("Error opening the file of parameters, it's possible that the file doesn't exist. Please verify it. \n");
				printf("\n ******* THIS IS THE NAME OF THE FILE RECEVIED : %s \n", configCrontrolFile.ObservedProfiles);
				fclose(fReadSpectro);
				exit(EXIT_FAILURE);
			}
			float aux1, aux2,aux3,aux4,aux5,aux6;
			while ((read = getline(&line, &len, fReadSpectro)) != -1 && contLine<nlambda) {
				sscanf(line,"%e %e %e %e %e %e",&aux1,&aux2,&aux3,&aux4,&aux5,&aux6);
				spectroPER[contLine] = aux3;
				spectroPER[contLine + nlambda] = aux4;
				spectroPER[contLine + nlambda * 2] = aux5;
				spectroPER[contLine + nlambda * 3] = aux6;
				contLine++;
			}
			fclose(fReadSpectro);
			printf("\n--------------------------------------------------------------------------------");
			printf("\nOBSERVED PROFILES FILE READ: %s ", configCrontrolFile.ObservedProfiles);
			printf("\n--------------------------------------------------------------------------------\n");
			Init_Model initModel;
			initModel.eta0 = 0;
			initModel.mac = 0;
			initModel.dopp = 0;
			initModel.aa = 0;
			initModel.alfa = 0; //0.38; //stray light factor
			initModel.S1 = 0;
			//invert with classical estimates
			estimacionesClasicas(wlines[1], vLambda, nlambda, spectroPER, &initModel,0);
			// save model to file
			char nameAuxOutputModel [4096];
			if(configCrontrolFile.ObservedProfiles[0]!='\0')
				strcpy(nameAuxOutputModel,get_basefilename(configCrontrolFile.ObservedProfiles));
			else
				strcpy(nameAuxOutputModel,get_basefilename(configCrontrolFile.InitialGuessModel));

			strcat(nameAuxOutputModel,"_model_ce");
			strcat(nameAuxOutputModel,MOD_FILE);
			FILE * fptr = fopen(nameAuxOutputModel, "w");
			if(fptr!=NULL){
				fprintf(fptr,"eta_0               :%lf\n",initModel.eta0);
				fprintf(fptr,"magnetic field [G]  :%lf\n",initModel.B);
				fprintf(fptr,"LOS velocity[km/s]  :%lf\n",initModel.vlos);
				fprintf(fptr,"Doppler width [A]   :%lf\n",initModel.dopp);
				fprintf(fptr,"damping             :%lf\n",initModel.aa);
				fprintf(fptr,"gamma [deg]         :%lf\n",initModel.gm);
				fprintf(fptr,"phi  [deg]          :%lf\n",initModel.az);
				fprintf(fptr,"S_0                 :%lf\n",initModel.S0);
				fprintf(fptr,"S_1                 :%lf\n",initModel.S1);
				fprintf(fptr,"v_mac               :%lf\n",initModel.mac);
				fprintf(fptr,"filling factor      :%lf\n",initModel.alfa);
				fprintf(fptr,"# Iterations        :%d\n",0);
				fprintf(fptr,"chisqr              :%le\n",0.0);
				fprintf(fptr,"\n\n");
				fclose(fptr);
			}
			else{
				printf("\n ¡¡¡¡¡ ERROR: OUTPUT MODEL FILE CAN NOT BE OPENED: %s \n !!!!!",nameAuxOutputModel);
			}
			free(spectroPER);
		}
		else if(strcmp(file_ext(configCrontrolFile.ObservedProfiles),FITS_FILE)==0){ // invert image from fits file
			fitsImage = readFitsSpectroImage(configCrontrolFile.ObservedProfiles,0,nlambda);
			printf("\n--------------------------------------------------------------------------------");
			printf("\nOBSERVED PROFILES FILE READ: %s", configCrontrolFile.ObservedProfiles);
			printf("\n--------------------------------------------------------------------------------\n");
			// ALLOCATE MEMORY FOR STORE THE RESULTS
			int indexPixel = 0;
			vModels = calloc (fitsImage->numPixels , sizeof(Init_Model));
			vChisqrf = calloc (fitsImage->numPixels , sizeof(float));
			vNumIter = calloc (fitsImage->numPixels , sizeof(int));
			for(indexPixel = 0; indexPixel < fitsImage->numPixels; indexPixel++){

				//Initial Model
				Init_Model initModel;
				initModel.eta0 = INITIAL_MODEL.eta0;
				initModel.B = INITIAL_MODEL.B; //200 700
				initModel.gm = INITIAL_MODEL.gm;
				initModel.az = INITIAL_MODEL.az;
				initModel.vlos = INITIAL_MODEL.vlos; //km/s 0
				initModel.mac = INITIAL_MODEL.mac;
				initModel.dopp = INITIAL_MODEL.dopp;
				initModel.aa = INITIAL_MODEL.aa;
				initModel.alfa = INITIAL_MODEL.alfa; //0.38; //stray light factor
				initModel.S0 = INITIAL_MODEL.S0;
				initModel.S1 = INITIAL_MODEL.S1;
				estimacionesClasicas(wlines[1],vLambda, nlambda, fitsImage->pixels[indexPixel].spectro, &initModel,0);
				vModels[indexPixel] = initModel;

			}
			char nameAuxOutputModel [4096];
			if(configCrontrolFile.ObservedProfiles[0]!='\0')
				strcpy(nameAuxOutputModel,get_basefilename(configCrontrolFile.ObservedProfiles));
			else
				strcpy(nameAuxOutputModel,get_basefilename(configCrontrolFile.InitialGuessModel));
			strcat(nameAuxOutputModel,"_model_ce");
			strcat(nameAuxOutputModel,FITS_FILE);
			if(!writeFitsImageModels(nameAuxOutputModel,fitsImage->rows,fitsImage->cols,vModels,vChisqrf,vNumIter,configCrontrolFile.saveChisqr)){
					printf("\n ERROR WRITING FILE OF MODELS: %s",nameAuxOutputModel);
			}
			free(vModels);
			free(vChisqrf);
			free(vNumIter);
		}
		else{
			printf("\n OBSERVED PROFILES DOESN'T HAVE CORRECT EXTENSION  .PER or .FITS ");
			exit(EXIT_FAILURE);
		}
	}
	else if(configCrontrolFile.NumberOfCycles==0){ // synthesis

		if(access(configCrontrolFile.StrayLightFile,F_OK)!=-1){ //  IF NOT EMPTY READ stray light file
			if(strcmp(file_ext(configCrontrolFile.StrayLightFile),PER_FILE)==0){
				slight = readPerStrayLightFile(configCrontrolFile.StrayLightFile,nlambda,vOffsetsLambda);
				printf("\n--------------------------------------------------------------------------------");
				printf("\nSTRAY LIGHT FILE READ: %s ", configCrontrolFile.StrayLightFile);
				printf("\n--------------------------------------------------------------------------------\n");
			}
			else if(strcmp(file_ext(configCrontrolFile.StrayLightFile),FITS_FILE)==0){
				slight= readFitsStrayLightFile(&configCrontrolFile,&nl_straylight,&ns_straylight,&nx_straylight, &ny_straylight);
				if(nx_straylight!=0 || ny_straylight!=0){
					printf("\n Stray light file has 4 dimensions and for Synthesis only 2 dimensiones file is accepted, henceforth, stray light will not used for synthesis. \n");
					free(slight);
					slight= NULL;
				}
				if(nl_straylight!=nlambda){
					printf("\n The number of wavelengths is different in the stray light file: %d and malla grid file %d. \n. Stray light will not used for synthesis.", nl_straylight,nlambda);
					free(slight);
					slight= NULL;
				}
				printf("\n--------------------------------------------------------------------------------");
				printf("\nSTRAY LIGHT FILE READ: %s ", configCrontrolFile.StrayLightFile);
				printf("\n--------------------------------------------------------------------------------\n");
			}
			else{
				printf("\n Stray light file hasn't extension .PER or .FITS, review it. \n. Stray light will not used for synthesis.\n");
				free(slight);
				slight= NULL;
			}
		}

		Init_Model initModel;
		initModel.eta0 = INITIAL_MODEL.eta0;
		initModel.B = INITIAL_MODEL.B; //200 700
		initModel.gm = INITIAL_MODEL.gm;
		initModel.az = INITIAL_MODEL.az;
		initModel.vlos = INITIAL_MODEL.vlos; //km/s 0
		initModel.mac = INITIAL_MODEL.mac;
		initModel.dopp = INITIAL_MODEL.dopp;
		initModel.aa = INITIAL_MODEL.aa;
		initModel.alfa = INITIAL_MODEL.alfa; //0.38; //stray light factor
		initModel.S0 = INITIAL_MODEL.S0;
		initModel.S1 = INITIAL_MODEL.S1;
		printf("\n--------------------------------------------------------------------------------");
		printf("\nATMOSPHERE MODEL FILE READ: %s ",configCrontrolFile.InitialGuessModel);
		printf("\n--------------------------------------------------------------------------------");
		printf("\nINITAL MODEL ATMOSPHERE: \n\n");
		printf("eta_0               :%lf\n",initModel.eta0);
		printf("magnetic field [G]  :%lf\n",initModel.B);
		printf("LOS velocity[km/s]  :%lf\n",initModel.vlos);
		printf("Doppler width [A]   :%lf\n",initModel.dopp);
		printf("damping             :%lf\n",initModel.aa);
		printf("gamma [deg]         :%lf\n",initModel.gm);
		printf("phi   [deg]         :%lf\n",initModel.az);
		printf("S_0                 :%lf\n",initModel.S0);
		printf("S_1                 :%lf\n",initModel.S1);
		printf("v_mac [km/s]        :%lf\n",initModel.mac);
		printf("filling factor      :%lf\n",initModel.alfa);
		printf("--------------------------------------------------------------------------------\n");

		AllocateMemoryDerivedSynthesis(nlambda);

		if(configCrontrolFile.ConvolveWithPSF && initModel.mac>0){
			printf("\n--------------------------------------------------------------------------------");
			printf("\nThe program needs to use convolution. Filter PSF activated and macroturbulence greater than zero. ");
			printf("\n--------------------------------------------------------------------------------\n");
		}
		else if(configCrontrolFile.ConvolveWithPSF){
			printf("\n--------------------------------------------------------------------------------");
			printf("\nThe program needs to use convolution. Filter PSF activated. ");
			printf("\n--------------------------------------------------------------------------------\n");
		}
		else if(initModel.mac>0){
			printf("\n--------------------------------------------------------------------------------");
			printf("\nThe program needs to use convolution. Macroturbulence in initial atmosphere model greater than zero.");
			printf("\n--------------------------------------------------------------------------------\n");
		}
		// synthesis
		mil_sinrf(cuantic, &initModel, wlines, vLambda, nlambda, spectra, configCrontrolFile.mu, slight,spectra_mac,spectra_slight, configCrontrolFile.ConvolveWithPSF);
		me_der(cuantic, &initModel, wlines, vLambda, nlambda, d_spectra, spectra_mac, spectra_slight, configCrontrolFile.mu, slight, configCrontrolFile.ConvolveWithPSF,configCrontrolFile.fix);

		// in this case basenamefile is from initmodel
		char nameAux [4096];

		if(configCrontrolFile.ObservedProfiles[0]!='\0')
			strcpy(nameAux,get_basefilename(configCrontrolFile.ObservedProfiles));
		else
			strcpy(nameAux,get_basefilename(configCrontrolFile.InitialGuessModel));
		strcat(nameAux,PER_FILE);
		FILE *fptr = fopen(nameAux, "w");
		if(fptr!=NULL){
			int kk;
			for (kk = 0; kk < nlambda; kk++)
			{
				fprintf(fptr,"%d\t%f\t%e\t%e\t%e\t%e\n", indexLine, (vLambda[kk]-configCrontrolFile.CentralWaveLenght)*1000, spectra[kk], spectra[kk + nlambda], spectra[kk + nlambda * 2], spectra[kk + nlambda * 3]);
			}
			fclose(fptr);
			printf("\n--------------------------------------------------------------------------------");
			printf("\n------------------SYNTHESIS DONE: %s",nameAux);
			printf("\n--------------------------------------------------------------------------------\n");
		}
		else{
			printf("\n ERROR !!! The output file can not be open: %s",nameAux);
		}

		/*int number_parametros = 0;
		for (number_parametros = 0; number_parametros < NTERMS; number_parametros++)
		{
			strcpy(nameAux,get_basefilename(configCrontrolFile.InitialGuessModel));
			strcat(nameAux,"_C_");
			char extension[10];
			sprintf(extension, "%d%s", number_parametros,".per");
			strcat(nameAux,extension);
			FILE *fptr = fopen(nameAux, "w");
			//printf("\n FUNCION RESPUESTA: %d \n",number_parametros);
			int kk;
			for (kk = 0; kk < nlambda; kk++)
			{
			fprintf(fptr,"1\t%lf\t%le\t%le\t%le\t%le\n", vLambda[kk],
			d_spectra[kk + nlambda * number_parametros],
			d_spectra[kk + nlambda * number_parametros + nlambda * NTERMS],
			d_spectra[kk + nlambda * number_parametros + nlambda * NTERMS * 2],
			d_spectra[kk + nlambda * number_parametros + nlambda * NTERMS * 3]);
			}
			fclose(fptr);
		}
		printf("\n");*/

	}
	else{ // INVERT PIXEL FROM PER FILE OR IMAGE FROM FITS FILE

		if(strcmp(file_ext(configCrontrolFile.ObservedProfiles),PER_FILE)==0){ // invert only per file
			float * spectroPER = calloc(nlambda*NPARMS,sizeof(float));
			FILE * fReadSpectro;
			char * line = NULL;
			size_t len = 0;
			ssize_t read;
			fReadSpectro = fopen(configCrontrolFile.ObservedProfiles, "r");

			int contLine=0;
			if (fReadSpectro == NULL)
			{
				printf("Error opening the file of parameters, it's possible that the file doesn't exist. Please verify it. \n");
				printf("\n ******* THIS IS THE NAME OF THE FILE RECEVIED : %s \n", configCrontrolFile.ObservedProfiles);
				fclose(fReadSpectro);
				exit(EXIT_FAILURE);
			}

			float aux1, aux2, aux3, aux4, aux5, aux6;
			while ((read = getline(&line, &len, fReadSpectro)) != -1) {
				sscanf(line,"%e %e %e %e %e %e",&aux1,&aux2,&aux3,&aux4,&aux5,&aux6);
				if(contLine<nlambda){
					spectroPER[contLine] = aux3;
					spectroPER[contLine + nlambda] = aux4;
					spectroPER[contLine + nlambda * 2] = aux5;
					spectroPER[contLine + nlambda * 3] = aux6;
				}
				contLine++;
			}
			fclose(fReadSpectro);
			printf("\n--------------------------------------------------------------------------------");
			printf("\nOBSERVED PROFILES FILE READ: %s ", configCrontrolFile.ObservedProfiles);
			printf("\n--------------------------------------------------------------------------------");
			printf("\nNumber of wavelengths in the observed profiles: %d",contLine);
			printf("\n--------------------------------------------------------------------------------\n");
			if(nlambda!=contLine){
				printf("\n--------------------------------------------------------------------------------\n");
				printf("\nERROR: The number of wavelenghts in observed profiles file  %d is different to number of wavelengths in malla grid %d\n",contLine,nlambda);
				exit(EXIT_FAILURE);
			}
			if(configCrontrolFile.fix[10] &&  access(configCrontrolFile.StrayLightFile,F_OK)!=-1){ //  IF NOT EMPTY READ stray light file
				if(strcmp(file_ext(configCrontrolFile.StrayLightFile),PER_FILE)==0){
					slight = readPerStrayLightFile(configCrontrolFile.StrayLightFile,nlambda,vOffsetsLambda);
					printf("\n--------------------------------------------------------------------------------");
					printf("\nSTRAY LIGHT FILE READ: %s ", configCrontrolFile.StrayLightFile);
					printf("\n--------------------------------------------------------------------------------\n");
				}
				else if(strcmp(file_ext(configCrontrolFile.StrayLightFile),FITS_FILE)==0){
					slight= readFitsStrayLightFile(&configCrontrolFile,&nl_straylight,&ns_straylight,&nx_straylight, &ny_straylight);
					if(nx_straylight!=0 || ny_straylight!=0){
						printf("\n Stray light file has 4 dimensions and for Inversion pixel only 2 dimensiones file is accepted, henceforth, stray light will not used for inversion pixel. \n");
						free(slight);
						slight= NULL;
					}
					if(nl_straylight!=nlambda){
						printf("\n The number of wavelengths is different in the stray light file: %d and malla grid file %d. \n. Stray light will not used for inversion pixel.", nl_straylight,nlambda);
						free(slight);
						slight= NULL;
					}
					printf("\n--------------------------------------------------------------------------------");
					printf("\nSTRAY LIGHT FILE READ: %s ", configCrontrolFile.StrayLightFile);
					printf("\n--------------------------------------------------------------------------------\n");
				}
				else{
					printf("\n Stray light file hasn't extension .PER or .FITS, review it. \n. Stray light will not used for inversion pixel.\n");
					free(slight);
					slight= NULL;
				}
			}

			AllocateMemoryDerivedSynthesis(nlambda);
			Init_Model initModel;
			initModel.eta0 = INITIAL_MODEL.eta0;
			initModel.B = INITIAL_MODEL.B; //200 700
			initModel.gm = INITIAL_MODEL.gm;
			initModel.az = INITIAL_MODEL.az;
			initModel.vlos = INITIAL_MODEL.vlos; //km/s 0
			initModel.mac = INITIAL_MODEL.mac;
			initModel.dopp = INITIAL_MODEL.dopp;
			initModel.aa = INITIAL_MODEL.aa;
			initModel.alfa = INITIAL_MODEL.alfa; //0.38; //stray light factor
			initModel.S0 = INITIAL_MODEL.S0;
			initModel.S1 = INITIAL_MODEL.S1;
			printf("\n--------------------------------------------------------------------------------");
			printf("\nATMOSPHERE MODEL FILE READ: %s ",configCrontrolFile.InitialGuessModel);
			printf("\n--------------------------------------------------------------------------------");
			printf("\nINITAL MODEL ATMOSPHERE: \n\n");
			printf("eta_0               :%lf\n",initModel.eta0);
			printf("magnetic field [G]  :%lf\n",initModel.B);
			printf("LOS velocity[km/s]  :%lf\n",initModel.vlos);
			printf("Doppler width [A]   :%lf\n",initModel.dopp);
			printf("damping             :%lf\n",initModel.aa);
			printf("gamma [deg]         :%lf\n",initModel.gm);
			printf("phi   [deg]         :%lf\n",initModel.az);
			printf("S_0                 :%lf\n",initModel.S0);
			printf("S_1                 :%lf\n",initModel.S1);
			printf("v_mac [km/s]        :%lf\n",initModel.mac);
			printf("filling factor      :%lf\n",initModel.alfa);
			printf("--------------------------------------------------------------------------------\n");

			if(configCrontrolFile.ConvolveWithPSF && initModel.mac>0){
				printf("\n--------------------------------------------------------------------------------");
				printf("\nThe program needs to use convolution. Filter PSF activated and macroturbulence greater than zero. ");
				printf("\n--------------------------------------------------------------------------------\n");
			}
			else if(configCrontrolFile.ConvolveWithPSF){
				printf("\n--------------------------------------------------------------------------------");
				printf("\nThe program needs to use convolution. Filter PSF activated. ");
				printf("\n--------------------------------------------------------------------------------\n");
			}
			else if(initModel.mac>0){
				printf("\n--------------------------------------------------------------------------------");
				printf("\nThe program needs to use convolution. Macroturbulence in initial atmosphere model greater than zero.");
				printf("\n--------------------------------------------------------------------------------\n");
			}
      		int numIter =0;
			printf("\n--------------------------------------------------------------------------------");
			printf("\nNumber of free parameters for inversion: %d", free_params);
			printf("\n--------------------------------------------------------------------------------\n");
      		lm_mils(cuantic, wlines, vLambda, nlambda, spectroPER, nlambda, &initModel, spectra, &chisqrf, slight, configCrontrolFile.toplim, configCrontrolFile.NumberOfCycles,
               configCrontrolFile.WeightForStokes, configCrontrolFile.fix, vSigma, configCrontrolFile.noise, configCrontrolFile.InitialDiagonalElement,&configCrontrolFile.ConvolveWithPSF,&numIter,configCrontrolFile.mu, configCrontrolFile.logclambda);

			// SAVE OUTPUT MODEL
			char nameAuxOutputModel [4096];

			if(configCrontrolFile.ObservedProfiles[0]!='\0')
				strcpy(nameAuxOutputModel,get_basefilename(configCrontrolFile.ObservedProfiles));
			else
				strcpy(nameAuxOutputModel,get_basefilename(configCrontrolFile.InitialGuessModel));

			strcat(nameAuxOutputModel,"_model");
			strcat(nameAuxOutputModel,MOD_FILE);

			FILE *fptr = fopen(nameAuxOutputModel, "w");
			if(fptr!=NULL){
				fprintf(fptr,"eta_0               :%lf\n",initModel.eta0);
				fprintf(fptr,"magnetic field [G]  :%lf\n",initModel.B);
				fprintf(fptr,"LOS velocity[km/s]  :%lf\n",initModel.vlos);
				fprintf(fptr,"Doppler width [A]   :%lf\n",initModel.dopp);
				fprintf(fptr,"damping             :%lf\n",initModel.aa);
				fprintf(fptr,"gamma [deg]         :%lf\n",initModel.gm);
				fprintf(fptr,"phi   [deg]         :%lf\n",initModel.az);
				fprintf(fptr,"S_0                 :%lf\n",initModel.S0);
				fprintf(fptr,"S_1                 :%lf\n",initModel.S1);
				fprintf(fptr,"v_mac [km/s]        :%lf\n",initModel.mac);
				fprintf(fptr,"filling factor      :%lf\n",initModel.alfa);
				fprintf(fptr,"# Iterations        :%d\n",numIter);
				fprintf(fptr,"chisqr              :%le\n",chisqrf);
				fprintf(fptr,"\n\n");
				fclose(fptr);
				printf("\n\n--------------------------------------------------------------------------------");
				printf("\nINVERTED MODEL SAVED IN FILE: %s",nameAuxOutputModel);
				printf("\n--------------------------------------------------------------------------------\n");
			}
			else{
				printf("\n ¡¡¡¡¡ ERROR: OUTPUT MODEL FILE CAN NOT BE OPENED\n !!!!! ");
			}

			// SAVE OUTPUT ADJUST SYNTHESIS PROFILES
			if(configCrontrolFile.SaveSynthesisAdjusted){
				char nameAuxOutputStokes [4096];
				if(configCrontrolFile.ObservedProfiles[0]!='\0')
					strcpy(nameAuxOutputStokes,get_basefilename(configCrontrolFile.ObservedProfiles));
				else
					strcpy(nameAuxOutputStokes,get_basefilename(configCrontrolFile.InitialGuessModel));
				strcat(nameAuxOutputStokes,STOKES_PER_EXT);
				FILE *fptr = fopen(nameAuxOutputStokes, "w");
				if(fptr!=NULL){
			      //printf("\n valores de spectro sintetizado\n");
					int kk;
					for (kk = 0; kk < nlambda; kk++)
					{
						fprintf(fptr,"%d\t%f\t%e\t%e\t%e\t%e\n", indexLine, (vLambda[kk]-configCrontrolFile.CentralWaveLenght)*1000, spectra[kk], spectra[kk + nlambda], spectra[kk + nlambda * 2], spectra[kk + nlambda * 3]);
					}
					//printf("\nVALORES DE LAS FUNCIONES RESPUESTA \n");
					fclose(fptr);
					printf("\n--------------------------------------------------------------------------------");
					printf("\nOutput profiles: %s",nameAuxOutputStokes);
					printf("\n--------------------------------------------------------------------------------\n");
				}
				else{
					printf("\n ¡¡¡¡¡ ERROR: OUTPUT SYNTHESIS PROFILE ADJUSTED FILE CAN NOT BE OPENED\n !!!!! ");
				}
			}
			free(spectroPER);
		}
		else if(strcmp(file_ext(configCrontrolFile.ObservedProfiles),FITS_FILE)==0){ // invert image from fits file

			// check if read stray light
			if(configCrontrolFile.fix[10] && access(configCrontrolFile.StrayLightFile,F_OK)!=-1){ //  IF NOT EMPTY READ stray light file
				if(strcmp(file_ext(configCrontrolFile.StrayLightFile),PER_FILE)==0){
					slight = readPerStrayLightFile(configCrontrolFile.StrayLightFile,nlambda,vOffsetsLambda);
					printf("\n--------------------------------------------------------------------------------");
					printf("\nSTRAY LIGHT FILE READ: %s ", configCrontrolFile.StrayLightFile);
					printf("\n--------------------------------------------------------------------------------\n");
				}
				else if(strcmp(file_ext(configCrontrolFile.StrayLightFile),FITS_FILE)==0){
					slight = readFitsStrayLightFile(&configCrontrolFile,&nl_straylight,&ns_straylight,&nx_straylight, &ny_straylight);
					if(nl_straylight!=nlambda){
						printf("\n The number of wavelengths is different in the stray light file: %d and malla grid file %d. \n. Stray light will not used for inversion.", nl_straylight,nlambda);
						free(slight);
						slight= NULL;
						exit(EXIT_FAILURE);
					}
					printf("\n--------------------------------------------------------------------------------");
					printf("\nSTRAY LIGHT FILE READ: %s", configCrontrolFile.StrayLightFile);
					printf("\n--------------------------------------------------------------------------------\n");
				}
				else{
					printf("\n Stray light file hasn't extension .PER or .FITS, review it. \n. Stray light will not used for inversion.\n");
					free(slight);
					slight= NULL;
					exit(EXIT_FAILURE);
				}
			}
			// READ PIXELS FROM IMAGE
			PRECISION timeReadImage;
			clock_t t;
			t = clock();
			fitsImage = readFitsSpectroImage(nameInputFileSpectra,0,nlambda);
			t = clock() - t;
			timeReadImage = ((PRECISION)t)/CLOCKS_PER_SEC; // in seconds
			printf("\n--------------------------------------------------------------------------------");
			printf("\nOBSERVED PROFILES FILE READ: %s", nameInputFileSpectra);
			printf("\n--------------------------------------------------------------------------------");
			printf("\nTIME TO READ FITS IMAGE:  %f seconds to execute ", timeReadImage);
			printf("\n--------------------------------------------------------------------------------\n");

			if(fitsImage!=NULL){
				FitsImage * imageStokesAdjust = NULL;
				if(configCrontrolFile.SaveSynthesisAdjusted){
					imageStokesAdjust = malloc(sizeof(FitsImage));
					imageStokesAdjust->rows = fitsImage->rows;
					imageStokesAdjust->cols = fitsImage->cols;
					imageStokesAdjust->nLambdas = fitsImage->nLambdas;
					imageStokesAdjust->numStokes = fitsImage->numStokes;
					imageStokesAdjust->pos_col = fitsImage->pos_col;
					imageStokesAdjust->pos_row = fitsImage->pos_row;
					imageStokesAdjust->pos_lambda = fitsImage->pos_lambda;
					imageStokesAdjust->pos_stokes_parameters = fitsImage->pos_stokes_parameters;
					imageStokesAdjust->numPixels = fitsImage->numPixels;
					imageStokesAdjust->pixels = calloc(imageStokesAdjust->numPixels, sizeof(vpixels));
					imageStokesAdjust->naxes = fitsImage->naxes;
					imageStokesAdjust->vCard = fitsImage->vCard;
					imageStokesAdjust->vKeyname = fitsImage->vKeyname;
					imageStokesAdjust->nkeys = fitsImage->nkeys;
					imageStokesAdjust->naxis = fitsImage->naxis;
					imageStokesAdjust->bitpix = fitsImage->bitpix;
					for( i=0;i<imageStokesAdjust->numPixels;i++){
						imageStokesAdjust->pixels[i].spectro = calloc ((imageStokesAdjust->numStokes*imageStokesAdjust->nLambdas),sizeof(float));
					}
				}
				printf("\n--------------------------------------------------------------------------------");
				printf("\nATMOSPHERE MODEL FILE READ: %s ",configCrontrolFile.InitialGuessModel);
				printf("\n--------------------------------------------------------------------------------");
				printf("\nINITAL MODEL ATMOSPHERE: \n\n");
				printf("eta_0               :%lf\n",INITIAL_MODEL.eta0);
				printf("magnetic field [G]  :%lf\n",INITIAL_MODEL.B);
				printf("LOS velocity[km/s]  :%lf\n",INITIAL_MODEL.vlos);
				printf("Doppler width [A]   :%lf\n",INITIAL_MODEL.dopp);
				printf("damping             :%lf\n",INITIAL_MODEL.aa);
				printf("gamma [deg]         :%lf\n",INITIAL_MODEL.gm);
				printf("phi   [deg]         :%lf\n",INITIAL_MODEL.az);
				printf("S_0                 :%lf\n",INITIAL_MODEL.S0);
				printf("S_1                 :%lf\n",INITIAL_MODEL.S1);
				printf("v_mac [km/s]        :%lf\n",INITIAL_MODEL.mac);
				printf("filling factor      :%lf\n",INITIAL_MODEL.alfa);
				printf("--------------------------------------------------------------------------------\n");

				if(configCrontrolFile.ConvolveWithPSF && INITIAL_MODEL.mac>0){
					printf("\n--------------------------------------------------------------------------------");
					printf("\nThe program needs to use convolution. Filter PSF activated and macroturbulence greater than zero. ");
					printf("\n--------------------------------------------------------------------------------\n");
				}
				else if(configCrontrolFile.ConvolveWithPSF){
					printf("\n--------------------------------------------------------------------------------");
					printf("\nThe program needs to use convolution. Filter PSF activated. ");
					printf("\n--------------------------------------------------------------------------------\n");
				}
				else if(INITIAL_MODEL.mac>0){
					printf("\n--------------------------------------------------------------------------------");
					printf("\nThe program needs to use convolution. Macroturbulence in initial atmosphere model greater than zero.");
					printf("\n--------------------------------------------------------------------------------\n");
				}
				printf("\n--------------------------------------------------------------------------------");
				printf("\nNumber of free parameters for inversion: %d", free_params);
				printf("\n--------------------------------------------------------------------------------\n");
				//***************************************** INIT MEMORY WITH SIZE OF LAMBDA ****************************************************//
				AllocateMemoryDerivedSynthesis(nlambda);
				int indexPixel = 0;

				// ALLOCATE MEMORY FOR STORE THE RESULTS

				vModels = calloc (fitsImage->numPixels , sizeof(Init_Model));
				vChisqrf = calloc (fitsImage->numPixels , sizeof(float));
				vNumIter = calloc (fitsImage->numPixels , sizeof(int));
				t = clock();
				printf("\n--------------------------------------------------------------------------------");
				printf("\n----------------------- IMAGE INVERSION IN PROGRESS ----------------------------");
				printf("\n--------------------------------------------------------------------------------\n");

				for(indexPixel = 0; indexPixel < fitsImage->numPixels; indexPixel++){

					//Initial Model
					Init_Model initModel;
					initModel.eta0 = INITIAL_MODEL.eta0;
					initModel.B = INITIAL_MODEL.B; //200 700
					initModel.gm = INITIAL_MODEL.gm;
					initModel.az = INITIAL_MODEL.az;
					initModel.vlos = INITIAL_MODEL.vlos; //km/s 0
					initModel.mac = INITIAL_MODEL.mac;
					initModel.dopp = INITIAL_MODEL.dopp;
					initModel.aa = INITIAL_MODEL.aa;
					initModel.alfa = INITIAL_MODEL.alfa; //0.38; //stray light factor
					initModel.S0 = INITIAL_MODEL.S0;
					initModel.S1 = INITIAL_MODEL.S1;

					// CLASSICAL ESTIMATES TO GET B, GAMMA
					estimacionesClasicas(wlines[1], vLambda, nlambda, fitsImage->pixels[indexPixel].spectro, &initModel,1);
					if (isnan(initModel.B))
						initModel.B = 1;
					if (isnan(initModel.vlos))
						initModel.vlos = 1e-3;
					if (isnan(initModel.gm))
						initModel.gm = 1;
					if (isnan(initModel.az))
						initModel.az = 1;
					// INVERSION RTE

					float * slightPixel;
					if(slight==NULL)
						slightPixel = NULL;
					else{
						if(nx_straylight && ny_straylight){
							slightPixel = slight+ (nlambda*NPARMS*indexPixel);
						}
						else {
							slightPixel = slight;
						}
					}
					vNumIter[indexPixel] = indexPixel;
					lm_mils(cuantic, wlines, vLambda, nlambda, fitsImage->pixels[indexPixel].spectro, nlambda, &initModel, spectra, &vChisqrf[indexPixel], slightPixel, configCrontrolFile.toplim, configCrontrolFile.NumberOfCycles,
							configCrontrolFile.WeightForStokes, configCrontrolFile.fix, vSigma,  configCrontrolFile.noise,configCrontrolFile.InitialDiagonalElement,&configCrontrolFile.ConvolveWithPSF,&vNumIter[indexPixel],configCrontrolFile.mu,configCrontrolFile.logclambda);

					vModels[indexPixel] = initModel;
					if(configCrontrolFile.SaveSynthesisAdjusted){
						int kk;
						for (kk = 0; kk < (nlambda * NPARMS); kk++)
						{
							imageStokesAdjust->pixels[indexPixel].spectro[kk] = spectra[kk] ;
						}
					}
				}
				t = clock() - t;
				timeReadImage = ((PRECISION)t)/CLOCKS_PER_SEC; // in seconds
				printf("\n\n--------------------------------------------------------------------------------");
				printf("\nFINISH EXECUTION OF INVERSION: %f seconds to execute ", timeReadImage);
				printf("\n--------------------------------------------------------------------------------");

				char nameAuxOutputModel [4096];
				if(configCrontrolFile.ObservedProfiles[0]!='\0')
					strcpy(nameAuxOutputModel,get_basefilename(configCrontrolFile.ObservedProfiles));
				else
					strcpy(nameAuxOutputModel,get_basefilename(configCrontrolFile.InitialGuessModel));

				strcat(nameAuxOutputModel,MOD_FITS);
				if(!writeFitsImageModels(nameAuxOutputModel,fitsImage->rows,fitsImage->cols,vModels,vChisqrf,vNumIter,configCrontrolFile.saveChisqr)){
						printf("\n ERROR WRITING FILE OF MODELS: %s",nameAuxOutputModel);
				}
				// PROCESS FILE OF SYNTETIC PROFILES

				if(configCrontrolFile.SaveSynthesisAdjusted){
					// WRITE SINTHETIC PROFILES TO FITS FILE
					char nameAuxOutputStokes [4096];
					if(configCrontrolFile.ObservedProfiles[0]!='\0')
						strcpy(nameAuxOutputStokes,get_basefilename(configCrontrolFile.ObservedProfiles));
					else
						strcpy(nameAuxOutputStokes,get_basefilename(configCrontrolFile.InitialGuessModel));
					strcat(nameAuxOutputStokes,STOKES_FIT_EXT);
					if(!writeFitsImageProfiles(nameAuxOutputStokes,nameInputFileSpectra,imageStokesAdjust)){
						printf("\n ERROR WRITING FILE OF SINTHETIC PROFILES: %s",nameOutputFilePerfiles);
					}
				}
				if(configCrontrolFile.SaveSynthesisAdjusted)
					free(imageStokesAdjust);
				free(vModels);
				free(vChisqrf);
				free(vNumIter);
			}
			else{
				printf("\n\n ***************************** FITS FILE WITH THE SPECTRO IMAGE CAN NOT BE READ IT ******************************\n");
			}

			freeFitsImage(fitsImage);
		}
		else{
			printf("\n OBSERVED PROFILES DOESN'T HAVE CORRECT EXTENSION  .PER or .FITS ");
			exit(EXIT_FAILURE);
		}
	}

	fftw_free(inFilterMAC);
	fftw_free(outFilterMAC);
	fftw_destroy_plan(planFilterMAC);
	fftw_free(inFilterMAC_DERIV);
	fftw_free(outFilterMAC_DERIV);
	fftw_destroy_plan(planFilterMAC_DERIV);
	fftw_free(inSpectraFwMAC);
	fftw_free(outSpectraFwMAC);
	fftw_destroy_plan(planForwardMAC);
	fftw_free(inSpectraBwMAC);
	fftw_free(outSpectraBwMAC);
	fftw_destroy_plan(planBackwardMAC);

	if(configCrontrolFile.ConvolveWithPSF){
		fftw_free(inSpectraFwPSF);
		fftw_free(outSpectraFwPSF);
		fftw_destroy_plan(planForwardPSF);
		fftw_free(inSpectraBwPSF);
		fftw_free(outSpectraBwPSF);
		fftw_destroy_plan(planBackwardPSF);

		fftw_free(fftw_G_PSF);
		fftw_free(fftw_G_MAC_PSF);
		fftw_free(fftw_G_MAC_DERIV_PSF);

		fftw_free(inPSF_MAC);
		fftw_free(inMulMacPSF);
		fftw_free(inPSF_MAC_DERIV);
		fftw_free(inMulMacPSFDeriv);
		fftw_free(outConvFilters);
		fftw_free(outConvFiltersDeriv);

		fftw_destroy_plan(planForwardPSF_MAC);
		fftw_destroy_plan(planForwardPSF_MAC_DERIV);
		fftw_destroy_plan(planBackwardPSF_MAC);
		fftw_destroy_plan(planBackwardPSF_MAC_DERIV);
	}

	free(cuantic);
	free(wlines);
	free(vSigma);
	FreeMemoryDerivedSynthesis();
	if(G!=NULL) free(G);
	gsl_eigen_symmv_free (workspace);
	gsl_vector_free(eval);
	gsl_matrix_free(evec);

	return 0;
}


#if !defined(DECAY_H)
#define DECAY_H

#include "SM.h"
#include "THDM.h"
#include <complex>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_integration.h>

using namespace std;

/**
* @brief Calculates the decay modes of 2HDM Higgs bosons
*
* Given a THDM object, a DecayTable can be generated. From this table, the
* Higgs boson decay widths and branching ratios are obtained. For the complete
* list of available decay modes, we refer to the complete documentation, or
* the list of member methods below.
*/
class DecayTable {

 public:

  /**
  * @brief Default constructor
  *
  * This default constructor takes a THDM object as argument for which
  * the decays are to be calculated. %SM properties are taken from the SM
  * object in the THDM.
  *
  * @param mod Two-Higgs doublet model for which to calculate decay modes
  */
  DecayTable(THDM mod);

  /**
  * @brief Sets underlying 2HDM
  *
  * This method sets the THDM underlying the DecayTable.
  *
  * @param model Two-Higgs doublet model for which to calculate decay modes
  */
	void set_model(THDM model);

  /**
  * @brief Underlying 2HDM
  *
  * Use to obtain the underlying THDM object
  *
  * @returns The THDM object on which this DecayTable operates
  */
	THDM get_model();

  /**
  * @brief Decay width \f$\Gamma(h\to u_1\overline{u}_2) \f$
  *
  * This method calculates the on-shell decay width for the decay of Higgs
  * boson \a h to a pair of up-type quarks. QCD corrections have been included.
  *
  * @param h  Index of Higgs boson (1,2,3 = h,H,A)
  * @param u1 Index of up-type quark (1,2,3 = \f$ u,c,t \f$)
  * @param u2 Index of up-type antiquark (1,2,3 = \f$ \bar{u},\bar{c},\bar{t} \f$)
  *
  * @returns The decay width in GeV
  */
  double  get_gamma_huu(int h, int u1, int u2);

  /**
  * @brief Decay width \f$ \Gamma(h\to d_1\overline{d}_2) \f$
  *
  * This method calculates the on-shell decay width for the decay of Higgs
  * boson \a h to a pair of down-type quarks. QCD corrections have been included.
  *
  * @param h  Index of Higgs boson (1,2,3 = h,H,A)
  * @param d1 Index of down-type quark (1,2,3 = \f$ d,s,b \f$)
  * @param d2 Index of down-type antiquark (1,2,3 = \f$ \bar{d},\bar{s},\bar{b} \f$)
  *
  * @returns The decay width in GeV
  */
  double  get_gamma_hdd(int h, int d1, int d2);

  /**
  * @brief Decay width \f$ \Gamma(h\to l_1\overline{l}_2) \f$
  *
  * This method calculates the on-shell decay width for the decay of Higgs
  * boson \a h to a pair of charged leptons.
  *
  * @param h  Index of Higgs boson (1,2,3 = h,H,A)
  * @param l1 Index of lepton (1,2,3 = \f$ e,\mu,\tau \f$)
  * @param l2 Index of antilepton (1,2,3 = \f$ \bar{e},\bar{\mu},\bar{\tau} \f$)
  *
  * @returns The decay width in GeV
  */
  double  get_gamma_hll(int h, int l1, int l2);

  /**
  * @brief Decay width \f$ \Gamma(h\to u\overline{d}) \f$
  *
  * This method calculates the on-shell decay width for the decay of Higgs
  * boson \a h to a pair of quarks. QCD corrections have been included.
  *
  * @param h  Index of Higgs boson (4 = H+)
  * @param d  Index of down-type antiquark (1,2,3 = \f$ \bar{d},\bar{s},\bar{b} \f$)
  * @param u  Index of up-type quark (1,2,3 = \f$ u,c,t \f$)
  *
  * @returns The decay width in GeV
  */
  double  get_gamma_hdu(int h, int d, int u);

  /**
  * @brief Decay width \f$ \Gamma(h\to l\overline{\nu}_{l'}) \f$
  *
  * This method calculates the on-shell decay width for the decay of Higgs
  * boson \a h to lepton-neutrino.
  *
  * @param h  Index of Higgs boson (4 = H+)
  * @param l  Index of charged lepton (1,2,3 = \f$ e^+,\mu^+,\tau^+ \f$)
  * @param n  Index of neutrino (1,2,3 = \f$ \nu_e,\nu_\mu,\nu_\tau \f$)
  *
  * @returns The decay width in GeV
  */
  double  get_gamma_hln(int h, int l, int n);

  /**
  * @brief Decay width \f$ \Gamma(h\to H_1 H_2) \f$
  *
  * This method calculates the on-shell decay width for the decay of Higgs
  * boson \a h to a pair of Higgs bosons
  *
  * @param h  Index of decaying Higgs boson (1,2,3,4 = h,H,A,H+)
  * @param h1 Index of first Higgs boson (1,2,3,4 = h,H,A,H+)
  * @param h2 Index of second Higgs boson (1,2,3,4 = h,H,A,H+)
  *
  * @returns The decay width in GeV
  */
  double  get_gamma_hhh(int h, int h1, int h2);

  /**
  * @brief Decay width \f$ \Gamma(h\to VV) \f$
  *
  * This method calculates the decay width for the Higgs boson \a h
  * to a pair of vector bosons. The decay mode with one vector
  * boson off-shell is included.
  *
  * @param h  Index of decaying Higgs boson (1,2,3,4 = h,H,A,H+)
  * @param v  Index of vector bosons (1,2,3 = \f$\gamma \f$,Z,W)
  *
  * @returns The decay width in GeV
  */
  double  get_gamma_hvv(int h, int v);

  /**
  * @brief Decay width \f$ \Gamma(h\to VH) \f$
  *
  * This method calculates the decay width for the Higgs boson \a h
  * to one massive vector and one Higgs boson. Decay with the vector
  * boson off-shell is included.
  *
  * @param h  Index of decaying Higgs boson (1,2,3,4 = h,H,A,H+)
  * @param V  Index of vector boson (2,3 = \f$\gamma \f$,Z,W)
  * @param H  Index of final-state Higgs boson (1,2,3,4 = h,H,A,H+)
	*
  * @returns The decay width in GeV
  */
  double  get_gamma_hvh(int H, int V, int h);

  /**
  * @brief Decay width \f$ \Gamma(h\to gg) \f$
  *
  * This method calculates the decay width for the Higgs boson \a h
  * to a pair of gluons. LO QCD corrections are included.
  *
  * @param h  Index of decaying Higgs boson (1,2,3,4 = h,H,A,H+)
	*
  * @returns The decay width in GeV
  */
  double  get_gamma_hgg(int h);

  /**
  * @brief Decay width \f$ \Gamma(h\to \gamma\gamma) \f$
  *
  * This method calculates the decay width for the neutral
  * Higgs boson \a h to a pair of photons.
  *
  * @param h  Index of decaying Higgs boson (1,2,3 = h,H,A)
	*
  * @returns The decay width in GeV
  */
	double  get_gamma_hgaga(int h);

  /**
  * @brief Decay width \f$ \Gamma(h\to Z\gamma) \f$
  *
  * This method calculates the decay width for the neutral
  * Higgs boson \a h to a Z and a photon.
  *
  * @param h  Index of decaying Higgs boson (1,2,3 = h,H,A)
	*
  * @returns The decay width in GeV
  */
	double  get_gamma_hZga(int h);

  /**
  * @brief Decay width \f$ \Gamma(h\to WZ) \f$
  *
  * This method calculates the decay width for the neutral
  * Higgs boson \a h to a Z and a photon.
  *
  * @param h  Index of decaying Higgs boson (4 = H+-)
    *
  * @returns The decay width in GeV
  */
    double  get_gamma_hWZ(int h);

  /**
  * @brief Decay width \f$ \Gamma(h\to W\gamma) \f$
  *
  * This method calculates the decay width for the neutral
  * Higgs boson \a h to a Z and a photon.
  *
  * @param h  Index of decaying Higgs boson (4 = H+-)
    *
  * @returns The decay width in GeV
  */
    double  get_gamma_hWga(int h);

  /**
  * @brief Total width \f$ \Gamma_h \f$
  *
  * Calculates the total decay width of Higgs boson \a h
  *
  * @param h  Index of Higgs boson (1,2,3,4 = h,H,A,H+)
	*
  * @returns Total width in GeV
  */
  double  get_gammatot_h(int h);

  /**
  * @brief Total width \f$ \Gamma_V \f$
  *
  * Returns the total decay width of vector boson \a v
  *
  * @param v  Index of vector boson (2,3 = Z,W)
	*
  * @returns Total width in GeV
  */
  double  get_gammatot_v(int v);

  /**
  * @brief Total width \f$ \Gamma_t \f$
  *
  * Returns the total decay width of the top quark
  *
  * @returns Total width in GeV
  */
  double  get_gammatot_top();

  /**
  * @brief Decay width for \f$ t \to H^+X \f$
  *
  * Returns the decay width of the top quark in the charged Higgs mode
  *
  * @returns Decay width in GeV
  *
  * @param u Index of decaying quark (1,2,3 = \f$ u,c,t \f$)
  * @param h Index of Higgs boson (4 = H+)
	* @param d Index of down-type quark (1,2,3 = \f$ d,s,b \f$)
  */
  double  get_gamma_uhd(int u, int h, int d);

  double  get_gamma_uhu(int u1, int h, int u2);

  /**
  *	@brief Prints the decay modes of a Higgs boson
  *
  * The decay modes of Higgs boson \a h are printed to stdout
  *
  * @param h Index of Higgs boson (1,2,3,4 = h,H,A,H+)
  */
  void    print_decays(int h);

  /**
  *	@brief Prints the total width of a Higgs boson
  *
  * The total decay width of Higgs boson \a h are printed to stdout
  *
  * @param h Index of Higgs boson (1,2,3,4 = h,H,A,H+)
  */
  void    print_width(int h);

  /**
  *	@brief Prints the decay modes of the top quark
  *
  * The decay modes of the top quark are printed to stdout
  */
  void    print_top_decays();

  /**
  *	@brief Prints decay information for a Higgs boson in LesHouches format
  *
  * The decay information for Higgs boson \a h are printed to a file in
  * LesHouches format
  *
  * @param output The name of the output file to write
  * @param h 			Index of Higgs boson (1,2,3,4 = h,H,A,H+)
  * @param full 	If \a true, all decay modes are printed, if \a false only the total width
  */
  void    print_decays_LesHouches(FILE* output, int h, bool full);

  /**
  *	@brief Prints decay information for the top quark in LesHouches format
  *
  * The decay information for the top quark are printed to a file in
  * LesHouches format
  *
  * @param output The name of the output file to write
  * @param full 	If \a true, all decay modes are printed, if \a false only the total width
  */
  void    print_top_decays_LesHouches(FILE* output, bool full);

  /**
  *     @brief Turns QCD corrections on or off
  *
  * This method is used to turn QCD corrections on or off. If the output is
  * meant to be used with the MadGraph/MadEvent 2HDMC model
  * QCD corrections should be turned off to get a consistent result.
  *
  * @param set  If \a true QCD corrections are turned on,
  *             if \a false QCD corrections are turned off
  */
  void    set_qcd(bool set);

  static double  DHp(double ui, double uj, double xi, double xj, double sqL);
  static double  DHm(double ui, double uj, double xi, double xj, double sqL);
  static double  BHp(double ui, double uj, double xi, double xj, double sqL);

 private:
  THDM model;
  SM sm;

  complex <double> F_sf(double t);
  complex <double> F_pf(double t);
  complex <double> F_0(double t);
  complex <double> F_1(double t);
  complex <double> ftau(double t);
  complex <double> gtau(double t);
  complex <double> I_1(double tau, double lambda);
  complex <double> I_2(double tau, double lambda);
  complex <double> FF_s(double tau, double lambda);
  complex <double> FF_p(double tau, double lambda);
  complex <double> FW(double tau, double lambda);
  complex <double> FHp(double tau, double lambda);

  double gammatot_h[5];
  double gamma_uhd[5][5][5];
  double gamma_uhu[5][5][5];
  double gamma_hdd[5][5][5];
  double gamma_huu[5][5][5];
  double gamma_hdu[5][5][5];
  double gamma_hll[5][5][5];
  double gamma_hln[5][5][5];
  double gamma_hgg[5];
  double gamma_hgaga[5];
  double gamma_hZga[5];
  double gamma_hWga[5]; // For H+- only
  double gamma_hWZ[5]; // For H+- only
  double gamma_hvv[5][5];
  double gamma_hvh[5][5][5];
  double gamma_hhh[5][5][5];

  double  br(double dG, double G);

  double  hvv_onshell(int h, int V, double M);
  double  hvv_offshell(int h, int V, double M);
  double  hvv_all(int h, int V, double M);
  double  hff_onshell(double M, double m1, double m1run, double m2, double m2run, complex<double> cs, complex<double> cp, int Nc, int h, bool tt);
  double  hpff_onshell(double M, double m1, double m1run, double m2, double m2run, complex<double> cs, complex<double> cp, int Nc, int h);
  double  htt_onshell(double M, double m1, double m2, int Nc, int h);
  double  htt_offshell(double M, double m1, double m2, int Nc, int h);
  double  htb_offshell(double M, double m1, double m1run, double m2, double m2run, complex<double> cs, complex<double> cp, int Nc);

  double  hvh_onshell(int H, int V, int h, double M);
  double  hvh_offshell(int H, int V, int h, double M);
  double  hdu_offshell(int h, int d, int u, double M);
  double  hgaga(int h);
  double  hZga(int h);
  double  hWga(int h);
  double  hWZ(int h);
  double  hgg(int h);
  double  PS2(double M, double m1, double m2);
  double  LAM(double m12, double m22, double m32);

  double  interp(double R, double x, double y, double c);

  bool    qcd_on;
  int     err_code;

  void    print_decay_LesHouches(FILE* output, double br, int id1, int id2);
  void    print_decay(const char *h, const char *id1, const char *id2, double g, double br);
  void    print_decays(FILE* output, int h, bool full, bool lh);

};

#endif


/*
 * Copyright (c) 1997-1999 Massachusetts Institute of Technology
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

/* This file was automatically generated --- DO NOT EDIT */
/* Generated on Mon Mar  8 17:45:11 EST 1999 */

#include <fftw-int.h>
#include <fftw.h>

/* Generated by: ./genfft -magic-alignment-check -magic-twiddle-load-all -magic-variables 4 -magic-loopi -notwiddleinv 32 */

/*
 * This function contains 372 FP additions, 84 FP multiplications,
 * (or, 340 additions, 52 multiplications, 32 fused multiply/add),
 * 92 stack variables, and 128 memory accesses
 */
static const fftw_real K195090322 = FFTW_KONST(+0.195090322016128267848284868477022240927691618);
static const fftw_real K980785280 = FFTW_KONST(+0.980785280403230449126182236134239036973933731);
static const fftw_real K831469612 = FFTW_KONST(+0.831469612302545237078788377617905756738560812);
static const fftw_real K555570233 = FFTW_KONST(+0.555570233019602224742830813948532874374937191);
static const fftw_real K382683432 = FFTW_KONST(+0.382683432365089771728459984030398866761344562);
static const fftw_real K923879532 = FFTW_KONST(+0.923879532511286756128183189396788286822416626);
static const fftw_real K707106781 = FFTW_KONST(+0.707106781186547524400844362104849039284835938);

/*
 * Generator Id's :
 * $Id: exprdag.ml,v 1.36 1999/02/19 17:22:11 athena Exp $
 * $Id: fft.ml,v 1.41 1999/02/19 17:22:13 athena Exp $
 * $Id: to_c.ml,v 1.24 1999/02/19 17:22:17 athena Exp $
 */

void fftwi_no_twiddle_32(const fftw_complex *input, fftw_complex *output, int istride, int ostride)
{
     fftw_real tmp7;
     fftw_real tmp339;
     fftw_real tmp70;
     fftw_real tmp313;
     fftw_real tmp97;
     fftw_real tmp215;
     fftw_real tmp179;
     fftw_real tmp241;
     fftw_real tmp14;
     fftw_real tmp314;
     fftw_real tmp77;
     fftw_real tmp340;
     fftw_real tmp182;
     fftw_real tmp216;
     fftw_real tmp104;
     fftw_real tmp242;
     fftw_real tmp153;
     fftw_real tmp236;
     fftw_real tmp53;
     fftw_real tmp60;
     fftw_real tmp287;
     fftw_real tmp336;
     fftw_real tmp360;
     fftw_real tmp290;
     fftw_real tmp293;
     fftw_real tmp294;
     fftw_real tmp170;
     fftw_real tmp233;
     fftw_real tmp333;
     fftw_real tmp359;
     fftw_real tmp164;
     fftw_real tmp234;
     fftw_real tmp173;
     fftw_real tmp237;
     fftw_real tmp22;
     fftw_real tmp318;
     fftw_real tmp343;
     fftw_real tmp85;
     fftw_real tmp112;
     fftw_real tmp185;
     fftw_real tmp220;
     fftw_real tmp245;
     fftw_real tmp29;
     fftw_real tmp321;
     fftw_real tmp342;
     fftw_real tmp92;
     fftw_real tmp119;
     fftw_real tmp184;
     fftw_real tmp223;
     fftw_real tmp244;
     fftw_real tmp126;
     fftw_real tmp229;
     fftw_real tmp38;
     fftw_real tmp45;
     fftw_real tmp278;
     fftw_real tmp329;
     fftw_real tmp357;
     fftw_real tmp281;
     fftw_real tmp284;
     fftw_real tmp285;
     fftw_real tmp143;
     fftw_real tmp226;
     fftw_real tmp326;
     fftw_real tmp356;
     fftw_real tmp137;
     fftw_real tmp227;
     fftw_real tmp146;
     fftw_real tmp230;
     ASSERT_ALIGNED_DOUBLE();
     {
	  fftw_real tmp3;
	  fftw_real tmp177;
	  fftw_real tmp66;
	  fftw_real tmp96;
	  fftw_real tmp6;
	  fftw_real tmp95;
	  fftw_real tmp69;
	  fftw_real tmp178;
	  ASSERT_ALIGNED_DOUBLE();
	  {
	       fftw_real tmp1;
	       fftw_real tmp2;
	       fftw_real tmp64;
	       fftw_real tmp65;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp1 = c_re(input[0]);
	       tmp2 = c_re(input[16 * istride]);
	       tmp3 = tmp1 + tmp2;
	       tmp177 = tmp1 - tmp2;
	       tmp64 = c_im(input[0]);
	       tmp65 = c_im(input[16 * istride]);
	       tmp66 = tmp64 + tmp65;
	       tmp96 = tmp64 - tmp65;
	  }
	  {
	       fftw_real tmp4;
	       fftw_real tmp5;
	       fftw_real tmp67;
	       fftw_real tmp68;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp4 = c_re(input[8 * istride]);
	       tmp5 = c_re(input[24 * istride]);
	       tmp6 = tmp4 + tmp5;
	       tmp95 = tmp4 - tmp5;
	       tmp67 = c_im(input[8 * istride]);
	       tmp68 = c_im(input[24 * istride]);
	       tmp69 = tmp67 + tmp68;
	       tmp178 = tmp67 - tmp68;
	  }
	  tmp7 = tmp3 + tmp6;
	  tmp339 = tmp3 - tmp6;
	  tmp70 = tmp66 + tmp69;
	  tmp313 = tmp66 - tmp69;
	  tmp97 = tmp95 + tmp96;
	  tmp215 = tmp96 - tmp95;
	  tmp179 = tmp177 - tmp178;
	  tmp241 = tmp177 + tmp178;
     }
     {
	  fftw_real tmp10;
	  fftw_real tmp98;
	  fftw_real tmp73;
	  fftw_real tmp99;
	  fftw_real tmp13;
	  fftw_real tmp102;
	  fftw_real tmp76;
	  fftw_real tmp101;
	  ASSERT_ALIGNED_DOUBLE();
	  {
	       fftw_real tmp8;
	       fftw_real tmp9;
	       fftw_real tmp71;
	       fftw_real tmp72;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp8 = c_re(input[4 * istride]);
	       tmp9 = c_re(input[20 * istride]);
	       tmp10 = tmp8 + tmp9;
	       tmp98 = tmp8 - tmp9;
	       tmp71 = c_im(input[4 * istride]);
	       tmp72 = c_im(input[20 * istride]);
	       tmp73 = tmp71 + tmp72;
	       tmp99 = tmp71 - tmp72;
	  }
	  {
	       fftw_real tmp11;
	       fftw_real tmp12;
	       fftw_real tmp74;
	       fftw_real tmp75;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp11 = c_re(input[28 * istride]);
	       tmp12 = c_re(input[12 * istride]);
	       tmp13 = tmp11 + tmp12;
	       tmp102 = tmp11 - tmp12;
	       tmp74 = c_im(input[28 * istride]);
	       tmp75 = c_im(input[12 * istride]);
	       tmp76 = tmp74 + tmp75;
	       tmp101 = tmp74 - tmp75;
	  }
	  tmp14 = tmp10 + tmp13;
	  tmp314 = tmp10 - tmp13;
	  tmp77 = tmp73 + tmp76;
	  tmp340 = tmp76 - tmp73;
	  {
	       fftw_real tmp180;
	       fftw_real tmp181;
	       fftw_real tmp100;
	       fftw_real tmp103;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp180 = tmp98 - tmp99;
	       tmp181 = tmp102 + tmp101;
	       tmp182 = K707106781 * (tmp180 + tmp181);
	       tmp216 = K707106781 * (tmp180 - tmp181);
	       tmp100 = tmp98 + tmp99;
	       tmp103 = tmp101 - tmp102;
	       tmp104 = K707106781 * (tmp100 + tmp103);
	       tmp242 = K707106781 * (tmp103 - tmp100);
	  }
     }
     {
	  fftw_real tmp49;
	  fftw_real tmp149;
	  fftw_real tmp169;
	  fftw_real tmp288;
	  fftw_real tmp52;
	  fftw_real tmp166;
	  fftw_real tmp152;
	  fftw_real tmp289;
	  fftw_real tmp56;
	  fftw_real tmp154;
	  fftw_real tmp157;
	  fftw_real tmp291;
	  fftw_real tmp59;
	  fftw_real tmp159;
	  fftw_real tmp162;
	  fftw_real tmp292;
	  ASSERT_ALIGNED_DOUBLE();
	  {
	       fftw_real tmp47;
	       fftw_real tmp48;
	       fftw_real tmp167;
	       fftw_real tmp168;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp47 = c_re(input[31 * istride]);
	       tmp48 = c_re(input[15 * istride]);
	       tmp49 = tmp47 + tmp48;
	       tmp149 = tmp47 - tmp48;
	       tmp167 = c_im(input[31 * istride]);
	       tmp168 = c_im(input[15 * istride]);
	       tmp169 = tmp167 - tmp168;
	       tmp288 = tmp167 + tmp168;
	  }
	  {
	       fftw_real tmp50;
	       fftw_real tmp51;
	       fftw_real tmp150;
	       fftw_real tmp151;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp50 = c_re(input[7 * istride]);
	       tmp51 = c_re(input[23 * istride]);
	       tmp52 = tmp50 + tmp51;
	       tmp166 = tmp50 - tmp51;
	       tmp150 = c_im(input[7 * istride]);
	       tmp151 = c_im(input[23 * istride]);
	       tmp152 = tmp150 - tmp151;
	       tmp289 = tmp150 + tmp151;
	  }
	  {
	       fftw_real tmp54;
	       fftw_real tmp55;
	       fftw_real tmp155;
	       fftw_real tmp156;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp54 = c_re(input[3 * istride]);
	       tmp55 = c_re(input[19 * istride]);
	       tmp56 = tmp54 + tmp55;
	       tmp154 = tmp54 - tmp55;
	       tmp155 = c_im(input[3 * istride]);
	       tmp156 = c_im(input[19 * istride]);
	       tmp157 = tmp155 - tmp156;
	       tmp291 = tmp155 + tmp156;
	  }
	  {
	       fftw_real tmp57;
	       fftw_real tmp58;
	       fftw_real tmp160;
	       fftw_real tmp161;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp57 = c_re(input[27 * istride]);
	       tmp58 = c_re(input[11 * istride]);
	       tmp59 = tmp57 + tmp58;
	       tmp159 = tmp57 - tmp58;
	       tmp160 = c_im(input[27 * istride]);
	       tmp161 = c_im(input[11 * istride]);
	       tmp162 = tmp160 - tmp161;
	       tmp292 = tmp160 + tmp161;
	  }
	  {
	       fftw_real tmp334;
	       fftw_real tmp335;
	       fftw_real tmp331;
	       fftw_real tmp332;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp153 = tmp149 - tmp152;
	       tmp236 = tmp149 + tmp152;
	       tmp53 = tmp49 + tmp52;
	       tmp60 = tmp56 + tmp59;
	       tmp287 = tmp53 - tmp60;
	       tmp334 = tmp49 - tmp52;
	       tmp335 = tmp292 - tmp291;
	       tmp336 = tmp334 - tmp335;
	       tmp360 = tmp334 + tmp335;
	       tmp290 = tmp288 + tmp289;
	       tmp293 = tmp291 + tmp292;
	       tmp294 = tmp290 - tmp293;
	       tmp170 = tmp166 + tmp169;
	       tmp233 = tmp169 - tmp166;
	       tmp331 = tmp288 - tmp289;
	       tmp332 = tmp56 - tmp59;
	       tmp333 = tmp331 - tmp332;
	       tmp359 = tmp332 + tmp331;
	       {
		    fftw_real tmp158;
		    fftw_real tmp163;
		    fftw_real tmp171;
		    fftw_real tmp172;
		    ASSERT_ALIGNED_DOUBLE();
		    tmp158 = tmp154 - tmp157;
		    tmp163 = tmp159 + tmp162;
		    tmp164 = K707106781 * (tmp158 + tmp163);
		    tmp234 = K707106781 * (tmp158 - tmp163);
		    tmp171 = tmp154 + tmp157;
		    tmp172 = tmp162 - tmp159;
		    tmp173 = K707106781 * (tmp171 + tmp172);
		    tmp237 = K707106781 * (tmp172 - tmp171);
	       }
	  }
     }
     {
	  fftw_real tmp18;
	  fftw_real tmp106;
	  fftw_real tmp81;
	  fftw_real tmp110;
	  fftw_real tmp21;
	  fftw_real tmp109;
	  fftw_real tmp84;
	  fftw_real tmp107;
	  fftw_real tmp316;
	  fftw_real tmp317;
	  ASSERT_ALIGNED_DOUBLE();
	  {
	       fftw_real tmp16;
	       fftw_real tmp17;
	       fftw_real tmp79;
	       fftw_real tmp80;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp16 = c_re(input[2 * istride]);
	       tmp17 = c_re(input[18 * istride]);
	       tmp18 = tmp16 + tmp17;
	       tmp106 = tmp16 - tmp17;
	       tmp79 = c_im(input[2 * istride]);
	       tmp80 = c_im(input[18 * istride]);
	       tmp81 = tmp79 + tmp80;
	       tmp110 = tmp79 - tmp80;
	  }
	  {
	       fftw_real tmp19;
	       fftw_real tmp20;
	       fftw_real tmp82;
	       fftw_real tmp83;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp19 = c_re(input[10 * istride]);
	       tmp20 = c_re(input[26 * istride]);
	       tmp21 = tmp19 + tmp20;
	       tmp109 = tmp19 - tmp20;
	       tmp82 = c_im(input[10 * istride]);
	       tmp83 = c_im(input[26 * istride]);
	       tmp84 = tmp82 + tmp83;
	       tmp107 = tmp82 - tmp83;
	  }
	  tmp22 = tmp18 + tmp21;
	  tmp316 = tmp18 - tmp21;
	  tmp317 = tmp81 - tmp84;
	  tmp318 = tmp316 - tmp317;
	  tmp343 = tmp316 + tmp317;
	  tmp85 = tmp81 + tmp84;
	  {
	       fftw_real tmp108;
	       fftw_real tmp111;
	       fftw_real tmp218;
	       fftw_real tmp219;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp108 = tmp106 - tmp107;
	       tmp111 = tmp109 + tmp110;
	       tmp112 = (K923879532 * tmp108) - (K382683432 * tmp111);
	       tmp185 = (K923879532 * tmp111) + (K382683432 * tmp108);
	       tmp218 = tmp106 + tmp107;
	       tmp219 = tmp110 - tmp109;
	       tmp220 = (K382683432 * tmp218) - (K923879532 * tmp219);
	       tmp245 = (K382683432 * tmp219) + (K923879532 * tmp218);
	  }
     }
     {
	  fftw_real tmp25;
	  fftw_real tmp116;
	  fftw_real tmp88;
	  fftw_real tmp114;
	  fftw_real tmp28;
	  fftw_real tmp113;
	  fftw_real tmp91;
	  fftw_real tmp117;
	  fftw_real tmp319;
	  fftw_real tmp320;
	  ASSERT_ALIGNED_DOUBLE();
	  {
	       fftw_real tmp23;
	       fftw_real tmp24;
	       fftw_real tmp86;
	       fftw_real tmp87;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp23 = c_re(input[30 * istride]);
	       tmp24 = c_re(input[14 * istride]);
	       tmp25 = tmp23 + tmp24;
	       tmp116 = tmp23 - tmp24;
	       tmp86 = c_im(input[30 * istride]);
	       tmp87 = c_im(input[14 * istride]);
	       tmp88 = tmp86 + tmp87;
	       tmp114 = tmp86 - tmp87;
	  }
	  {
	       fftw_real tmp26;
	       fftw_real tmp27;
	       fftw_real tmp89;
	       fftw_real tmp90;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp26 = c_re(input[6 * istride]);
	       tmp27 = c_re(input[22 * istride]);
	       tmp28 = tmp26 + tmp27;
	       tmp113 = tmp26 - tmp27;
	       tmp89 = c_im(input[6 * istride]);
	       tmp90 = c_im(input[22 * istride]);
	       tmp91 = tmp89 + tmp90;
	       tmp117 = tmp89 - tmp90;
	  }
	  tmp29 = tmp25 + tmp28;
	  tmp319 = tmp25 - tmp28;
	  tmp320 = tmp88 - tmp91;
	  tmp321 = tmp319 + tmp320;
	  tmp342 = tmp320 - tmp319;
	  tmp92 = tmp88 + tmp91;
	  {
	       fftw_real tmp115;
	       fftw_real tmp118;
	       fftw_real tmp221;
	       fftw_real tmp222;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp115 = tmp113 + tmp114;
	       tmp118 = tmp116 - tmp117;
	       tmp119 = (K382683432 * tmp115) + (K923879532 * tmp118);
	       tmp184 = (K923879532 * tmp115) - (K382683432 * tmp118);
	       tmp221 = tmp114 - tmp113;
	       tmp222 = tmp116 + tmp117;
	       tmp223 = (K923879532 * tmp221) + (K382683432 * tmp222);
	       tmp244 = (K382683432 * tmp221) - (K923879532 * tmp222);
	  }
     }
     {
	  fftw_real tmp34;
	  fftw_real tmp122;
	  fftw_real tmp142;
	  fftw_real tmp279;
	  fftw_real tmp37;
	  fftw_real tmp139;
	  fftw_real tmp125;
	  fftw_real tmp280;
	  fftw_real tmp41;
	  fftw_real tmp127;
	  fftw_real tmp130;
	  fftw_real tmp282;
	  fftw_real tmp44;
	  fftw_real tmp132;
	  fftw_real tmp135;
	  fftw_real tmp283;
	  ASSERT_ALIGNED_DOUBLE();
	  {
	       fftw_real tmp32;
	       fftw_real tmp33;
	       fftw_real tmp140;
	       fftw_real tmp141;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp32 = c_re(input[istride]);
	       tmp33 = c_re(input[17 * istride]);
	       tmp34 = tmp32 + tmp33;
	       tmp122 = tmp32 - tmp33;
	       tmp140 = c_im(input[istride]);
	       tmp141 = c_im(input[17 * istride]);
	       tmp142 = tmp140 - tmp141;
	       tmp279 = tmp140 + tmp141;
	  }
	  {
	       fftw_real tmp35;
	       fftw_real tmp36;
	       fftw_real tmp123;
	       fftw_real tmp124;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp35 = c_re(input[9 * istride]);
	       tmp36 = c_re(input[25 * istride]);
	       tmp37 = tmp35 + tmp36;
	       tmp139 = tmp35 - tmp36;
	       tmp123 = c_im(input[9 * istride]);
	       tmp124 = c_im(input[25 * istride]);
	       tmp125 = tmp123 - tmp124;
	       tmp280 = tmp123 + tmp124;
	  }
	  {
	       fftw_real tmp39;
	       fftw_real tmp40;
	       fftw_real tmp128;
	       fftw_real tmp129;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp39 = c_re(input[5 * istride]);
	       tmp40 = c_re(input[21 * istride]);
	       tmp41 = tmp39 + tmp40;
	       tmp127 = tmp39 - tmp40;
	       tmp128 = c_im(input[5 * istride]);
	       tmp129 = c_im(input[21 * istride]);
	       tmp130 = tmp128 - tmp129;
	       tmp282 = tmp128 + tmp129;
	  }
	  {
	       fftw_real tmp42;
	       fftw_real tmp43;
	       fftw_real tmp133;
	       fftw_real tmp134;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp42 = c_re(input[29 * istride]);
	       tmp43 = c_re(input[13 * istride]);
	       tmp44 = tmp42 + tmp43;
	       tmp132 = tmp42 - tmp43;
	       tmp133 = c_im(input[29 * istride]);
	       tmp134 = c_im(input[13 * istride]);
	       tmp135 = tmp133 - tmp134;
	       tmp283 = tmp133 + tmp134;
	  }
	  {
	       fftw_real tmp327;
	       fftw_real tmp328;
	       fftw_real tmp324;
	       fftw_real tmp325;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp126 = tmp122 - tmp125;
	       tmp229 = tmp122 + tmp125;
	       tmp38 = tmp34 + tmp37;
	       tmp45 = tmp41 + tmp44;
	       tmp278 = tmp38 - tmp45;
	       tmp327 = tmp34 - tmp37;
	       tmp328 = tmp283 - tmp282;
	       tmp329 = tmp327 - tmp328;
	       tmp357 = tmp327 + tmp328;
	       tmp281 = tmp279 + tmp280;
	       tmp284 = tmp282 + tmp283;
	       tmp285 = tmp281 - tmp284;
	       tmp143 = tmp139 + tmp142;
	       tmp226 = tmp142 - tmp139;
	       tmp324 = tmp279 - tmp280;
	       tmp325 = tmp41 - tmp44;
	       tmp326 = tmp324 - tmp325;
	       tmp356 = tmp325 + tmp324;
	       {
		    fftw_real tmp131;
		    fftw_real tmp136;
		    fftw_real tmp144;
		    fftw_real tmp145;
		    ASSERT_ALIGNED_DOUBLE();
		    tmp131 = tmp127 - tmp130;
		    tmp136 = tmp132 + tmp135;
		    tmp137 = K707106781 * (tmp131 + tmp136);
		    tmp227 = K707106781 * (tmp131 - tmp136);
		    tmp144 = tmp127 + tmp130;
		    tmp145 = tmp135 - tmp132;
		    tmp146 = K707106781 * (tmp144 + tmp145);
		    tmp230 = K707106781 * (tmp145 - tmp144);
	       }
	  }
     }
     {
	  fftw_real tmp277;
	  fftw_real tmp301;
	  fftw_real tmp304;
	  fftw_real tmp306;
	  fftw_real tmp296;
	  fftw_real tmp300;
	  fftw_real tmp299;
	  fftw_real tmp305;
	  ASSERT_ALIGNED_DOUBLE();
	  {
	       fftw_real tmp275;
	       fftw_real tmp276;
	       fftw_real tmp302;
	       fftw_real tmp303;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp275 = tmp70 - tmp77;
	       tmp276 = tmp22 - tmp29;
	       tmp277 = tmp275 - tmp276;
	       tmp301 = tmp276 + tmp275;
	       tmp302 = tmp278 + tmp285;
	       tmp303 = tmp294 - tmp287;
	       tmp304 = K707106781 * (tmp302 + tmp303);
	       tmp306 = K707106781 * (tmp303 - tmp302);
	  }
	  {
	       fftw_real tmp286;
	       fftw_real tmp295;
	       fftw_real tmp297;
	       fftw_real tmp298;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp286 = tmp278 - tmp285;
	       tmp295 = tmp287 + tmp294;
	       tmp296 = K707106781 * (tmp286 - tmp295);
	       tmp300 = K707106781 * (tmp286 + tmp295);
	       tmp297 = tmp7 - tmp14;
	       tmp298 = tmp92 - tmp85;
	       tmp299 = tmp297 + tmp298;
	       tmp305 = tmp297 - tmp298;
	  }
	  c_im(output[28 * ostride]) = tmp277 - tmp296;
	  c_im(output[12 * ostride]) = tmp277 + tmp296;
	  c_re(output[20 * ostride]) = tmp299 - tmp300;
	  c_re(output[4 * ostride]) = tmp299 + tmp300;
	  c_im(output[20 * ostride]) = tmp301 - tmp304;
	  c_im(output[4 * ostride]) = tmp301 + tmp304;
	  c_re(output[28 * ostride]) = tmp305 - tmp306;
	  c_re(output[12 * ostride]) = tmp305 + tmp306;
     }
     {
	  fftw_real tmp31;
	  fftw_real tmp311;
	  fftw_real tmp310;
	  fftw_real tmp312;
	  fftw_real tmp62;
	  fftw_real tmp63;
	  fftw_real tmp94;
	  fftw_real tmp307;
	  ASSERT_ALIGNED_DOUBLE();
	  {
	       fftw_real tmp15;
	       fftw_real tmp30;
	       fftw_real tmp308;
	       fftw_real tmp309;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp15 = tmp7 + tmp14;
	       tmp30 = tmp22 + tmp29;
	       tmp31 = tmp15 + tmp30;
	       tmp311 = tmp15 - tmp30;
	       tmp308 = tmp281 + tmp284;
	       tmp309 = tmp290 + tmp293;
	       tmp310 = tmp308 + tmp309;
	       tmp312 = tmp309 - tmp308;
	  }
	  {
	       fftw_real tmp46;
	       fftw_real tmp61;
	       fftw_real tmp78;
	       fftw_real tmp93;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp46 = tmp38 + tmp45;
	       tmp61 = tmp53 + tmp60;
	       tmp62 = tmp46 + tmp61;
	       tmp63 = tmp46 - tmp61;
	       tmp78 = tmp70 + tmp77;
	       tmp93 = tmp85 + tmp92;
	       tmp94 = tmp78 - tmp93;
	       tmp307 = tmp78 + tmp93;
	  }
	  c_re(output[16 * ostride]) = tmp31 - tmp62;
	  c_re(output[0]) = tmp31 + tmp62;
	  c_im(output[8 * ostride]) = tmp63 + tmp94;
	  c_im(output[24 * ostride]) = tmp94 - tmp63;
	  c_im(output[16 * ostride]) = tmp307 - tmp310;
	  c_im(output[0]) = tmp307 + tmp310;
	  c_re(output[24 * ostride]) = tmp311 - tmp312;
	  c_re(output[8 * ostride]) = tmp311 + tmp312;
     }
     {
	  fftw_real tmp121;
	  fftw_real tmp189;
	  fftw_real tmp187;
	  fftw_real tmp193;
	  fftw_real tmp148;
	  fftw_real tmp190;
	  fftw_real tmp175;
	  fftw_real tmp191;
	  ASSERT_ALIGNED_DOUBLE();
	  {
	       fftw_real tmp105;
	       fftw_real tmp120;
	       fftw_real tmp183;
	       fftw_real tmp186;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp105 = tmp97 - tmp104;
	       tmp120 = tmp112 - tmp119;
	       tmp121 = tmp105 - tmp120;
	       tmp189 = tmp105 + tmp120;
	       tmp183 = tmp179 - tmp182;
	       tmp186 = tmp184 - tmp185;
	       tmp187 = tmp183 + tmp186;
	       tmp193 = tmp183 - tmp186;
	  }
	  {
	       fftw_real tmp138;
	       fftw_real tmp147;
	       fftw_real tmp165;
	       fftw_real tmp174;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp138 = tmp126 - tmp137;
	       tmp147 = tmp143 - tmp146;
	       tmp148 = (K555570233 * tmp138) - (K831469612 * tmp147);
	       tmp190 = (K831469612 * tmp138) + (K555570233 * tmp147);
	       tmp165 = tmp153 - tmp164;
	       tmp174 = tmp170 - tmp173;
	       tmp175 = (K555570233 * tmp165) + (K831469612 * tmp174);
	       tmp191 = (K555570233 * tmp174) - (K831469612 * tmp165);
	  }
	  {
	       fftw_real tmp176;
	       fftw_real tmp188;
	       fftw_real tmp192;
	       fftw_real tmp194;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp176 = tmp148 - tmp175;
	       c_im(output[29 * ostride]) = tmp121 - tmp176;
	       c_im(output[13 * ostride]) = tmp121 + tmp176;
	       tmp188 = tmp148 + tmp175;
	       c_re(output[21 * ostride]) = tmp187 - tmp188;
	       c_re(output[5 * ostride]) = tmp187 + tmp188;
	       tmp192 = tmp190 + tmp191;
	       c_im(output[21 * ostride]) = tmp189 - tmp192;
	       c_im(output[5 * ostride]) = tmp189 + tmp192;
	       tmp194 = tmp191 - tmp190;
	       c_re(output[29 * ostride]) = tmp193 - tmp194;
	       c_re(output[13 * ostride]) = tmp193 + tmp194;
	  }
     }
     {
	  fftw_real tmp197;
	  fftw_real tmp209;
	  fftw_real tmp207;
	  fftw_real tmp213;
	  fftw_real tmp200;
	  fftw_real tmp210;
	  fftw_real tmp203;
	  fftw_real tmp211;
	  ASSERT_ALIGNED_DOUBLE();
	  {
	       fftw_real tmp195;
	       fftw_real tmp196;
	       fftw_real tmp205;
	       fftw_real tmp206;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp195 = tmp97 + tmp104;
	       tmp196 = tmp185 + tmp184;
	       tmp197 = tmp195 - tmp196;
	       tmp209 = tmp195 + tmp196;
	       tmp205 = tmp179 + tmp182;
	       tmp206 = tmp112 + tmp119;
	       tmp207 = tmp205 + tmp206;
	       tmp213 = tmp205 - tmp206;
	  }
	  {
	       fftw_real tmp198;
	       fftw_real tmp199;
	       fftw_real tmp201;
	       fftw_real tmp202;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp198 = tmp126 + tmp137;
	       tmp199 = tmp143 + tmp146;
	       tmp200 = (K980785280 * tmp198) - (K195090322 * tmp199);
	       tmp210 = (K195090322 * tmp198) + (K980785280 * tmp199);
	       tmp201 = tmp153 + tmp164;
	       tmp202 = tmp170 + tmp173;
	       tmp203 = (K980785280 * tmp201) + (K195090322 * tmp202);
	       tmp211 = (K980785280 * tmp202) - (K195090322 * tmp201);
	  }
	  {
	       fftw_real tmp204;
	       fftw_real tmp208;
	       fftw_real tmp212;
	       fftw_real tmp214;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp204 = tmp200 - tmp203;
	       c_im(output[25 * ostride]) = tmp197 - tmp204;
	       c_im(output[9 * ostride]) = tmp197 + tmp204;
	       tmp208 = tmp200 + tmp203;
	       c_re(output[17 * ostride]) = tmp207 - tmp208;
	       c_re(output[ostride]) = tmp207 + tmp208;
	       tmp212 = tmp210 + tmp211;
	       c_im(output[17 * ostride]) = tmp209 - tmp212;
	       c_im(output[ostride]) = tmp209 + tmp212;
	       tmp214 = tmp211 - tmp210;
	       c_re(output[25 * ostride]) = tmp213 - tmp214;
	       c_re(output[9 * ostride]) = tmp213 + tmp214;
	  }
     }
     {
	  fftw_real tmp323;
	  fftw_real tmp347;
	  fftw_real tmp350;
	  fftw_real tmp352;
	  fftw_real tmp338;
	  fftw_real tmp346;
	  fftw_real tmp345;
	  fftw_real tmp351;
	  ASSERT_ALIGNED_DOUBLE();
	  {
	       fftw_real tmp315;
	       fftw_real tmp322;
	       fftw_real tmp348;
	       fftw_real tmp349;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp315 = tmp313 - tmp314;
	       tmp322 = K707106781 * (tmp318 - tmp321);
	       tmp323 = tmp315 + tmp322;
	       tmp347 = tmp315 - tmp322;
	       tmp348 = (K382683432 * tmp329) - (K923879532 * tmp326);
	       tmp349 = (K923879532 * tmp333) + (K382683432 * tmp336);
	       tmp350 = tmp348 - tmp349;
	       tmp352 = tmp348 + tmp349;
	  }
	  {
	       fftw_real tmp330;
	       fftw_real tmp337;
	       fftw_real tmp341;
	       fftw_real tmp344;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp330 = (K382683432 * tmp326) + (K923879532 * tmp329);
	       tmp337 = (K382683432 * tmp333) - (K923879532 * tmp336);
	       tmp338 = tmp330 + tmp337;
	       tmp346 = tmp337 - tmp330;
	       tmp341 = tmp339 - tmp340;
	       tmp344 = K707106781 * (tmp342 - tmp343);
	       tmp345 = tmp341 - tmp344;
	       tmp351 = tmp341 + tmp344;
	  }
	  c_im(output[22 * ostride]) = tmp323 - tmp338;
	  c_im(output[6 * ostride]) = tmp323 + tmp338;
	  c_re(output[30 * ostride]) = tmp345 - tmp346;
	  c_re(output[14 * ostride]) = tmp345 + tmp346;
	  c_im(output[30 * ostride]) = tmp347 - tmp350;
	  c_im(output[14 * ostride]) = tmp347 + tmp350;
	  c_re(output[22 * ostride]) = tmp351 - tmp352;
	  c_re(output[6 * ostride]) = tmp351 + tmp352;
     }
     {
	  fftw_real tmp355;
	  fftw_real tmp367;
	  fftw_real tmp370;
	  fftw_real tmp372;
	  fftw_real tmp362;
	  fftw_real tmp366;
	  fftw_real tmp365;
	  fftw_real tmp371;
	  ASSERT_ALIGNED_DOUBLE();
	  {
	       fftw_real tmp353;
	       fftw_real tmp354;
	       fftw_real tmp368;
	       fftw_real tmp369;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp353 = tmp314 + tmp313;
	       tmp354 = K707106781 * (tmp343 + tmp342);
	       tmp355 = tmp353 + tmp354;
	       tmp367 = tmp353 - tmp354;
	       tmp368 = (K923879532 * tmp357) - (K382683432 * tmp356);
	       tmp369 = (K382683432 * tmp359) + (K923879532 * tmp360);
	       tmp370 = tmp368 - tmp369;
	       tmp372 = tmp368 + tmp369;
	  }
	  {
	       fftw_real tmp358;
	       fftw_real tmp361;
	       fftw_real tmp363;
	       fftw_real tmp364;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp358 = (K923879532 * tmp356) + (K382683432 * tmp357);
	       tmp361 = (K923879532 * tmp359) - (K382683432 * tmp360);
	       tmp362 = tmp358 + tmp361;
	       tmp366 = tmp361 - tmp358;
	       tmp363 = tmp339 + tmp340;
	       tmp364 = K707106781 * (tmp318 + tmp321);
	       tmp365 = tmp363 - tmp364;
	       tmp371 = tmp363 + tmp364;
	  }
	  c_im(output[18 * ostride]) = tmp355 - tmp362;
	  c_im(output[2 * ostride]) = tmp355 + tmp362;
	  c_re(output[26 * ostride]) = tmp365 - tmp366;
	  c_re(output[10 * ostride]) = tmp365 + tmp366;
	  c_im(output[26 * ostride]) = tmp367 - tmp370;
	  c_im(output[10 * ostride]) = tmp367 + tmp370;
	  c_re(output[18 * ostride]) = tmp371 - tmp372;
	  c_re(output[2 * ostride]) = tmp371 + tmp372;
     }
     {
	  fftw_real tmp225;
	  fftw_real tmp249;
	  fftw_real tmp247;
	  fftw_real tmp253;
	  fftw_real tmp232;
	  fftw_real tmp250;
	  fftw_real tmp239;
	  fftw_real tmp251;
	  ASSERT_ALIGNED_DOUBLE();
	  {
	       fftw_real tmp217;
	       fftw_real tmp224;
	       fftw_real tmp243;
	       fftw_real tmp246;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp217 = tmp215 - tmp216;
	       tmp224 = tmp220 - tmp223;
	       tmp225 = tmp217 + tmp224;
	       tmp249 = tmp217 - tmp224;
	       tmp243 = tmp241 - tmp242;
	       tmp246 = tmp244 - tmp245;
	       tmp247 = tmp243 - tmp246;
	       tmp253 = tmp243 + tmp246;
	  }
	  {
	       fftw_real tmp228;
	       fftw_real tmp231;
	       fftw_real tmp235;
	       fftw_real tmp238;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp228 = tmp226 - tmp227;
	       tmp231 = tmp229 - tmp230;
	       tmp232 = (K195090322 * tmp228) + (K980785280 * tmp231);
	       tmp250 = (K195090322 * tmp231) - (K980785280 * tmp228);
	       tmp235 = tmp233 - tmp234;
	       tmp238 = tmp236 - tmp237;
	       tmp239 = (K195090322 * tmp235) - (K980785280 * tmp238);
	       tmp251 = (K980785280 * tmp235) + (K195090322 * tmp238);
	  }
	  {
	       fftw_real tmp240;
	       fftw_real tmp248;
	       fftw_real tmp252;
	       fftw_real tmp254;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp240 = tmp232 + tmp239;
	       c_im(output[23 * ostride]) = tmp225 - tmp240;
	       c_im(output[7 * ostride]) = tmp225 + tmp240;
	       tmp248 = tmp239 - tmp232;
	       c_re(output[31 * ostride]) = tmp247 - tmp248;
	       c_re(output[15 * ostride]) = tmp247 + tmp248;
	       tmp252 = tmp250 - tmp251;
	       c_im(output[31 * ostride]) = tmp249 - tmp252;
	       c_im(output[15 * ostride]) = tmp249 + tmp252;
	       tmp254 = tmp250 + tmp251;
	       c_re(output[23 * ostride]) = tmp253 - tmp254;
	       c_re(output[7 * ostride]) = tmp253 + tmp254;
	  }
     }
     {
	  fftw_real tmp257;
	  fftw_real tmp269;
	  fftw_real tmp267;
	  fftw_real tmp273;
	  fftw_real tmp260;
	  fftw_real tmp270;
	  fftw_real tmp263;
	  fftw_real tmp271;
	  ASSERT_ALIGNED_DOUBLE();
	  {
	       fftw_real tmp255;
	       fftw_real tmp256;
	       fftw_real tmp265;
	       fftw_real tmp266;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp255 = tmp215 + tmp216;
	       tmp256 = tmp245 + tmp244;
	       tmp257 = tmp255 + tmp256;
	       tmp269 = tmp255 - tmp256;
	       tmp265 = tmp241 + tmp242;
	       tmp266 = tmp220 + tmp223;
	       tmp267 = tmp265 - tmp266;
	       tmp273 = tmp265 + tmp266;
	  }
	  {
	       fftw_real tmp258;
	       fftw_real tmp259;
	       fftw_real tmp261;
	       fftw_real tmp262;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp258 = tmp226 + tmp227;
	       tmp259 = tmp229 + tmp230;
	       tmp260 = (K831469612 * tmp258) + (K555570233 * tmp259);
	       tmp270 = (K831469612 * tmp259) - (K555570233 * tmp258);
	       tmp261 = tmp233 + tmp234;
	       tmp262 = tmp236 + tmp237;
	       tmp263 = (K831469612 * tmp261) - (K555570233 * tmp262);
	       tmp271 = (K555570233 * tmp261) + (K831469612 * tmp262);
	  }
	  {
	       fftw_real tmp264;
	       fftw_real tmp268;
	       fftw_real tmp272;
	       fftw_real tmp274;
	       ASSERT_ALIGNED_DOUBLE();
	       tmp264 = tmp260 + tmp263;
	       c_im(output[19 * ostride]) = tmp257 - tmp264;
	       c_im(output[3 * ostride]) = tmp257 + tmp264;
	       tmp268 = tmp263 - tmp260;
	       c_re(output[27 * ostride]) = tmp267 - tmp268;
	       c_re(output[11 * ostride]) = tmp267 + tmp268;
	       tmp272 = tmp270 - tmp271;
	       c_im(output[27 * ostride]) = tmp269 - tmp272;
	       c_im(output[11 * ostride]) = tmp269 + tmp272;
	       tmp274 = tmp270 + tmp271;
	       c_re(output[19 * ostride]) = tmp273 - tmp274;
	       c_re(output[3 * ostride]) = tmp273 + tmp274;
	  }
     }
}

fftw_codelet_desc fftwi_no_twiddle_32_desc =
{
     "fftwi_no_twiddle_32",
     (void (*)()) fftwi_no_twiddle_32,
     32,
     FFTW_BACKWARD,
     FFTW_NOTW,
     521,
     0,
     (const int *) 0,
};