Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
ptwXY_convenient.c
Go to the documentation of this file.
1/*
2# <<BEGIN-copyright>>
3# Copyright 2019, Lawrence Livermore National Security, LLC.
4# This file is part of the gidiplus package (https://github.com/LLNL/gidiplus).
5# gidiplus is licensed under the MIT license (see https://opensource.org/licenses/MIT).
6# SPDX-License-Identifier: MIT
7# <<END-copyright>>
8*/
9
10#include <stdlib.h>
11#include <math.h>
12#include <float.h>
13
14#include "ptwXY.h"
15
16static nfu_status ptwXY_createGaussianCenteredSigma1_2( statusMessageReporting *smr, ptwXYPoints *ptwXY, double x1, double y1,
17 double x2, double y2, int addX1Point );
18/*
19************************************************************
20*/
22
23 int64_t i, n;
24 ptwXPoints *xArray;
25
26 if( ptwXY_simpleCoalescePoints( smr, ptwXY ) != nfu_Okay ) {
28 return( NULL );
29 }
30 n = ptwXY->length;
31
32 if( ( xArray = ptwX_new( smr, n ) ) == NULL ) {
34 return( NULL );
35 }
36 for( i = 0; i < n; i++ ) xArray->points[i] = ptwXY->points[i].x;
37 xArray->length = n;
38
39 return( xArray );
40}
41/*
42************************************************************
43*/
45
46 int64_t iXY, iX, nXY = ptwXY_length( NULL, ptwXY ), nX = ptwX_length( NULL, Xs );
47 ptwXYPoint *point1, *point2;
48 ptwXY_interpolation interpolation = ptwXY_getInterpolation( ptwXY );
49 ptwXPoints *Ys = NULL;
50
51 *offset = 0;
52
53 if( ptwXY_simpleCoalescePoints( smr, ptwXY ) != nfu_Okay ) {
55 return( NULL );
56 }
57
58 if( Xs->status != nfu_Okay ) {
59 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid destination." );
60 return( NULL );
61 }
62
63 if( ( nXY == 1 ) || ( nX == 1 ) ) {
64 smr_setReportError2( smr, nfu_SMR_libraryID, nfu_tooFewPoints, "number of points less than 2: %lld %lld", nXY, nX );
65 return( NULL );
66 }
67
68 if( ( nXY == 0 ) || ( nX == 0 ) ) {
69 if( ( Ys = ptwX_new( smr, 0 ) ) == NULL ) {
71 return( NULL );
72 }
73 return( Ys );
74 }
75
76 point1 = &ptwXY->points[0];
77 point2 = &ptwXY->points[nXY-1];
78
79 for( iX = 0; iX < nX; ++iX ) {
80 if( Xs->points[iX] >= point1->x ) break;
81 }
82 *offset = iX;
83
84 for( iX = 0; iX < nX; ++iX ) {
85 if( Xs->points[iX] > point2->x ) break;
86 }
87 nX = iX;
88 iX = *offset;
89
90 if( ( Ys = ptwX_new( smr, nX - iX ) ) == NULL ) {
92 return( NULL );
93 }
94 if( nX - iX < 2 ) return( Ys );
95
96 for( iXY = 1; iXY < nXY; ++iXY ) {
97 point2 = &ptwXY->points[iXY];
98 if( point2->x >= Xs->points[iX] ) break;
99 point1 = point2;
100 }
101
102 for( ; iXY < nXY; ++iXY ) {
103 point2 = &ptwXY->points[iXY];
104
105 while( iX < nX ) {
106 double xValue = Xs->points[iX], yValue;
107
108 if( xValue > point2->x ) break;
109
110 if( ptwXY_interpolatePoint( smr, interpolation, xValue, &yValue, point1->x, point1->y, point2->x, point2->y ) != nfu_Okay ) {
112 ptwX_free( Ys );
113 return( NULL );
114 }
115 if( ptwX_setPointAtIndex( smr, Ys, ptwX_length( NULL, Ys ), yValue ) != nfu_Okay ) {
117 ptwX_free( Ys );
118 return( NULL );
119 }
120 ++iX;
121 }
122 point1 = point2;
123 }
124
125 return( Ys );
126}
127
128/*
129************************************************************
130*/
131nfu_status ptwXY_mapToXsAndAdd( statusMessageReporting *a_smr, ptwXYPoints *a_ptwXY, int64_t a_offset, int64_t a_length, double const *a_Xs,
132 double *a_results, double a_scaleFractor ) {
133
134 int64_t offset, startIndex, length, length_m1;
135 double x1, x2, y1, y2;
136 ptwXYPoint *point;
137 ptwXY_interpolation interpolation = ptwXY_getInterpolation( a_ptwXY );
138 double xValue, yValue;
139
140 if( a_offset < 0 ) a_offset = 0; /* This and next line also ensure that a_length > 0. */
141 if( a_offset >= a_length ) return( nfu_Okay );
142
143 offset = a_offset;
144 nfu_status status = ptwXY_startIndex( a_smr, a_ptwXY, a_Xs[a_offset], &startIndex, &length );
145 if( status != nfu_Okay ) return( status );
146 if( startIndex < 0 ) {
147 if( startIndex == -2 ) {
148 if( a_Xs[a_length-1] >= a_ptwXY->points[0].x ) startIndex = 0; /* Case A. */
149 }
150 if( startIndex < 0 ) return( nfu_Okay );
151 }
152
153 length_m1 = length - 1;
154 point = &a_ptwXY->points[startIndex];
155 x1 = point->x;
156 y1 = point->y;
157 while( startIndex < length_m1 ) {
158 ++startIndex;
159 point = &a_ptwXY->points[startIndex];
160 x2 = point->x;
161 y2 = point->y;
162
163 for( ; offset < a_length; ++offset ) {
164 xValue = a_Xs[offset];
165
166 if( xValue < x1 ) continue; /* Can happend per case A above. */
167 if( xValue > x2 ) break;
168
169 if( ( status = ptwXY_interpolatePoint( a_smr, interpolation, xValue, &yValue, x1, y1, x2, y2 ) ) != nfu_Okay ) {
171 return( status );
172 }
173 a_results[offset] += a_scaleFractor * yValue;
174 }
175 x1 = x2;
176 y1 = y2;
177 }
178
179 return( nfu_Okay );
180}
181
182/*
183************************************************************
184*/
185nfu_status ptwXY_dullEdges( statusMessageReporting *smr, ptwXYPoints *ptwXY, double lowerEps, double upperEps, int positiveXOnly ) {
186
187#define minEps 5e-16
188
189 nfu_status status;
190 double xm, xp, dx, y, x1, y1, x2, y2, sign;
191 ptwXYPoint *p;
192
193/* This routine can only be used for linear interpolation for the y-axes since for log interpolation, y cannot be 0.
194This needs to be fixed and documented. */
195 if( ptwXY->status != nfu_Okay ) {
196 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid source." );
197 return( ptwXY->status );
198 }
199
201 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_otherInterpolation, "Other interpolation not allowed." );
202 return( nfu_otherInterpolation );
203 }
204
205 if( ptwXY->interpolation == ptwXY_interpolationFlat ) {
206 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_invalidInterpolation, "Flat interpolation not allowed." );
207 return( nfu_invalidInterpolation );
208 }
209
210 if( ptwXY->length < 2 ) return( nfu_Okay );
211
212 if( lowerEps != 0. ) {
213 if( fabs( lowerEps ) < minEps ) {
214 sign = 1;
215 if( lowerEps < 0. ) sign = -1;
216 lowerEps = sign * minEps;
217 }
218
219 p = ptwXY_getPointAtIndex_Unsafely( ptwXY, 0 );
220 x1 = p->x;
221 y1 = p->y;
222 p = ptwXY_getPointAtIndex_Unsafely( ptwXY, 1 );
223 x2 = p->x;
224 y2 = p->y;
225
226 if( y1 != 0. ) {
227 dx = fabs( x1 * lowerEps );
228 if( x1 == 0 ) dx = fabs( lowerEps );
229 xm = x1 - dx;
230 xp = x1 + dx;
231 if( ( xp + dx ) < x2 ) {
232 if( ( status = ptwXY_getValueAtX( smr, ptwXY, xp, &y ) ) != nfu_Okay ) return( ptwXY->status = status );
233 if( ( status = ptwXY_setValueAtX( smr, ptwXY, xp, y ) ) != nfu_Okay ) return( ptwXY->status = status ); }
234 else {
235 xp = x2;
236 y = y2;
237 }
238 if( lowerEps > 0 ) {
239 if( ( status = ptwXY_setValueAtX( smr, ptwXY, x1, 0. ) ) != nfu_Okay ) return( ptwXY->status = status ); }
240 else {
241 if( ( xm < 0. ) && ( x1 >= 0. ) && positiveXOnly ) {
242 if( ( status = ptwXY_setValueAtX( smr, ptwXY, x1, 0. ) ) != nfu_Okay ) return( ptwXY->status = status ); }
243 else {
244 if( ( status = ptwXY_setValueAtX( smr, ptwXY, xm, 0. ) ) != nfu_Okay ) return( ptwXY->status = status );
245 if( ( status = ptwXY_interpolatePoint( smr, ptwXY->interpolation, x1, &y, xm, 0., xp, y ) ) != nfu_Okay )
246 return( ptwXY->status = status );
247 if( ( status = ptwXY_setValueAtX( smr, ptwXY, x1, y ) ) != nfu_Okay ) return( ptwXY->status = status );
248 }
249 }
250 }
251 }
252
253 if( upperEps != 0. ) {
254 if( fabs( upperEps ) < minEps ) {
255 sign = 1;
256 if( upperEps < 0. ) sign = -1;
257 upperEps = sign * minEps;
258 }
259
260 p = ptwXY_getPointAtIndex_Unsafely( ptwXY, ptwXY->length - 2 );
261 x1 = p->x;
262 y1 = p->y;
263 p = ptwXY_getPointAtIndex_Unsafely( ptwXY, ptwXY->length - 1 );
264 x2 = p->x;
265 y2 = p->y;
266
267 if( y2 != 0. ) {
268 dx = fabs( x2 * upperEps );
269 if( x2 == 0 ) dx = fabs( upperEps );
270 xm = x2 - dx;
271 xp = x2 + dx;
272 if( ( xm - dx ) > x1 ) {
273 if( ( status = ptwXY_getValueAtX( smr, ptwXY, xm, &y ) ) != nfu_Okay ) return( ptwXY->status = status );
274 if( ( status = ptwXY_setValueAtX( smr, ptwXY, xm, y ) ) != nfu_Okay ) return( ptwXY->status = status ); }
275 else {
276 xm = x1;
277 y = y1;
278 }
279 if( upperEps < 0 ) {
280 if( ( status = ptwXY_setValueAtX( smr, ptwXY, x2, 0. ) ) != nfu_Okay ) return( ptwXY->status = status ); }
281 else {
282 if( ( status = ptwXY_setValueAtX( smr, ptwXY, xp, 0. ) ) != nfu_Okay ) return( ptwXY->status = status );
283 if( ( status = ptwXY_interpolatePoint( smr, ptwXY->interpolation, x2, &y, xm, y, xp, 0. ) ) != nfu_Okay )
284 return( ptwXY->status = status );
285 if( ( status = ptwXY_setValueAtX( smr, ptwXY, x2, y ) ) != nfu_Okay ) return( ptwXY->status = status );
286 }
287 }
288 }
289
290 return( ptwXY->status );
291
292#undef minEps
293}
294/*
295************************************************************
296*/
298
299 int64_t i, i1, j, k, n = ptwXY->length;
300 double x, y;
301 ptwXYPoint *p1, *p2;
302
303 if( n < 2 ) return( ptwXY->status );
304 if( epsilon < 4 * DBL_EPSILON ) epsilon = 4 * DBL_EPSILON;
305 if( ptwXY_simpleCoalescePoints( smr, ptwXY ) != nfu_Okay ) {
307 return( ptwXY->status );
308 }
309
310 p2 = ptwXY->points;
311 x = p2->x;
312 for( i1 = 1, p2++; i1 < ( n - 1 ); i1++, p2++ ) { /* The first point shall remain the first point and all points close to it are deleted. */
313 if( ( p2->x - x ) > 0.5 * epsilon * ( fabs( x ) + fabs( p2->x ) ) ) break;
314 }
315 if( i1 != 1 ) {
316 for( i = i1, p1 = &(ptwXY->points[1]); i < n; i++, p1++, p2++ ) *p1 = *p2;
317 n = ptwXY->length = ptwXY->length - i1 + 1;
318 }
319
320 p1 = &(ptwXY->points[n-1]);
321 x = p1->x;
322 for( i1 = n - 2, p1--; i1 > 0; i1--, p1-- ) { /* The last point shall remain the last point and all points close to it are deleted. */
323 if( x - p1->x > 0.5 * epsilon * ( fabs( x ) + fabs( p1->x ) ) ) break;
324 }
325 if( i1 != ( n - 2 ) ) {
326 ptwXY->points[i1 + 1] = ptwXY->points[n - 1];
327 n = ptwXY->length = i1 + 2;
328 }
329
330 for( i = 1; i < n - 1; i++ ) {
331 p1 = &(ptwXY->points[i]);
332 x = p1->x;
333 y = p1->y;
334 for( j = i + 1, p2 = &(ptwXY->points[i+1]); j < n - 1; j++, p2++ ) {
335 if( ( p2->x - p1->x ) > 0.5 * epsilon * ( fabs( p2->x ) + fabs( p1->x ) ) ) break;
336 x += p2->x;
337 y += p2->y;
338 }
339 if( ( k = ( j - i ) ) > 1 ) {
340 p1->x = x / k;
341 p1->y = y / k;
342 for( p1 = &(ptwXY->points[i+1]); j < n; j++, p1++, p2++ ) *p1 = *p2;
343 n -= ( k - 1 );
344 }
345 }
346 ptwXY->length = n;
347
348 return( ptwXY->status );
349}
350/*
351************************************************************
352*/
354
355 int64_t i, i1, i2, lengthX = ptwX_length( smr, ptwX );
356 double x, y, domainMin, domainMax;
357 ptwXYPoints *n = NULL;
358
359 if( ptwX->status != nfu_Okay ) {
360 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid ptwXPoints." );
361 return( NULL );
362 }
363
364 if( ptwXY_simpleCoalescePoints( smr, ptwXY ) != nfu_Okay ) {
366 return( NULL );
367 }
368
370 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_otherInterpolation, "Other interpolation not allowed." );
371 return( NULL );
372 }
373
374 if( ( n = ptwXY_clone( smr, ptwXY ) ) == NULL ) {
376 return( NULL );
377 }
378
379 if( ptwXY->length == 0 ) return( n );
380 domainMin = ptwXY->points[0].x;
381 domainMax = ptwXY->points[ptwXY->length - 1].x;
382
383 if( ( domainMin >= ptwX->points[lengthX-1] ) || ( domainMax <= ptwX->points[0] ) ) { /* No overlap. */
384 n->length = 0;
385 return( n );
386 }
387
388 for( i = 0; i < lengthX; i++ ) { /* Fill in ptwXY at x-points in ptwX. */
389 x = ptwX->points[i];
390 if( x <= domainMin ) continue;
391 if( x >= domainMax ) break;
392 if( ptwXY_getValueAtX( smr, ptwXY, x, &y ) != nfu_Okay ) goto Err;
393 if( ptwXY_setValueAtX( smr, n, x, y ) != nfu_Okay ) goto Err;
394 }
395 if( ptwXY_simpleCoalescePoints( smr, n ) != nfu_Okay ) goto Err;
396
397 i1 = 0;
398 i2 = n->length - 1;
399 if( lengthX > 0 ) {
400 x = ptwX->points[0];
401 if( x > n->points[i1].x ) {
402 for( ; i1 < n->length; i1++ ) {
403 if( n->points[i1].x == x ) break;
404 }
405 }
406
407 x = ptwX->points[lengthX - 1];
408 if( x < n->points[i2].x ) {
409 for( ; i2 > i1; i2-- ) {
410 if( n->points[i2].x == x ) break;
411 }
412 }
413 }
414 i2++;
415
416 if( i1 != 0 ) {
417 for( i = i1; i < i2; i++ ) n->points[i - i1] = n->points[i];
418 }
419 n->length = i2 - i1;
420
421 return( n );
422
423Err:
425 ptwXY_free( n );
426 return( NULL );
427}
428/*
429************************************************************
430*/
432
433 nfu_status status = nfu_Okay;
434 int64_t n1 = ptwXY1->length, n2 = ptwXY2->length;
435 ptwXYPoint *xy1, *xy2;
436
437 if( ptwXY1->status != nfu_Okay ) {
438 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid source1." );
439 return( ptwXY1->status );
440 }
441
442 if( ptwXY2->status != nfu_Okay ) {
443 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid source2." );
444 return( ptwXY2->status );
445 }
446
447 if( n1 == 0 ) return( nfu_empty );
448 if( n2 == 0 ) return( nfu_empty );
449 if( n1 < 2 ) {
450 status = nfu_tooFewPoints; }
451 else if( n2 < 2 ) {
452 status = nfu_tooFewPoints; }
453 else {
454 xy1 = ptwXY_getPointAtIndex_Unsafely( ptwXY1, 0 );
455 xy2 = ptwXY_getPointAtIndex_Unsafely( ptwXY2, 0 );
456 if( xy1->x < xy2->x ) {
457 if( xy2->y != 0. ) status = nfu_domainsNotMutual; }
458 else if( xy1->x > xy2->x ) {
459 if( xy1->y != 0. ) status = nfu_domainsNotMutual;
460 }
461
462 if( status == nfu_Okay ) {
463 xy1 = ptwXY_getPointAtIndex_Unsafely( ptwXY1, n1 - 1 );
464 xy2 = ptwXY_getPointAtIndex_Unsafely( ptwXY2, n2 - 1 );
465 if( xy1->x < xy2->x ) {
466 if( xy1->y != 0. ) status = nfu_domainsNotMutual; }
467 else if( xy1->x > xy2->x ) {
468 if( xy2->y != 0. ) status = nfu_domainsNotMutual;
469 }
470 }
471 }
472 return( status );
473}
474/*
475************************************************************
476*/
478 int epsilonFactor, double epsilon ) {
479
480 nfu_status status = nfu_Okay;
481 int64_t n1 = ptwXY1->length, n2 = ptwXY2->length;
482 double sum, diff;
483 ptwXYPoint *xy1, *xy2;
484
485 epsilon = fabs( epsilon ) + fabs( epsilonFactor * DBL_EPSILON );
486
487 if( ptwXY1->status != nfu_Okay ) {
488 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid source1." );
489 return( ptwXY1->status );
490 }
491 if( ptwXY2->status != nfu_Okay ) {
492 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid source2." );
493 return( ptwXY2->status );
494 }
495
496 if( n1 == 0 ) return( nfu_empty );
497 if( n2 == 0 ) return( nfu_empty );
498 if( n1 < 2 ) {
499 status = nfu_tooFewPoints; }
500 else if( n2 < 2 ) {
501 status = nfu_tooFewPoints; }
502 else {
503 xy1 = ptwXY_getPointAtIndex_Unsafely( ptwXY1, 0 );
504 xy2 = ptwXY_getPointAtIndex_Unsafely( ptwXY2, 0 );
505 if( xy1->x < xy2->x ) {
506 if( xy2->y != 0. ) {
507 sum = fabs( xy1->x ) + fabs( xy2->x );
508 diff = fabs( xy2->x - xy1->x );
509 if( diff > epsilon * sum ) {
510 status = nfu_domainsNotMutual; }
511 else {
512 xy1->x = xy2->x;
513 }
514 } }
515 else if( xy1->x > xy2->x ) {
516 if( xy1->y != 0. ) {
517 sum = fabs( xy1->x ) + fabs( xy2->x );
518 diff = fabs( xy2->x - xy1->x );
519 if( diff > epsilon * sum ) {
520 status = nfu_domainsNotMutual; }
521 else {
522 xy2->x = xy1->x;
523 }
524 }
525 }
526
527 if( status == nfu_Okay ) {
528 xy1 = ptwXY_getPointAtIndex_Unsafely( ptwXY1, n1 - 1 );
529 xy2 = ptwXY_getPointAtIndex_Unsafely( ptwXY2, n2 - 1 );
530 if( xy1->x < xy2->x ) {
531 if( xy1->y != 0. ) {
532 sum = fabs( xy1->x ) + fabs( xy2->x );
533 diff = fabs( xy2->x - xy1->x );
534 if( diff > epsilon * sum ) {
535 status = nfu_domainsNotMutual; }
536 else {
537 xy2->x = xy1->x;
538 }
539 } }
540 else if( xy1->x > xy2->x ) {
541 if( xy2->y != 0. ) {
542 sum = fabs( xy1->x ) + fabs( xy2->x );
543 diff = fabs( xy2->x - xy1->x );
544 if( diff > epsilon * sum ) {
545 status = nfu_domainsNotMutual; }
546 else {
547 xy1->x = xy2->x;
548 }
549 }
550 }
551 }
552 }
553 return( status );
554}
555/*
556************************************************************
557*/
558nfu_status ptwXY_mutualifyDomains( statusMessageReporting *smr, ptwXYPoints *ptwXY1, double lowerEps1, double upperEps1,
559 int positiveXOnly1, ptwXYPoints *ptwXY2, double lowerEps2, double upperEps2, int positiveXOnly2 ) {
560
561 nfu_status status;
562 int64_t n1 = ptwXY1->length, n2 = ptwXY2->length;
563 int code1, code2;
564 ptwXYPoint *xy1, *xy2;
565
566 switch( status = ptwXY_areDomainsMutual( smr, ptwXY1, ptwXY2 ) ) {
567 case nfu_Okay :
568 case nfu_empty :
569 return( nfu_Okay );
571 break;
572 default :
574 return( status );
575 }
576
577 if( ptwXY1->interpolation == ptwXY_interpolationOther ) {
578 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_otherInterpolation, "Other interpolation not allowed for source1." );
579 return( nfu_otherInterpolation );
580 }
581 if( ptwXY2->interpolation == ptwXY_interpolationOther ) {
582 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_otherInterpolation, "Other interpolation not allowed for source2." );
583 return( nfu_otherInterpolation );
584 }
585
586 if( ptwXY1->interpolation == ptwXY_interpolationFlat ) {
587 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_invalidInterpolation, "Flat interpolation not allowed for source1." );
588 return( nfu_invalidInterpolation );
589 }
590 if( ptwXY2->interpolation == ptwXY_interpolationFlat ) {
591 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_invalidInterpolation, "Flat interpolation not allowed for source2." );
592 return( nfu_invalidInterpolation );
593 }
594
595 xy1 = ptwXY_getPointAtIndex_Unsafely( ptwXY1, 0 );
596 xy2 = ptwXY_getPointAtIndex_Unsafely( ptwXY2, 0 );
597 code1 = 0;
598 if( xy1->x < xy2->x ) {
599 lowerEps1 = 0.;
600 if( xy2->y == 0. ) {
601 lowerEps2 = 0.; }
602 else {
603 if( lowerEps2 == 0 ) {
604 code1 = -1; }
605 else {
606 if( ( xy2->x - xy1->x ) < lowerEps2 * ( fabs( xy1->x ) + fabs( xy2->x ) ) ) {
607 lowerEps2 = 0;
608 xy1->x = xy2->x;
609 status = ptwXY_areDomainsMutual( smr, ptwXY1, ptwXY2 );
610 }
611 }
612 } }
613 else if( xy1->x > xy2->x ) {
614 lowerEps2 = 0.;
615 if( xy1->y == 0. ) {
616 lowerEps1 = 0.; }
617 else {
618 if( lowerEps1 == 0 ) {
619 code1 = 1; }
620 else {
621 if( ( xy1->x - xy2->x ) < lowerEps1 * ( fabs( xy1->x ) + fabs( xy2->x ) ) ) {
622 lowerEps1 = 0;
623 xy2->x = xy1->x;
624 status = ptwXY_areDomainsMutual( smr, ptwXY1, ptwXY2 );
625 }
626 }
627 } }
628 else {
629 lowerEps1 = lowerEps2 = 0.;
630 }
631
632 xy1 = ptwXY_getPointAtIndex_Unsafely( ptwXY1, n1 - 1 );
633 xy2 = ptwXY_getPointAtIndex_Unsafely( ptwXY2, n2 - 1 );
634 code2 = 0;
635 if( xy1->x < xy2->x ) {
636 upperEps2 = 0.;
637 if( xy1->y == 0. ) {
638 upperEps1 = 0.; }
639 else {
640 if( upperEps1 == 0 ) {
641 code2 = -1; }
642 else {
643 if( ( xy2->x - xy1->x ) < upperEps1 * ( fabs( xy1->x ) + fabs( xy2->x ) ) ) {
644 upperEps1 = 0;
645 xy2->x = xy1->x;
646 status = ptwXY_areDomainsMutual( smr, ptwXY1, ptwXY2 );
647 }
648 }
649 } }
650 else if( xy1->x > xy2->x ) {
651 upperEps1 = 0.;
652 if( xy2->y == 0. ) {
653 upperEps2 = 0.; }
654 else {
655 if( upperEps2 == 0 ) {
656 code2 = 1; }
657 else {
658 if( ( xy1->x - xy2->x ) < upperEps2 * ( fabs( xy1->x ) + fabs( xy2->x ) ) ) {
659 upperEps2 = 0;
660 xy1->x = xy2->x;
661 status = ptwXY_areDomainsMutual( smr, ptwXY1, ptwXY2 );
662 }
663 }
664 } }
665 else {
666 upperEps1 = upperEps2 = 0.;
667 }
668
669 if( ( lowerEps1 != 0. ) || ( upperEps1 != 0. ) ) {
670 if( ( status = ptwXY_dullEdges( smr, ptwXY1, lowerEps1, upperEps1, positiveXOnly1 ) ) != nfu_Okay ) {
672 return( status );
673 }
674 }
675 if( ( lowerEps2 != 0. ) || ( upperEps2 != 0. ) ) {
676 if( ( status = ptwXY_dullEdges( smr, ptwXY2, lowerEps2, upperEps2, positiveXOnly2 ) ) != nfu_Okay ) {
678 return( status );
679 }
680 }
681
682 if( status == nfu_domainsNotMutual ) {
683 char str[256] = "";
684
685 if( code1 == 1 ) strcat( str, " lowerEps1" );
686 if( code1 == -1 ) strcat( str, " lowerEps2" );
687 if( code2 == 1 ) strcat( str, " upperEps2" );
688 if( code2 == -1 ) strcat( str, " upperEps1" );
690 "The following inputs are 0 and must be a non 0 value: %s.", str );
691 status = nfu_badInput;
692 }
693
694 return( status );
695}
696/*
697************************************************************
698*/
699nfu_status ptwXY_copyToC_XY( statusMessageReporting *smr, ptwXYPoints *ptwXY, int64_t index1, int64_t index2,
700 int64_t allocatedSize, int64_t *numberOfPoints, double *xys ) {
701
702 int64_t i;
703 double *d = xys;
704 ptwXYPoint *pointFrom;
705
706 if( ptwXY_simpleCoalescePoints( smr, ptwXY ) != nfu_Okay ) {
707 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid source." );
708 return( ptwXY->status );
709 }
710
711 if( index1 < 0 ) index1 = 0;
712 if( index2 > ptwXY->length ) index2 = ptwXY->length;
713 if( index2 < index1 ) index2 = index1;
714 *numberOfPoints = index2 - index1;
715 if( allocatedSize < ( index2 - index1 ) ) return( nfu_insufficientMemory );
716
717 for( i = index1, pointFrom = ptwXY->points; i < index2; i++, pointFrom++ ) {
718 *(d++) = pointFrom->x;
719 *(d++) = pointFrom->y;
720 }
721
722 return( nfu_Okay );
723}
724/*
725************************************************************
726*/
727nfu_status ptwXY_valuesToC_XsAndYs( statusMessageReporting *smr, ptwXYPoints *ptwXY, double **xs, double **ys ) {
728
729 int64_t i1, length;
730 double *xps, *yps;
731 ptwXYPoint *pointFrom;
732
733 if( ptwXY_simpleCoalescePoints( smr, ptwXY ) != nfu_Okay ) {
734 smr_setReportError2p( smr, nfu_SMR_libraryID, nfu_badSelf, "Invalid source." );
735 return( ptwXY->status );
736 }
737 length = ptwXY_length( NULL, ptwXY );
738
739 if( ( *xs = (double *) smr_malloc2( smr, (size_t) length * sizeof( double ), 0, "xs" ) ) == NULL ) {
741 return( nfu_mallocError );
742 }
743 if( ( *ys = (double *) smr_malloc2( smr, (size_t) length * sizeof( double ), 0, "ys" ) ) == NULL ) {
745 smr_freeMemory2( *xs );
746 return( nfu_mallocError );
747 }
748
749 for( i1 = 0, pointFrom = ptwXY->points, xps = *xs, yps = *ys; i1 < length; ++i1, ++pointFrom, ++xps, ++yps ) {
750 *xps = pointFrom->x;
751 *yps = pointFrom->y;
752 }
753
754 return( nfu_Okay );
755}
756/*
757************************************************************
758*/
759ptwXYPoints *ptwXY_valueTo_ptwXY( statusMessageReporting *smr, double x1, double x2, double y ) {
760
761 ptwXYPoints *n1;
762
763 if( x1 >= x2 ) {
765 "X-values not ascend: x1 = %.17e, x2 = %.17e", x1, x2 );
766 return( NULL );
767 }
768 if( ( n1 = ptwXY_new( smr, ptwXY_interpolationLinLin, NULL, ptwXY_maxBiSectionMax, ptwXY_minAccuracy, 2, 0, 0 ) ) == NULL ) {
770 return( NULL );
771 }
772 if( ptwXY_setValueAtX( smr, n1, x1, y ) != nfu_Okay ) goto Err;
773 if( ptwXY_setValueAtX( smr, n1, x2, y ) != nfu_Okay ) goto Err;
774 return( n1 );
775
776Err:
778 ptwXY_free( n1 );
779 return( NULL );
780}
781/*
782************************************************************
783*/
785
786 int64_t i, n;
787 ptwXYPoint *pm, *pp;
788 double x1, y1, x2, y2, accuracy2, rangeMin = 1e-10;
789 ptwXYPoints *gaussian;
790
791 if( accuracy < 1e-5 ) accuracy = 1e-5;
792 if( accuracy > 1e-1 ) accuracy = 1e-1;
793 if( ( gaussian = ptwXY_new( smr, ptwXY_interpolationLinLin, NULL, 1., accuracy, 200, 100, 0 ) ) == NULL ) {
795 return( NULL );
796 }
797
798 accuracy2 = accuracy = gaussian->accuracy;
799 if( accuracy2 > 5e-3 ) accuracy2 = 5e-3;
800
801 x1 = -sqrt( -2. * log( rangeMin ) );
802 y1 = rangeMin;
803 x2 = -5.2;
804 y2 = exp( -0.5 * x2 * x2 );
805 if( ptwXY_setValueAtX( smr, gaussian, x1, y1 ) != nfu_Okay ) goto Err;
806 gaussian->accuracy = 20 * accuracy2;
807 if( ptwXY_createGaussianCenteredSigma1_2( smr, gaussian, x1, y1, x2, y2, 1 ) != nfu_Okay ) goto Err;
808 x1 = x2;
809 y1 = y2;
810 x2 = -4.;
811 y2 = exp( -0.5 * x2 * x2 );
812 gaussian->accuracy = 5 * accuracy2;
813 if( ptwXY_createGaussianCenteredSigma1_2( smr, gaussian, x1, y1, x2, y2, 1 ) != nfu_Okay ) goto Err;
814 x1 = x2;
815 y1 = y2;
816 x2 = -1;
817 y2 = exp( -0.5 * x2 * x2 );
818 gaussian->accuracy = accuracy;
819 if( ptwXY_createGaussianCenteredSigma1_2( smr, gaussian, x1, y1, x2, y2, 1 ) != nfu_Okay ) goto Err;
820 x1 = x2;
821 y1 = y2;
822 x2 = 0;
823 y2 = exp( -0.5 * x2 * x2 );
824 if( ptwXY_createGaussianCenteredSigma1_2( smr, gaussian, x1, y1, x2, y2, 1 ) != nfu_Okay ) goto Err;
825
826 n = gaussian->length;
827 if( ptwXY_coalescePoints( smr, gaussian, 2 * n + 1, NULL, 0 ) != nfu_Okay ) goto Err;
828 if( ptwXY_setValueAtX( smr, gaussian, 0., 1. ) != nfu_Okay ) goto Err;
829 pp = &(gaussian->points[gaussian->length]);
830 for( i = 0, pm = pp - 2; i < n; i++, pp++, pm-- ) {
831 *pp = *pm;
832 pp->x *= -1;
833 }
834 gaussian->length = 2 * n + 1;
835
836 return( gaussian );
837
838Err:
839 ptwXY_free( gaussian );
841 return( NULL );
842}
843/*
844************************************************************
845*/
846static nfu_status ptwXY_createGaussianCenteredSigma1_2( statusMessageReporting *smr, ptwXYPoints *ptwXY,
847 double x1, double y1, double x2, double y2, int addX1Point ) {
848
849 nfu_status status = nfu_Okay;
850 int morePoints = 0;
851 double x = 0.5 * ( x1 + x2 );
852 double y = exp( -0.5 * x * x ), rangeMin = ( y1 * ( x2 - x ) + y2 * ( x - x1 ) ) / ( x2 - x1 );
853
854 if( fabs( y - rangeMin ) > y * ptwXY->accuracy ) morePoints = 1;
855 if( morePoints && ( status = ptwXY_createGaussianCenteredSigma1_2( smr, ptwXY, x, y, x2, y2, 0 ) ) != nfu_Okay ) return( status );
856 if( ( status = ptwXY_setValueAtX( smr, ptwXY, x, y ) ) != nfu_Okay ) return( status );
857 if( morePoints && ( status = ptwXY_createGaussianCenteredSigma1_2( smr, ptwXY, x1, y1, x, y, 0 ) ) != nfu_Okay ) return( status );
858 if( addX1Point ) status = ptwXY_setValueAtX( smr, ptwXY, x1, y1 );
859 return( status );
860}
861/*
862************************************************************
863*/
864ptwXYPoints *ptwXY_createGaussian( statusMessageReporting *smr, double accuracy, double xCenter, double sigma,
865 double amplitude, double domainMin, double domainMax, double dullEps ) {
866
867 int64_t i;
868 ptwXYPoints *gaussian, *sliced;
869 ptwXYPoint *point;
870
871 if( ( gaussian = ptwXY_createGaussianCenteredSigma1( smr, accuracy ) ) == NULL ) {
873 return( NULL );
874 }
875
876 for( i = 0, point = gaussian->points; i < gaussian->length; i++, point++ ) {
877 point->x = point->x * sigma + xCenter;
878 point->y *= amplitude;
879 }
880 if( ( gaussian->points[0].x < domainMin ) || ( gaussian->points[gaussian->length - 1].x > domainMax ) ) {
881 if( ( sliced = ptwXY_domainSlice( smr, gaussian, domainMin, domainMax, 10, 1 ) ) == NULL ) goto Err;
882 ptwXY_free( gaussian );
883 gaussian = sliced;
884 }
885
886 return( gaussian );
887
888Err:
890 ptwXY_free( gaussian );
891 return( NULL );
892}
G4double epsilon(G4double density, G4double temperature)
G4ThreadLocal T * G4GeomSplitter< T >::offset
@ nfu_domainsNotMutual
@ nfu_XNotAscending
@ nfu_invalidInterpolation
@ nfu_Okay
@ nfu_badSelf
@ nfu_mallocError
@ nfu_insufficientMemory
@ nfu_tooFewPoints
@ nfu_badInput
@ nfu_Error
@ nfu_empty
@ nfu_otherInterpolation
enum nfu_status_e nfu_status
int nfu_SMR_libraryID
#define ptwXY_minAccuracy
Definition ptwXY.h:26
ptwXYPoints * ptwXY_domainSlice(statusMessageReporting *smr, ptwXYPoints *ptwXY, double domainMin, double domainMax, int64_t secondarySize, int fill)
Definition ptwXY_core.c:422
nfu_status ptwXY_setValueAtX(statusMessageReporting *smr, ptwXYPoints *ptwXY, double x, double y)
ptwXY_interpolation ptwXY_getInterpolation(ptwXYPoints *ptwXY)
Definition ptwXY_core.c:518
nfu_status ptwXY_startIndex(statusMessageReporting *a_smr, ptwXYPoints *a_ptwXY, double a_x, int64_t *a_startIndex, int64_t *a_length)
Definition ptwXY_core.c:818
ptwXYPoints * ptwXY_clone(statusMessageReporting *smr, ptwXYPoints *ptwXY)
Definition ptwXY_core.c:302
nfu_status ptwXY_coalescePoints(statusMessageReporting *smr, ptwXYPoints *ptwXY, int64_t size, ptwXYPoint *newPoint, int forceSmallerResize)
Definition ptwXY_core.c:667
enum ptwXY_interpolation_e ptwXY_interpolation
@ ptwXY_interpolationFlat
Definition ptwXY.h:38
@ ptwXY_interpolationLinLin
Definition ptwXY.h:37
@ ptwXY_interpolationOther
Definition ptwXY.h:38
struct ptwXYPoints_s ptwXYPoints
#define ptwXY_maxBiSectionMax
Definition ptwXY.h:25
nfu_status ptwXY_interpolatePoint(statusMessageReporting *smr, ptwXY_interpolation interpolation, double x, double *y, double x1, double y1, double x2, double y2)
ptwXYPoints * ptwXY_new(statusMessageReporting *smr, ptwXY_interpolation interpolation, char const *interpolationString, double biSectionMax, double accuracy, int64_t primarySize, int64_t secondarySize, int userFlag)
Definition ptwXY_core.c:28
int64_t ptwXY_length(statusMessageReporting *smr, ptwXYPoints *ptwXY)
Definition ptwXY_core.c:793
struct ptwXYPoint_s ptwXYPoint
ptwXYPoints * ptwXY_free(ptwXYPoints *ptwXY)
Definition ptwXY_core.c:782
ptwXYPoint * ptwXY_getPointAtIndex_Unsafely(ptwXYPoints const *ptwXY, int64_t index)
nfu_status ptwXY_getValueAtX(statusMessageReporting *smr, ptwXYPoints *ptwXY, double x, double *y)
nfu_status ptwXY_simpleCoalescePoints(statusMessageReporting *smr, ptwXYPoints *ptwXY)
Definition ptwXY_core.c:734
nfu_status ptwXY_dullEdges(statusMessageReporting *smr, ptwXYPoints *ptwXY, double lowerEps, double upperEps, int positiveXOnly)
#define minEps
nfu_status ptwXY_valuesToC_XsAndYs(statusMessageReporting *smr, ptwXYPoints *ptwXY, double **xs, double **ys)
nfu_status ptwXY_copyToC_XY(statusMessageReporting *smr, ptwXYPoints *ptwXY, int64_t index1, int64_t index2, int64_t allocatedSize, int64_t *numberOfPoints, double *xys)
ptwXYPoints * ptwXY_createGaussianCenteredSigma1(statusMessageReporting *smr, double accuracy)
ptwXYPoints * ptwXY_intersectionWith_ptwX(statusMessageReporting *smr, ptwXYPoints *ptwXY, ptwXPoints *ptwX)
nfu_status ptwXY_tweakDomainsToMutualify(statusMessageReporting *smr, ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2, int epsilonFactor, double epsilon)
ptwXPoints * ptwXY_getXArray(statusMessageReporting *smr, ptwXYPoints *ptwXY)
nfu_status ptwXY_areDomainsMutual(statusMessageReporting *smr, ptwXYPoints *ptwXY1, ptwXYPoints *ptwXY2)
nfu_status ptwXY_mutualifyDomains(statusMessageReporting *smr, ptwXYPoints *ptwXY1, double lowerEps1, double upperEps1, int positiveXOnly1, ptwXYPoints *ptwXY2, double lowerEps2, double upperEps2, int positiveXOnly2)
nfu_status ptwXY_mapToXsAndAdd(statusMessageReporting *a_smr, ptwXYPoints *a_ptwXY, int64_t a_offset, int64_t a_length, double const *a_Xs, double *a_results, double a_scaleFractor)
nfu_status ptwXY_mergeClosePoints(statusMessageReporting *smr, ptwXYPoints *ptwXY, double epsilon)
ptwXYPoints * ptwXY_valueTo_ptwXY(statusMessageReporting *smr, double x1, double x2, double y)
ptwXYPoints * ptwXY_createGaussian(statusMessageReporting *smr, double accuracy, double xCenter, double sigma, double amplitude, double domainMin, double domainMax, double dullEps)
ptwXPoints * ptwXY_ysMappedToXs(statusMessageReporting *smr, ptwXYPoints *ptwXY, ptwXPoints *Xs, int64_t *offset)
int64_t ptwX_length(statusMessageReporting *smr, ptwXPoints *ptwX)
Definition ptwX_core.c:222
struct ptwXPoints_s ptwXPoints
nfu_status ptwX_setPointAtIndex(statusMessageReporting *smr, ptwXPoints *ptwX, int64_t index, double x)
Definition ptwX_core.c:304
ptwXPoints * ptwX_free(ptwXPoints *ptwX)
Definition ptwX_core.c:213
ptwXPoints * ptwX_new(statusMessageReporting *smr, int64_t size)
Definition ptwX_core.c:22
#define smr_setReportError2(smr, libraryID, code, fmt,...)
#define smr_setReportError2p(smr, libraryID, code, fmt)
#define smr_freeMemory2(p)
#define smr_malloc2(smr, size, zero, forItem)
nfu_status status
Definition ptwX.h:28
int64_t length
Definition ptwX.h:29
double * points
Definition ptwX.h:32
double y
Definition ptwXY.h:64
double x
Definition ptwXY.h:64
ptwXYPoint * points
Definition ptwXY.h:93
ptwXY_interpolation interpolation
Definition ptwXY.h:81
double accuracy
Definition ptwXY.h:85
int64_t length
Definition ptwXY.h:87
nfu_status status
Definition ptwXY.h:80
#define DBL_EPSILON
Definition templates.hh:66