Geant4  10.02.p02
nf_stringToDoubles.cc
Go to the documentation of this file.
1 /*
2 # <<BEGIN-copyright>>
3 # <<END-copyright>>
4 */
5 
6 #include <stdlib.h>
7 #include <cmath>
8 
9 #include "nf_utilities.h"
10 
11 #ifdef WIN32
12  #include <float.h>
13  #define isfinite _finite
14 #else
15  #define isfinite std::isfinite
16 #endif
17 
18 #if defined __cplusplus
19 namespace GIDI {
20 using namespace GIDI;
21 #endif
22 
23 #define numberOfStaticDoubles ( 100 * 1000 )
24 
25 static nfu_status nfu_stringToListOfDoubles2( char const *str, int64_t *numberConverted, double **doublePtr, char **endCharacter );
26 /*
27 ========================================================================
28 */
29 nfu_status nfu_stringToListOfDoubles( char const *str, int64_t *numberConverted, double **doublePtr, char **endCharacter ) {
30 
31  *numberConverted = 0;
32  *doublePtr = NULL;
33  return( nfu_stringToListOfDoubles2( str, numberConverted, doublePtr, endCharacter ) );
34 }
35 /*
36 ========================================================================
37 */
38 static nfu_status nfu_stringToListOfDoubles2( char const *str, int64_t *numberConverted, double **doublePtr, char **endCharacter ) {
39 
40  int64_t i1, i2, numberConverted_initial = *numberConverted;
41  double staticDoubles[numberOfStaticDoubles];
42  nfu_status status = nfu_Okay;
43 
44  for( i1 = 0; i1 < numberOfStaticDoubles; i1++, (*numberConverted)++ ) {
45  staticDoubles[i1] = strtod( str, endCharacter );
46  if( str == (char const *) *endCharacter ) {
47  if( *numberConverted > 0 ) {
48  if( ( *doublePtr = (double *) nfu_malloc( (size_t) *numberConverted * sizeof( double ) ) ) == NULL ) status = nfu_mallocError;
49  }
50  break;
51  }
52  str = (char const *) *endCharacter;
53  }
54 
55  if( ( status == nfu_Okay ) && ( *doublePtr == NULL ) ) status = nfu_stringToListOfDoubles2( str, numberConverted, doublePtr, endCharacter );
56  if( *doublePtr != NULL ) {
57  double *doublePtr2 = &((*doublePtr)[numberConverted_initial]);
58 
59  for( i2 = 0; i2 < i1; i2++, doublePtr2++ ) *doublePtr2 = staticDoubles[i2];
60  }
61  return( status );
62 }
63 /*
64 ============================================================
65 */
66 char *nf_floatToShortestString( double value, int significantDigits, int favorEFormBy, int flags ) {
67 
68  int n1, ne, nf, digitsRightOfPeriod_f, exponent;
69  char Str_e[512], Str_f[512], *Str_r = Str_e, Fmt[32], *e1, *e2;
70  const char *sign = "";
71 
72  if( flags & nf_floatToShortestString_includeSign ) sign = "+";
73 
74  if( !isfinite( value ) ) {
75  sprintf( Fmt, "%%%sf", sign );
76  sprintf( Str_e, Fmt, value );
77  return( strdup( Str_e ) );
78  }
79 
80  significantDigits--;
81  if( significantDigits < 0 ) significantDigits = 0;
82  if( significantDigits > 24 ) significantDigits = 24;
83 
84  sprintf( Fmt, "%%%s.%de", sign, significantDigits );
85  sprintf( Str_e, Fmt, value );
86 
87  e1 = strchr( Str_e, 'e' );
88  if( significantDigits == 0 ) {
89  if( *(e1 - 1) != '.' ) {
90  char *e3;
91 
92  e2 = strchr( e1, 0 );
93  e3 = e2 + 1;
94  for( ; e2 != e1; e2--, e3-- ) *e3 = *e2;
95  *(e1++) = '.';
96  }
97  }
98  *e1 = 0;
99  n1 = (int) strlen( Str_e ) - 1;
100  if( flags & nf_floatToShortestString_trimZeros ) while( Str_e[n1] == '0' ) n1--; // Loop checking, 11.06.2015, T. Koi
101  ne = flags & nf_floatToShortestString_keepPeriod;
102  if( !( flags & nf_floatToShortestString_keepPeriod ) ) if( Str_e[n1] == '.' ) n1--;
103  n1++;
104  Str_e[n1] = 0;
105 
106  e1++;
107  exponent = (int) strtol( e1, &e2, 10 );
108  if( exponent != 0 ) { /* If 0, the exponent was "e+00". */
109  for( e1 = Str_e; *e1 != 0; e1++ ) ;
110  sprintf( e1, "e%d", exponent );
111 
112  digitsRightOfPeriod_f = significantDigits - exponent;
113  if( ( digitsRightOfPeriod_f > 25 ) || ( exponent > 50 ) ) return( strdup( Str_r ) );
114  if( digitsRightOfPeriod_f < 0 ) digitsRightOfPeriod_f = 0;
115 
116  sprintf( Fmt, "%%%s.%df", sign, digitsRightOfPeriod_f );
117  sprintf( Str_f, Fmt, value );
118 
119  ne = (int) strlen( Str_e );
120  nf = (int) strlen( Str_f );
121  if( strchr( Str_f, '.' ) != NULL ) { /* '.' in string. */
122  if( flags & nf_floatToShortestString_trimZeros ) while( Str_f[nf-1] == '0' ) nf--; // Loop checking, 11.06.2015, T. Koi
123  if( Str_f[nf-1] == '.' ) {
124  if( !( flags & nf_floatToShortestString_keepPeriod ) ) nf--;
125  } }
126  else { /* Maybe we want a '.' else it looks like an integer, "12345." vs "12345". */
127  if( flags & nf_floatToShortestString_keepPeriod ) {
128  Str_f[nf] = '.';
129  nf++;
130  }
131  }
132  Str_f[nf] = 0;
133 
134  if( ( nf + favorEFormBy ) < ne ) Str_r = Str_f;
135  }
136  return( strdup( Str_r ) );
137 }
138 
139 #if defined __cplusplus
140 }
141 #endif
#define numberOfStaticDoubles
static const G4double e2
nfu_status nfu_stringToListOfDoubles(char const *str, int64_t *numberConverted, double **doublePtr, char **endCharacter)
char * nf_floatToShortestString(double value, int significantDigits, int favorEFormBy, int flags)
#define isfinite
static const G4double e1
static nfu_status nfu_stringToListOfDoubles2(char const *str, int64_t *numberConverted, double **doublePtr, char **endCharacter)
static const G4double e3
G4int sign(const T t)
A simple sign function that allows us to port fortran code to c++ more easily.
void * nfu_malloc(size_t size)