// util.h  Ube + Ave  23 January 2012
#ifndef __UTIL_H
#define __UTIL_H
#define DEFAULT_TIMECPR  1380
#define DEFAULT_TIMELIMIT  7200
#define DEFAULT_ITNCPR  2000
#define DEFAULT_ITNLIMIT  4000 
#define DEFAULT_NATTPARAXIS 4
#define DEFAULT_NINSTRINDEXES 4  // Unconsistent model if this figure is changed
#define DEFAULT_NINSTRVALUES 6  // Unconsistent model if this figure is changed
#define DEFAULT_NASTROP 5
#define DEFAULT_NCOLSFITS 17 // present number of columns in the files GsrSystemRow*.fits
#define DEFAULT_EXTCONSTROWS 6 // number of extended contraints rows
#define DEFAULT_BARCONSTROWS 6 // number of extended contraints rows
// define per inserimento funzione ran2
#define IM1 2147483563
#define IM2 2147483399
#define AM (1.0/IM1)
#define IMM1 (IM1-1)
#define IA1 40014
#define IA2 40692
#define IQ1 53668
#define IQ2 52774
#define IR1 12211
#define IR2 3791
#define NTAB 32
#define NDIV (1+IMM1/NTAB)
#define EPS 1.2e-7
#define RNMX (1.0-EPS)
#define VER "7.1"
//

#include <dirent.h>
#include "fitsio.h"
#include <string.h>
#include <mpi.h>
#include <unistd.h>
#include <time.h>
#include "cblas.h"


#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))

void printerror(int status);

/* Called in an error during malloc occurs. Returns 1. */
int err_malloc(const char *s, int id);

int sel(const struct dirent *a);
int selextConstrStar(const struct dirent *a);
int selextConstrAtt(const struct dirent *a);
int selbarConstrStar(const struct dirent *a);


int selSM(const struct dirent *a);
int selKT(const struct dirent *a);
int selII(const struct dirent *a);
int selMI(const struct dirent *a);
int selAll(const struct dirent *a);
int selGSB(const struct dirent *a);
int selLastGSB(const struct dirent *a);

void instrDeMask(long instrInput,int acSc, int* instrOutput);
struct nullSpace {
    double vectNorm[6];
    double compMin[6];
    double compMax[6];
    double compVar[6];
    double compAvg[6];
    
};
struct comData {
	int myid;
	int nproc;
	long int * mapNoss;
	long int * mapNcoeff;
	long int mapNossBefore, mapNossAfter;
	long int nvinc;
	long int nobs;
	long int parOss;   
	long nunk, nunkSplit;
	long nDegFreedomAtt;
	long offsetAttParam,offsetInstrParam , offsetGlobParam, VroffsetAttParam; 
	long nStar;
    short nAstroP, nAttP, nInstrP, nGlobP, nAstroPSolved, nInstrPSolved; // number of astrometric, attitude, instrument,
	int multMI;
    int lsInstrFlag,ssInstrFlag,nuInstrFlag,maInstrFlag;
    int nElemIC,nOfInstrConstr;
    long cCDLSAACZP;
    int nElemICSS;
    int nElemICLSAL;
    int nElemICLSAC;
    short nAttAxes, nAttParAxis;
	int nAttParam,nInstrParam,nGlobalParam;
	int **mapStar;
	long VrIdAstroPDim;
	long VrIdAstroPDimMax;
	int *constrPE;
	int setBound[4];
	int instrConst[4];  // instrConst[0]=nFovs instrConst[1]= nCCDs instrConst[2]=nPixelColumns instrConst[3]=nTimeIntervals
	int timeCPR, timeLimit, itnCPR,itnCPRstop,itnCPRend, itnLimit,itn,noCPR;
    long offsetCMag,offsetCnu,offsetCdelta_eta,offsetCDelta_eta_1,offsetCDelta_eta_2;
    long offsetCDelta_eta_3,offsetCdelta_zeta,offsetCDelta_zeta_1,offsetCDelta_zeta_2;
	int nthreads;
	long **mapForThread;
	int nSubsetAtt, nSubsetInstr;
	int NOnSubsetAtt, NOnSubsetInstr;
	int Test,debugMode;
    int extConstraint,nEqExtConstr,numOfExtStar,numOfExtAttCol,startingAttColExtConstr;
    int barConstraint,nEqBarConstr,numOfBarStar;
    long lastStarConstr;
    long firstStarConstr;
    int nOfElextObs;
    int nOfElBarObs;
    char *outputDir;
    double nullSpaceAttfact,extConstrW,barConstrW;
    time_t totSec;
};
 	
 
void instrIndexIdToColIndexGlobal(int* instrIndexPointer, int* instrConst,int totrows ,struct comData comlsqr, int* instrCols);
void ColIndexToinstrIndexIdGlobal(int* instrIndexPointer, int* instrConst,int totrows ,struct comData comlsqr, int* instrCols);
void restartSetup(int *itn,
				double *knownTerms, 
				double *beta,
				double *alpha,
				double *vVect, 
				double *anorm,
				double *rhobar,
				double *phibar,
				double *wVect,
				double *xSolution,
				double *standardError,
				double *dnorm,
				double *sn2,
				double *cs2,
				double *z,
				double *xnorm1,
				double *res2,
				int *nstop,
				struct comData comlsqr);


void writeCheckPoint(int itn, 
				double *knownTerms, 
				double beta,
				double alpha,
				double *vVect, 
				double anorm,
				double rhobar,
				double phibar,
				double *wVect,
				double *xSolution,
				double *standardError,
				double dnorm,
				double sn2,
				double cs2,
				double z,
				double xnorm1,
				double res2,
				int nstop,
				struct comData comlsqr);
			

void SumCirc(double *vectToSum, struct comData comlsqr);

void initThread(long int  *matrixIndex,struct comData *comlsqr);

void precondSystemMatrix(double *systemMatrix, double *preCondVect, long int  *matrixIndex,int *instrCol,struct comData comlsqr);

void mpi_allreduce(double *source, double *dest,  long int lcount, 
                   MPI_Datatype datatype, MPI_Op op, MPI_Comm comm);


void mpi_recv(double *source, long int lcount, MPI_Datatype datatype, int peSource, int tag, MPI_Comm comm,MPI_Status *status);


void mpi_send(double *source,   long int lcount, MPI_Datatype datatype, int peDest, int tag, MPI_Comm comm);

// 3.5 Aggiunte dichiarazioni di funzioni per parametro aggiuntivo IDtest
double gauss(double ave, double sigma, long init2);


double ran2(long *idum);

void ByteSwap(unsigned char * b, int n);
void printerrorsingle(int status);

int invMap(int nAstroPSolved,int *inv);

void writeBinFiles(double* systemMatrix,long* matrixIndex,int* instrIndex,double* knownTerms,char* wrfileDir,char* wpath, struct comData comlsqr,int debugMode);

int cmpfunc (const void * a, const void * b);

int randint(int max);

int randint1(int min, int max);

long randlong(long max);

long randlong1(long min, long max);

long instr_hash(int FoV, int CCD, int PixelColumn, int TimeInterval);
int fill_extract(long *values, long *pos_min, long pos_max, long *number);
struct nullSpace cknullSpace(double * systemMatrix,long * matrixIndex,double * attNS,struct comData  comlsqr);
char* subString (const char* input, int offset, int len, char* dest);
double legendre(int deg, double x);
int computeInstrConstr (struct comData comlsqr,double * instrCoeffConstr,int * instrColsConstr,int * instrConstrIlung);
void swapInstrCoeff(double * instrCoeff, long repeat, long nrows);
float simfullram(long &nStar, long &nobs, float memGlobal, int nparams, int nAttParam, int nInstrParam);
#endif
