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