11 #if defined __cplusplus
16 static double ptwXY_mod2(
double v,
double m,
int pythonMod );
17 static nfu_status
ptwXY_mul2_s_ptwXY( ptwXYPoints *
n, ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2,
double x1,
double y1,
double x2,
double y2,
int level );
18 static nfu_status
ptwXY_div_s_ptwXY( ptwXYPoints *
n, ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2,
double x1,
double y1,
double x2,
double y2,
19 int level,
int isNAN1,
int isNAN2 );
20 static ptwXYPoints *
ptwXY_div_ptwXY_forFlats( ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, nfu_status *status,
int safeDivide );
29 ptwXYOverflowPoint *o, *overflowHeader = &(ptwXY->overflowHeader);
31 if( ptwXY->status != nfu_Okay )
return( ptwXY->status );
33 for( i = 0, p = ptwXY->points; i < nonOverflowLength; i++, p++ ) p->y = slope * p->y + offset;
34 for( o = overflowHeader->next; o != overflowHeader; o = o->next ) o->point.y = slope * o->point.y + offset;
35 return( ptwXY->status );
47 ptwXY->status = nfu_divByZero; }
51 return( ptwXY->status );
60 ptwXYOverflowPoint *o, *overflowHeader = &(ptwXY->overflowHeader);
62 if( ptwXY->status != nfu_Okay )
return( ptwXY->status );
63 if( ptwXY->interpolation == ptwXY_interpolationOther )
return( nfu_otherInterpolation );
65 for( i = 0, p = ptwXY->points; i < nonOverflowLength; i++, p++ )
if( p->y == 0. ) ptwXY->status = nfu_divByZero;
66 for( o = overflowHeader->next; o != overflowHeader; o = o->next )
if( o->point.y == 0. ) ptwXY->status = nfu_divByZero;
67 if( ptwXY->status != nfu_divByZero ) {
68 for( i = 0, p = ptwXY->points; i < nonOverflowLength; i++, p++ ) p->y = value / p->y;
69 for( o = overflowHeader->next; o != overflowHeader; o = o->next ) o->point.y = value / o->point.y;
71 return( ptwXY->status );
76 nfu_status
ptwXY_mod( ptwXYPoints *ptwXY,
double m,
int pythonMod ) {
80 ptwXYOverflowPoint *o, *overflowHeader = &(ptwXY->overflowHeader);
82 if( ptwXY->status != nfu_Okay )
return( ptwXY->status );
83 if( m == 0 )
return( ptwXY->status = nfu_divByZero );
85 for( i = 0, p = ptwXY->points; i < nonOverflowLength; i++, p++ ) p->y =
ptwXY_mod2( p->y, m, pythonMod );
86 for( o = overflowHeader->next; o != overflowHeader; o = o->next ) o->point.y =
ptwXY_mod2( o->point.y, m, pythonMod );
87 return( ptwXY->status );
92 static double ptwXY_mod2(
double v,
double m,
int pythonMod ) {
94 double r = std::fmod( std::fabs( v ), std::fabs( m ) );
97 if( ( v * m ) < 0. ) r = std::fabs( m ) - std::fabs( r );
98 if( m < 0. ) r *= -1.; }
100 if( v < 0. ) r *= -1.;
108 ptwXYPoints *
ptwXY_binary_ptwXY( ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2,
double v1,
double v2,
double v1v2, nfu_status *status ) {
111 int unionOptions = ptwXY_union_fill | ptwXY_union_mergeClosePoints;
116 *status = nfu_otherInterpolation;
117 if( ptwXY1->interpolation == ptwXY_interpolationOther )
return( NULL );
118 if( ptwXY2->interpolation == ptwXY_interpolationOther )
return( NULL );
120 if( ( ptwXY1->interpolation == ptwXY_interpolationFlat ) || ( ptwXY2->interpolation == ptwXY_interpolationFlat ) ) {
121 *status = nfu_invalidInterpolation;
122 if( ( ptwXY1->interpolation != ptwXY2->interpolation ) )
return( NULL );
124 if( ( n =
ptwXY_union( ptwXY1, ptwXY2, status, unionOptions ) ) != NULL ) {
125 for( i = 0, p = n->points; i < n->length; i++, p++ ) {
127 p->y = v1 * p->y + v2 * y + v1v2 * y * p->y;
138 ptwXYPoints *
ptwXY_add_ptwXY( ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, nfu_status *status ) {
142 if( ptwXY1->length == 0 ) {
144 else if( ptwXY2->length == 0 ) {
154 ptwXYPoints *
ptwXY_sub_ptwXY( ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, nfu_status *status ) {
158 if( ptwXY1->length == 0 ) {
161 else if( ptwXY2->length == 0 ) {
171 ptwXYPoints *
ptwXY_mul_ptwXY( ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, nfu_status *status ) {
175 if( ptwXY1->length == 0 ) {
177 else if( ptwXY2->length == 0 ) {
187 ptwXYPoints *
ptwXY_mul2_ptwXY( ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, nfu_status *status ) {
190 ptwXYPoints *
n = NULL;
192 double x1, y1, x2, y2, u1, u2, v1, v2, xz1 = 0, xz2 = 0,
x;
194 *status = nfu_otherInterpolation;
195 if( ptwXY1->interpolation == ptwXY_interpolationOther )
return( NULL );
196 if( ptwXY2->interpolation == ptwXY_interpolationOther )
return( NULL );
197 if( ( n =
ptwXY_mul_ptwXY( ptwXY1, ptwXY2, status ) ) == NULL )
return( n );
198 if( ptwXY1->interpolation == ptwXY_interpolationFlat )
return( n );
199 if( ptwXY2->interpolation == ptwXY_interpolationFlat )
return( n );
200 length = n->length - 1;
202 x2 = n->points[length].x;
203 for( i = length - 1; i >= 0; i-- ) {
211 xz1 = ( u1 * x2 - u2 * x1 ) / ( u1 - u2 );
216 xz2 = ( v1 * x2 - v2 * x1 ) / ( v1 - v2 );
221 x = 0.5 * ( xz1 + xz2 );
231 x2 = n->points[n->length-1].x;
232 y2 = n->points[n->length-1].y;
233 for( i = n->length - 2; i >= 0; i-- ) {
236 if( ( *status =
ptwXY_mul2_s_ptwXY( n, ptwXY1, ptwXY2, x1, y1, x2, y2, 0 ) ) != nfu_Okay )
goto Err;
251 static nfu_status
ptwXY_mul2_s_ptwXY( ptwXYPoints *
n, ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2,
double x1,
double y1,
double x2,
double y2,
int level ) {
254 double u1, u2, v1, v2,
x, y, yp, dx,
a1,
a2;
256 if( ( x2 - x1 ) < ClosestAllowXFactor *
DBL_EPSILON * ( std::fabs( x1 ) + std::fabs( x2 ) ) )
return( nfu_Okay );
257 if( level >= n->biSectionMax )
return( nfu_Okay );
263 if( ( u1 == u2 ) || ( v1 == v2 ) )
return( nfu_Okay );
265 if( y1 == 0 ) a1 = 0.;
267 if( y2 == 0 ) a2 = 0.;
268 if( ( a1 == 0. ) || ( a2 == 0. ) ) {
269 x = 0.5 * ( x1 + x2 ); }
271 if( ( a1 * a2 < 0. ) )
return( nfu_Okay );
272 a1 = std::sqrt( std::fabs( a1 ) );
273 a2 = std::sqrt( std::fabs( a2 ) );
274 x = ( a2 * x1 + a1 * x2 ) / ( a2 + a1 );
277 yp = ( u1 * v1 * ( x2 -
x ) + u2 * v2 * ( x - x1 ) ) / dx;
278 y = ( u1 * ( x2 -
x ) + u2 * ( x - x1 ) ) * ( v1 * ( x2 - x ) + v2 * ( x - x1 ) ) / ( dx * dx );
279 if( std::fabs( y - yp ) < std::fabs( y * n->accuracy ) )
return( nfu_Okay );
281 if( ( status =
ptwXY_mul2_s_ptwXY( n, ptwXY1, ptwXY2, x, y, x2, y2, level ) ) != nfu_Okay )
return( status );
288 ptwXYPoints *
ptwXY_div_ptwXY( ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, nfu_status *status,
int safeDivide ) {
291 int64_t i, j, k, zeros = 0, length, iYs;
292 double x1, x2, y1, y2, u1, u2, v1, v2, y, xz, nan =
nfu_getNAN( ), s1, s2;
293 ptwXYPoints *
n = NULL;
298 *status = nfu_otherInterpolation;
299 if( ptwXY1->interpolation == ptwXY_interpolationOther )
return( NULL );
300 if( ptwXY2->interpolation == ptwXY_interpolationOther )
return( NULL );
301 if( ( ptwXY1->interpolation == ptwXY_interpolationFlat ) || ( ptwXY1->interpolation == ptwXY_interpolationFlat ) )
305 if( ( n =
ptwXY_union( ptwXY1, ptwXY2, status, ptwXY_union_fill | ptwXY_union_mergeClosePoints ) ) != NULL ) {
306 for( i = 0, p = n->points; i < n->length; i++, p++ ) {
315 if( *status != nfu_XOutsideDomain )
goto Err;
318 if( ( *status =
ptwXY_getSlopeAtX( ptwXY2, p->x,
'-', &s2 ) ) != nfu_Okay )
goto Err;
326 if( i < ( n->length - 1 ) ) {
328 if( *status != nfu_XOutsideDomain )
goto Err;
331 if( ( *status =
ptwXY_getSlopeAtX( ptwXY2, p->x,
'+', &s2 ) ) != nfu_Okay )
goto Err;
339 p->y = ( y1 + y2 ) / iYs;
343 *status = nfu_divByZero;
353 length = n->length - 1;
355 x2 = n->points[length].x;
356 for( i = length - 1; i >= 0; i-- ) {
363 xz = ( u1 * x2 - u2 * x1 ) / ( u1 - u2 );
368 *status = nfu_divByZero;
372 xz = ( v1 * x2 - v2 * x1 ) / ( v1 - v2 );
379 x2 = n->points[n->length-1].x;
380 y2 = n->points[n->length-1].y;
382 for( i = n->length - 2; i >= 0; i-- ) {
386 if( !isNAN1 || !isNAN2 ) {
387 if( ( *status =
ptwXY_div_s_ptwXY( n, ptwXY1, ptwXY2, x1, y1, x2, y2, 0, isNAN1, isNAN2 ) ) != nfu_Okay )
goto Err;
396 for( i = 0; i < n->length; i++ )
if( !
nfu_isNAN( n->points[i].y ) )
break;
398 if( i == n->length ) {
400 for( i = 0; i < n->length; i++ ) n->points[i].y = 0.; }
402 n->points[0].y = 2. * n->points[i].y;
406 for( i = n->length - 1; i > 0; i-- )
if( !
nfu_isNAN( n->points[i].y ) )
break;
407 if(
nfu_isNAN( n->points[n->length - 1].y ) ) {
408 n->points[n->length - 1].y = 2. * n->points[i].y;
412 for( i = 0; i < n->length; i++ )
if(
nfu_isNAN( n->points[i].y ) )
break;
413 for( k = i + 1, j = i; k < n->length; k++ ) {
414 if(
nfu_isNAN( n->points[k].y ) )
continue;
415 n->points[j] = n->points[k];
432 static nfu_status
ptwXY_div_s_ptwXY( ptwXYPoints *
n, ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2,
double x1,
double y1,
double x2,
double y2,
433 int level,
int isNAN1,
int isNAN2 ) {
436 double u1, u2, v1, v2, v,
x, y, yp, dx,
a1,
a2;
438 if( ( x2 - x1 ) < ClosestAllowXFactor *
DBL_EPSILON * ( std::fabs( x1 ) + std::fabs( x2 ) ) )
return( nfu_Okay );
439 if( level >= n->biSectionMax )
return( nfu_Okay );
443 if( ( status =
ptwXY_getValueAtX( ptwXY2, x1, &v1 ) ) != nfu_Okay )
return( status );
444 if( ( status =
ptwXY_getValueAtX( ptwXY2, x2, &v2 ) ) != nfu_Okay )
return( status );
446 x = 0.5 * ( x1 + x2 );
448 if( ( status =
ptwXY_getValueAtX( ptwXY2, x, &v1 ) ) != nfu_Okay )
return( status );
451 x = 0.5 * ( x1 + x2 );
453 if( ( status =
ptwXY_getValueAtX( ptwXY2, x, &v2 ) ) != nfu_Okay )
return( status );
456 if( ( u1 == u2 ) || ( v1 == v2 ) )
return( nfu_Okay );
457 if( ( y1 == 0. ) || ( y2 == 0. ) ) {
458 x = 0.5 * ( x1 + x2 ); }
460 if( ( u1 * u2 < 0. ) )
return( nfu_Okay );
461 a1 = std::sqrt( std::fabs( u1 ) );
462 a2 = std::sqrt( std::fabs( u2 ) );
463 x = ( a2 * x1 + a1 * x2 ) / ( a2 + a1 );
466 v = v1 * ( x2 -
x ) + v2 * ( x - x1 );
467 if( ( v1 == 0. ) || ( v2 == 0. ) || ( v == 0. ) )
return( nfu_Okay );
468 yp = ( u1 / v1 * ( x2 -
x ) + u2 / v2 * ( x - x1 ) ) / dx;
469 y = ( u1 * ( x2 -
x ) + u2 * ( x - x1 ) ) / v;
470 if( std::fabs( y - yp ) < std::fabs( y * n->accuracy ) )
return( nfu_Okay );
473 if( ( status =
ptwXY_div_s_ptwXY( n, ptwXY1, ptwXY2, x, y, x2, y2, level, 0, isNAN2 ) ) != nfu_Okay )
return( status );
483 ptwXYPoints *
n = NULL;
487 *status = nfu_invalidInterpolation;
488 if( ptwXY1->interpolation != ptwXY_interpolationFlat )
return( NULL );
489 if( ptwXY2->interpolation != ptwXY_interpolationFlat )
return( NULL );
490 if( ( n =
ptwXY_union( ptwXY1, ptwXY2, status, ptwXY_union_fill | ptwXY_union_mergeClosePoints ) ) != NULL ) {
491 for( i = 0, p = n->points; i < n->length; i++, p++ ) {
494 if( ( safeDivide ) && ( p->y == 0 ) ) {
495 *status = nfu_divByZero;
516 if( status == nfu_XOutsideDomain ) status = nfu_Okay;
520 #if defined __cplusplus
nfu_status ptwXY_neg(ptwXYPoints *ptwXY)
nfu_status ptwXY_areDomainsMutual(ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2)
int64_t ptwXY_getNonOverflowLength(ptwXYPoints const *ptwXY)
static ptwXYPoints * ptwXY_div_ptwXY_forFlats(ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, nfu_status *status, int safeDivide)
nfu_status ptwXY_add_double(ptwXYPoints *ptwXY, double value)
ptwXYPoints * ptwXY_mul2_ptwXY(ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, nfu_status *status)
nfu_status ptwXY_simpleCoalescePoints(ptwXYPoints *ptwXY)
nfu_status ptwXY_sub_fromDouble(ptwXYPoints *ptwXY, double value)
static double ptwXY_mod2(double v, double m, int pythonMod)
ptwXYPoints * ptwXY_free(ptwXYPoints *ptwXY)
nfu_status ptwXY_mul_double(ptwXYPoints *ptwXY, double value)
nfu_status ptwXY_getSlopeAtX(ptwXYPoints *ptwXY, double x, const char side, double *slope)
nfu_status ptwXY_setValueAtX(ptwXYPoints *ptwXY, double x, double y)
nfu_status ptwXY_sub_doubleFrom(ptwXYPoints *ptwXY, double value)
nfu_status ptwXY_div_doubleFrom(ptwXYPoints *ptwXY, double value)
static nfu_status ptwXY_getValueAtX_ignore_XOutsideDomainError(ptwXYPoints *ptwXY1, double x, double *y)
ptwXYPoints * ptwXY_mul_ptwXY(ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, nfu_status *status)
static nfu_status ptwXY_div_s_ptwXY(ptwXYPoints *n, ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, double x1, double y1, double x2, double y2, int level, int isNAN1, int isNAN2)
nfu_status ptwXY_div_fromDouble(ptwXYPoints *ptwXY, double value)
ptwXYPoints * ptwXY_add_ptwXY(ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, nfu_status *status)
ptwXYPoints * ptwXY_clone(ptwXYPoints *ptwXY, nfu_status *status)
void ptwXY_update_biSectionMax(ptwXYPoints *ptwXY1, double oldLength)
nfu_status ptwXY_getValueAtX(ptwXYPoints *ptwXY, double x, double *y)
const G4double x[NPOINTSGL]
ptwXYPoints * ptwXY_union(ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, nfu_status *status, int unionOptions)
nfu_status ptwXY_slopeOffset(ptwXYPoints *ptwXY, double slope, double offset)
ptwXYPoints * ptwXY_sub_ptwXY(ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, nfu_status *status)
nfu_status ptwXY_mod(ptwXYPoints *ptwXY, double m, int pythonMod)
static nfu_status ptwXY_mul2_s_ptwXY(ptwXYPoints *n, ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, double x1, double y1, double x2, double y2, int level)
ptwXYPoints * ptwXY_binary_ptwXY(ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, double v1, double v2, double v1v2, nfu_status *status)
ptwXYPoints * ptwXY_div_ptwXY(ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, nfu_status *status, int safeDivide)