10 #include <nf_Legendre.h>
11 #include <nf_integration.h>
13 #if defined __cplusplus
22 ptwXY_createFromFunction_callback
func;
25 double x1, x2, y1,
y2;
29 double x2,
double *integral );
34 nfu_status
ptwXY_f_integrate( ptwXY_interpolation interpolation,
double x1,
double y1,
double x2,
double y2,
double *value ) {
36 nfu_status status = nfu_Okay;
40 switch( interpolation ) {
41 case ptwXY_interpolationLinLin :
42 *value = 0.5 * ( y1 + y2 ) * ( x2 - x1 );
44 case ptwXY_interpolationLinLog :
45 if( ( y1 <= 0. ) || ( y2 <= 0. ) ) {
46 status = nfu_badIntegrationInput; }
49 if( std::fabs( r - 1. ) < 1e-4 ) {
51 *value = y1 * ( x2 - x1 ) / ( 1. + r * ( -0.5 + r * ( 1. / 3. + r * ( -0.25 + .2 * r ) ) ) ); }
53 *value = ( y2 - y1 ) * ( x2 - x1 ) /
G4Log( r );
57 case ptwXY_interpolationLogLin :
58 if( ( x1 <= 0. ) || ( x2 <= 0. ) ) {
59 status = nfu_badIntegrationInput; }
62 if( std::fabs( r - 1. ) < 1e-4 ) {
64 r = r * ( -0.5 + r * ( 1. / 3. + r * ( -0.25 + .2 * r ) ) );
65 *value = x1 * ( y2 - y1 ) * r / ( 1. + r ) + y2 * ( x2 - x1 ); }
67 *value = ( y1 - y2 ) * ( x2 - x1 ) /
G4Log( r ) + x2 * y2 - x1 * y1;
71 case ptwXY_interpolationLogLog :
72 if( ( x1 <= 0. ) || ( x2 <= 0. ) || ( y1 <= 0. ) || ( y2 <= 0. ) ) {
73 status = nfu_badIntegrationInput; }
76 double a,
z, lx, ly,
s, f;
79 if( std::fabs( r - 1. ) < 1e-4 ) {
80 ly = ( y2 - y1 ) / y1;
81 ly = ly * ( 1. + ly * ( -0.5 + ly * ( 1. / 3. - 0.25 * ly ) ) ); }
86 if( std::fabs( r - 1. ) < 1e-4 ) {
87 lx = ( x2 - x1 ) / x1;
88 lx = lx * ( 1 + lx * ( -0.5 + lx * ( 1. / 3. - 0.25 * lx ) ) ); }
93 if( std::fabs( r - 1. ) < 1e-3 ) {
100 for( i = 0, s = 0.; i <
n; i++, a++, f-- ) s = ( 1. + s ) * a * z / f;
101 *value = y1 * ( x2 - x1 ) * ( 1. + s ); }
107 case ptwXY_interpolationFlat :
108 *value = y1 * ( x2 - x1 );
110 case ptwXY_interpolationOther :
111 status = nfu_otherInterpolation;
118 double ptwXY_integrate( ptwXYPoints *ptwXY,
double xMin,
double xMax, nfu_status *status ) {
120 int64_t i,
n = ptwXY->length;
121 double sum = 0., dSum,
x, y, x1, x2, y1, y2, _sign = 1.;
124 if( ( *status = ptwXY->status ) != nfu_Okay )
return( 0. );
125 *status = nfu_otherInterpolation;
126 if( ptwXY->interpolation == ptwXY_interpolationOther )
return( 0. );
134 if( n < 2 )
return( 0. );
137 for( i = 0, point = ptwXY->points; i < n; i++, point++ ) {
138 if( point->x >= xMin )
break;
140 if( i == n )
return( 0. );
147 if( ( *status =
ptwXY_interpolatePoint( ptwXY->interpolation, xMin, &y, x1, y1, x2, y2 ) ) != nfu_Okay )
return( 0. );
151 if( ( *status =
ptwXY_interpolatePoint( ptwXY->interpolation, xMax, &yMax, x1, y1, x2, y2 ) ) != nfu_Okay )
return( 0. );
152 if( ( *status =
ptwXY_f_integrate( ptwXY->interpolation, xMin, y, xMax, yMax, &sum ) ) != nfu_Okay )
return( 0. );
155 if( ( *status =
ptwXY_f_integrate( ptwXY->interpolation, xMin, y, x2, y2, &sum ) ) != nfu_Okay )
return( 0. );
161 for( ; i <
n; i++, point++ ) {
167 if( ( *status =
ptwXY_interpolatePoint( ptwXY->interpolation, xMax, &y, x1, y1, x2, y2 ) ) != nfu_Okay )
return( 0. );
168 if( ( *status =
ptwXY_f_integrate( ptwXY->interpolation, x1, y1, xMax, y, &dSum ) ) != nfu_Okay )
return( 0. );
172 if( ( *status =
ptwXY_f_integrate( ptwXY->interpolation, x1, y1, x2, y2, &dSum ) ) != nfu_Okay )
return( 0. );
176 return( _sign * sum );
183 if( ( *status = ptwXY->status ) != nfu_Okay )
return( 0. );
199 if( status != nfu_Okay )
return( status );
201 status = nfu_badNorm; }
203 for( i = 0; i < ptwXY->length; i++ ) ptwXY->points[i].y /= sum;
212 if( ( *status = ptwXY->status ) != nfu_Okay )
return( 0. );
213 if( ptwXY->length < 2 )
return( 0. );
221 int64_t i,
n = ptwXY->length;
222 double sum = 0.,
x, y, x1, x2, y1, y2, _sign = 1.;
225 if( ( *status = ptwXY->status ) != nfu_Okay )
return( 0. );
226 *status = nfu_unsupportedInterpolation;
227 if( ( ptwXY->interpolation != ptwXY_interpolationLinLin ) &&
228 ( ptwXY->interpolation != ptwXY_interpolationFlat ) )
return( 0. );
230 if( n < 2 )
return( 0. );
239 for( i = 0, point = ptwXY->points; i < n; ++i, ++point ) {
240 if( point->x >= xMin )
break;
242 if( i == n )
return( 0. );
247 if( ( *status =
ptwXY_interpolatePoint( ptwXY->interpolation, xMin, &y, point[-1].x, point[-1].y, x2, y2 ) ) != nfu_Okay )
return( 0. );
256 for( ; i <
n; ++i, ++point ) {
262 if( ( *status =
ptwXY_interpolatePoint( ptwXY->interpolation, xMax, &y, x1, y1, x2, y2 ) ) != nfu_Okay )
return( 0. );
266 switch( ptwXY->interpolation ) {
267 case ptwXY_interpolationFlat :
268 sum += ( x2 - x1 ) * y1 * 3 * ( x1 + x2 );
270 case ptwXY_interpolationLinLin :
271 sum += ( x2 - x1 ) * ( y1 * ( 2 * x1 + x2 ) + y2 * ( x1 + 2 * x2 ) );
276 if( x2 == xMax )
break;
279 return( _sign * sum / 6 );
286 if( ( *status = ptwXY->status ) != nfu_Okay )
return( 0. );
287 if( ptwXY->length < 2 )
return( 0. );
295 int64_t i,
n = ptwXY->length;
296 double sum = 0.,
x, y, x1, x2, y1, y2, _sign = 1., sqrt_x1, sqrt_x2, inv_apb, c;
299 if( ( *status = ptwXY->status ) != nfu_Okay )
return( 0. );
300 *status = nfu_unsupportedInterpolation;
301 if( ( ptwXY->interpolation != ptwXY_interpolationLinLin ) &&
302 ( ptwXY->interpolation != ptwXY_interpolationFlat ) )
return( 0. );
304 if( n < 2 )
return( 0. );
313 for( i = 0, point = ptwXY->points; i < n; ++i, ++point ) {
314 if( point->x >= xMin )
break;
316 if( i == n )
return( 0. );
321 if( ( *status =
ptwXY_interpolatePoint( ptwXY->interpolation, xMin, &y, point[-1].x, point[-1].y, x2, y2 ) ) != nfu_Okay )
return( 0. );
330 sqrt_x2 = std::sqrt( x2 );
331 for( ; i <
n; ++i, ++point ) {
338 if( ( *status =
ptwXY_interpolatePoint( ptwXY->interpolation, xMax, &y, x1, y1, x2, y2 ) ) != nfu_Okay )
return( 0. );
342 sqrt_x2 = std::sqrt( x2 );
343 inv_apb = sqrt_x1 + sqrt_x2;
344 c = 2. * ( sqrt_x1 * sqrt_x2 + x1 + x2 );
345 switch( ptwXY->interpolation ) {
346 case ptwXY_interpolationFlat :
347 sum += ( sqrt_x2 - sqrt_x1 ) * y1 * 2.5 * c;
349 case ptwXY_interpolationLinLin :
350 sum += ( sqrt_x2 - sqrt_x1 ) * ( y1 * ( c + x1 * ( 1. + sqrt_x2 / inv_apb ) ) + y2 * ( c + x2 * ( 1. + sqrt_x1 / inv_apb ) ) );
355 if( x2 == xMax )
break;
358 return( 2. / 15. * _sign * sum );
363 ptwXPoints *
ptwXY_groupOneFunction( ptwXYPoints *ptwXY, ptwXPoints *groupBoundaries, ptwXY_group_normType normType, ptwXPoints *ptwX_norm, nfu_status *status ) {
366 double x1, y1, x2, y2, y2p, xg1, xg2, sum;
368 ptwXPoints *groupedData = NULL;
371 if( ( *status = groupBoundaries->status ) != nfu_Okay )
return( NULL );
372 *status = nfu_otherInterpolation;
373 if( ptwXY->interpolation == ptwXY_interpolationOther )
return( NULL );
376 if( normType == ptwXY_group_normType_norm ) {
377 if( ptwX_norm == NULL ) {
378 *status = nfu_badNorm;
381 *status = ptwX_norm->status;
382 if( ptwX_norm->status != nfu_Okay )
return( NULL );
384 *status = nfu_badNorm;
390 if( f->length == 0 )
return(
ptwX_createLine( ngs, ngs, 0, 0, status ) );
392 if( ( groupedData =
ptwX_new( ngs, status ) ) == NULL )
goto err;
393 xg1 = groupBoundaries->points[0];
396 for( igs = 0, i = 1; igs < ngs; igs++ ) {
397 xg2 = groupBoundaries->points[igs+1];
400 for( ; i < f->length; i++, x1 = x2, y1 = y2 ) {
402 if( x2 > xg2 )
break;
403 y2p = y2 = f->points[i].y;
404 if( f->interpolation == ptwXY_interpolationFlat ) y2p = y1;
405 sum += ( y1 + y2p ) * ( x2 - x1 );
409 if( normType == ptwXY_group_normType_dx ) {
410 sum /= ( xg2 - xg1 ); }
411 else if( normType == ptwXY_group_normType_norm ) {
412 if( ptwX_norm->points[igs] == 0. ) {
413 *status = nfu_divByZero;
416 sum /= ptwX_norm->points[igs];
419 groupedData->points[igs] = 0.5 * sum;
420 groupedData->length++;
425 return( groupedData );
429 if( groupedData != NULL )
ptwX_free( groupedData );
435 ptwXPoints *
ptwXY_groupTwoFunctions( ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, ptwXPoints *groupBoundaries, ptwXY_group_normType normType,
436 ptwXPoints *ptwX_norm, nfu_status *status ) {
439 double x1, fy1, gy1, x2, fy2, gy2, fy2p, gy2p, xg1, xg2, sum;
440 ptwXYPoints *f = NULL, *ff, *
g = NULL, *gg = NULL;
441 ptwXPoints *groupedData = NULL;
445 if( ( *status = groupBoundaries->status ) != nfu_Okay )
return( NULL );
446 *status = nfu_otherInterpolation;
447 if( ptwXY1->interpolation == ptwXY_interpolationOther )
return( NULL );
448 if( ptwXY2->interpolation == ptwXY_interpolationOther )
return( NULL );
451 if( normType == ptwXY_group_normType_norm ) {
452 if( ptwX_norm == NULL ) {
453 *status = nfu_badNorm;
456 if( ( *status = ptwX_norm->status ) != nfu_Okay )
return( NULL );
458 *status = nfu_badNorm;
465 if( ( ff->length == 0 ) || ( gg->length == 0 ) ) {
472 if( ( f =
ptwXY_union( ff, gg, status, ptwXY_union_fill ) ) == NULL )
goto err;
473 if( ( g =
ptwXY_union( gg, f, status, ptwXY_union_fill ) ) == NULL )
goto err;
475 if( ( groupedData =
ptwX_new( ngs, status ) ) == NULL )
goto err;
476 xg1 = groupBoundaries->points[0];
478 fy1 = f->points[0].y;
479 gy1 = g->points[0].y;
480 for( igs = 0, i = 1; igs < ngs; igs++ ) {
481 xg2 = groupBoundaries->points[igs+1];
484 for( ; i < f->length; i++, x1 = x2, fy1 = fy2, gy1 = gy2 ) {
486 if( x2 > xg2 )
break;
487 fy2p = fy2 = f->points[i].y;
488 if( f->interpolation == ptwXY_interpolationFlat ) fy2p = fy1;
489 gy2p = gy2 = g->points[i].y;
490 if( g->interpolation == ptwXY_interpolationFlat ) gy2p = gy1;
491 sum += ( ( fy1 + fy2p ) * ( gy1 + gy2p ) + fy1 * gy1 + fy2p * gy2p ) * ( x2 - x1 );
495 if( normType == ptwXY_group_normType_dx ) {
496 sum /= ( xg2 - xg1 ); }
497 else if( normType == ptwXY_group_normType_norm ) {
498 if( ptwX_norm->points[igs] == 0. ) {
499 *status = nfu_divByZero;
502 sum /= ptwX_norm->points[igs];
505 groupedData->points[igs] = sum / 6.;
506 groupedData->length++;
514 return( groupedData );
521 if( groupedData != NULL )
ptwX_free( groupedData );
528 ptwXY_group_normType normType, ptwXPoints *ptwX_norm, nfu_status *status ) {
531 double x1, fy1, gy1, hy1, x2, fy2, gy2, hy2, fy2p, gy2p, hy2p, xg1, xg2, sum;
532 ptwXYPoints *f = NULL, *ff, *fff = NULL, *
g = NULL, *gg = NULL, *h = NULL, *hh = NULL;
533 ptwXPoints *groupedData = NULL;
538 if( ( *status = groupBoundaries->status ) != nfu_Okay )
return( NULL );
539 *status = nfu_otherInterpolation;
540 if( ptwXY1->interpolation == ptwXY_interpolationOther )
return( NULL );
541 if( ptwXY2->interpolation == ptwXY_interpolationOther )
return( NULL );
542 if( ptwXY3->interpolation == ptwXY_interpolationOther )
return( NULL );
545 if( normType == ptwXY_group_normType_norm ) {
546 if( ptwX_norm == NULL ) {
547 *status = nfu_badNorm;
550 if( ( *status = ptwX_norm->status ) != nfu_Okay )
return( NULL );
552 *status = nfu_badNorm;
560 if( ( ff->length == 0 ) || ( gg->length == 0 ) || ( hh->length == 0 ) )
return(
ptwX_createLine( ngs, ngs, 0, 0, status ) );
565 if( ( fff =
ptwXY_union( ff, gg, status, ptwXY_union_fill ) ) == NULL )
goto err;
566 if( ( h =
ptwXY_union( hh, fff, status, ptwXY_union_fill ) ) == NULL )
goto err;
567 if( ( f =
ptwXY_union( fff, h, status, ptwXY_union_fill ) ) == NULL )
goto err;
568 if( ( g =
ptwXY_union( gg, h, status, ptwXY_union_fill ) ) == NULL )
goto err;
570 if( ( groupedData =
ptwX_new( ngs, status ) ) == NULL )
goto err;
571 xg1 = groupBoundaries->points[0];
573 fy1 = f->points[0].y;
574 gy1 = g->points[0].y;
575 hy1 = h->points[0].y;
576 for( igs = 0, i = 1; igs < ngs; igs++ ) {
577 xg2 = groupBoundaries->points[igs+1];
580 for( ; i < f->length; i++, x1 = x2, fy1 = fy2, gy1 = gy2, hy1 = hy2 ) {
582 if( x2 > xg2 )
break;
583 fy2p = fy2 = f->points[i].y;
584 if( f->interpolation == ptwXY_interpolationFlat ) fy2p = fy1;
585 gy2p = gy2 = g->points[i].y;
586 if( g->interpolation == ptwXY_interpolationFlat ) gy2p = gy1;
587 hy2p = hy2 = h->points[i].y;
588 if( h->interpolation == ptwXY_interpolationFlat ) hy2p = hy1;
589 sum += ( ( fy1 + fy2p ) * ( gy1 + gy2p ) * ( hy1 + hy2p ) + 2 * fy1 * gy1 * hy1 + 2 * fy2p * gy2p * hy2p ) * ( x2 - x1 );
593 if( normType == ptwXY_group_normType_dx ) {
594 sum /= ( xg2 - xg1 ); }
595 else if( normType == ptwXY_group_normType_norm ) {
596 if( ptwX_norm->points[igs] == 0. ) {
597 *status = nfu_divByZero;
600 sum /= ptwX_norm->points[igs];
603 groupedData->points[igs] = sum / 12.;
604 groupedData->length++;
615 return( groupedData );
625 if( groupedData != NULL )
ptwX_free( groupedData );
634 ptwXPoints *runningIntegral = NULL;
635 double integral = 0., sum;
638 if( ( runningIntegral =
ptwX_new( ptwXY->length, status ) ) == NULL )
goto err;
641 for( i = 1; i < ptwXY->length; i++ ) {
642 if( ( *status =
ptwXY_f_integrate( ptwXY->interpolation, ptwXY->points[i-1].x, ptwXY->points[i-1].y,
643 ptwXY->points[i].x, ptwXY->points[i].y, &sum ) ) != nfu_Okay )
goto err;
647 return( runningIntegral );
650 if( runningIntegral != NULL )
ptwX_free( runningIntegral );
657 double xMin,
double xMax,
int degree,
int recursionLimit,
double tolerance, nfu_status *status ) {
659 int64_t i1, i2, n1 = ptwXY->length;
661 double integral = 0., integral_,
sign = -1., xa, xb;
665 if( ( *status = ptwXY->status ) != nfu_Okay )
return( 0. );
667 if( xMin == xMax )
return( 0. );
668 if( n1 < 2 )
return( 0. );
678 if( xMin >= ptwXY->points[n1-1].x )
return( 0. );
679 if( xMax <= ptwXY->points[0].
x )
return( 0. );
681 for( i1 = 0; i1 < ( n1 - 1 ); i1++ ) {
682 if( ptwXY->points[i1+1].x > xMin )
break;
684 for( i2 = n1 - 1; i2 > i1; i2-- ) {
685 if( ptwXY->points[i2-1].x < xMax )
break;
687 point = &(ptwXY->points[i1]);
690 integrateWithFunctionInfo.
func = func;
691 integrateWithFunctionInfo.
argList = argList;
692 integrateWithFunctionInfo.
interpolation = ptwXY->interpolation;
693 integrateWithFunctionInfo.
x2 = point->x;
694 integrateWithFunctionInfo.
y2 = point->y;
697 for( ; i1 < i2; i1++ ) {
698 integrateWithFunctionInfo.
x1 = integrateWithFunctionInfo.
x2;
699 integrateWithFunctionInfo.
y1 = integrateWithFunctionInfo.
y2;
701 integrateWithFunctionInfo.
x2 = point->x;
702 integrateWithFunctionInfo.
y2 = point->y;
704 if( xb > xMax ) xb = xMax;
706 xa, xb, recursionLimit, tolerance, &integral_, &evaluations );
707 if( *status != nfu_Okay )
return( 0. );
708 integral += integral_;
718 double x2,
double *integral ) {
736 integrateWithFunctionInfo->
x1, integrateWithFunctionInfo->
y1,
737 integrateWithFunctionInfo->
x2, integrateWithFunctionInfo->
y2 ) ) == nfu_Okay ) {
738 status = integrateWithFunctionInfo->
func( x, y, integrateWithFunctionInfo->
argList );
744 #if defined __cplusplus
static G4Pow * GetInstance()
G4double powA(G4double A, G4double y) const
double ptwXY_integrateDomainWithWeight_sqrt_x(ptwXYPoints *ptwXY, nfu_status *status)
ptwXYPoints * ptwXY_intersectionWith_ptwX(ptwXYPoints *ptwXY, ptwXPoints *ptwX, nfu_status *status)
nfu_status ptwX_setPointAtIndex(ptwXPoints *ptwX, int64_t index, double x)
nfu_status ptwXY_normalize(ptwXYPoints *ptwXY)
double ptwXY_integrateWithFunction(ptwXYPoints *ptwXY, ptwXY_createFromFunction_callback func, void *argList, double xMin, double xMax, int degree, int recursionLimit, double tolerance, nfu_status *status)
ptwXPoints * ptwXY_groupThreeFunctions(ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, ptwXYPoints *ptwXY3, ptwXPoints *groupBoundaries, ptwXY_group_normType normType, ptwXPoints *ptwX_norm, nfu_status *status)
static const G4float tolerance
nfu_status ptwXY_simpleCoalescePoints(ptwXYPoints *ptwXY)
ptwXYPoints * ptwXY_free(ptwXYPoints *ptwXY)
double ptwXY_getXMax(ptwXYPoints *ptwXY)
struct ptwXY_integrateWithFunctionInfo_s ptwXY_integrateWithFunctionInfo
ptwXPoints * ptwX_new(int64_t size, nfu_status *status)
nfu_status ptwXY_f_integrate(ptwXY_interpolation interpolation, double x1, double y1, double x2, double y2, double *value)
ptwXPoints * ptwX_createLine(int64_t size, int64_t length, double slope, double offset, nfu_status *status)
double ptwXY_integrate(ptwXYPoints *ptwXY, double xMin, double xMax, nfu_status *status)
nfu_status nf_GnG_adaptiveQuadrature(nf_GnG_adaptiveQuadrature_callback quadratureFunction, nf_Legendre_GaussianQuadrature_callback integrandFunction, void *argList, double x1, double x2, int maxDepth, double tolerance, double *integral, long *evaluations)
double ptwXY_integrateDomainWithWeight_x(ptwXYPoints *ptwXY, nfu_status *status)
static nfu_status ptwXY_integrateWithFunction3(double x, double *y, void *argList)
static nfu_status ptwXY_integrateWithFunction2(nf_Legendre_GaussianQuadrature_callback integrandFunction, void *argList, double x1, double x2, double *integral)
ptwXPoints * ptwX_free(ptwXPoints *ptwX)
ptwXY_interpolation interpolation
ptwXPoints * ptwXY_groupOneFunction(ptwXYPoints *ptwXY, ptwXPoints *groupBoundaries, ptwXY_group_normType normType, ptwXPoints *ptwX_norm, nfu_status *status)
ptwXPoints * ptwXY_groupTwoFunctions(ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, ptwXPoints *groupBoundaries, ptwXY_group_normType normType, ptwXPoints *ptwX_norm, nfu_status *status)
G4double G4Log(G4double x)
int64_t ptwX_length(ptwXPoints *ptwX)
double ptwXY_integrateWithWeight_sqrt_x(ptwXYPoints *ptwXY, double xMin, double xMax, nfu_status *status)
const G4double x[NPOINTSGL]
double ptwXY_integrateWithWeight_x(ptwXYPoints *ptwXY, double xMin, double xMax, nfu_status *status)
static const double degree
ptwXYPoints * ptwXY_union(ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, nfu_status *status, int unionOptions)
ptwXPoints * ptwXY_runningIntegral(ptwXYPoints *ptwXY, nfu_status *status)
nfu_status nf_Legendre_GaussianQuadrature(int degree, double x1, double x2, nf_Legendre_GaussianQuadrature_callback func, void *argList, double *integral)
double ptwXY_getXMin(ptwXYPoints *ptwXY)
ptwXY_createFromFunction_callback func
nfu_status ptwXY_tweakDomainsToMutualify(ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, int epsilonFactor, double epsilon)
nfu_status ptwXY_interpolatePoint(ptwXY_interpolation interpolation, double x, double *y, double x1, double y1, double x2, double y2)
double ptwXY_integrateDomain(ptwXYPoints *ptwXY, nfu_status *status)
G4int sign(const T t)
A simple sign function that allows us to port fortran code to c++ more easily.