ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ptwX_core.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ptwX_core.cc
1 /*
2 # <<BEGIN-copyright>>
3 # <<END-copyright>>
4 */
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <cmath>
9 #include <cstdlib> //for std::abs(int)
10 #include <float.h>
11 
12 #include "ptwX.h"
13 
14 #if defined __cplusplus
15 namespace GIDI {
16 using namespace GIDI;
17 #endif
18 
19 static int ptwX_sort_descending( void const *p1, void const *p2 );
20 static int ptwX_sort_ascending( void const *p1, void const *p2 );
21 /*
22 ************************************************************
23 */
24 ptwXPoints *ptwX_new( int64_t size, nfu_status *status ) {
25 
26  ptwXPoints *ptwX = (ptwXPoints *) nfu_calloc( sizeof( ptwXPoints ), 1 );
27 
28  *status = nfu_mallocError;
29  if( ptwX == NULL ) return( NULL );
30  ptwX_setup( ptwX, size );
31  if( ( *status = ptwX->status ) != nfu_Okay ) ptwX = (ptwXPoints *) nfu_free( ptwX );
32  return( ptwX );
33 }
34 /*
35 ************************************************************
36 */
37 nfu_status ptwX_setup( ptwXPoints *ptwX, int64_t size ) {
38 
39  ptwX->status = nfu_Okay;
40  ptwX->length = 0;
41  ptwX->allocatedSize = 0;
42  ptwX->mallocFailedSize = 0;
43  ptwX->points = NULL;
44  ptwX_reallocatePoints( ptwX, size, 0 );
45  return( ptwX->status );
46 }
47 /*
48 ************************************************************
49 */
50 ptwXPoints *ptwX_create( int64_t size, int64_t length, double const *xs, nfu_status *status ) {
51 
52  ptwXPoints *ptwX = ptwX_new( size, status );
53 
54  if( ptwX != NULL ) {
55  if( ( *status = ptwX_setData( ptwX, length, xs ) ) != nfu_Okay ) ptwX = ptwX_free( ptwX );
56  }
57  return( ptwX );
58 }
59 /*
60 ************************************************************
61 */
62 ptwXPoints *ptwX_createLine( int64_t size, int64_t length, double slope, double offset, nfu_status *status ) {
63 
64  int64_t i1;
65  double *p1;
66  ptwXPoints *ptwX;
67 
68  if( size < length ) size = length;
69  if( ( ptwX = ptwX_new( size, status ) ) != NULL ) {
70  for( i1 = 0, p1 = ptwX->points; i1 < length; i1++, p1++ ) *p1 = slope * i1 + offset;
71  ptwX->length = length;
72  }
73  return( ptwX );
74 }
75 /*
76 ************************************************************
77 */
79 
80  if( dest->status == nfu_Okay ) return( dest->status );
81  if( src->status == nfu_Okay ) return( src->status );
82  ptwX_clear( dest );
83  return( ptwX_setData( dest, src->length, src->points ) );
84 }
85 /*
86 ************************************************************
87 */
89 
90  return( ptwX_slice( ptwX, 0, ptwX->length, status ) );
91 }
92 /*
93 ************************************************************
94 */
95 ptwXPoints *ptwX_slice( ptwXPoints *ptwX, int64_t index1, int64_t index2, nfu_status *status ) {
96 
97  int64_t i, j, length;
98  ptwXPoints *n;
99 
100  *status = nfu_badSelf;
101  if( ptwX->status != nfu_Okay ) return( NULL );
102  *status = nfu_badIndex;
103  if( index1 < 0 ) return( NULL );
104  if( index2 < index1 ) return( NULL );
105  if( index2 > ptwX->length ) return( NULL );
106  length = ( index2 - index1 );
107  if( ( n = ptwX_new( length, status ) ) == NULL ) return( n );
108  *status = n->status;
109  for( j = 0, i = index1; i < index2; i++, j++ ) n->points[j] = ptwX->points[i];
110  n->length = length;
111  return( n );
112 }
113 /*
114 ************************************************************
115 */
116 nfu_status ptwX_reallocatePoints( ptwXPoints *ptwX, int64_t size, int forceSmallerResize ) {
117 
118  if( size < ptwX_minimumSize ) size = ptwX_minimumSize; /* ptwX_minimumSize must be > 0 for other routines to work properly. */
119  if( size < ptwX->length ) size = ptwX->length;
120  if( size != ptwX->allocatedSize ) {
121  if( size > ptwX->allocatedSize ) { /* Increase size of allocated points. */
122  ptwX->points = (double *) nfu_realloc( (size_t) size * sizeof( double ), ptwX->points ); }
123  else if( ( ptwX->allocatedSize > 2 * size ) || forceSmallerResize ) { /* Decrease size, if at least 1/2 size reduction or if forced to. */
124  ptwX->points = (double *) nfu_realloc( (size_t) size * sizeof( double ), ptwX->points );
125  }
126  if( ptwX->points == NULL ) {
127  ptwX->mallocFailedSize = size;
128  size = 0;
129  ptwX->status = nfu_mallocError;
130  }
131  ptwX->allocatedSize = size;
132  }
133 
134  return( ptwX->status );
135 }
136 /*
137 ************************************************************
138 */
140 
141  ptwX->length = 0;
142  return( ptwX->status );
143 }
144 /*
145 ************************************************************
146 */
148 
149  ptwX->length = 0;
150  ptwX->allocatedSize = 0;
151  ptwX->points = (double *) nfu_free( ptwX->points );
152 
153  return( nfu_Okay );
154 }
155 /*
156 ************************************************************
157 */
159 
160  if( ptwX != NULL ) ptwX_release( ptwX );
161  return( (ptwXPoints *) nfu_free( ptwX ) );
162 }
163 /*
164 ************************************************************
165 */
166 int64_t ptwX_length( ptwXPoints *ptwX ) {
167 
168  return( ptwX->length );
169 }
170 /*
171 ************************************************************
172 */
173 nfu_status ptwX_setData( ptwXPoints *ptwX, int64_t length, double const *xs ) {
174 
175  int64_t i;
176 
177  if( ptwX->status != nfu_Okay ) return( ptwX->status );
178 
179  if( length > ptwX->allocatedSize ) {
180  ptwX_reallocatePoints( ptwX, length, 0 );
181  if( ptwX->status != nfu_Okay ) return( ptwX->status );
182  }
183  for( i = 0; i < length; i++ ) ptwX->points[i] = xs[i];
184  ptwX->length = length;
185 
186  return( ptwX->status );
187 }
188 /*
189 ************************************************************
190 */
191 nfu_status ptwX_deletePoints( ptwXPoints *ptwX, int64_t i1, int64_t i2 ) {
192 
193  int64_t n = ptwX->length - ( i2 - i1 );
194 
195  if( ptwX->status != nfu_Okay ) return( ptwX->status );
196  if( ( i1 < 0 ) || ( i1 > i2 ) || ( i2 > ptwX->length ) ) return( nfu_badIndex );
197  if( i1 != i2 ) {
198  for( ; i2 < ptwX->length; i1++, i2++ ) ptwX->points[i1] = ptwX->points[i2];
199  ptwX->length = n;
200  }
201  return( ptwX->status );
202 }
203 /*
204 ************************************************************
205 */
206 double *ptwX_getPointAtIndex( ptwXPoints *ptwX, int64_t index ) {
207 
208  if( ptwX->status != nfu_Okay ) return( NULL );
209  if( ( index < 0 ) || ( index >= ptwX->length ) ) return( NULL );
210  return( &(ptwX->points[index]) );
211 }
212 /*
213 ************************************************************
214 */
215 double ptwX_getPointAtIndex_Unsafely( ptwXPoints *ptwX, int64_t index ) {
216 
217  return( ptwX->points[index] );
218 }
219 /*
220 ************************************************************
221 */
222 nfu_status ptwX_setPointAtIndex( ptwXPoints *ptwX, int64_t index, double x ) {
223 
224  nfu_status status;
225 
226  if( ptwX->status != nfu_Okay ) return( ptwX->status );
227  if( ( index < 0 ) || ( index > ptwX->length ) ) return( nfu_badIndex );
228  if( index == ptwX->allocatedSize ) {
229  if( ( status = ptwX_reallocatePoints( ptwX, ptwX->allocatedSize + 10, 0 ) ) != nfu_Okay ) return( status );
230  }
231  ptwX->points[index] = x;
232  if( index == ptwX->length ) ptwX->length++;
233  return( nfu_Okay );
234 }
235 /*
236 ************************************************************
237 */
238 nfu_status ptwX_insertPointsAtIndex( ptwXPoints *ptwX, int64_t index, int64_t n1, double const *xs ) {
239 
240  nfu_status status;
241  int64_t i1, i2, n1p, size = n1 + ptwX->length;
242 
243  if( ptwX->status != nfu_Okay ) return( ptwX->status );
244  if( n1 < 1 ) return( nfu_Okay );
245  if( ( index < 0 ) || ( index > ptwX->length ) ) return( nfu_badIndex );
246  if( size > ptwX->allocatedSize ) {
247  if( ( status = ptwX_reallocatePoints( ptwX, size, 0 ) ) != nfu_Okay ) return( status );
248  }
249  for( i1 = ptwX->length - 1, i2 = size - 1, n1p = ptwX->length - index + 1; n1p > 0; i1--, i2--, n1p-- ) ptwX->points[i2] = ptwX->points[i1];
250  for( i1 = 0, i2 = index; i1 < n1; i1++, i2++ ) ptwX->points[i2] = xs[i1];
251  ptwX->length += n1;
252  return( nfu_Okay );
253 }
254 /*
255 ************************************************************
256 */
258 /*
259 * Returns -1 list is descending, 1 if ascending and 0 otherwise (i.e., mixed).
260 */
261  int order = 1;
262  int64_t i;
263  double x1, x2;
264 
265  if( ptwX->length < 2 ) return( 0 );
266 
267  if( ( x1 = ptwX->points[0] ) < ( x2 = ptwX->points[1] ) ) { /* Check for ascending order. */
268  for( i = 2; i < ptwX->length; i++ ) {
269  x1 = x2;
270  x2 = ptwX->points[i];
271  if( x2 <= x1 ) return( 0 );
272  } }
273  else {
274  if( x1 == x2 ) return( 0 );
275  order = -1; /* Check for descending order. */
276  for( i = 2; i < ptwX->length; i++ ) {
277  x1 = x2;
278  x2 = ptwX->points[i];
279  if( x1 <= x2 ) return( 0 );
280  }
281  }
282  return( order );
283 }
284 /*
285 ************************************************************
286 */
287 ptwXPoints *ptwX_fromString( char const *str, char **endCharacter, nfu_status *status ) {
288 
289  int64_t numberConverted;
290  double *doublePtr;
291  ptwXPoints *ptwX = NULL;
292 
293  if( ( *status = nfu_stringToListOfDoubles( str, &numberConverted, &doublePtr, endCharacter ) ) != nfu_Okay ) return( NULL );
294  ptwX = ptwX_create( numberConverted, numberConverted, doublePtr, status );
295  nfu_free( doublePtr );
296  return( ptwX );
297 }
298 /*
299 ************************************************************
300 */
301 nfu_status ptwX_countOccurrences( ptwXPoints *ptwX, double value, int *count ) {
302 
303  int64_t i1;
304 
305  *count = 0;
306  for( i1 = 0; i1 < ptwX->length; i1++ ) {
307  if( ptwX->points[i1] == value ) (*count)++;
308  }
309  return( nfu_Okay );
310 }
311 /*
312 ************************************************************
313 */
315 
316  int64_t i1, i2 = ptwX->length - 1, n1 = ptwX->length / 2;
317  double tmp;
318 
319  for( i1 = 0; i1 < n1; i1++, i2-- ) {
320  tmp = ptwX->points[i1];
321  ptwX->points[i1] = ptwX->points[i2];
322  ptwX->points[i2] = tmp;
323  }
324  return( nfu_Okay );
325 }
326 /*
327 ************************************************************
328 */
330 
331  int (*cmp)( void const *, void const * ) = ptwX_sort_descending;
332 
333  if( order == ptwX_sort_order_ascending ) cmp = ptwX_sort_ascending;
334  qsort( ptwX->points, (size_t) ptwX->length, sizeof( ptwX->points[0] ), cmp );
335  return( nfu_Okay );
336 }
337 /*
338 ************************************************************
339 */
340 static int ptwX_sort_descending( void const *p1, void const *p2 ) { return( -ptwX_sort_ascending( p1, p2 ) ); }
341 static int ptwX_sort_ascending( void const *p1, void const *p2 ) {
342 
343  double *d1 = (double *) p1, *d2 = (double *) p2;
344 
345  if( *d1 < *d2 ) return( -1 );
346  if( *d1 == *d2 ) return( 0 );
347  return( 1 );
348 }
349 /*
350 ************************************************************
351 */
352 nfu_status ptwX_closesDifference( ptwXPoints *ptwX, double value, int64_t *index, double *difference ) {
353 
354  return( ptwX_closesDifferenceInRange( ptwX, 0, ptwX->length, value, index, difference ) );
355 }
356 /*
357 ************************************************************
358 */
359 nfu_status ptwX_closesDifferenceInRange( ptwXPoints *ptwX, int64_t i1, int64_t i2, double value, int64_t *index, double *difference ) {
360 /*
361 * Finds the closes datum to value. If *difference is zero, datum is same as value.
362 */
363  double d1;
364 
365  *index = -1;
366  *difference = -1;
367  if( ptwX->status != nfu_Okay ) return( ptwX->status );
368  if( i1 < 0 ) i1 = 0;
369  if( i2 > ptwX->length ) i2 = ptwX->length;
370  if( i1 >= i2 ) return( nfu_Okay );
371  *index = i1;
372  *difference = value - ptwX->points[i1];
373  for( i1++; i1 < i2; i1++ ) {
374  d1 = value - ptwX->points[i1];
375  if( std::fabs( *difference ) > std::fabs( d1 ) ) {
376  *index = i1;
377  *difference = d1;
378  }
379  }
380  return( nfu_Okay );
381 }
382 /*
383 ************************************************************
384 */
385 ptwXPoints *ptwX_unique( ptwXPoints *ptwX, int order, nfu_status *status ) {
386 /*
387 * If order < 0 order is descending, if order > 0 order is ascending, otherwise, order is the same as ptwX.
388 */
389  int64_t i1, i2, n1 = 0;
390  double x1, *p2;
391  ptwXPoints *ptwX2 = NULL;
392 
393  if( order == 0 ) {
394  if( ( ptwX2 = ptwX_new( ptwX->length, status ) ) == NULL ) return( NULL );
395  for( i1 = 0; i1 < ptwX->length; i1++ ) {
396  x1 = ptwX->points[i1];
397  for( i2 = 0, p2 = ptwX2->points; i2 < ptwX2->length; i2++, p2++ ) {
398  if( *p2 == x1 ) break;
399  }
400  if( i2 == ptwX2->length ) {
401  ptwX2->points[ptwX2->length] = x1;
402  ptwX2->length++;
403  }
404  } }
405  else {
406  if( ( ptwX2 = ptwX_clone( ptwX, status ) ) == NULL ) return( NULL );
407  if( ( *status = ptwX_sort( ptwX2, ptwX_sort_order_ascending ) ) != nfu_Okay ) goto err;
408 
409  if( ptwX2->length > 1 ) {
410  x1 = ptwX2->points[n1];
411  n1++;
412  for( i1 = 1; i1 < ptwX2->length; i1++ ) {
413  if( x1 != ptwX2->points[i1] ) {
414  x1 = ptwX2->points[i1];
415  ptwX2->points[n1] = x1;
416  n1++;
417  }
418  }
419  ptwX2->length = n1;
420  if( order < 0 ) {
421  if( ( *status = ptwX_sort( ptwX2, ptwX_sort_order_descending ) ) != nfu_Okay ) goto err;
422  }
423  }
424  }
425  return( ptwX2 );
426 
427 err:
428  if( ptwX2 != NULL ) ptwX_free( ptwX2 );
429  return( NULL );
430 }
431 /*
432 ************************************************************
433 */
435 
436  int64_t i1;
437  double *p1;
438 
439  if( ptwX->status != nfu_Okay ) return( ptwX->status );
440  for( i1 = 0, p1 = ptwX->points; i1 < ptwX->length; i1++, p1++ ) *p1 = std::fabs( *p1 );
441  return( nfu_Okay );
442 }
443 /*
444 ************************************************************
445 */
447 
448  return( ptwX_slopeOffset( ptwX, -1, 0 ) );
449 }
450 /*
451 ************************************************************
452 */
454 
455  return( ptwX_slopeOffset( ptwX, 1, value ) );
456 }
457 /*
458 ************************************************************
459 */
461 
462  return( ptwX_slopeOffset( ptwX, value, 0 ) );
463 }
464 /*
465 ************************************************************
466 */
467 nfu_status ptwX_slopeOffset( ptwXPoints *ptwX, double slope, double offset ) {
468 
469  int64_t i1;
470  double *p1;
471 
472  if( ptwX->status != nfu_Okay ) return( ptwX->status );
473  for( i1 = 0, p1 = ptwX->points; i1 < ptwX->length; i1++, p1++ ) *p1 = slope * *p1 + offset;
474  return( nfu_Okay );
475 }
476 /*
477 ************************************************************
478 */
480 
481  int64_t i1;
482  double *p1 = ptwX1->points, *p2 = ptwX2->points;
483 
484  if( ptwX1->status != nfu_Okay ) return( ptwX1->status );
485  if( ptwX2->status != nfu_Okay ) return( ptwX2->status );
486  if( ptwX1->length != ptwX2->length ) return( nfu_domainsNotMutual );
487 
488  for( i1 = 0; i1 < ptwX1->length; i1++, p1++, p2++ ) *p1 += *p2;
489  return( nfu_Okay );
490 }
491 /*
492 ************************************************************
493 */
495 
496  int64_t i1;
497  double *p1 = ptwX1->points, *p2 = ptwX2->points;
498 
499  if( ptwX1->status != nfu_Okay ) return( ptwX1->status );
500  if( ptwX2->status != nfu_Okay ) return( ptwX2->status );
501  if( ptwX1->length != ptwX2->length ) return( nfu_domainsNotMutual );
502 
503  for( i1 = 0; i1 < ptwX1->length; i1++, p1++, p2++ ) *p1 -= *p2;
504  return( nfu_Okay );
505 }
506 /*
507 ************************************************************
508 */
509 nfu_status ptwX_xMinMax( ptwXPoints *ptwX, double *xMin, double *xMax ) {
510 
511  int64_t i1, n1 = ptwX->length;
512  *xMin = *xMax = 0;
513  double *p1 = ptwX->points;
514 
515  if( ptwX->status != nfu_Okay ) return( ptwX->status );
516  if( n1 > 0 ) {
517  *xMin = *xMax = *(p1++);
518  for( i1 = 1; i1 < n1; ++i1, ++p1 ) {
519  if( *p1 < *xMin ) *xMin = *p1;
520  if( *p1 > *xMax ) *xMax = *p1;
521  }
522  }
523  return( nfu_Okay );
524 }
525 /*
526 ************************************************************
527 */
528 nfu_status ptwX_compare( ptwXPoints *ptwX1, ptwXPoints *ptwX2, int *comparison ) {
529 
530  int64_t i1, n1 = ptwX1->length, n2 = ptwX2->length, nn = n1;
531  double *p1 = ptwX1->points, *p2 = ptwX2->points;
532 
533  *comparison = 0;
534  if( ptwX1->status != nfu_Okay ) return( ptwX1->status );
535  if( ptwX2->status != nfu_Okay ) return( ptwX2->status );
536  if( nn > n2 ) nn = n2;
537  for( i1 = 0; i1 < nn; i1++, p1++, p2++ ) {
538  if( *p1 == *p2 ) continue;
539  *comparison = 1;
540  if( *p1 < *p2 ) *comparison = -1;
541  return( nfu_Okay );
542  }
543  if( n1 < n2 ) {
544  *comparison = -1; }
545  else if( n1 > n2 ) {
546  *comparison = 1;
547  }
548  return( nfu_Okay );
549 }
550 /*
551 ************************************************************
552 */
553 int ptwX_close( ptwXPoints *ptwX1, ptwXPoints *ptwX2, int epsilonFactor, double epsilon, nfu_status *status ) {
554 
555  int64_t i1, n1 = ptwX1->length;
556  double larger;
557  double *p1 = ptwX1->points, *p2 = ptwX2->points;
558 
559  epsilon = std::fabs( epsilon ) + std::abs( epsilonFactor ) * DBL_EPSILON;
560 
561  *status = ptwX1->status;
562  if( ptwX1->status != nfu_Okay ) return( -1 );
563  *status = ptwX2->status;
564  if( ptwX2->status != nfu_Okay ) return( -1 );
565  *status = nfu_domainsNotMutual;
566  if( n1 != ptwX2->length ) return( -1 );
567 
568  *status = nfu_Okay;
569  for( i1 = 0; i1 < n1; i1++, p1++, p2++ ) {
570  larger = std::fabs( *p1 );
571  if( std::fabs( *p2 ) > larger ) larger = std::fabs( *p2 );
572  if( std::fabs( *p2 - *p1 ) > epsilon * larger ) return( (int) ( i1 + 1 ) );
573  }
574  return( 0 );
575 }
576 
577 #if defined __cplusplus
578 }
579 #endif