#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
typedef int INT;

#include <gsl/gsl_rng.h>		//
#include <gsl/gsl_randist.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_blas.h>
#include <gsl/gsl_multifit_nlin.h>	// 
#include <gsl/gsl_sf_trig.h>
#include <gsl/gsl_sf_bessel.h>		//

#include "FtlCalcDetectorEffi.hh"


double	dwSqrt1Buf[N_INTG_NUM+1];
double	dwSqrt2Buf[N_INTG_NUM+1];

#define N_CORE_NUM 	(4)

#define C_FTL_N3HE         (1.43063e20)
#define C_FTL_SIG_ABS_HE   (2.96277e-21)
#define C_FTL_N_SUS        (8.62570e22)
#define C_FTL_SIG_ABS_SUS  (1.58388e-24)
#define C_FTL_SIG_SCT_SUS  (1.06820e-23)

// The String for Header Infomation
const char C_FTL_STR_FILE_HEADER[]         = "Data File for Taikan Detecotor Efficiency.";
const char C_FTL_STR_DATA_FORMAT_VERSION[] = "DATA FORMAT VERSION             :01.00.00";
const char C_FTL_STR_SUS_TYPE[]	           = "SUS TYPE                        :";
const char C_FTL_STR_DELTA_SIZE[]          = "DELTA_SIZE                      :";
const char C_FTL_STR_RADIUS[]              = "radius of PSD                   :";
const char C_FTL_STR_THICKNESS[]           = "thickness of PSD                :";

const char C_FTL_STR_DENCITY_3HE[]         = "number dencity of 3He           :";
const char C_FTL_STR_ABS_HE[]              = "absorption cross-section of He  :";
const char C_FTL_STR_N_SUS[]               = "number dencity of SUS           :";
const char C_FTL_STR_ABS_SUS[]             = "absorption cross-section of SUS :";
const char C_FTL_STR_SCT_SUS[]             = "scatting cross-section of SUS   :";
// The buffer size. The buffer is used to write or read the data file.
const unsigned int  C_FTL_TMP_BUF_SIZE              = 60;	


typedef struct detctorThData {
	unsigned long	nStNo;	// start No of integrate in this thread
	unsigned long	nEndNo;	// end   No of integrate in this thread
	unsigned long	nMaxNo;	//  
	unsigned long	nNo;	// 
	double			dwLambda;
	double			dwSec;
	double         	dwSum;	//    
	
	// thread control
	pthread_t        th;
	sem_t            sync; 
	sem_t            start;
} DetectorThData;

//****************************
// Constant Variables
//****************************
const double C_FTL_DW_R			= 0.4f;		//[cm]
const double C_FTL_DW_D			= 0.02f;	//[cm]

#define C_FTL_DW_RD      (stSusInfo.dwRadius-stSusInfo.dwDepth)
#define C_FTL_DW_RD2     (C_FTL_DW_RD*C_FTL_DW_RD)
#define C_FTL_DW_RDR     ((stSusInfo.dwRadius-stSusInfo.dwDepth)/stSusInfo.dwRadius)

#define C_FTL_DW_RANGE   C_FTL_DW_RDR

const double C_FTL_DW_A		= 0.8480f;
const double C_FTL_DW_B		= 0.1366f;
const double C_FTL_DW_C		= 0.9214f;

//
//// Lambda
//const double	C_FTL_DW_LAMBDA_MAX			= 	15.0f;
//const double	C_FTL_DW_LAMBDA_MIN			= 	0.0f;
//const double	C_FTL_DW_LAMBDA_GAP			= 	C_FTL_DW_DELTA;
//const int		C_FTL_N_LAMBDA_INTERVAL_NUM	= (C_FTL_DW_LAMBDA_MAX - C_FTL_DW_LAMBDA_MIN)/C_FTL_DW_LAMBDA_GAP;
//
//// Sec
//const double	C_FTL_DW_SEC_MAX			= 	1.0f;
//const double	C_FTL_DW_SEC_MIN			= 	2.0f;
//const double	C_FTL_DW_SEC_GAP			= 	C_FTL_DW_DELTA;
//const int		C_FTL_N_SEC_INTERVAL_NUM	= (C_FTL_DW_SEC_MAX - C_FTL_DW_SEC_MIN)/C_FTL_DW_SEC_GAP;

// Decalaration of static member
STRCT_SUS_INFO  FtlCalcDetectorEffi::stSusInfo;

//****************************
// INTGRATE:x**2 dt
// Thread FUnc
// Thread Version
//****************************
//static void *FtlCalcDetectorEffi::thread_function(void *thdata)
void *FtlCalcDetectorEffi::thread_function(void *thdata)
{
	//double ret;
	double sum=0;
	double val=0;

	double tmpSqrt1;
	double tmpSqrt2;
	double tmp4;
	double tmp5;
	double dwLmbda;
	double dwSec;
	unsigned long i=0;
    
	DetectorThData    *priv = (DetectorThData *)thdata;

	dwLmbda	= priv->dwLambda;
	dwSec	= priv->dwSec;
	
	i = priv->nStNo;
	
	// This calculats on Simpson's rule
	//                  b - a
	// Int_a~b f(x)dx = -----{f(a)+Sigma 2*f( x_2j ) Sigma 4*f( x_(2j-1) ) + f(b)}
	//                    3  
	
	// f(a) 
	if (0 == i) {
		tmpSqrt1 = dwSqrt1Buf[i];
		tmpSqrt2 = dwSqrt2Buf[i];
		
		tmp4 = 1.0-exp(-stSusInfo.dwPrmA*dwLmbda*tmpSqrt1*dwSec);
		tmp5 = exp(-(stSusInfo.dwPrmB*dwLmbda+stSusInfo.dwPrmC)*tmpSqrt2*dwSec);
		val =  tmp4*tmp5;
		sum += val;
		i++;
	} else {
		;
	}

	for (;i<priv->nEndNo;i++) {
		
		tmpSqrt1 = dwSqrt1Buf[i];
		tmpSqrt2 = dwSqrt2Buf[i];
		
		tmp4 = 1.0-exp(-stSusInfo.dwPrmA*dwLmbda*tmpSqrt1*dwSec);
		tmp5 = exp(-(stSusInfo.dwPrmB*dwLmbda+stSusInfo.dwPrmC)*tmpSqrt2*dwSec);
		val =  tmp4*tmp5;
		if (i&1) {
			// f( x_(2j-1)  )
			sum += 4.0*val;
		} else {
			// f( x_(2j)  )
			sum += 2.0*val;
		}
	}

	// f(b)
	if (priv->nEndNo == priv->nMaxNo) {
		// f(dwT)
		tmpSqrt1 = dwSqrt1Buf[i];
		tmpSqrt2 = dwSqrt2Buf[i];
		
		tmp4 = 1.0-exp(-stSusInfo.dwPrmA*dwLmbda*tmpSqrt1*dwSec);
		tmp5 = exp(-(stSusInfo.dwPrmB*dwLmbda+stSusInfo.dwPrmC)*tmpSqrt2*dwSec);
		val =  tmp4*tmp5;

		sum += val;
	}

	priv->dwSum = sum;


	/* done */
	return (void *) NULL;

}

//****************************
// INTGRATE:
//****************************
double FtlCalcDetectorEffi::dwCalcInteg(double dwLambda, double dwSec)
{

    int                 rtn, i;
    DetectorThData       *thdata;
    double dwSum = 0;

    /* initialize thread data */
    thdata = (DetectorThData*)calloc(sizeof(DetectorThData), N_CORE_NUM);
    if (thdata == NULL) {
        perror("calloc()");
        return (0.0);
    }

    // Prepare thread function
    for (i = 0; i <N_CORE_NUM ; i++) {
        thdata[i].nStNo  = (N_INTG_NUM/N_CORE_NUM)*i;
        thdata[i].nEndNo = (N_INTG_NUM/N_CORE_NUM)*(i+1);
        thdata[i].nMaxNo = N_INTG_NUM;
        thdata[i].nNo = i;
        thdata[i].dwLambda = dwLambda;
        thdata[i].dwSec = dwSec;

        rtn = pthread_create(&thdata[i].th, NULL, thread_function, (void *) (&thdata[i]));
        if (rtn != 0) {
            fprintf(stderr, "pthread_create() #%0d failed for %d.", i, rtn);
            return (0.0);
        }
    }

    /* join */
    for (i = 0; i <N_CORE_NUM ; i++) {
        pthread_join(thdata[i].th, NULL);
        dwSum += thdata[i].dwSum;
    }

    dwSum = dwSum*C_FTL_DW_RANGE/(3.0*N_INTG_NUM) ;
    free(thdata);

    return (dwSum);
}



//****************************
// Constructor
//****************************
FtlCalcDetectorEffi::FtlCalcDetectorEffi()
{
	// initialization	
	stSusInfo.dwPrmA = C_FTL_DW_A;
	stSusInfo.dwPrmB = C_FTL_DW_B;
	stSusInfo.dwPrmC = C_FTL_DW_C;

	// radius of PSD
	stSusInfo.dwRadius = C_FTL_DW_R;
	// thickness of PSD
	stSusInfo.dwDepth  = C_FTL_DW_D;
	
	// number dencity of 3He
	stSusInfo.dwN3He       = C_FTL_N3HE;
	// absorption cross-section of He 
	stSusInfo.dwSigAbsHe   = C_FTL_SIG_ABS_HE;
	// number dencity of SUS
	stSusInfo.dwN_Sus      = C_FTL_N_SUS;
	// absorption cross-section of SUS
	stSusInfo.dwSigAbsSus  = C_FTL_SIG_ABS_SUS; 
	// scatting   cross-section of SUS
	stSusInfo.dwSigScttSus = C_FTL_SIG_SCT_SUS;

#if 1
	printf("dwPrmA=%0.9f \n", stSusInfo.dwPrmA);
	printf("dwPrmB=%0.9f \n", stSusInfo.dwPrmB);
	printf("dwPrmC=%0.9f \n", stSusInfo.dwPrmC);
#endif	

	
	stSusInfo.dwPrmA = stSusInfo.dwN3He*stSusInfo.dwSigAbsHe*2.0f;
	printf("dwPrmA=%0.9f \n", stSusInfo.dwPrmA);
	stSusInfo.dwPrmB = stSusInfo.dwN_Sus*stSusInfo.dwSigAbsSus;
	printf("dwPrmB=%0.9f \n", stSusInfo.dwPrmB);
	stSusInfo.dwPrmC = stSusInfo.dwN_Sus*stSusInfo.dwSigScttSus;
	printf("dwPrmC=%0.9f \n", stSusInfo.dwPrmC);
	
	CalcBuf();
}

//****************************
// Destructor
//****************************
FtlCalcDetectorEffi::~FtlCalcDetectorEffi()
{
}


//****************************
// saveData
// Saving the data of Detector Efficiency
//****************************
void FtlCalcDetectorEffi::saveData(string strFullPath, string strSusType)
{
	FILE* file;
	size_t retSize;
	char tmpBuf[C_FTL_TMP_BUF_SIZE];
	file = fopen(strFullPath.c_str(), "wb");


	// Description of this data
	if (0>sprintf(tmpBuf,"%s\n",C_FTL_STR_FILE_HEADER)) {
		printf("over buffer size\n");
	}
	
	retSize = fwrite(tmpBuf, sizeof(char), C_FTL_TMP_BUF_SIZE,file);
	assert(retSize==C_FTL_TMP_BUF_SIZE);	
	
	// Version
	if (0>sprintf(tmpBuf,"%s\n",C_FTL_STR_DATA_FORMAT_VERSION)) {
		printf("over buffer size\n");
	}
	retSize = fwrite(tmpBuf, sizeof(char), C_FTL_TMP_BUF_SIZE,file);
	assert(retSize==C_FTL_TMP_BUF_SIZE);	
		std::cout << "@@@@ saveData() step 3" << std::endl;
	// SUS Type Name
	if (0>sprintf(tmpBuf,"%s%s\n",C_FTL_STR_SUS_TYPE, strSusType.c_str())) {
		printf("over buffer size\n");
	}
	retSize = fwrite(tmpBuf, sizeof(char), C_FTL_TMP_BUF_SIZE,file);
	assert(retSize==C_FTL_TMP_BUF_SIZE);	
	
	
	// Delta of the detector efficiency Matrix
	if (0>sprintf(tmpBuf,"%s%0.5f\n",C_FTL_STR_DELTA_SIZE, C_FTL_DW_DELTA)) {
		printf("over buffer size\n");
	}
	retSize = fwrite(tmpBuf, sizeof(char), C_FTL_TMP_BUF_SIZE,file);
	assert(retSize==C_FTL_TMP_BUF_SIZE);	
	
	// radius of PSD
	if (0>sprintf(tmpBuf,"%s%0.5e\n", C_FTL_STR_RADIUS, stSusInfo.dwRadius)) {
		printf("over buffer size\n");
	}
	retSize = fwrite(tmpBuf, sizeof(char), C_FTL_TMP_BUF_SIZE,file);
	assert(retSize==C_FTL_TMP_BUF_SIZE);	
	
	// thickness of PSD
	if (0>sprintf(tmpBuf,"%s%0.5e\n", C_FTL_STR_THICKNESS, stSusInfo.dwDepth)) {
		printf("over buffer size\n");
	}
	retSize = fwrite(tmpBuf, sizeof(char), C_FTL_TMP_BUF_SIZE,file);
	assert(retSize==C_FTL_TMP_BUF_SIZE);	
	
	// number dencity of 3He
	if (0>sprintf(tmpBuf,"%s%0.5e\n", C_FTL_STR_DENCITY_3HE, stSusInfo.dwN3He)) {
		printf("over buffer size\n");
	}
	retSize = fwrite(tmpBuf, sizeof(char), C_FTL_TMP_BUF_SIZE,file);
	assert(retSize==C_FTL_TMP_BUF_SIZE);	
	
	// absorption cross-section of He
	if (0>sprintf(tmpBuf,"%s%0.5e\n", C_FTL_STR_ABS_HE, stSusInfo.dwSigAbsHe)) {
		printf("over buffer size\n");
	}
	retSize = fwrite(tmpBuf, sizeof(char), C_FTL_TMP_BUF_SIZE,file);
	assert(retSize==C_FTL_TMP_BUF_SIZE);	
	
	
	// number dencity of SUS
	if (0>sprintf(tmpBuf,"%s%0.5e\n", C_FTL_STR_N_SUS, stSusInfo.dwN_Sus)) {
		printf("over buffer size\n");
	}
	retSize = fwrite(tmpBuf, sizeof(char), C_FTL_TMP_BUF_SIZE,file);
	assert(retSize==C_FTL_TMP_BUF_SIZE);	
	
	// absorption cross-section of SUS
	if (0>sprintf(tmpBuf,"%s%0.5e\n", C_FTL_STR_ABS_SUS, stSusInfo.dwSigAbsSus)) {
		printf("over buffer size\n");
	}
	retSize = fwrite(tmpBuf, sizeof(char), C_FTL_TMP_BUF_SIZE,file);
	assert(retSize==C_FTL_TMP_BUF_SIZE);	
	
	// scatting   cross-section of SUS
	if (0>sprintf(tmpBuf,"%s%0.5e\n", C_FTL_STR_SCT_SUS, stSusInfo.dwSigScttSus)) {
		printf("over buffer size\n");
	}
	retSize = fwrite(tmpBuf, sizeof(char), C_FTL_TMP_BUF_SIZE,file);
	assert(retSize==C_FTL_TMP_BUF_SIZE);
	

	
	// save the detector Efficiency
	retSize = fwrite(dwResultBox, sizeof(double), sizeof(dwResultBox)/sizeof(double),file);
	assert(retSize==sizeof(dwResultBox)/sizeof(double));	//[inamura 140204]

	fclose(file);
}


//****************************
// saveData
// Saving the data of Detector Efficiency
//****************************
bool FtlCalcDetectorEffi::loadData(string strFullPath)
{
	FILE* file;
	size_t result;
	char tmpBuf[C_FTL_TMP_BUF_SIZE];
	printf("Load Start.\n");
	file = fopen(strFullPath.c_str(), "rb");
	int i;
	
	if (NULL==file) {
		printf("File is not found.\n");
		return false;
	}
	
	// Read Header Infomation
	for (i=0;i<11;i++) {
		memset(tmpBuf,'\0',C_FTL_TMP_BUF_SIZE);
		result = fread(tmpBuf, sizeof(char), C_FTL_TMP_BUF_SIZE,file);
		if (result != C_FTL_TMP_BUF_SIZE) {
			printf("File contents has an error.\n");
			printf("%02d:%s",i,tmpBuf);
		} else {
			printf("%02d:%s",i,tmpBuf);
		}
	}

	result = fread(dwLoadBox, sizeof(double), sizeof(dwLoadBox)/sizeof(double), file);
	if (result != sizeof(dwLoadBox)/sizeof(double)) {
		printf("File contents has an error.\n");
	}
	
	
	fclose(file);
	printf("Load End.\n");


#if 0 
{
	int i,j;
	double pdiff=0.0;
	double mdiff=0.0;
	double diff=0.0;
	for (i=0;i<C_FTL_N_LAMBDA_INTERVAL_NUM;i++) {
		for (j=0;j<C_FTL_N_SEC_INTERVAL_NUM;j++) {
			if (i!=0 && j!=0) {
				diff = dwLoadBox[i-1][j] - dwLoadBox[i][j];
				if (diff>pdiff) {
					pdiff = diff;
				}	
				if (mdiff>diff) {
					mdiff = diff;
				}	
				diff = dwLoadBox[i][j-1] - dwLoadBox[i][j];
				if (diff>pdiff) {
					pdiff = diff;
				}	
				if (mdiff>diff) {
					mdiff = diff;
				}	
			}		 
		}
	}
	
	printf("pdiff=%0.9f\n",pdiff);	
	printf("ndiff=%0.9f\n",mdiff);	
}
#endif	


	return true;
}
void FtlCalcDetectorEffi::outputSampleData(void)
{
	int i;
	double dwLambda;
	double dwSec=1.0;
	double ret;
	const double dwDelta = 0.1;
	const int num = 200;	
	for (i=0;i<=num;i++) {
			dwLambda = i*dwDelta;
			ret = dwCalcInteg(dwLambda,dwSec);
			printf ("%0.1f, %0.9f\n",dwLambda,ret);
	}
	
}

void FtlCalcDetectorEffi::CalcBuf(void)
{
	int i;
	double u;
	double tmpRu;

	for (i=0;i<N_INTG_NUM+1;i++) {
		//u=delta*double(i);
		u = (double(i)/double(N_INTG_NUM))*C_FTL_DW_RANGE;
		tmpRu=stSusInfo.dwRadius*u;
		if (i!=N_INTG_NUM) {
			dwSqrt1Buf[i] = sqrt(C_FTL_DW_RD2-tmpRu*tmpRu);
		} else {
			dwSqrt1Buf[i] = 0;
		}
		dwSqrt2Buf[i] = stSusInfo.dwRadius * sqrt(1.0-u*u) - dwSqrt1Buf[i];
	}
}

//************************
//
//************************
void FtlCalcDetectorEffi::SetPrm(
	double dwRadius,	// radius of PSD
	double dwDepth,		// thickness of PSD
	double dwN3He,		// number dencity of 3He
	double dwSigAbsHe,	// absorption cross-section of He
	double dwN_Sus,		// number dencity of SUS
	double dwSigAbsSus,	// absorption cross-section of SUS
	double dwSigScttSus	// scatting   cross-section of SUS
) {

#if 1
	printf("dwPrmA=%0.9f \n", stSusInfo.dwPrmA);
	printf("dwPrmB=%0.9f \n", stSusInfo.dwPrmB);
	printf("dwPrmC=%0.9f \n", stSusInfo.dwPrmC);
#endif	

	// radius of PSD
	stSusInfo.dwRadius     = dwRadius;  
	// thickness of PSD
	stSusInfo.dwDepth      = dwDepth;
	// number dencity of 3He	
	stSusInfo.dwN3He       = dwN3He;
	// absorption cross-section of He 
	stSusInfo.dwSigAbsHe   = dwSigAbsHe;
	// number dencity of SUS	
	stSusInfo.dwN_Sus      = dwN_Sus;
	// absorption cross-section of SUS
	stSusInfo.dwSigAbsSus  = dwSigAbsSus; 
	// scatting   cross-section of SUS
	stSusInfo.dwSigScttSus = dwSigScttSus;
	
	// 兣=1-佺exp(-2冃abs丒R(1-u^2)^1/2)du偱丄冃abs偺學悢2傪妡偗偰偄傞丅
	stSusInfo.dwPrmA = dwN3He*dwSigAbsHe*2.0f;
	printf("dwPrmA=%0.9f \n", stSusInfo.dwPrmA);
	stSusInfo.dwPrmB = dwN_Sus*dwSigAbsSus;
	printf("dwPrmB=%0.9f \n", stSusInfo.dwPrmB);
	stSusInfo.dwPrmC = dwN_Sus*dwSigScttSus;
	printf("dwPrmC=%0.9f \n", stSusInfo.dwPrmC);
	
	CalcBuf();

	return;
}

void FtlCalcDetectorEffi::makeData(void)
{
	int i;
	int j;
	
	double ret;

	double dwLambda;
	double dwSec;
	
	for (i=0;i<C_FTL_N_LAMBDA_INTERVAL_NUM;i++) {
		printf("%d/%d\n",i, C_FTL_N_LAMBDA_INTERVAL_NUM);
		dwLambda = C_FTL_DW_LAMBDA_MIN + C_FTL_DW_LAMBDA_GAP * ((double)i);
		for (j=0;j<C_FTL_N_SEC_INTERVAL_NUM;j++) {
			dwSec = C_FTL_DW_SEC_MIN + C_FTL_DW_SEC_GAP * ((double)j);
			
			ret = dwCalcInteg(dwLambda,dwSec);
			dwResultBox[i][j] = ret;
		}
	}

#if 1
{
	double dwMax = -1.0f;
	double dwMin = 1.0f;
	double dwDiff;

	for (i=1;i<C_FTL_N_LAMBDA_INTERVAL_NUM;i++) {
		for (j=1;j<C_FTL_N_SEC_INTERVAL_NUM;j++) {
			dwDiff = dwResultBox[i][j] - dwResultBox[i-1][j-1];
			if (dwMax<dwDiff) {
				dwMax = dwDiff;	
			} else if (dwDiff<dwMin){
				dwMin = dwDiff;	
			}			
			dwDiff = dwResultBox[i][j] - dwResultBox[i][j-1];
			if (dwMax<dwDiff) {
				dwMax = dwDiff;	
			} else if (dwDiff<dwMin){
				dwMin = dwDiff;	
			}			
			dwDiff = dwResultBox[i][j] - dwResultBox[i-1][j];
			if (dwMax<dwDiff) {
				dwMax = dwDiff;	
			} else if (dwDiff<dwMin){
				dwMin = dwDiff;	
			}			
		}
	}
	printf("Max Delta:%0.9f\n",dwMax);
	printf("Min Delta:%0.9f\n",dwMin);
}
#endif

	
}


double FtlCalcDetectorEffi::PutApproximateVal(double lambda,double sec)
{
	double dwLambdaPos;
	double dwSecPos;
	double dwLambdaFloor;
	double dwSecFloor;

	double dwA;
	double dwB;

	int nLambdaIdx;
	int nSecIdx;
	double ret;

	dwLambdaPos	= (lambda - C_FTL_DW_LAMBDA_MIN) / C_FTL_DW_LAMBDA_GAP;	
	dwSecPos	= (sec - C_FTL_DW_SEC_MIN)/ C_FTL_DW_SEC_GAP;
	
	dwLambdaFloor	= floor(dwLambdaPos);	
	dwSecFloor	= floor(dwSecPos);

	nLambdaIdx = (int)dwLambdaFloor;
	nSecIdx = (int)dwSecFloor;

	dwA = dwLambdaPos - dwLambdaFloor;
	dwB = dwSecPos - dwSecFloor;

	assert((0<=dwA) && (dwA<=1.0f));	
	assert((0<=dwB) && (dwB<=1.0f));	

	ret	= (1.0-dwA)*(1.0-dwB)*dwLoadBox[nLambdaIdx][nSecIdx]	
	    	+ (1.0-dwA)*dwB*dwLoadBox[nLambdaIdx][nSecIdx+1]	
	    	+ dwA*(1.0-dwB)*dwLoadBox[nLambdaIdx+1][nSecIdx]	
	    	+ dwA*dwB*dwLoadBox[nLambdaIdx+1][nSecIdx+1];	

	return ret;
}


#if IS_TEST_MODE 
void FtlCalcDetectorEffi::doIntegTest(void)
{
	double retVal;
	double retVal1;
	double retVal2;
	double expect;
	double retApp;
	
	retVal = dwCalcInteg(2.0,1.5);
	retApp = PutApproximateVal(2.0,1.5);
	expect = 0.4722165860441;
	printf("result=%0.9f :expection=%0.9f retApp = %0.9f, diff=%0.9f diff(Exp-App)=%0.9f\n",
		retVal,
		expect,
		retApp,
		retVal-expect,
		retApp-expect
	);

	retVal = dwCalcInteg(1.0,1.5);
	retApp = PutApproximateVal(1.0,1.5);
	expect = 0.2846274608701;
	printf("result=%0.9f :expection=%0.9f retApp = %0.9f, diff=%0.9f diff(Exp-App)=%0.9f\n",
		retVal,
		expect,
		retApp,
		retVal-expect,
		retApp-expect
	);

	retVal = dwCalcInteg(0.5,1.5);
	retApp = PutApproximateVal(0.5,1.5);
	expect = 0.1571626712879;
	printf("result=%0.9f :expection=%0.9f retApp = %0.9f, diff=%0.9f diff(Exp-App)=%0.9f\n",
		retVal,
		expect,
		retApp,
		retVal-expect,
		retApp-expect
	);

	retVal = dwCalcInteg(1.7, 1.2);
	retApp = PutApproximateVal(1.7, 1.2);
	expect = 0.36376278202124;
	printf("result=%0.9f :expection=%0.9f retApp = %0.9f, diff=%0.9f diff(Exp-App)=%0.9f\n",
		retVal,
		expect,
		retApp,
		retVal-expect,
		retApp-expect
	);

	retVal = dwCalcInteg(1.3, 1.2);
	retApp = PutApproximateVal(1.3, 1.2);
	expect = 0.29574061868454;
	printf("result=%0.9f :expection=%0.9f retApp = %0.9f, diff=%0.9f diff(Exp-App)=%0.9f\n",
		retVal,
		expect,
		retApp,
		retVal-expect,
		retApp-expect
	);

	retVal = dwCalcInteg(0.9, 1.2);
	retApp = PutApproximateVal(0.9, 1.2);
	expect = 0.21802228711848;
	printf("result=%0.9f :expection=%0.9f retApp = %0.9f, diff=%0.9f diff(Exp-App)=%0.9f\n",
		retVal,
		expect,
		retApp,
		retVal-expect,
		retApp-expect
	);
	retVal1 = dwCalcInteg(0.9, 1.2);
	retVal2 = dwCalcInteg(0.9+C_FTL_DW_DELTA, 1.2+C_FTL_DW_DELTA);
	printf("Delta test %0.9f %0.9f %0.9f\n",retVal1,retVal2,retVal1-retVal2);

{
	double dwD = 0.95560f;
	double dwL = 1.24530f;
	
	printf("\n");
	printf("\n");
	printf("\n");
	
	retVal1 = dwCalcInteg(dwD,dwL);
	retVal2 = PutApproximateVal(dwD,dwL);
	printf("Delta test %0.9f %0.9f %0.9f at %0.9f %0.9f\n",retVal1,retVal2,retVal1-retVal2, dwD, dwL);

	dwD = 0.095560f;
	dwL = 1.024530f;
	
	retVal1 = dwCalcInteg(dwD,dwL);
	retVal2 = PutApproximateVal(dwD,dwL);
	printf("Delta test %0.9f %0.9f %0.9f at %0.9f %0.9f\n",retVal1,retVal2,retVal1-retVal2, dwD, dwL);
}

}
#endif	

