fix8  version 1.4.0
Open Source C++ FIX Framework
modp_numtoa.c File Reference
#include <stdint.h>
#include <stdio.h>
#include <math.h>
#include <fix8/f8dll.h>

Go to the source code of this file.

Functions

static void strreverse (char *begin, char *end)
 
F8API size_t modp_dtoa (double value, char *str, int prec)
 Convert double to ascii. More...
 

Variables

static const double pow10_ []
 

Function Documentation

F8API size_t modp_dtoa ( double  value,
char *  str,
int  prec 
)

Convert double to ascii.

Parameters
valuethe source value
strthe target string
precnumber of precision digits

Definition at line 68 of file modp_numtoa.c.

References pow10_, and strreverse().

Referenced by FIX8::Field< fp_type, field >::print().

69 {
70  /* if input is larger than thres_max, revert to exponential */
71  const double thres_max = (double)(0x7FFFFFFF);
72 
73  double diff = 0.0;
74  char* wstr = str;
75  int neg = 0;
76  int whole = 0;
77  double tmp = 0.0;
78  uint32_t frac = 0;
79 
80  /* Hacky test for NaN
81  * under -fast-math this won't work, but then you also won't
82  * have correct nan values anyways. The alternative is
83  * to link with libmath (bad) or hack IEEE double bits (bad)
84  */
85  if (! (value == value)) {
86  str[0] = 'n'; str[1] = 'a'; str[2] = 'n'; str[3] = '\0';
87  return 3; // DD
88  }
89 
90  if (prec < 0) {
91  prec = 0;
92  } else if (prec > 9) {
93  /* precision of >= 10 can lead to overflow errors */
94  prec = 9;
95  }
96 
97 
98  /* we'll work in positive values and deal with the
99  negative sign issue later */
100  if (value < 0) {
101  neg = 1;
102  value = -value;
103  }
104 
105  whole = (int) value;
106  tmp = (value - whole) * pow10_[prec];
107  frac = (uint32_t)(tmp);
108  diff = tmp - frac;
109 
110  if (diff > 0.5) {
111  ++frac;
112  /* handle rollover, e.g. case 0.99 with prec 1 is 1.0 */
113  if (frac >= pow10_[prec]) {
114  frac = 0;
115  ++whole;
116  }
117  } else if (diff == 0.5 && ((frac == 0) || (frac & 1))) {
118  /* if halfway, round up if odd, OR
119  if last digit is 0. That last part is strange */
120  ++frac;
121  }
122 
123  /* for very large numbers switch back to native sprintf for exponentials.
124  anyone want to write code to replace this? */
125  /*
126  normal printf behavior is to print EVERY whole number digit
127  which can be 100s of characters overflowing your buffers == bad
128  */
129  if (value > thres_max)
130  return sprintf(str, "%e", neg ? -value : value); // DD
131 
132  if (prec == 0) {
133  diff = value - whole;
134  if (diff > 0.5) {
135  /* greater than 0.5, round up, e.g. 1.6 -> 2 */
136  ++whole;
137  } else if (diff == 0.5 && (whole & 1)) {
138  /* exactly 0.5 and ODD, then round up */
139  /* 1.5 -> 2, but 2.5 -> 2 */
140  ++whole;
141  }
142  } else { // these mods DD: remove trailing zero in prec (unless there is only one 0)
143  int count = prec, done = 0;
144  // now do fractional part, as an unsigned number
145  do
146  {
147  --count;
148  if (frac % 10)
149  done += (*wstr++ = (char)(48 + (frac % 10)));
150  else if (done)
151  *wstr++ = '0';
152  }
153  while (frac /= 10);
154  // add extra 0s
155  if (!done)
156  *wstr++ = '0';
157  else
158  while (count-- > 0)
159  *wstr++ = '0';
160  // add decimal
161  *wstr++ = '.';
162  }
163 
164  // do whole part
165  // Take care of sign
166  // Conversion. Number is reversed.
167  do
168  *wstr++ = (char)(48 + (whole % 10));
169  while (whole /= 10);
170  if (neg)
171  *wstr++ = '-';
172  *wstr = 0;
173  strreverse(str, wstr-1);
174  return wstr - str; // DD
175 }
static void strreverse(char *begin, char *end)
Definition: modp_numtoa.c:60
static const double pow10_[]
Definition: modp_numtoa.c:57
static void strreverse ( char *  begin,
char *  end 
)
static

Definition at line 60 of file modp_numtoa.c.

Referenced by modp_dtoa().

61 {
62  char aux;
63  while (end > begin)
64  aux = *end, *end-- = *begin, *begin++ = aux;
65 }

Variable Documentation

const double pow10_[]
static
Initial value:
= {1, 10, 100, 1000, 10000, 100000, 1000000,
10000000, 100000000, 1000000000}

Powers of 10 10^0 to 10^9

Definition at line 57 of file modp_numtoa.c.

Referenced by modp_dtoa().