Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/hadronic/models/lend/src/ptwXY_interpolation.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /processes/hadronic/models/lend/src/ptwXY_interpolation.cc (Version 11.3.0) and /processes/hadronic/models/lend/src/ptwXY_interpolation.cc (Version 10.3.p3)


  1 /*                                                  1 /*
  2 # <<BEGIN-copyright>>                               2 # <<BEGIN-copyright>>
  3 # <<END-copyright>>                                 3 # <<END-copyright>>
  4 */                                                  4 */
  5                                                     5 
  6 #include <cmath>                                    6 #include <cmath>
  7 #include <float.h>                                  7 #include <float.h>
  8                                                     8 
  9 #include "ptwXY.h"                                  9 #include "ptwXY.h"
 10                                                    10 
 11 #if defined __cplusplus                            11 #if defined __cplusplus
 12 #include "G4Exp.hh"                                12 #include "G4Exp.hh"
 13 #include "G4Log.hh"                                13 #include "G4Log.hh"
 14 #include "G4Pow.hh"                                14 #include "G4Pow.hh"
 15 namespace GIDI {                                   15 namespace GIDI {
 16 using namespace GIDI;                              16 using namespace GIDI;
 17 #endif                                             17 #endif
 18                                                    18 
 19 typedef nfu_status (*interpolation_func)( ptwX     19 typedef nfu_status (*interpolation_func)( ptwXYPoints *desc, double x1, double y1, double x2, double y2, int depth );
 20                                                    20 
 21 static double ptwXY_flatInterpolationToLinear_     21 static double ptwXY_flatInterpolationToLinear_eps( double px, double eps );
 22 static nfu_status ptwXY_toOtherInterpolation2(     22 static nfu_status ptwXY_toOtherInterpolation2( ptwXYPoints *desc, ptwXYPoints *src, interpolation_func func );
 23 static nfu_status ptwXY_LogLogToLinLin( ptwXYP     23 static nfu_status ptwXY_LogLogToLinLin( ptwXYPoints *desc, double x1, double y1, double x2, double y2, int depth );
 24 static nfu_status ptwXY_LinLogToLinLin( ptwXYP     24 static nfu_status ptwXY_LinLogToLinLin( ptwXYPoints *desc, double x1, double y1, double x2, double y2, int depth );
 25 static nfu_status ptwXY_LogLinToLinLin( ptwXYP     25 static nfu_status ptwXY_LogLinToLinLin( ptwXYPoints *desc, double x1, double y1, double x2, double y2, int depth );
 26 static nfu_status ptwXY_otherToLinLin( ptwXYPo     26 static nfu_status ptwXY_otherToLinLin( ptwXYPoints *desc, double x1, double y1, double x2, double y2, int depth );
 27 /*                                                 27 /*
 28 **********************************************     28 ************************************************************
 29 */                                                 29 */
 30 nfu_status ptwXY_interpolatePoint( ptwXY_inter     30 nfu_status ptwXY_interpolatePoint( ptwXY_interpolation interpolation, double x, double *y, double x1, double y1, double x2, double y2 ) {
 31                                                    31 
 32     nfu_status status = nfu_Okay;                  32     nfu_status status = nfu_Okay;
 33                                                    33 
 34     if( interpolation == ptwXY_interpolationOt     34     if( interpolation == ptwXY_interpolationOther ) return( nfu_otherInterpolation );
 35     if( ( x1 > x2 ) || ( x < x1 ) || ( x > x2      35     if( ( x1 > x2 ) || ( x < x1 ) || ( x > x2 ) ) return( nfu_invalidInterpolation );
 36     if( y1 == y2 ) {                               36     if( y1 == y2 ) {
 37         *y = y1; }                                 37         *y = y1; }
 38     else if( x1 == x2 ) {                          38     else if( x1 == x2 ) {
 39         *y = 0.5 * ( y1  + y2 ); }                 39         *y = 0.5 * ( y1  + y2 ); }
 40     else if( x == x1 ) {                           40     else if( x == x1 ) {
 41         *y = y1; }                                 41         *y = y1; }
 42     else if( x == x2 ) {                           42     else if( x == x2 ) {
 43         *y = y2; }                                 43         *y = y2; }
 44     else {                                         44     else {
 45         switch( interpolation ) {                  45         switch( interpolation ) {
 46         case ptwXY_interpolationLinLin :           46         case ptwXY_interpolationLinLin :
 47             *y = ( y1 * ( x2 - x ) + y2 * ( x      47             *y = ( y1 * ( x2 - x ) + y2 * ( x - x1 ) ) / ( x2 - x1 );
 48             break;                                 48             break;
 49         case ptwXY_interpolationLogLin :           49         case ptwXY_interpolationLogLin :
 50             if( ( x <= 0. ) || ( x1 <= 0. ) ||     50             if( ( x <= 0. ) || ( x1 <= 0. ) || ( x2 <= 0. ) ) return( nfu_invalidInterpolation );
 51             *y = ( y1 * G4Log( x2 / x ) + y2 *     51             *y = ( y1 * G4Log( x2 / x ) + y2 * G4Log( x / x1 ) ) / G4Log( x2 / x1 );
 52             break;                                 52             break;
 53         case ptwXY_interpolationLinLog :           53         case ptwXY_interpolationLinLog :
 54             if( ( y1 <= 0. ) || ( y2 <= 0. ) )     54             if( ( y1 <= 0. ) || ( y2 <= 0. ) ) return( nfu_invalidInterpolation );
 55             *y = G4Exp( ( G4Log( y1 ) * ( x2 -     55             *y = G4Exp( ( G4Log( y1 ) * ( x2 - x ) + G4Log( y2 ) * ( x - x1 ) ) / ( x2 - x1 ) );
 56             break;                                 56             break;
 57         case ptwXY_interpolationLogLog :           57         case ptwXY_interpolationLogLog :
 58             if( ( x <= 0. ) || ( x1 <= 0. ) ||     58             if( ( x <= 0. ) || ( x1 <= 0. ) || ( x2 <= 0. ) ) return( nfu_invalidInterpolation );
 59             if( ( y1 <= 0. ) || ( y2 <= 0. ) )     59             if( ( y1 <= 0. ) || ( y2 <= 0. ) ) return( nfu_invalidInterpolation );
 60             *y = G4Exp( ( G4Log( y1 ) * G4Log(     60             *y = G4Exp( ( G4Log( y1 ) * G4Log( x2 / x ) + G4Log( y2 ) * G4Log( x / x1 ) ) / G4Log( x2 / x1 ) );
 61             break;                                 61             break;
 62         case ptwXY_interpolationFlat :             62         case ptwXY_interpolationFlat :
 63             *y = y1;                               63             *y = y1;
 64             break;                                 64             break;
 65         default :                                  65         default :
 66             status = nfu_invalidInterpolation;     66             status = nfu_invalidInterpolation;
 67         }                                          67         }
 68     }                                              68     }
 69     return( status );                              69     return( status );
 70 }                                                  70 }
 71 /*                                                 71 /*
 72 **********************************************     72 ************************************************************
 73 */                                                 73 */
 74 ptwXYPoints *ptwXY_flatInterpolationToLinear(      74 ptwXYPoints *ptwXY_flatInterpolationToLinear( ptwXYPoints *ptwXY, double lowerEps, double upperEps, nfu_status *status ) {
 75                                                    75 
 76     int64_t i, length;                             76     int64_t i, length;
 77     double x;                                      77     double x;
 78     ptwXYPoints *n;                                78     ptwXYPoints *n;
 79     ptwXYPoint *p1 = NULL, *p2 = NULL, *p3;        79     ptwXYPoint *p1 = NULL, *p2 = NULL, *p3;
 80                                                    80 
 81 #define minEps 5e-16                               81 #define minEps 5e-16
 82                                                    82 
 83     if( ( *status = ptwXY_simpleCoalescePoints     83     if( ( *status = ptwXY_simpleCoalescePoints( ptwXY ) ) != nfu_Okay ) return( NULL );
 84     *status = nfu_invalidInterpolation;            84     *status = nfu_invalidInterpolation;
 85     if( ptwXY->interpolation != ptwXY_interpol     85     if( ptwXY->interpolation != ptwXY_interpolationFlat ) return( NULL );
 86     *status = nfu_badInput;                        86     *status = nfu_badInput;
 87     if( ( lowerEps < 0 ) || ( upperEps < 0 ) |     87     if( ( lowerEps < 0 ) || ( upperEps < 0 ) || ( ( lowerEps == 0 ) && ( upperEps == 0 ) ) ) return( NULL );
 88     if( ( lowerEps != 0 ) && ( lowerEps < minE     88     if( ( lowerEps != 0 ) && ( lowerEps < minEps ) ) lowerEps = minEps;
 89     if( ( upperEps != 0 ) && ( upperEps < minE     89     if( ( upperEps != 0 ) && ( upperEps < minEps ) ) upperEps = minEps;
 90                                                    90 
 91     length = ptwXY->length * ( 1 + ( lowerEps      91     length = ptwXY->length * ( 1 + ( lowerEps == 0 ? 0 : 1 ) + ( lowerEps == 0 ? 0 : 1 ) );
 92     if( ( n = ptwXY_new( ptwXY_interpolationLi     92     if( ( n = ptwXY_new( ptwXY_interpolationLinLin, NULL, ptwXY->biSectionMax, ptwXY->accuracy, length, ptwXY->overflowLength, status, ptwXY->userFlag ) ) == NULL ) return( NULL );
 93                                                    93 
 94     p3 = ptwXY->points;                            94     p3 = ptwXY->points;
 95     if( ptwXY->length > 0 ) ptwXY_setValueAtX(     95     if( ptwXY->length > 0 ) ptwXY_setValueAtX( n, p3->x, p3->y );
 96     for( i = 0; i < ptwXY->length; i++, p3++ )     96     for( i = 0; i < ptwXY->length; i++, p3++ ) {
 97         if( i > 1 ) {                              97         if( i > 1 ) {
 98             if( lowerEps > 0 ) {                   98             if( lowerEps > 0 ) {
 99                 x = ptwXY_flatInterpolationToL     99                 x = ptwXY_flatInterpolationToLinear_eps( p2->x, -lowerEps );
100                 if( x > p1->x ) {                 100                 if( x > p1->x ) {
101                     if( ( *status = ptwXY_setV    101                     if( ( *status = ptwXY_setValueAtX( n, x, p1->y ) ) != nfu_Okay ) goto Err;
102                 }                                 102                 }
103             }                                     103             }
104             if( lowerEps == 0 ) if( ( *status     104             if( lowerEps == 0 ) if( ( *status = ptwXY_setValueAtX( n, p2->x, p1->y ) ) != nfu_Okay ) goto Err;
105             if( upperEps == 0 ) if( ( *status     105             if( upperEps == 0 ) if( ( *status = ptwXY_setValueAtX( n, p2->x, p2->y ) ) != nfu_Okay ) goto Err;
106             if( upperEps > 0 ) {                  106             if( upperEps > 0 ) {
107                 x = ptwXY_flatInterpolationToL    107                 x = ptwXY_flatInterpolationToLinear_eps( p2->x, upperEps );
108                 if( x < p3->x ) {                 108                 if( x < p3->x ) {
109                     if( ( *status = ptwXY_setV    109                     if( ( *status = ptwXY_setValueAtX( n, x, p2->y ) ) != nfu_Okay ) goto Err;
110                 }                                 110                 }
111             }                                     111             }
112         }                                         112         }
113         p1 = p2;                                  113         p1 = p2;
114         p2 = p3;                                  114         p2 = p3;
115     }                                             115     }
116     if( ptwXY->length > 1 ) {                     116     if( ptwXY->length > 1 ) {
117         if( ( lowerEps != 0 ) && ( p1->y != p2    117         if( ( lowerEps != 0 ) && ( p1->y != p2->y ) ) {
118             x = ptwXY_flatInterpolationToLinea    118             x = ptwXY_flatInterpolationToLinear_eps( p2->x, -lowerEps );
119             if( x > p1->x ) {                     119             if( x > p1->x ) {
120                 if( ( *status = ptwXY_setValue    120                 if( ( *status = ptwXY_setValueAtX( n, x, p1->y ) ) != nfu_Okay ) goto Err;
121             }                                     121             }
122         }                                         122         }
123         if( ( *status = ptwXY_setValueAtX( n,     123         if( ( *status = ptwXY_setValueAtX( n, p2->x, p2->y ) ) != nfu_Okay ) goto Err;
124     }                                             124     }
125                                                   125 
126     return( n );                                  126     return( n );
127                                                   127 
128 Err:                                              128 Err:
129     ptwXY_free( n );                              129     ptwXY_free( n );
130     return( NULL );                               130     return( NULL );
131                                                   131 
132 #undef minEps                                     132 #undef minEps
133 }                                                 133 }
134 /*                                                134 /*
135 **********************************************    135 ************************************************************
136 */                                                136 */
137 static double ptwXY_flatInterpolationToLinear_    137 static double ptwXY_flatInterpolationToLinear_eps( double px, double eps ) {
138                                                   138 
139     double x;                                     139     double x;
140                                                   140 
141     if( px < 0 ) {                                141     if( px < 0 ) {
142         x = ( 1 - eps ) * px; }                   142         x = ( 1 - eps ) * px; }
143     else if( px > 0 ) {                           143     else if( px > 0 ) {
144         x = ( 1 + eps ) * px; }                   144         x = ( 1 + eps ) * px; }
145     else {                                        145     else {
146         x = eps;                                  146         x = eps;
147     }                                             147     }
148     return( x );                                  148     return( x );
149 }                                                 149 }
150 /*                                                150 /*
151 **********************************************    151 ************************************************************
152 */                                                152 */
153 ptwXYPoints *ptwXY_toOtherInterpolation( ptwXY    153 ptwXYPoints *ptwXY_toOtherInterpolation( ptwXYPoints *ptwXY, ptwXY_interpolation interpolationTo, double accuracy, nfu_status *status ) {
154 /*                                                154 /*
155 *   This function only works when 'ptwXY->inte    155 *   This function only works when 'ptwXY->interpolation == interpolationTo' or when interpolationTo is ptwXY_interpolationLinLin.
156 */                                                156 */
157     ptwXYPoints *n1;                              157     ptwXYPoints *n1;
158     interpolation_func func = NULL;               158     interpolation_func func = NULL;
159                                                   159 
160     if( ( *status = ptwXY->status ) != nfu_Oka    160     if( ( *status = ptwXY->status ) != nfu_Okay ) return( NULL );
161     if( ptwXY->interpolation == interpolationT    161     if( ptwXY->interpolation == interpolationTo ) {
162         *status = nfu_Okay;                       162         *status = nfu_Okay;
163         return( ptwXY_clone( ptwXY, status ) )    163         return( ptwXY_clone( ptwXY, status ) ); }
164     else {                                        164     else {
165         if( interpolationTo == ptwXY_interpola    165         if( interpolationTo == ptwXY_interpolationLinLin ) {
166             switch( ptwXY->interpolation ) {      166             switch( ptwXY->interpolation ) {
167             case ptwXY_interpolationLogLog :      167             case ptwXY_interpolationLogLog :
168                 func = ptwXY_LogLogToLinLin; b    168                 func = ptwXY_LogLogToLinLin; break;
169             case ptwXY_interpolationLinLog :      169             case ptwXY_interpolationLinLog :
170                 func = ptwXY_LinLogToLinLin; b    170                 func = ptwXY_LinLogToLinLin; break;
171             case ptwXY_interpolationLogLin :      171             case ptwXY_interpolationLogLin :
172                 func = ptwXY_LogLinToLinLin; b    172                 func = ptwXY_LogLinToLinLin; break;
173             case ptwXY_interpolationOther :       173             case ptwXY_interpolationOther :
174                 if( ptwXY->interpolationOtherI    174                 if( ptwXY->interpolationOtherInfo.getValueFunc != NULL ) func = ptwXY_otherToLinLin;
175                 break;                            175                 break;
176             case ptwXY_interpolationLinLin :      176             case ptwXY_interpolationLinLin :        /* Stops compilers from complaining. */
177             case ptwXY_interpolationFlat :        177             case ptwXY_interpolationFlat :
178                 break;                            178                 break;
179             }                                     179             }
180         }                                         180         }
181     }                                             181     }
182     *status = nfu_unsupportedInterpolationConv    182     *status = nfu_unsupportedInterpolationConversion;
183     if( func == NULL ) return( NULL );            183     if( func == NULL ) return( NULL );
184                                                   184 
185     *status = nfu_Okay;                           185     *status = nfu_Okay;
186     if( ( n1 = ptwXY_cloneToInterpolation( ptw    186     if( ( n1 = ptwXY_cloneToInterpolation( ptwXY, interpolationTo, status ) ) == NULL ) return( NULL );
187     if( accuracy < ptwXY->accuracy ) accuracy     187     if( accuracy < ptwXY->accuracy ) accuracy = ptwXY->accuracy;
188     n1->accuracy = accuracy;                      188     n1->accuracy = accuracy;
189                                                   189 
190     n1->interpolationOtherInfo.getValueFunc =     190     n1->interpolationOtherInfo.getValueFunc = ptwXY->interpolationOtherInfo.getValueFunc;
191     n1->interpolationOtherInfo.argList = ptwXY    191     n1->interpolationOtherInfo.argList = ptwXY->interpolationOtherInfo.argList;
192     *status = ptwXY_toOtherInterpolation2( n1,    192     *status = ptwXY_toOtherInterpolation2( n1, ptwXY, func );
193     n1->interpolationOtherInfo.getValueFunc =     193     n1->interpolationOtherInfo.getValueFunc = NULL;
194     n1->interpolationOtherInfo.argList = NULL;    194     n1->interpolationOtherInfo.argList = NULL;
195     if( *status != nfu_Okay ) n1 = ptwXY_free(    195     if( *status != nfu_Okay ) n1 = ptwXY_free( n1 );
196     return( n1 );                                 196     return( n1 );
197 }                                                 197 }
198 /*                                                198 /*
199 **********************************************    199 ************************************************************
200 */                                                200 */
201 static nfu_status ptwXY_toOtherInterpolation2(    201 static nfu_status ptwXY_toOtherInterpolation2( ptwXYPoints *desc, ptwXYPoints *src, interpolation_func func ) {
202                                                   202 
203     nfu_status status;                            203     nfu_status status;
204     int64_t i;                                    204     int64_t i;
205     double x1, y1, x2, y2;                        205     double x1, y1, x2, y2;
206                                                   206 
207     if( ( status = ptwXY_simpleCoalescePoints(    207     if( ( status = ptwXY_simpleCoalescePoints( src ) ) != nfu_Okay ) return( status );
208                                                   208 
209     x1 = src->points[0].x;                        209     x1 = src->points[0].x;
210     y1 = src->points[0].y;                        210     y1 = src->points[0].y;
211     for( i = 1; i < src->length; i++ ) {          211     for( i = 1; i < src->length; i++ ) {
212         x2 = src->points[i].x;                    212         x2 = src->points[i].x;
213         y2 = src->points[i].y;                    213         y2 = src->points[i].y;
214         if( ( x1 != x2 ) && ( y1 != y2 ) ) {      214         if( ( x1 != x2 ) && ( y1 != y2 ) ) {
215             if( ( status = func( desc, x1, y1,    215             if( ( status = func( desc, x1, y1, x2, y2, 0 ) ) != nfu_Okay ) break;
216         }                                         216         }
217         x1 = x2;                                  217         x1 = x2;
218         y1 = y2;                                  218         y1 = y2;
219     }                                             219     }
220     return( status );                             220     return( status );
221 }                                                 221 }
222 /*                                                222 /*
223 **********************************************    223 ************************************************************
224 */                                                224 */
225 static nfu_status ptwXY_LogLogToLinLin( ptwXYP    225 static nfu_status ptwXY_LogLogToLinLin( ptwXYPoints *desc, double x1, double y1, double x2, double y2, int depth ) {
226                                                   226 
227     nfu_status status = nfu_Okay;                 227     nfu_status status = nfu_Okay;
228     double x, y, u, u2 = x2 / x1, v2 = y2 / y1    228     double x, y, u, u2 = x2 / x1, v2 = y2 / y1, logYXs, logXs = G4Log( u2 ), logYs = G4Log( v2 ), vLin, vLog, w;
229                                                   229 
230     logYXs = logYs / logXs;                       230     logYXs = logYs / logXs;
231                                                   231 
232     if( depth > 16 ) return( nfu_Okay );          232     if( depth > 16 ) return( nfu_Okay );
233     if( std::fabs( logYXs  - 1 ) < 1e-5 ) {       233     if( std::fabs( logYXs  - 1 ) < 1e-5 ) {
234         u = 0.5 * ( 1 + u2 );                     234         u = 0.5 * ( 1 + u2 );
235         w = ( logYXs  - 1 ) * logXs;              235         w = ( logYXs  - 1 ) * logXs;
236         vLog = u * ( 1. + w * ( 1 + 0.5 * w )     236         vLog = u * ( 1. + w * ( 1 + 0.5 * w ) ); }
237     else {                                        237     else {
238         u = logYXs * ( u2 - v2 ) / ( ( 1 - log    238         u = logYXs * ( u2 - v2 ) / ( ( 1 - logYXs ) * ( v2 - 1 ) );
239         vLog = G4Pow::GetInstance()->powA( u,     239         vLog = G4Pow::GetInstance()->powA( u, logYXs );
240     }                                             240     }
241     vLin = ( u2 - u + v2 * ( u - 1 ) ) / ( u2     241     vLin = ( u2 - u + v2 * ( u - 1 ) ) / ( u2 - 1 );
242     if( std::fabs( vLog - vLin ) <= ( vLog * d    242     if( std::fabs( vLog - vLin ) <= ( vLog * desc->accuracy ) ) return( status );
243     x = x1 * u;                                   243     x = x1 * u;
244     y = y1 * vLog;                                244     y = y1 * vLog;
245     if( ( status = ptwXY_setValueAtX( desc, x,    245     if( ( status = ptwXY_setValueAtX( desc, x, y ) ) != nfu_Okay ) return( status );
246     if( ( status = ptwXY_LogLogToLinLin( desc,    246     if( ( status = ptwXY_LogLogToLinLin( desc, x1, y1, x, y, depth + 1 ) ) != nfu_Okay ) return( status );
247     return( ptwXY_LogLogToLinLin( desc, x, y,     247     return( ptwXY_LogLogToLinLin( desc, x, y, x2, y2, depth + 1 ) );
248 }                                                 248 }
249 /*                                                249 /*
250 **********************************************    250 ************************************************************
251 */                                                251 */
252 static nfu_status ptwXY_LinLogToLinLin( ptwXYP    252 static nfu_status ptwXY_LinLogToLinLin( ptwXYPoints *desc, double x1, double y1, double x2, double y2, int depth ) {
253                                                   253 
254     nfu_status status = nfu_Okay;                 254     nfu_status status = nfu_Okay;
255     double x, y, logYs = G4Log( y2 / y1 ), yLi    255     double x, y, logYs = G4Log( y2 / y1 ), yLinLin;
256                                                   256 
257     if( depth > 16 ) return( nfu_Okay );          257     if( depth > 16 ) return( nfu_Okay );
258     x = ( x2 - x1 ) / ( y2 - y1 ) * ( ( y2 - y    258     x = ( x2 - x1 ) / ( y2 - y1 ) * ( ( y2 - y1 ) / logYs - y1 ) + x1;
259     y = y1 * G4Exp( logYs / ( x2 - x1 ) * ( x     259     y = y1 * G4Exp( logYs / ( x2 - x1 ) * ( x - x1 ) );
260     yLinLin = ( y1 * ( x2 - x ) + y2 * ( x - x    260     yLinLin = ( y1 * ( x2 - x ) + y2 * ( x - x1 ) ) / ( x2 - x1 );
261     if( std::fabs( y - yLinLin ) <= ( y * desc    261     if( std::fabs( y - yLinLin ) <= ( y * desc->accuracy ) ) return( status );
262     if( ( status = ptwXY_setValueAtX( desc, x,    262     if( ( status = ptwXY_setValueAtX( desc, x, y ) ) != nfu_Okay ) return( status );
263     if( ( status = ptwXY_LinLogToLinLin( desc,    263     if( ( status = ptwXY_LinLogToLinLin( desc, x1, y1, x, y, depth + 1 ) ) != nfu_Okay ) return( status );
264     return( ptwXY_LinLogToLinLin( desc, x, y,     264     return( ptwXY_LinLogToLinLin( desc, x, y, x2, y2, depth + 1 ) );
265 }                                                 265 }
266 /*                                                266 /*
267 **********************************************    267 ************************************************************
268 */                                                268 */
269 static nfu_status ptwXY_LogLinToLinLin( ptwXYP    269 static nfu_status ptwXY_LogLinToLinLin( ptwXYPoints *desc, double x1, double y1, double x2, double y2, int depth ) {
270                                                   270 
271     nfu_status status = nfu_Okay;                 271     nfu_status status = nfu_Okay;
272     double x = std::sqrt( x2 * x1 ), y, logXs     272     double x = std::sqrt( x2 * x1 ), y, logXs = G4Log( x2 / x1 ), yLinLin;
273                                                   273 
274     if( depth > 16 ) return( nfu_Okay );          274     if( depth > 16 ) return( nfu_Okay );
275 #if 0 /* The next line is very unstable at det    275 #if 0 /* The next line is very unstable at determineing x. Initial x must be chosen better. */
276     x = ( y1 * x2 - y2 * x1 ) / ( y1 * logXs +    276     x = ( y1 * x2 - y2 * x1 ) / ( y1 * logXs + ( y2 - y1 ) * ( std::log( x / x1 ) - 1 ) );
277 #endif                                            277 #endif
278     y = ( y2 - y1 ) * G4Log( x / x1 ) / logXs     278     y = ( y2 - y1 ) * G4Log( x / x1 ) / logXs + y1;
279     yLinLin = ( y1 * ( x2 - x ) + y2 * ( x - x    279     yLinLin = ( y1 * ( x2 - x ) + y2 * ( x - x1 ) ) / ( x2 - x1 );
280     if( std::fabs( y - yLinLin ) <= ( y * desc    280     if( std::fabs( y - yLinLin ) <= ( y * desc->accuracy ) ) return( status );
281     if( ( status = ptwXY_setValueAtX( desc, x,    281     if( ( status = ptwXY_setValueAtX( desc, x, y ) ) != nfu_Okay ) return( status );
282     if( ( status = ptwXY_LogLinToLinLin( desc,    282     if( ( status = ptwXY_LogLinToLinLin( desc, x1, y1, x, y, depth + 1 ) ) != nfu_Okay ) return( status );
283     return( ptwXY_LogLinToLinLin( desc, x, y,     283     return( ptwXY_LogLinToLinLin( desc, x, y, x2, y2, depth + 1 ) );
284 }                                                 284 }
285 /*                                                285 /*
286 **********************************************    286 ************************************************************
287 */                                                287 */
288 static nfu_status ptwXY_otherToLinLin( ptwXYPo    288 static nfu_status ptwXY_otherToLinLin( ptwXYPoints *desc, double x1, double y1, double x2, double y2, int depth ) {
289                                                   289 
290     nfu_status status;                            290     nfu_status status;
291     double x = 0.5 * ( x1 + x2 ), y, yLinLin;     291     double x = 0.5 * ( x1 + x2 ), y, yLinLin;
292     ptwXY_getValue_callback getValueFunc = des    292     ptwXY_getValue_callback getValueFunc = desc->interpolationOtherInfo.getValueFunc;
293     void *argList = desc->interpolationOtherIn    293     void *argList = desc->interpolationOtherInfo.argList;
294                                                   294 
295     if( depth > 16 ) return( nfu_Okay );          295     if( depth > 16 ) return( nfu_Okay );
296     if( ( status = getValueFunc( argList, x, &    296     if( ( status = getValueFunc( argList, x, &y, x1, y1, x2, y2 ) ) != nfu_Okay ) return( status );
297     yLinLin = ( y1 * ( x2 - x ) + y2 * ( x - x    297     yLinLin = ( y1 * ( x2 - x ) + y2 * ( x - x1 ) ) / ( x2 - x1 );
298     if( std::fabs( y - yLinLin ) <= ( y * desc    298     if( std::fabs( y - yLinLin ) <= ( y * desc->accuracy ) ) return( status );
299     if( ( status = ptwXY_setValueAtX( desc, x,    299     if( ( status = ptwXY_setValueAtX( desc, x, y ) ) != nfu_Okay ) return( status );
300     if( ( status = ptwXY_otherToLinLin( desc,     300     if( ( status = ptwXY_otherToLinLin( desc, x1, y1, x, y, depth + 1 ) ) != nfu_Okay ) return( status );
301     return( ptwXY_otherToLinLin( desc, x, y, x    301     return( ptwXY_otherToLinLin( desc, x, y, x2, y2, depth + 1 ) );
302 }                                                 302 }
303 /*                                                303 /*
304 **********************************************    304 ************************************************************
305 */                                                305 */
306 ptwXYPoints *ptwXY_toUnitbase( ptwXYPoints *pt    306 ptwXYPoints *ptwXY_toUnitbase( ptwXYPoints *ptwXY, nfu_status *status ) {
307                                                   307 
308     int64_t i;                                    308     int64_t i;
309     ptwXYPoints *n;                               309     ptwXYPoints *n;
310     ptwXYPoint *p;                                310     ptwXYPoint *p;
311     double xMin, xMax, dx, inverseDx;             311     double xMin, xMax, dx, inverseDx;
312                                                   312 
313     *status = nfu_tooFewPoints;                   313     *status = nfu_tooFewPoints;
314     if( ptwXY->length < 2 ) return( NULL );       314     if( ptwXY->length < 2 ) return( NULL );
315     if( ( n = ptwXY_clone( ptwXY, status ) ) =    315     if( ( n = ptwXY_clone( ptwXY, status ) ) == NULL ) return( NULL );
316                                                   316 
317     xMin = n->points[0].x;                        317     xMin = n->points[0].x;
318     xMax = n->points[n->length-1].x;              318     xMax = n->points[n->length-1].x;
319     dx = xMax - xMin;                             319     dx = xMax - xMin;
320     inverseDx = 1. / dx;                          320     inverseDx = 1. / dx;
321     for( i = 0, p = n->points; i < n->length;     321     for( i = 0, p = n->points; i < n->length; i++, p++ ) {
322         p->x = ( p->x - xMin ) * inverseDx;       322         p->x = ( p->x - xMin ) * inverseDx;
323         p->y = p->y * dx;                         323         p->y = p->y * dx;
324     }                                             324     }
325     n->points[n->length-1].x = 1.;                325     n->points[n->length-1].x = 1.;                          /* Make sure last point is realy 1. */
326     return( n );                                  326     return( n );
327 }                                                 327 }
328 /*                                                328 /*
329 **********************************************    329 ************************************************************
330 */                                                330 */
331 ptwXYPoints *ptwXY_fromUnitbase( ptwXYPoints *    331 ptwXYPoints *ptwXY_fromUnitbase( ptwXYPoints *ptwXY, double xMin, double xMax, nfu_status *status ) {
332                                                   332 
333     int64_t i, length;                            333     int64_t i, length;
334     ptwXYPoints *n;                               334     ptwXYPoints *n;
335     ptwXYPoint *p, *p2;                           335     ptwXYPoint *p, *p2;
336     double dx, inverseDx, xLast = 0.;             336     double dx, inverseDx, xLast = 0.;
337                                                   337 
338     *status = nfu_tooFewPoints;                   338     *status = nfu_tooFewPoints;
339     if( ptwXY->length < 2 ) return( NULL );       339     if( ptwXY->length < 2 ) return( NULL );
340     if( ( n = ptwXY_clone( ptwXY, status ) ) =    340     if( ( n = ptwXY_clone( ptwXY, status ) ) == NULL ) return( NULL );
341                                                   341 
342     dx = xMax - xMin;                             342     dx = xMax - xMin;
343     inverseDx = 1. / dx;                          343     inverseDx = 1. / dx;
344     length = n->length;                           344     length = n->length;
345     for( i = 0, p2 = p = n->points; i < length    345     for( i = 0, p2 = p = n->points; i < length; ++i, ++p ) {
346         p2->x = p->x * dx + xMin;                 346         p2->x = p->x * dx + xMin;
347         if( i > 0 ) {                             347         if( i > 0 ) {
348             if( std::fabs( p2->x - xLast ) <=     348             if( std::fabs( p2->x - xLast ) <= 10. * DBL_EPSILON * ( std::fabs( p2->x ) + std::fabs( xLast ) ) ) {
349                 --(n->length);                    349                 --(n->length);
350                 continue;                         350                 continue;
351             }                                     351             }
352         }                                         352         }
353         p2->y = p->y * inverseDx;                 353         p2->y = p->y * inverseDx;
354         xLast = p2->x;                            354         xLast = p2->x;
355         ++p2;                                     355         ++p2;
356     }                                             356     }
357     n->points[n->length-1].x = xMax;              357     n->points[n->length-1].x = xMax;                          /* Make sure last point is realy xMax. */
358     return( n );                                  358     return( n );
359 }                                                 359 }
360 /*                                                360 /*
361 **********************************************    361 ************************************************************
362 */                                                362 */
363 ptwXYPoints *ptwXY_unitbaseInterpolate( double    363 ptwXYPoints *ptwXY_unitbaseInterpolate( double w, double w1, ptwXYPoints *ptwXY1, double w2, ptwXYPoints *ptwXY2, nfu_status *status ) {
364 /*                                                364 /* 
365 *   Should we not be checking the interpolatio    365 *   Should we not be checking the interpolation members???????
366 */                                                366 */
367     int64_t i;                                    367     int64_t i;
368     ptwXYPoints *n1 = NULL, *n2 = NULL, *a = N    368     ptwXYPoints *n1 = NULL, *n2 = NULL, *a = NULL, *r = NULL;
369     ptwXYPoint *p;                                369     ptwXYPoint *p;
370     double f, g, xMin, xMax;                      370     double f, g, xMin, xMax;
371                                                   371 
372     *status = nfu_XOutsideDomain;                 372     *status = nfu_XOutsideDomain;
373     if( w <= w1 ) {                               373     if( w <= w1 ) {
374         if( w < w1 ) return( NULL );              374         if( w < w1 ) return( NULL );
375         return( ptwXY_clone( ptwXY1, status )     375         return( ptwXY_clone( ptwXY1, status ) );
376     }                                             376     }
377     if( w >= w2 ) {                               377     if( w >= w2 ) {
378         if( w > w2 ) return( NULL );              378         if( w > w2 ) return( NULL );
379         return( ptwXY_clone( ptwXY2, status )     379         return( ptwXY_clone( ptwXY2, status ) );
380     }                                             380     }
381     if( ( n1 = ptwXY_toUnitbase( ptwXY1, statu    381     if( ( n1 = ptwXY_toUnitbase( ptwXY1, status ) ) == NULL ) return( NULL );
382     if( ( n2 = ptwXY_toUnitbase( ptwXY2, statu    382     if( ( n2 = ptwXY_toUnitbase( ptwXY2, status ) ) == NULL ) goto Err;
383     f = ( w - w1 ) / ( w2 - w1 );                 383     f = ( w - w1 ) / ( w2 - w1 );
384     g = 1. - f;                                   384     g = 1. - f;
385     for( i = 0, p = n1->points; i < n1->length    385     for( i = 0, p = n1->points; i < n1->length; i++, p++ ) p->y *= g;
386     for( i = 0, p = n2->points; i < n2->length    386     for( i = 0, p = n2->points; i < n2->length; i++, p++ ) p->y *= f;
387     if( ( a = ptwXY_add_ptwXY( n1, n2, status     387     if( ( a = ptwXY_add_ptwXY( n1, n2, status ) ) == NULL ) goto Err;
388                                                   388 
389     xMin = g * ptwXY1->points[0].x + f * ptwXY    389     xMin = g * ptwXY1->points[0].x + f * ptwXY2->points[0].x;
390     xMax = g * ptwXY1->points[ptwXY1->length-1    390     xMax = g * ptwXY1->points[ptwXY1->length-1].x + f * ptwXY2->points[ptwXY2->length-1].x;
391     if( ( r = ptwXY_fromUnitbase( a, xMin, xMa    391     if( ( r = ptwXY_fromUnitbase( a, xMin, xMax, status ) ) == NULL ) goto Err;
392     ptwXY_free( n1 );                             392     ptwXY_free( n1 );
393     ptwXY_free( n2 );                             393     ptwXY_free( n2 );
394     ptwXY_free( a );                              394     ptwXY_free( a );
395     return( r );                                  395     return( r );
396                                                   396 
397 Err:                                              397 Err:
398     if( n1 != NULL ) ptwXY_free( n1 );            398     if( n1 != NULL ) ptwXY_free( n1 );
399     if( n2 != NULL ) ptwXY_free( n2 );            399     if( n2 != NULL ) ptwXY_free( n2 );
400     if( a  != NULL ) ptwXY_free( a );             400     if( a  != NULL ) ptwXY_free( a );
401     return( NULL );                               401     return( NULL );
402 }                                                 402 }
403                                                   403 
404 #if defined __cplusplus                           404 #if defined __cplusplus
405 }                                                 405 }
406 #endif                                            406 #endif
407                                                   407