|
| 1 | +// Copyright 2026 Matt Borland |
| 2 | +// Distributed under the Boost Software License, Version 1.0. |
| 3 | +// https://www.boost.org/LICENSE_1_0.txt |
| 4 | +// |
| 5 | +// This file demonstrates the difference between decompose, frexp10 and |
| 6 | +// normalize, all of which inspect the internal representation of a |
| 7 | +// decimal floating point value but expose it in different ways. |
| 8 | + |
| 9 | +#include <boost/decimal/decimal32_t.hpp> // For the type decimal32_t |
| 10 | +#include <boost/decimal/decimal_fast32_t.hpp>// For the type decimal_fast32_t |
| 11 | +#include <boost/decimal/cmath.hpp> // For decompose, frexp10, normalize |
| 12 | +#include <boost/decimal/iostream.hpp> // For decimal support for <iostream> |
| 13 | +#include <array> |
| 14 | +#include <iostream> |
| 15 | + |
| 16 | +template <typename Decimal> |
| 17 | +void show(const Decimal value) |
| 18 | +{ |
| 19 | + // decompose returns the encoded significand, biased exponent and sign. |
| 20 | + // For IEEE types this preserves the cohort that was used at construction. |
| 21 | + // For fast types the value is normalized in the constructor, so the |
| 22 | + // components always reflect the normalized form. |
| 23 | + const auto components {boost::decimal::decompose(value)}; |
| 24 | + |
| 25 | + // frexp10 returns the cohort-agnostic significand together with the |
| 26 | + // matching exponent written through the pointer argument. The significand |
| 27 | + // is normalized to the full precision of the type (for decimal32_t the |
| 28 | + // range is [1'000'000, 9'999'999]). |
| 29 | + int frexp_exp {}; |
| 30 | + const auto frexp_sig {boost::decimal::frexp10(value, &frexp_exp)}; |
| 31 | + |
| 32 | + // normalize returns a decimal of the same type whose representation has |
| 33 | + // had the cohort effects removed. For fast types this is a no-op since |
| 34 | + // they are already normalized. |
| 35 | + const auto normalized {boost::decimal::normalize(value)}; |
| 36 | + |
| 37 | + std::cout << " value = " << value << '\n' |
| 38 | + << " decompose : sig = " << components.sig |
| 39 | + << ", exp = " << components.exp |
| 40 | + << ", sign = " << components.sign << '\n' |
| 41 | + << " frexp10 : sig = " << frexp_sig |
| 42 | + << ", exp = " << frexp_exp << '\n' |
| 43 | + << " normalize = " << normalized << "\n\n"; |
| 44 | +} |
| 45 | + |
| 46 | +int main() |
| 47 | +{ |
| 48 | + // All three values compare equal but use different cohorts. |
| 49 | + constexpr std::array<boost::decimal::decimal32_t, 3> ieee_values { |
| 50 | + boost::decimal::decimal32_t{3, 2}, |
| 51 | + boost::decimal::decimal32_t{300, 0}, |
| 52 | + boost::decimal::decimal32_t{3000000, -4} |
| 53 | + }; |
| 54 | + |
| 55 | + std::cout << "IEEE decimal32_t (cohort is preserved by the encoding):\n\n"; |
| 56 | + for (const auto& v : ieee_values) |
| 57 | + { |
| 58 | + show(v); |
| 59 | + } |
| 60 | + |
| 61 | + // The same set of inputs given to a fast type all encode identically. |
| 62 | + constexpr std::array<boost::decimal::decimal_fast32_t, 3> fast_values { |
| 63 | + boost::decimal::decimal_fast32_t{3, 2}, |
| 64 | + boost::decimal::decimal_fast32_t{300, 0}, |
| 65 | + boost::decimal::decimal_fast32_t{3000000, -4} |
| 66 | + }; |
| 67 | + |
| 68 | + std::cout << "decimal_fast32_t (always normalized internally):\n\n"; |
| 69 | + for (const auto& v : fast_values) |
| 70 | + { |
| 71 | + show(v); |
| 72 | + } |
| 73 | + |
| 74 | + return 0; |
| 75 | +} |
0 commit comments