// // corecrt_internal_fltintrn.h // // Copyright (c) Microsoft Corporation. All rights reserved. // // Floating point conversion routines for internal use. This is a C++ header. // #pragma once #include #include #include #include //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // // Types // //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ template struct __acrt_floating_type_traits; template <> struct __acrt_floating_type_traits { enum : int32_t { mantissa_bits = FLT_MANT_DIG, exponent_bits = sizeof(float) * CHAR_BIT - FLT_MANT_DIG, maximum_binary_exponent = FLT_MAX_EXP - 1, minimum_binary_exponent = FLT_MIN_EXP - 1, exponent_bias = 127 }; enum : uint32_t { exponent_mask = (1u << (exponent_bits )) - 1, normal_mantissa_mask = (1u << (mantissa_bits )) - 1, denormal_mantissa_mask = (1u << (mantissa_bits - 1)) - 1, special_nan_mantissa_mask = (1u << (mantissa_bits - 2)) }; struct components_type { uint32_t _mantissa : mantissa_bits - 1; uint32_t _exponent : exponent_bits; uint32_t _sign : 1; }; static_assert(sizeof(components_type) == sizeof(float), "unexpected components size"); }; template <> struct __acrt_floating_type_traits { enum : int32_t { mantissa_bits = DBL_MANT_DIG, exponent_bits = sizeof(double) * CHAR_BIT - DBL_MANT_DIG, maximum_binary_exponent = DBL_MAX_EXP - 1, minimum_binary_exponent = DBL_MIN_EXP - 1, exponent_bias = 1023 }; enum : uint64_t { exponent_mask = (1ui64 << (exponent_bits )) - 1, normal_mantissa_mask = (1ui64 << (mantissa_bits )) - 1, denormal_mantissa_mask = (1ui64 << (mantissa_bits - 1)) - 1, special_nan_mantissa_mask = (1ui64 << (mantissa_bits - 2)) }; struct components_type { uint64_t _mantissa : mantissa_bits - 1; uint64_t _exponent : exponent_bits; uint64_t _sign : 1; }; static_assert(sizeof(components_type) == sizeof(double), "unexpected components size"); }; enum class __acrt_fp_class : uint32_t { finite, infinity, quiet_nan, signaling_nan, indeterminate, }; enum class __acrt_has_trailing_digits { trailing, no_trailing }; // Precision is the number of digits after the decimal point, but // this has different implications for how many digits need to be // generated based upon how the number will be formatted. enum class __acrt_precision_style { fixed, // 123.456 %f style requires '3' precision to generate 6 digits to format "123.456". scientific // 123.456 %e style requires '5' precision to generate 6 digits to format "1.23456e+02". }; // This rounding mode is used to know if we are using functions like gcvt vs printf enum class __acrt_rounding_mode { legacy, standard }; inline __acrt_fp_class __cdecl __acrt_fp_classify(double const& value) throw() { using floating_traits = __acrt_floating_type_traits; using components_type = floating_traits::components_type; components_type const& components = reinterpret_cast(value); bool const value_is_nan_or_infinity = components._exponent == (1u << floating_traits::exponent_bits) - 1; if (!value_is_nan_or_infinity) { return __acrt_fp_class::finite; } else if (components._mantissa == 0) { return __acrt_fp_class::infinity; } else if (components._sign == 1 && components._mantissa == floating_traits::special_nan_mantissa_mask) { return __acrt_fp_class::indeterminate; } else if (components._mantissa & floating_traits::special_nan_mantissa_mask) // Quiet NAN { return __acrt_fp_class::quiet_nan; } else // Signaling NAN { return __acrt_fp_class::signaling_nan; } } inline bool __cdecl __acrt_fp_is_negative(double const& value) throw() { using floating_traits = __acrt_floating_type_traits; using components_type = floating_traits::components_type; components_type const& components = reinterpret_cast(value); return components._sign == 1; } struct _strflt { int sign; // Zero if positive otherwise negative int decpt; // Exponent of floating point number char* mantissa; // Pointer to mantissa in string form }; typedef _strflt* STRFLT; //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // // Floating Point Conversion Routines // //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ _CRT_BEGIN_C_HEADER // Result buffer count for __acrt_fp_format has a minimum value that depends on the precision requested. // This requirement originates and propagates from the fp_format_e_internal function (in convert\cvt.cpp) // This macro can be used to annotate result_buffer_count in the below functions #define _In_fits_precision_(precision_arg) \ _When_(precision_arg <= 0, _Pre_satisfies_(_Curr_ > 9)) \ _When_(precision_arg > 0, _Pre_satisfies_(_Curr_ > 9 + precision_arg)) _Success_(return == 0) errno_t __cdecl __acrt_fp_format( _In_ double const* value, _Maybe_unsafe_(_Inout_updates_z_, result_buffer_count) char* result_buffer, _In_fits_precision_(precision) size_t result_buffer_count, _Out_writes_(scratch_buffer_count) char* scratch_buffer, _In_ size_t scratch_buffer_count, _In_ int format, _In_ int precision, _In_ uint64_t options, _In_ __acrt_rounding_mode rounding_mode, _Inout_ __crt_cached_ptd_host& ptd ); errno_t __cdecl __acrt_fp_strflt_to_string( _Out_writes_z_(buffer_count) char* buffer, _When_((digits > 0), _In_ _Pre_satisfies_(buffer_count > digits + 1)) _When_((digits <= 0), _In_ _Pre_satisfies_(buffer_count > 1)) _In_ size_t buffer_count, _In_ int digits, _Inout_ STRFLT value, _In_ __acrt_has_trailing_digits trailing_digits, _In_ __acrt_rounding_mode rounding_mode, _Inout_ __crt_cached_ptd_host& ptd ); __acrt_has_trailing_digits __cdecl __acrt_fltout( _In_ _CRT_DOUBLE value, _In_ unsigned precision, _In_ __acrt_precision_style precision_style, _Out_ STRFLT result, _Out_writes_z_(buffer_count) char* buffer, _In_ size_t buffer_count ); _CRT_END_C_HEADER