ReactOS 0.4.16-dev-853-g88d9285
cfout.cpp
Go to the documentation of this file.
1//
2// cfout.cpp
3//
4// Copyright (c) Microsoft Corporation. All rights reserved.
5//
6// Floating point binary to decimal conversion routines
7//
10#include <fenv.h>
11#include <string.h>
12
13
14
15using namespace __crt_strtox;
16
17namespace
18{
19 // Guard class for floating point control word modifications in the interrupt exception mask.
21 {
22 public:
23 explicit fp_control_word_guard(unsigned int const mask = ~0u) : _mask(mask)
24 {
25 _controlfp_s(&_original_control_word, 0, 0);
26 }
27
28 fp_control_word_guard(unsigned int const new_control, unsigned int const mask) : _mask(mask)
29 {
30 unsigned int float_control;
31 _controlfp_s(&_original_control_word, 0, 0);
32 _controlfp_s(&float_control, new_control, _mask);
33 }
34
36 {
37 unsigned int reset_cw;
38 _controlfp_s(&reset_cw, _original_control_word, _mask);
39 }
40
41 private:
43 unsigned int _mask;
44 };
45
47 {
48 public:
49
51 {
52 // The calls to feholdexcept and fesetenv are relatively expensive,
53 // so we only call them if there are any unmasked exceptions.
54 fegetenv(&_environment);
55 if ((_environment._Fe_ctl & FE_ALL_EXCEPT) == FE_ALL_EXCEPT)
56 {
57 _requires_reset = false;
58 }
59 else
60 {
61 feholdexcept(&_environment);
62 _requires_reset = true;
63 }
64 }
65
67 {
68 if (_requires_reset)
69 {
70 fesetenv(&_environment);
71 }
72 }
73
74 private:
75
78
81 };
82}
83
84
85
86// This function converts a finite, positive floating point value into its
87// decimal representation. The decimal mantissa and exponent are returned
88// via the out parameters and the return value affirms if there were trailing
89// digits. If the value is zero, negative, infinity, or nan, the behavior is
90// undefined.
91//
92// This function is based on the digit generation algorithm described in the
93// paper "Printing floating point numbers quickly and accurately," by Robert G.
94// Burger and R. Kent Dybvig, from ACM SIGPLAN 1996 Conference on Programming
95// Language Design and Implementation, June 1996. This function deviates from
96// that algorithm in its termination conditions: the Burger-Dybvig algorithm
97// terminates when it runs out of significant digits; this function continues
98// generating digits, even if they are insignificant (this allows us to print
99// large, exactly representable values exactly, e.g. large powers of two).
100//
101// This function stops generating digits when the first of the following
102// conditions is true: [1] the mantissa buffer is exhausted, [2] sufficient
103// digits have been generated for a %f specifier with the requested precision,
104// or [3] all remaining digits are known to be zero.
105template <typename FloatingType>
107 FloatingType const value,
108 uint32_t const precision,
109 __acrt_precision_style const precision_style,
110 int* const exponent,
111 char* const mantissa_buffer,
112 size_t const mantissa_buffer_count
113 ) throw()
114{
115 using floating_traits = __acrt_floating_type_traits<FloatingType>;
116 using components_type = typename floating_traits::components_type;
117
118 _ASSERTE(mantissa_buffer_count > 0);
119
120 components_type const& value_components = reinterpret_cast<components_type const&>(value);
121
122 // Special handling is required for denormal values: because the implicit
123 // high order bit is a zero, not a one, we need to [1] not set that bit when
124 // we expand the mantissa, and [2] increment the exponent to account for the
125 // extra shift.
126 bool const is_denormal = value_components._exponent == 0;
127
128 uint64_t const mantissa_adjustment = is_denormal
129 ? 0
130 : static_cast<uint64_t>(1) << (floating_traits::mantissa_bits - 1);
131
132 int32_t const exponent_adjustment = is_denormal
133 ? 2
134 : 1;
135
136 // f and e are the unbiased mantissa and exponent, respectively. (Where one-
137 // -letter variable names are used, they match the same variables from the
138 // Burger-Dybvig paper.)
139 uint64_t const f = value_components._mantissa + mantissa_adjustment;
140 int32_t const e =
141 static_cast<int32_t>(value_components._exponent) -
142 floating_traits::exponent_bias -
143 floating_traits::mantissa_bits +
144 exponent_adjustment;
145
146 // k is the decimal exponent, such that the resulting decimal number is of
147 // the form 0.mmmmm * 10^k, where mmmm are the mantissa digits we generate.
148 // Note that the use of log10 here may not give the correct result: it may
149 // be off by one, e.g. as is the case for powers of ten (log10(100) is two,
150 // but the correct value of k for 100 is 3). We detect off-by-one errors
151 // later and correct for them.
152 int32_t k = static_cast<int32_t>(ceil(log10(value)));
153 if (k == INT32_MAX || k == INT32_MIN)
154 {
155 _ASSERTE(("unexpected input value; log10 failed", 0));
156 k = 0;
157 }
158
159 // The floating point number is represented as a fraction, r / s. The
160 // initialization of these two values is as described in the Burger-Dybvig
161 // paper.
163 big_integer s{};
164
165 if (e >= 0)
166 {
167 if (r != make_big_integer_power_of_two(floating_traits::mantissa_bits - 1))
168 {
169 shift_left(r, e + 1); // f * b^e * 2
170 s = make_big_integer(2); // 2
171 }
172 else
173 {
174 shift_left(r, e + 2); // f * b^(e+1) * 2
175 s = make_big_integer(4); // b * 2
176 }
177 }
178 else
179 {
180 if (e == floating_traits::minimum_binary_exponent ||
181 r != make_big_integer_power_of_two(floating_traits::mantissa_bits - 1))
182 {
183 shift_left(r, 1); // f * 2
184 s = make_big_integer_power_of_two(-e + 1); // b^-e * 2
185 }
186 else
187 {
188 shift_left(r, 2); // f * b * 2
189 s = make_big_integer_power_of_two(-e + 2); // b^(-e+1) * 2
190 }
191 }
192
193 if (k >= 0)
194 {
196 }
197 else
198 {
200 }
201
202 char* mantissa_it = mantissa_buffer;
203
204 // Perform a trial digit generation to handle off-by-one errors in the
205 // computation of 'k': There are three possible cases, which we handle
206 // in turn:
207 multiply(r, 10);
208 uint32_t const initial_digit = static_cast<uint32_t>(divide(r, s));
209
210 // If the initial digit was computed as 10, k is too small. We increment k
211 // and adjust s as if it had been computed with the correct k above. We
212 // then treat the digit as a one, which is what it would have been extracted
213 // as had k, r, and s been correct to begin with.
214 if (initial_digit == 10)
215 {
216 ++k;
217 *mantissa_it++ = '1';
218 multiply(s, 10);
219 }
220 // If the initial digit is zero, k is too large. We decrement k and ignore
221 // the zero that we read (the next digit that we read will be the "real"
222 // initial digit.
223 else if (initial_digit == 0)
224 {
225 --k;
226 }
227 // Otherwise, k was correct and the digit we read was the actual initial
228 // digit of the number; just store it.
229 else
230 {
231 *mantissa_it++ = static_cast<char>('0' + initial_digit);
232 }
233
234 *exponent = k; // k is now correct; store it for our caller
235
236 // convert_to_fos_high_precision() generates digits assuming we're formatting with %f
237 // When %e is the format specifier, adding the exponent to the number of required digits
238 // is not needed.
239 uint32_t const required_digits = k >= 0 && precision <= INT_MAX && precision_style == __acrt_precision_style::fixed
240 ? k + precision
241 : precision;
242
243 char* const mantissa_last = mantissa_buffer + __min(mantissa_buffer_count - 1, required_digits);
244
245 // We must track whether there are any non-zero digits that were not written to the mantissa,
246 // since just checking whether 'r' is zero is insufficient for knowing whether there are any
247 // remaining zeros after the generated digits.
248 bool unwritten_nonzero_digits_in_chunk = false;
249 for (;;)
250 {
251 if (mantissa_it == mantissa_last)
252 {
253 break;
254 }
255
256 if (is_zero(r))
257 {
258 break;
259 }
260
261 // To reduce the number of expensive high precision division operations,
262 // we generate multiple digits per iteration. Our quotient type is a
263 // uint32_t, and the largest power of ten representable by a uint32_t is
264 // 10^9, so we generate nine digits per iteration.
265 uint32_t const digits_per_iteration = 9;
266 uint32_t const digits_per_iteration_multiplier = 1000 * 1000 * 1000;
267
268 multiply(r, digits_per_iteration_multiplier);
269 uint32_t quotient = static_cast<uint32_t>(divide(r, s));
270
271 _ASSERTE(quotient < digits_per_iteration_multiplier);
272
273 // Decompose the quotient into its nine component digits by repeatedly
274 // dividing by ten. This generates digits in reverse order.
275 #pragma warning(suppress: 6293) // For-loop counts down from minimum
276 for (uint32_t i = digits_per_iteration - 1; i != static_cast<uint32_t>(-1); --i)
277 {
278 char const d = static_cast<char>('0' + quotient % 10);
279 quotient /= 10;
280
281 // We may not have room in the mantissa buffer for all of the digits.
282 // Ignore the ones for which we do not have room.
283 // Last value in mantissa must be null terminator, account for one place after digit generation.
284 if (static_cast<uint32_t>(mantissa_last - mantissa_it) <= i)
285 {
286 if (d != '0')
287 {
288 unwritten_nonzero_digits_in_chunk = true;
289 }
290
291 continue;
292 }
293
294 mantissa_it[i] = d;
295 }
296
297 mantissa_it += __min(digits_per_iteration, mantissa_last - mantissa_it);
298 }
299
300 *mantissa_it = '\0';
301
302 // To detect whether there are zeros after the generated digits for the purposes of rounding,
303 // we must check whether 'r' is zero, but also whether there were any non-zero numbers that were
304 // not written to the mantissa in the last evaluated chunk.
305 bool const all_zeros_after_chunk = is_zero(r);
306
307 if (all_zeros_after_chunk && !unwritten_nonzero_digits_in_chunk)
308 {
310 }
311
313}
314
317 unsigned const precision,
318 __acrt_precision_style const precision_style,
319 STRFLT const flt,
320 char* const result,
321 size_t const result_count
322 )
323{
324 using floating_traits = __acrt_floating_type_traits<double>;
325 using components_type = floating_traits::components_type;
326
327 scoped_fp_state_reset const reset_fp_state;
328
329 components_type& components = reinterpret_cast<components_type&>(value);
330
331 flt->sign = components._sign == 1 ? '-' : ' ';
332 flt->mantissa = result;
333
334 unsigned int float_control;
335 _controlfp_s(&float_control, 0, 0);
336 bool const value_is_zero = components._exponent == 0 && (components._mantissa == 0 || float_control & _DN_FLUSH);
337 if (value_is_zero)
338 {
339 flt->decpt = 0;
340 _ERRCHECK(strcpy_s(result, result_count, "0"));
342 }
343
344 // Handle special cases:
345 __acrt_fp_class const classification = __acrt_fp_classify(value.x);
346 if (classification != __acrt_fp_class::finite)
347 {
348 flt->decpt = 1;
349 }
350
351 switch (classification)
352 {
357 }
358
359 // Make the number positive before we pass it to the digit generator:
360 components._sign = 0;
361
362 // The digit generator produces a truncated sequence of digits. To allow
363 // our caller to correctly round the mantissa, we need to generate an extra
364 // digit.
365 fp_control_word_guard const fpc(_MCW_EM, _MCW_EM);
366 return convert_to_fos_high_precision(value.x, precision + 1, precision_style, &flt->decpt, result, result_count);
367}
#define __cdecl
Definition: accygwin.h:79
static __forceinline __acrt_has_trailing_digits __cdecl convert_to_fos_high_precision(FloatingType const value, uint32_t const precision, __acrt_precision_style const precision_style, int *const exponent, char *const mantissa_buffer, size_t const mantissa_buffer_count)
Definition: cfout.cpp:106
__acrt_has_trailing_digits __cdecl __acrt_fltout(_CRT_DOUBLE value, unsigned const precision, __acrt_precision_style const precision_style, STRFLT const flt, char *const result, size_t const result_count)
Definition: cfout.cpp:315
fp_control_word_guard(unsigned int const new_control, unsigned int const mask)
Definition: cfout.cpp:28
fp_control_word_guard(unsigned int const mask=~0u)
Definition: cfout.cpp:23
scoped_fp_state_reset & operator=(scoped_fp_state_reset const &)
scoped_fp_state_reset(scoped_fp_state_reset const &)
#define _ERRCHECK(e)
__acrt_has_trailing_digits
__acrt_fp_class __cdecl __acrt_fp_classify(double const &value)
#define _ASSERTE(expr)
Definition: crtdbg.h:114
#define FE_ALL_EXCEPT
Definition: fenv.h:16
int __cdecl fesetenv(const fenv_t *)
int __cdecl feholdexcept(fenv_t *)
int __cdecl fegetenv(fenv_t *envp)
result_buffer_count char *const _In_ int const _In_ bool const _In_ unsigned const _In_ STRFLT const _In_ bool const _Inout_ __crt_cached_ptd_host &ptd throw()
Definition: cvt.cpp:119
floating_traits::components_type components_type
Definition: cvt.cpp:357
__int64 exponent
Definition: cvt.cpp:529
INT32 int32_t
Definition: types.h:71
UINT32 uint32_t
Definition: types.h:75
UINT64 uint64_t
Definition: types.h:77
double log10(double x)
Definition: freeldr.c:190
GLdouble s
Definition: gl.h:2039
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLenum GLenum GLuint components
Definition: glext.h:9620
GLenum GLint GLuint mask
Definition: glext.h:6028
GLfloat f
Definition: glext.h:7540
GLuint64EXT * result
Definition: glext.h:11304
GLenum GLint GLint * precision
Definition: glext.h:7539
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
#define _MCW_EM
Definition: float.h:40
#define _DN_FLUSH
Definition: float.h:63
_Check_return_ _CRTIMP double __cdecl ceil(_In_ double x)
#define __min(a, b)
Definition: stdlib.h:102
_CRT_MANAGED_FP_DEPRECATE _ACRTIMP errno_t __cdecl _controlfp_s(_Out_opt_ unsigned int *_CurrentState, _In_ unsigned int _NewValue, _In_ unsigned int _Mask)
#define INT32_MAX
Definition: intsafe.h:151
#define INT32_MIN
Definition: intsafe.h:124
#define INT_MAX
Definition: intsafe.h:150
#define d
Definition: ke_i.h:81
#define e
Definition: ke_i.h:82
#define strcpy_s(d, l, s)
Definition: utility.h:200
int k
Definition: mpi.c:3369
__forceinline bool __cdecl is_zero(big_integer const &value)
__forceinline big_integer __cdecl make_big_integer(uint64_t const value)
uint64_t __cdecl divide(big_integer &numerator, big_integer const &denominator)
__forceinline bool __cdecl multiply(big_integer &multiplicand, uint32_t const multiplier)
__forceinline bool __cdecl multiply_by_power_of_ten(big_integer &x, uint32_t const power)
__forceinline bool __cdecl shift_left(big_integer &x, uint32_t const n)
__forceinline big_integer __cdecl make_big_integer_power_of_two(uint32_t const power)
Definition: fenv.h:46
Definition: pdh_main.c:96
#define const
Definition: zconf.h:233