MCPcopy Create free account
hub / github.com/ObEngine/ObEngine / format_float

Function format_float

extlibs/fmt/include/fmt/format-inl.h:1043–1112  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1041// if T is a IEEE754 binary32 or binary64 and snprintf otherwise.
1042template <typename T>
1043int format_float(T value, int precision, float_specs specs, buffer<char>& buf) {
1044 static_assert(!std::is_same<T, float>::value, "");
1045 FMT_ASSERT(value >= 0, "value is negative");
1046
1047 const bool fixed = specs.format == float_format::fixed;
1048 if (value <= 0) { // <= instead of == to silence a warning.
1049 if (precision <= 0 || !fixed) {
1050 buf.push_back('0');
1051 return 0;
1052 }
1053 buf.resize(to_unsigned(precision));
1054 std::uninitialized_fill_n(buf.data(), precision, '0');
1055 return -precision;
1056 }
1057
1058 if (!specs.use_grisu) return snprintf_float(value, precision, specs, buf);
1059
1060 int exp = 0;
1061 const int min_exp = -60; // alpha in Grisu.
1062 int cached_exp10 = 0; // K in Grisu.
1063 if (precision < 0) {
1064 fp fp_value;
1065 auto boundaries = specs.binary32
1066 ? fp_value.assign_float_with_boundaries(value)
1067 : fp_value.assign_with_boundaries(value);
1068 fp_value = normalize(fp_value);
1069 // Find a cached power of 10 such that multiplying value by it will bring
1070 // the exponent in the range [min_exp, -32].
1071 const fp cached_pow = get_cached_power(
1072 min_exp - (fp_value.e + fp::significand_size), cached_exp10);
1073 // Multiply value and boundaries by the cached power of 10.
1074 fp_value = fp_value * cached_pow;
1075 boundaries.lower = multiply(boundaries.lower, cached_pow.f);
1076 boundaries.upper = multiply(boundaries.upper, cached_pow.f);
1077 assert(min_exp <= fp_value.e && fp_value.e <= -32);
1078 --boundaries.lower; // \tilde{M}^- - 1 ulp -> M^-_{\downarrow}.
1079 ++boundaries.upper; // \tilde{M}^+ + 1 ulp -> M^+_{\uparrow}.
1080 // Numbers outside of (lower, upper) definitely do not round to value.
1081 grisu_shortest_handler handler{buf.data(), 0,
1082 boundaries.upper - fp_value.f};
1083 auto result =
1084 grisu_gen_digits(fp(boundaries.upper, fp_value.e),
1085 boundaries.upper - boundaries.lower, exp, handler);
1086 if (result == digits::error) {
1087 exp += handler.size - cached_exp10 - 1;
1088 fallback_format(value, buf, exp);
1089 return exp;
1090 }
1091 buf.resize(to_unsigned(handler.size));
1092 } else {
1093 if (precision > 17) return snprintf_float(value, precision, specs, buf);
1094 fp normalized = normalize(fp(value));
1095 const auto cached_pow = get_cached_power(
1096 min_exp - (normalized.e + fp::significand_size), cached_exp10);
1097 normalized = normalized * cached_pow;
1098 fixed_handler handler{buf.data(), 0, precision, -cached_exp10, fixed};
1099 if (grisu_gen_digits(normalized, 1, exp, handler) == digits::error)
1100 return snprintf_float(value, precision, specs, buf);

Callers 1

writeMethod · 0.70

Calls 11

snprintf_floatFunction · 0.85
get_cached_powerFunction · 0.85
multiplyFunction · 0.85
fpClass · 0.85
fallback_formatFunction · 0.85
resizeMethod · 0.80
normalizeFunction · 0.70
push_backMethod · 0.45
dataMethod · 0.45

Tested by

no test coverage detected