TerraForge3D  2.3.1
3D Terrain And Landscape Generator

◆ compute_boundaries()

template<typename FloatType >
boundaries nlohmann::detail::dtoa_impl::compute_boundaries ( FloatType  value)

Compute the (normalized) diyfp representing the input number 'value' and its boundaries.

Precondition
value must be finite and positive

Definition at line 15709 of file json.hpp.

15710{
15711 JSON_ASSERT(std::isfinite(value));
15712 JSON_ASSERT(value > 0);
15713 // Convert the IEEE representation into a diyfp.
15714 //
15715 // If v is denormal:
15716 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
15717 // If v is normalized:
15718 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
15719 static_assert(std::numeric_limits<FloatType>::is_iec559,
15720 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
15721 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
15722 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
15723 constexpr int kMinExp = 1 - kBias;
15724 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
15725 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
15726 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
15727 const std::uint64_t E = bits >> (kPrecision - 1);
15728 const std::uint64_t F = bits & (kHiddenBit - 1);
15729 const bool is_denormal = E == 0;
15730 const diyfp v = is_denormal
15731 ? diyfp(F, kMinExp)
15732 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
15733 // Compute the boundaries m- and m+ of the floating-point value
15734 // v = f * 2^e.
15735 //
15736 // Determine v- and v+, the floating-point predecessor and successor if v,
15737 // respectively.
15738 //
15739 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
15740 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
15741 //
15742 // v+ = v + 2^e
15743 //
15744 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
15745 // between m- and m+ round to v, regardless of how the input rounding
15746 // algorithm breaks ties.
15747 //
15748 // ---+-------------+-------------+-------------+-------------+--- (A)
15749 // v- m- v m+ v+
15750 //
15751 // -----------------+------+------+-------------+-------------+--- (B)
15752 // v- m- v m+ v+
15753 const bool lower_boundary_is_closer = F == 0 && E > 1;
15754 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
15755 const diyfp m_minus = lower_boundary_is_closer
15756 ? diyfp(4 * v.f - 1, v.e - 2) // (B)
15757 : diyfp(2 * v.f - 1, v.e - 1); // (A)
15758 // Determine the normalized w+ = m+.
15759 const diyfp w_plus = diyfp::normalize(m_plus);
15760 // Determine w- = m- such that e_(w-) = e_(w+).
15761 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
15762 return {diyfp::normalize(v), w_minus, w_plus};
15763}