1 //
2 // corecrt_internal_fltintrn.h
3 //
4 //      Copyright (c) Microsoft Corporation. All rights reserved.
5 //
6 // Floating point conversion routines for internal use.  This is a C++ header.
7 //
8 #pragma once
9 
10 #include <corecrt_internal.h>
11 #include <float.h>
12 #include <stdint.h>
13 #include <stdlib.h>
14 
15 
16 
17 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18 //
19 // Types
20 //
21 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
22 template <typename FloatingType>
23 struct __acrt_floating_type_traits;
24 
25 template <>
26 struct __acrt_floating_type_traits<float>
27 {
28     enum : int32_t
29     {
30         mantissa_bits            = FLT_MANT_DIG,
31         exponent_bits            = sizeof(float) * CHAR_BIT - FLT_MANT_DIG,
32 
33         maximum_binary_exponent  = FLT_MAX_EXP - 1,
34         minimum_binary_exponent  = FLT_MIN_EXP - 1,
35 
36         exponent_bias            = 127
37     };
38 
39     enum : uint32_t
40     {
41         exponent_mask             = (1u << (exponent_bits    )) - 1,
42         normal_mantissa_mask      = (1u << (mantissa_bits    )) - 1,
43         denormal_mantissa_mask    = (1u << (mantissa_bits - 1)) - 1,
44 
45         special_nan_mantissa_mask = (1u << (mantissa_bits - 2))
46     };
47 
48     struct components_type
49     {
50         uint32_t _mantissa : mantissa_bits - 1;
51         uint32_t _exponent : exponent_bits;
52         uint32_t _sign     : 1;
53     };
54 
55     static_assert(sizeof(components_type) == sizeof(float), "unexpected components size");
56 };
57 
58 template <>
59 struct __acrt_floating_type_traits<double>
60 {
61     enum : int32_t
62     {
63         mantissa_bits            = DBL_MANT_DIG,
64         exponent_bits            = sizeof(double) * CHAR_BIT - DBL_MANT_DIG,
65 
66         maximum_binary_exponent  = DBL_MAX_EXP - 1,
67         minimum_binary_exponent  = DBL_MIN_EXP - 1,
68 
69         exponent_bias            = 1023
70     };
71 
72     enum : uint64_t
73     {
74         exponent_mask             = (1ull << (exponent_bits    )) - 1,
75         normal_mantissa_mask      = (1ull << (mantissa_bits    )) - 1,
76         denormal_mantissa_mask    = (1ull << (mantissa_bits - 1)) - 1,
77 
78         special_nan_mantissa_mask = (1ull << (mantissa_bits - 2))
79     };
80 
81     struct components_type
82     {
83         uint64_t _mantissa : mantissa_bits - 1;
84         uint64_t _exponent : exponent_bits;
85         uint64_t _sign     : 1;
86     };
87 
88     static_assert(sizeof(components_type) == sizeof(double), "unexpected components size");
89 };
90 
91 enum class __acrt_fp_class : uint32_t
92 {
93     finite,
94     infinity,
95     quiet_nan,
96     signaling_nan,
97     indeterminate,
98 };
99 
100 enum class __acrt_has_trailing_digits
101 {
102     trailing,
103     no_trailing
104 };
105 
106 // Precision is the number of digits after the decimal point, but
107 // this has different implications for how many digits need to be
108 // generated based upon how the number will be formatted.
109 enum class __acrt_precision_style
110 {
111     fixed,      // 123.456 %f style requires '3' precision to generate 6 digits to format "123.456".
112     scientific  // 123.456 %e style requires '5' precision to generate 6 digits to format "1.23456e+02".
113 };
114 
115 // This rounding mode is used to know if we are using functions like gcvt vs printf
116 enum class __acrt_rounding_mode
117 {
118     legacy,
119     standard
120 };
121 
122 inline __acrt_fp_class __cdecl __acrt_fp_classify(double const& value) throw()
123 {
124     using floating_traits = __acrt_floating_type_traits<double>;
125     using components_type = floating_traits::components_type;
126 
127     components_type const& components = reinterpret_cast<components_type const&>(value);
128 
129     bool const value_is_nan_or_infinity = components._exponent == (1u << floating_traits::exponent_bits) - 1;
130     if (!value_is_nan_or_infinity)
131     {
132         return __acrt_fp_class::finite;
133     }
134     else if (components._mantissa == 0)
135     {
136         return __acrt_fp_class::infinity;
137     }
138     else if (components._sign == 1 && components._mantissa == floating_traits::special_nan_mantissa_mask)
139     {
140         return __acrt_fp_class::indeterminate;
141     }
142     else if (components._mantissa & floating_traits::special_nan_mantissa_mask) // Quiet NAN
143     {
144         return __acrt_fp_class::quiet_nan;
145     }
146     else // Signaling NAN
147     {
148         return __acrt_fp_class::signaling_nan;
149     }
150 }
151 
152 inline bool __cdecl __acrt_fp_is_negative(double const& value) throw()
153 {
154     using floating_traits = __acrt_floating_type_traits<double>;
155     using components_type = floating_traits::components_type;
156 
157     components_type const& components = reinterpret_cast<components_type const&>(value);
158 
159     return components._sign == 1;
160 }
161 
162 struct _strflt
163 {
164     int   sign;     // Zero if positive otherwise negative
165     int   decpt;    // Exponent of floating point number
166     char* mantissa; // Pointer to mantissa in string form
167 };
168 
169 typedef _strflt* STRFLT;
170 
171 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
172 //
173 // Floating Point Conversion Routines
174 //
175 //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
176 _CRT_BEGIN_C_HEADER
177 
178 // Result buffer count for __acrt_fp_format has a minimum value that depends on the precision requested.
179 // This requirement originates and propagates from the fp_format_e_internal function (in convert\cvt.cpp)
180 // This macro can be used to annotate result_buffer_count in the below functions
181 #define _In_fits_precision_(precision_arg)                                        \
182         _When_(precision_arg <= 0, _Pre_satisfies_(_Curr_ > 9))                   \
183         _When_(precision_arg >  0, _Pre_satisfies_(_Curr_ > 9 + precision_arg))
184 
185 _Success_(return == 0)
186 errno_t __cdecl __acrt_fp_format(
187     _In_                                                   double const*          value,
188     _Maybe_unsafe_(_Inout_updates_z_, result_buffer_count) char*                  result_buffer,
189     _In_fits_precision_(precision)                         size_t                 result_buffer_count,
190     _Out_writes_(scratch_buffer_count)                     char*                  scratch_buffer,
191     _In_                                                   size_t                 scratch_buffer_count,
192     _In_                                                   int                    format,
193     _In_                                                   int                    precision,
194     _In_                                                   uint64_t               options,
195     _In_                                                   __acrt_rounding_mode   rounding_mode,
196     _Inout_                                                __crt_cached_ptd_host& ptd
197     );
198 
199 errno_t __cdecl __acrt_fp_strflt_to_string(
200     _Out_writes_z_(buffer_count) char*  buffer,
201     _When_((digits >  0), _In_ _Pre_satisfies_(buffer_count > digits + 1))
202     _When_((digits <= 0), _In_ _Pre_satisfies_(buffer_count > 1))
203     _In_                         size_t buffer_count,
204     _In_                         int    digits,
205     _Inout_                      STRFLT value,
206     _In_                         __acrt_has_trailing_digits trailing_digits,
207     _In_                         __acrt_rounding_mode rounding_mode,
208     _Inout_                      __crt_cached_ptd_host& ptd
209     );
210 
211 __acrt_has_trailing_digits __cdecl __acrt_fltout(
212     _In_                         _CRT_DOUBLE            value,
213     _In_                         unsigned               precision,
214     _In_                         __acrt_precision_style precision_style,
215     _Out_                        STRFLT                 result,
216     _Out_writes_z_(buffer_count) char*                  buffer,
217     _In_                         size_t                 buffer_count
218     );
219 
220 _CRT_END_C_HEADER
221