12 #if defined __cplusplus
29 if( ( *status = ptwXY->status ) != nfu_Okay )
return( NULL );
33 if( ( xArray =
ptwX_new( n, status ) ) == NULL )
return( NULL );
34 for( i = 0; i <
n; i++ ) xArray->points[i] = ptwXY->points[i].x;
42 nfu_status
ptwXY_dullEdges( ptwXYPoints *ptwXY,
double lowerEps,
double upperEps,
int positiveXOnly ) {
47 double xm, xp, dx, y, x1, y1, x2, y2,
sign;
52 if( ( status = ptwXY->status ) != nfu_Okay )
return( status );
53 if( ptwXY->interpolation == ptwXY_interpolationFlat )
return( nfu_invalidInterpolation );
54 if( ptwXY->interpolation == ptwXY_interpolationOther )
return( nfu_otherInterpolation );
56 if( ptwXY->length < 2 )
return( nfu_Okay );
58 if( lowerEps != 0. ) {
59 if( std::fabs( lowerEps ) <
minEps ) {
61 if( lowerEps < 0. ) sign = -1;
73 dx = std::fabs( x1 * lowerEps );
74 if( x1 == 0 ) dx = std::fabs( lowerEps );
77 if( ( xp + dx ) < x2 ) {
78 if( ( status =
ptwXY_getValueAtX( ptwXY, xp, &y ) ) != nfu_Okay )
return( status );
79 if( ( status =
ptwXY_setValueAtX( ptwXY, xp, y ) ) != nfu_Okay )
return( status ); }
85 if( ( status =
ptwXY_setValueAtX( ptwXY, x1, 0. ) ) != nfu_Okay )
return( status ); }
87 if( ( xm < 0. ) && ( x1 >= 0. ) && positiveXOnly ) {
88 if( ( status =
ptwXY_setValueAtX( ptwXY, x1, 0. ) ) != nfu_Okay )
return( status ); }
90 if( ( status =
ptwXY_setValueAtX( ptwXY, xm, 0. ) ) != nfu_Okay )
return( status );
91 if( ( status =
ptwXY_interpolatePoint( ptwXY->interpolation, x1, &y, xm, 0., xp, y ) ) != nfu_Okay )
return( status );
92 if( ( status =
ptwXY_setValueAtX( ptwXY, x1, y ) ) != nfu_Okay )
return( status );
98 if( upperEps != 0. ) {
99 if( std::fabs( upperEps ) <
minEps ) {
101 if( upperEps < 0. ) sign = -1;
113 dx = std::fabs( x2 * upperEps );
114 if( x2 == 0 ) dx = std::fabs( upperEps );
117 if( ( xm - dx ) > x1 ) {
118 if( ( status =
ptwXY_getValueAtX( ptwXY, xm, &y ) ) != nfu_Okay )
return( status );
119 if( ( status =
ptwXY_setValueAtX( ptwXY, xm, y ) ) != nfu_Okay )
return( status ); }
125 if( ( status =
ptwXY_setValueAtX( ptwXY, x2, 0. ) ) != nfu_Okay )
return( status ); }
127 if( ( status =
ptwXY_setValueAtX( ptwXY, xp, 0. ) ) != nfu_Okay )
return( status );
128 if( ( status =
ptwXY_interpolatePoint( ptwXY->interpolation, x2, &y, xm, y, xp, 0. ) ) != nfu_Okay )
return( status );
129 if( ( status =
ptwXY_setValueAtX( ptwXY, x2, y ) ) != nfu_Okay )
return( status );
134 return( ptwXY->status );
143 int64_t i, i1, j, k,
n = ptwXY->length;
147 if( n < 2 )
return( ptwXY->status );
153 for( i1 = 1, p2++; i1 < ( n - 1 ); i1++, p2++ ) {
154 if( ( p2->x - x ) > 0.5 * epsilon * ( std::fabs( x ) + std::fabs( p2->x ) ) )
break;
157 for( i = i1, p1 = &(ptwXY->points[1]); i <
n; i++, p1++, p2++ ) *p1 = *p2;
158 n = ptwXY->length = ptwXY->length - i1 + 1;
161 p1 = &(ptwXY->points[n-1]);
163 for( i1 = n - 2, p1--; i1 > 0; i1--, p1-- ) {
164 if( x - p1->x > 0.5 * epsilon * ( std::fabs( x ) + std::fabs( p1->x ) ) )
break;
166 if( i1 != ( n - 2 ) ) {
167 ptwXY->points[i1 + 1] = ptwXY->points[n - 1];
168 n = ptwXY->length = i1 + 2;
171 for( i = 1; i < n - 1; i++ ) {
172 p1 = &(ptwXY->points[i]);
175 for( j = i + 1, p2 = &(ptwXY->points[i+1]); j < n - 1; j++, p2++ ) {
176 if( ( p2->x - p1->x ) > 0.5 * epsilon * ( std::fabs( p2->x ) + std::fabs( p1->x ) ) )
break;
180 if( ( k = ( j - i ) ) > 1 ) {
183 for( p1 = &(ptwXY->points[i+1]); j <
n; j++, p1++, p2++ ) *p1 = *p2;
189 return( ptwXY->status );
197 double x, y, xMin, xMax;
198 ptwXYPoints *
n = NULL;
200 if( ( *status = ptwXY->status ) != nfu_Okay )
return( NULL );
201 if( ( *status = ptwX->status ) != nfu_Okay )
return( NULL );
203 *status = nfu_otherInterpolation;
204 if( ptwXY->interpolation == ptwXY_interpolationOther )
return( NULL );
205 if( ( n =
ptwXY_clone( ptwXY, status ) ) == NULL )
return( NULL );
206 if( ptwXY->length == 0 )
return( n );
207 xMin = ptwXY->points[0].x;
208 xMax = ptwXY->points[ptwXY->length - 1].x;
210 if( ( xMin >= ptwX->points[lengthX-1] ) || ( xMax <= ptwX->points[0] ) ) {
215 for( i = 0; i < lengthX; i++ ) {
217 if( x <= xMin )
continue;
218 if( x >= xMax )
break;
228 if( x > n->points[i1].x ) {
229 for( ; i1 < n->length; i1++ ) {
230 if( n->points[i1].x == x )
break;
234 x = ptwX->points[lengthX - 1];
235 if( x < n->points[i2].x ) {
236 for( ; i2 > i1; i2-- ) {
237 if( n->points[i2].x == x )
break;
244 for( i = i1; i < i2; i++ ) n->points[i - i1] = n->points[i];
260 int64_t n1 = ptwXY1->length, n2 = ptwXY2->length;
261 ptwXYPoint *xy1, *xy2;
263 if( ( status = ptwXY1->status ) != nfu_Okay )
return( status );
264 if( ( status = ptwXY2->status ) != nfu_Okay )
return( status );
265 if( n1 == 0 )
return( nfu_empty );
266 if( n2 == 0 )
return( nfu_empty );
268 status = nfu_tooFewPoints; }
270 status = nfu_tooFewPoints; }
274 if( xy1->x < xy2->x ) {
275 if( xy2->y != 0. ) status = nfu_domainsNotMutual; }
276 else if( xy1->x > xy2->x ) {
277 if( xy1->y != 0. ) status = nfu_domainsNotMutual;
280 if( status == nfu_Okay ) {
283 if( xy1->x < xy2->x ) {
284 if( xy1->y != 0. ) status = nfu_domainsNotMutual; }
285 else if( xy1->x > xy2->x ) {
286 if( xy2->y != 0. ) status = nfu_domainsNotMutual;
298 int64_t n1 = ptwXY1->length, n2 = ptwXY2->length;
300 ptwXYPoint *xy1, *xy2;
302 epsilon = std::fabs( epsilon ) + std::fabs( epsilonFactor *
DBL_EPSILON );
304 if( ( status = ptwXY1->status ) != nfu_Okay )
return( status );
305 if( ( status = ptwXY2->status ) != nfu_Okay )
return( status );
306 if( n1 == 0 )
return( nfu_empty );
307 if( n2 == 0 )
return( nfu_empty );
309 status = nfu_tooFewPoints; }
311 status = nfu_tooFewPoints; }
315 if( xy1->x < xy2->x ) {
317 sum = std::fabs( xy1->x ) + std::fabs( xy2->x );
318 diff = std::fabs( xy2->x - xy1->x );
319 if( diff > epsilon * sum ) {
320 status = nfu_domainsNotMutual; }
325 else if( xy1->x > xy2->x ) {
327 sum = std::fabs( xy1->x ) + std::fabs( xy2->x );
328 diff = std::fabs( xy2->x - xy1->x );
329 if( diff > epsilon * sum ) {
330 status = nfu_domainsNotMutual; }
337 if( status == nfu_Okay ) {
340 if( xy1->x < xy2->x ) {
342 sum = std::fabs( xy1->x ) + std::fabs( xy2->x );
343 diff = std::fabs( xy2->x - xy1->x );
344 if( diff > epsilon * sum ) {
345 status = nfu_domainsNotMutual; }
350 else if( xy1->x > xy2->x ) {
352 sum = std::fabs( xy1->x ) + std::fabs( xy2->x );
353 diff = std::fabs( xy2->x - xy1->x );
354 if( diff > epsilon * sum ) {
355 status = nfu_domainsNotMutual; }
369 ptwXYPoints *ptwXY2,
double lowerEps2,
double upperEps2,
int positiveXOnly2 ) {
372 int64_t n1 = ptwXY1->length, n2 = ptwXY2->length;
373 ptwXYPoint *xy1, *xy2;
379 case nfu_domainsNotMutual :
385 if( ptwXY1->interpolation == ptwXY_interpolationOther )
return( nfu_otherInterpolation );
386 if( ptwXY2->interpolation == ptwXY_interpolationOther )
return( nfu_otherInterpolation );
387 if( ptwXY1->interpolation == ptwXY_interpolationFlat )
return( nfu_invalidInterpolation );
388 if( ptwXY2->interpolation == ptwXY_interpolationFlat )
return( nfu_invalidInterpolation );
392 if( xy1->x < xy2->x ) {
394 if( xy2->y == 0. ) lowerEps2 = 0.; }
395 else if( xy1->x > xy2->x ) {
397 if( xy1->y == 0. ) lowerEps1 = 0.; }
399 lowerEps1 = lowerEps2 = 0.;
404 if( xy1->x < xy2->x ) {
406 if( xy1->y == 0. ) upperEps1 = 0.; }
407 else if( xy1->x > xy2->x ) {
409 if( xy2->y == 0. ) upperEps2 = 0.; }
411 upperEps1 = upperEps2 = 0.;
414 if( ( lowerEps1 != 0. ) || ( upperEps1 != 0. ) )
415 if( ( status =
ptwXY_dullEdges( ptwXY1, lowerEps1, upperEps1, positiveXOnly1 ) ) != nfu_Okay )
return( status );
416 if( ( lowerEps2 != 0. ) || ( upperEps2 != 0. ) )
417 if( ( status =
ptwXY_dullEdges( ptwXY2, lowerEps2, upperEps2, positiveXOnly2 ) ) != nfu_Okay )
return( status );
424 nfu_status
ptwXY_copyToC_XY( ptwXYPoints *ptwXY, int64_t index1, int64_t index2, int64_t allocatedSize, int64_t *numberOfPoints,
double *xys ) {
429 ptwXYPoint *pointFrom;
431 if( ptwXY->status != nfu_Okay )
return( ptwXY->status );
434 if( index1 < 0 ) index1 = 0;
435 if( index2 > ptwXY->length ) index2 = ptwXY->length;
436 if( index2 < index1 ) index2 = index1;
437 *numberOfPoints = index2 - index1;
438 if( allocatedSize < ( index2 - index1 ) )
return( nfu_insufficientMemory );
440 for( i = index1, pointFrom = ptwXY->points; i < index2; i++, pointFrom++ ) {
441 *(d++) = pointFrom->x;
442 *(d++) = pointFrom->y;
454 ptwXYPoint *pointFrom;
457 if( ptwXY->status != nfu_Okay )
return( ptwXY->status );
460 if( ( *xs = (
double *) malloc( length *
sizeof(
double ) ) ) == NULL )
return( nfu_mallocError );
461 if( ( *ys = (
double *) malloc( length *
sizeof(
double ) ) ) == NULL ) {
464 return( nfu_mallocError );
467 for( i1 = 0, pointFrom = ptwXY->points, xps = *xs, yps = *ys; i1 < length; ++i1, ++pointFrom, ++xps, ++yps ) {
481 *status = nfu_XNotAscending;
482 if( x1 >= x2 )
return( NULL );
484 if( ( n =
ptwXY_new( ptwXY_interpolationLinLin, NULL, ptwXY_maxBiSectionMax, ptwXY_minAccuracy, 2, 0, status, 0 ) ) == NULL )
return( NULL );
496 double x1, y1, x2, y2, accuracy2, yMin = 1e-10;
497 ptwXYPoints *gaussian;
499 if( accuracy < 1e-5 ) accuracy = 1e-5;
500 if( accuracy > 1e-1 ) accuracy = 1e-1;
501 if( ( gaussian =
ptwXY_new( ptwXY_interpolationLinLin, NULL, 1., accuracy, 200, 100, status, 0 ) ) == NULL )
return( NULL );
502 accuracy2 = accuracy = gaussian->accuracy;
503 if( accuracy2 > 5e-3 ) accuracy2 = 5e-3;
505 x1 = -std::sqrt( -2. *
G4Log( yMin ) );
508 y2 =
G4Exp( -0.5 * x2 * x2 );
510 gaussian->accuracy = 20 * accuracy2;
515 y2 =
G4Exp( -0.5 * x2 * x2 );
516 gaussian->accuracy = 5 * accuracy2;
521 y2 =
G4Exp( -0.5 * x2 * x2 );
522 gaussian->accuracy = accuracy;
527 y2 =
G4Exp( -0.5 * x2 * x2 );
530 n = gaussian->length;
533 pp = &(gaussian->points[gaussian->length]);
534 for( i = 0, pm = pp - 2; i <
n; i++, pp++, pm-- ) {
538 gaussian->length = 2 * n + 1;
551 nfu_status status = nfu_Okay;
553 double x = 0.5 * ( x1 + x2 );
554 double y =
G4Exp( -x * x / 2 ), yMin = ( y1 * ( x2 - x ) + y2 * ( x - x1 ) ) / ( x2 - x1 );
556 if( std::fabs( y - yMin ) > y * ptwXY->accuracy ) morePoints = 1;
558 if( ( status =
ptwXY_setValueAtX( ptwXY, x, y ) ) != nfu_Okay )
return( status );
566 ptwXYPoints *
ptwXY_createGaussian(
double accuracy,
double xCenter,
double sigma,
double amplitude,
double xMin,
double xMax,
567 double , nfu_status *status ) {
570 ptwXYPoints *gaussian, *sliced;
574 for( i = 0, point = gaussian->points; i < gaussian->length; i++, point++ ) {
575 point->x = point->x * sigma + xCenter;
576 point->y *= amplitude;
578 if( ( gaussian->points[0].x < xMin ) || ( gaussian->points[gaussian->length - 1].x > xMax ) ) {
579 if( ( sliced =
ptwXY_xSlice( gaussian, xMin, xMax, 10, 1, status ) ) == NULL )
goto Err;
591 #if defined __cplusplus
ptwXYPoints * ptwXY_intersectionWith_ptwX(ptwXYPoints *ptwXY, ptwXPoints *ptwX, nfu_status *status)
ptwXPoints * ptwXY_getXArray(ptwXYPoints *ptwXY, nfu_status *status)
nfu_status ptwXY_mergeClosePoints(ptwXYPoints *ptwXY, double epsilon)
int64_t ptwXY_length(ptwXYPoints *ptwXY)
nfu_status ptwXY_areDomainsMutual(ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2)
ptwXYPoints * ptwXY_createGaussian(double accuracy, double xCenter, double sigma, double amplitude, double xMin, double xMax, double, nfu_status *status)
nfu_status ptwXY_valueTo_ptwXAndY(ptwXYPoints *ptwXY, double **xs, double **ys)
nfu_status ptwXY_simpleCoalescePoints(ptwXYPoints *ptwXY)
ptwXYPoints * ptwXY_free(ptwXYPoints *ptwXY)
nfu_status ptwXY_mutualifyDomains(ptwXYPoints *ptwXY1, double lowerEps1, double upperEps1, int positiveXOnly1, ptwXYPoints *ptwXY2, double lowerEps2, double upperEps2, int positiveXOnly2)
nfu_status ptwXY_setValueAtX(ptwXYPoints *ptwXY, double x, double y)
ptwXYPoints * ptwXY_valueTo_ptwXY(double x1, double x2, double y, nfu_status *status)
ptwXPoints * ptwX_new(int64_t size, nfu_status *status)
ptwXYPoints * ptwXY_createGaussianCenteredSigma1(double accuracy, nfu_status *status)
nfu_status ptwXY_coalescePoints(ptwXYPoints *ptwXY, int64_t size, ptwXYPoint *newPoint, int forceSmallerResize)
ptwXYPoints * ptwXY_xSlice(ptwXYPoints *ptwXY, double xMin, double xMax, int64_t secondarySize, int fill, nfu_status *status)
G4double G4Log(G4double x)
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
ptwXYPoints * ptwXY_clone(ptwXYPoints *ptwXY, nfu_status *status)
int64_t ptwX_length(ptwXPoints *ptwX)
ptwXYPoint * ptwXY_getPointAtIndex_Unsafely(ptwXYPoints *ptwXY, int64_t index)
nfu_status ptwXY_getValueAtX(ptwXYPoints *ptwXY, double x, double *y)
static nfu_status ptwXY_createGaussianCenteredSigma1_2(ptwXYPoints *ptwXY, double x1, double y1, double x2, double y2, int addX1Point)
nfu_status ptwXY_tweakDomainsToMutualify(ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, int epsilonFactor, double epsilon)
nfu_status ptwXY_dullEdges(ptwXYPoints *ptwXY, double lowerEps, double upperEps, int positiveXOnly)
ptwXYPoints * ptwXY_new(ptwXY_interpolation interpolation, ptwXY_interpolationOtherInfo const *interpolationOtherInfo, double biSectionMax, double accuracy, int64_t primarySize, int64_t secondarySize, nfu_status *status, int userFlag)
nfu_status ptwXY_interpolatePoint(ptwXY_interpolation interpolation, double x, double *y, double x1, double y1, double x2, double y2)
G4int sign(const T t)
A simple sign function that allows us to port fortran code to c++ more easily.
double epsilon(double density, double temperature)
nfu_status ptwXY_copyToC_XY(ptwXYPoints *ptwXY, int64_t index1, int64_t index2, int64_t allocatedSize, int64_t *numberOfPoints, double *xys)