From 66df6d63d158e65211cdcef866e2afa8fd4f4cfa Mon Sep 17 00:00:00 2001 From: ckormanyos Date: Tue, 7 Apr 2026 22:05:19 +0200 Subject: [PATCH 1/3] Attempt constepr-ification of hash functions --- include/boost/multiprecision/complex_adaptor.hpp | 2 +- .../multiprecision/concepts/mp_number_archetypes.hpp | 2 +- include/boost/multiprecision/cpp_bin_float.hpp | 2 +- include/boost/multiprecision/cpp_dec_float.hpp | 2 +- .../cpp_df_qf/cpp_df_qf_detail_ccmath_limits.hpp | 4 +++- include/boost/multiprecision/cpp_int/misc.hpp | 2 +- include/boost/multiprecision/debug_adaptor.hpp | 2 +- include/boost/multiprecision/detail/hash.hpp | 12 ++++++------ include/boost/multiprecision/float128.hpp | 2 +- include/boost/multiprecision/gmp.hpp | 6 +++--- include/boost/multiprecision/logged_adaptor.hpp | 2 +- include/boost/multiprecision/mpc.hpp | 2 +- include/boost/multiprecision/mpfi.hpp | 2 +- include/boost/multiprecision/mpfr.hpp | 2 +- include/boost/multiprecision/number.hpp | 8 ++++---- include/boost/multiprecision/rational_adaptor.hpp | 2 +- include/boost/multiprecision/tommath.hpp | 2 +- 17 files changed, 29 insertions(+), 27 deletions(-) diff --git a/include/boost/multiprecision/complex_adaptor.hpp b/include/boost/multiprecision/complex_adaptor.hpp index 40ec4d74d..4f08ed0b7 100644 --- a/include/boost/multiprecision/complex_adaptor.hpp +++ b/include/boost/multiprecision/complex_adaptor.hpp @@ -983,7 +983,7 @@ inline void eval_set_real(complex_adaptor& result, const T& arg) } template -inline std::size_t hash_value(const complex_adaptor& val) +constexpr std::size_t hash_value(const complex_adaptor& val) { std::size_t result = hash_value(val.real_data()); std::size_t result2 = hash_value(val.imag_data()); diff --git a/include/boost/multiprecision/concepts/mp_number_archetypes.hpp b/include/boost/multiprecision/concepts/mp_number_archetypes.hpp index 6c025ee44..71ced92e4 100644 --- a/include/boost/multiprecision/concepts/mp_number_archetypes.hpp +++ b/include/boost/multiprecision/concepts/mp_number_archetypes.hpp @@ -212,7 +212,7 @@ inline int eval_fpclassify(const number_backend_float_architype& arg) return BOOST_MP_FPCLASSIFY(arg.m_value); } -inline std::size_t hash_value(const number_backend_float_architype& v) +constexpr std::size_t hash_value(const number_backend_float_architype& v) { std::hash hasher; return hasher(v.m_value); diff --git a/include/boost/multiprecision/cpp_bin_float.hpp b/include/boost/multiprecision/cpp_bin_float.hpp index 487eb5270..9e6245d69 100644 --- a/include/boost/multiprecision/cpp_bin_float.hpp +++ b/include/boost/multiprecision/cpp_bin_float.hpp @@ -2075,7 +2075,7 @@ int eval_signbit(const cpp_bin_float& val) } template -inline std::size_t hash_value(const cpp_bin_float& val) +constexpr std::size_t hash_value(const cpp_bin_float& val) { std::size_t result = hash_value(val.bits()); boost::multiprecision::detail::hash_combine(result, val.exponent(), val.sign()); diff --git a/include/boost/multiprecision/cpp_dec_float.hpp b/include/boost/multiprecision/cpp_dec_float.hpp index 27cf3d6b3..a264a30c3 100644 --- a/include/boost/multiprecision/cpp_dec_float.hpp +++ b/include/boost/multiprecision/cpp_dec_float.hpp @@ -3632,7 +3632,7 @@ inline int eval_signbit(const cpp_dec_float& } template -inline std::size_t hash_value(const cpp_dec_float& val) +constexpr std::size_t hash_value(const cpp_dec_float& val) { return val.hash(); } diff --git a/include/boost/multiprecision/cpp_df_qf/cpp_df_qf_detail_ccmath_limits.hpp b/include/boost/multiprecision/cpp_df_qf/cpp_df_qf_detail_ccmath_limits.hpp index 7f364b844..6c09a16d2 100644 --- a/include/boost/multiprecision/cpp_df_qf/cpp_df_qf_detail_ccmath_limits.hpp +++ b/include/boost/multiprecision/cpp_df_qf/cpp_df_qf_detail_ccmath_limits.hpp @@ -180,7 +180,9 @@ struct numeric_limits self_type { // This double value has only one bit set and so is exact. - return 1.92592994438723585305597794258492732e-34; + // N[2^-112, 84] + + return 1.92592994438723585305597794258492731853810164821538819523993879556655883789062500000e-34; } static constexpr auto round_error() noexcept -> self_type { return static_cast(0.5F); } diff --git a/include/boost/multiprecision/cpp_int/misc.hpp b/include/boost/multiprecision/cpp_int/misc.hpp index c464cfae1..d2504db7b 100644 --- a/include/boost/multiprecision/cpp_int/misc.hpp +++ b/include/boost/multiprecision/cpp_int/misc.hpp @@ -1406,7 +1406,7 @@ eval_msb(const cpp_int_backend -inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const cpp_int_backend& val) noexcept +constexpr std::size_t hash_value(const cpp_int_backend& val) noexcept { std::size_t result = 0; for (std::size_t i = 0; i < val.size(); ++i) diff --git a/include/boost/multiprecision/debug_adaptor.hpp b/include/boost/multiprecision/debug_adaptor.hpp index 08b11386a..1879e5c4b 100644 --- a/include/boost/multiprecision/debug_adaptor.hpp +++ b/include/boost/multiprecision/debug_adaptor.hpp @@ -562,7 +562,7 @@ int eval_signbit(const debug_adaptor& val) } template -std::size_t hash_value(const debug_adaptor& val) +constexpr std::size_t hash_value(const debug_adaptor& val) { return hash_value(val.value()); } diff --git a/include/boost/multiprecision/detail/hash.hpp b/include/boost/multiprecision/detail/hash.hpp index 664680f80..9b6bd3121 100644 --- a/include/boost/multiprecision/detail/hash.hpp +++ b/include/boost/multiprecision/detail/hash.hpp @@ -13,7 +13,7 @@ namespace boost { namespace multiprecision { namespace detail { template -inline std::size_t hash_value(const T& v) +BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const T& v) { std::hash hasher; return hasher(v); @@ -21,19 +21,19 @@ inline std::size_t hash_value(const T& v) #if defined(BOOST_HAS_INT128) -std::size_t hash_value(const uint128_type& val); +constexpr std::size_t hash_value(const uint128_type& val); -inline std::size_t hash_value(const int128_type& val) +constexpr std::size_t hash_value(const int128_type& val) { return hash_value(static_cast(val)); } #endif -inline void hash_combine(std::size_t&) {} +constexpr void hash_combine(std::size_t&) {} template -inline void hash_combine(std::size_t& seed, const T& v, Args... args) +constexpr void hash_combine(std::size_t& seed, const T& v, Args... args) { constexpr std::size_t adder = 0x9e3779b9; seed = seed ^ (hash_value(v) + adder + (seed<<6) + (seed>>2)); @@ -42,7 +42,7 @@ inline void hash_combine(std::size_t& seed, const T& v, Args... args) #if defined(BOOST_HAS_INT128) -inline std::size_t hash_value(const uint128_type& val) +constexpr std::size_t hash_value(const uint128_type& val) { std::size_t result = static_cast(val); hash_combine(result, static_cast(val >> 64)); diff --git a/include/boost/multiprecision/float128.hpp b/include/boost/multiprecision/float128.hpp index 81d7be741..439135957 100644 --- a/include/boost/multiprecision/float128.hpp +++ b/include/boost/multiprecision/float128.hpp @@ -634,7 +634,7 @@ inline int eval_signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const float128_backend& } #endif -inline std::size_t hash_value(const float128_backend& val) +constexpr std::size_t hash_value(const float128_backend& val) { return boost::multiprecision::detail::hash_value(static_cast(val.value())); } diff --git a/include/boost/multiprecision/gmp.hpp b/include/boost/multiprecision/gmp.hpp index e15e2604a..1cc673f4f 100644 --- a/include/boost/multiprecision/gmp.hpp +++ b/include/boost/multiprecision/gmp.hpp @@ -1384,7 +1384,7 @@ inline void eval_frexp(gmp_float& result, const gmp_float& v } template -inline std::size_t hash_value(const gmp_float& val) +constexpr std::size_t hash_value(const gmp_float& val) { std::size_t result = 0; for (int i = 0; i < std::abs(val.data()[0]._mp_size); ++i) @@ -2353,7 +2353,7 @@ eval_powm(gmp_int& result, const gmp_int& base, Integer p, const gmp_int& m) mpz_powm_ui(result.data(), base.data(), p, m.data()); } -inline std::size_t hash_value(const gmp_int& val) +constexpr std::size_t hash_value(const gmp_int& val) { // We should really use mpz_limbs_read here, but that's unsupported on older versions: std::size_t result = 0; @@ -3131,7 +3131,7 @@ void assign_components(gmp_rational& result, const T& a, const gmp_int& b) } -inline std::size_t hash_value(const gmp_rational& val) +constexpr std::size_t hash_value(const gmp_rational& val) { std::size_t result = 0; for (int i = 0; i < std::abs(val.data()[0]._mp_num._mp_size); ++i) diff --git a/include/boost/multiprecision/logged_adaptor.hpp b/include/boost/multiprecision/logged_adaptor.hpp index acdfb53b1..19399e46f 100644 --- a/include/boost/multiprecision/logged_adaptor.hpp +++ b/include/boost/multiprecision/logged_adaptor.hpp @@ -645,7 +645,7 @@ int eval_signbit(const logged_adaptor& val) } template -std::size_t hash_value(const logged_adaptor& val) +constexpr std::size_t hash_value(const logged_adaptor& val) { return hash_value(val.value()); } diff --git a/include/boost/multiprecision/mpc.hpp b/include/boost/multiprecision/mpc.hpp index 48c622aed..3649ec2f6 100644 --- a/include/boost/multiprecision/mpc.hpp +++ b/include/boost/multiprecision/mpc.hpp @@ -1650,7 +1650,7 @@ inline void eval_set_imag(mpc_complex_backend& result, const long long #endif template -inline std::size_t hash_value(const mpc_complex_backend& val) +constexpr std::size_t hash_value(const mpc_complex_backend& val) { std::size_t result = 0; std::size_t len = val.data()[0].re[0]._mpfr_prec / mp_bits_per_limb; diff --git a/include/boost/multiprecision/mpfi.hpp b/include/boost/multiprecision/mpfi.hpp index 828ee338e..e8055668c 100644 --- a/include/boost/multiprecision/mpfi.hpp +++ b/include/boost/multiprecision/mpfi.hpp @@ -1310,7 +1310,7 @@ inline void eval_log2(mpfi_float_backend& result, const mpfi_float_bac } template -inline std::size_t hash_value(const mpfi_float_backend& val) +constexpr std::size_t hash_value(const mpfi_float_backend& val) { std::size_t result = 0; std::size_t len = val.left_data()[0]._mpfr_prec / mp_bits_per_limb; diff --git a/include/boost/multiprecision/mpfr.hpp b/include/boost/multiprecision/mpfr.hpp index c426da53c..903ff0eb5 100644 --- a/include/boost/multiprecision/mpfr.hpp +++ b/include/boost/multiprecision/mpfr.hpp @@ -1979,7 +1979,7 @@ inline int eval_signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const mpfr_float_backen } template -inline std::size_t hash_value(const mpfr_float_backend& val) +constexpr std::size_t hash_value(const mpfr_float_backend& val) { std::size_t result = 0; std::size_t len = val.data()[0]._mpfr_prec / mp_bits_per_limb; diff --git a/include/boost/multiprecision/number.hpp b/include/boost/multiprecision/number.hpp index aac21d3cc..35d4b50ff 100644 --- a/include/boost/multiprecision/number.hpp +++ b/include/boost/multiprecision/number.hpp @@ -2364,7 +2364,7 @@ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR void swap(number -inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const number& val) +constexpr std::size_t hash_value(const number& val) { return hash_value(val.backend()); } @@ -2443,7 +2443,7 @@ inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number d } template -inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const rational >& val) +constexpr std::size_t hash_value(const rational >& val) { std::size_t result = hash_value(val.numerator()); boost::multiprecision::detail::hash_combine(result, hash_value(val.denominator())); @@ -2471,12 +2471,12 @@ namespace std { template struct hash > { - BOOST_MP_CXX14_CONSTEXPR std::size_t operator()(const boost::multiprecision::number& val) const { return hash_value(val); } + constexpr std::size_t operator()(const boost::multiprecision::number& val) const { return hash_value(val); } }; template struct hash > > { - BOOST_MP_CXX14_CONSTEXPR std::size_t operator()(const boost::rational >& val) const + constexpr std::size_t operator()(const boost::rational >& val) const { std::size_t result = hash_value(val.numerator()); boost::multiprecision::detail::hash_combine(result, hash_value(val.denominator())); diff --git a/include/boost/multiprecision/rational_adaptor.hpp b/include/boost/multiprecision/rational_adaptor.hpp index 8a024719d..7694bbf28 100644 --- a/include/boost/multiprecision/rational_adaptor.hpp +++ b/include/boost/multiprecision/rational_adaptor.hpp @@ -417,7 +417,7 @@ inline typename std::enable_if::value == number_kind_integer> // Hashing support, not strictly required, but it is used in our tests: // template -inline std::size_t hash_value(const rational_adaptor& arg) +constexpr std::size_t hash_value(const rational_adaptor& arg) { std::size_t result = hash_value(arg.num()); std::size_t result2 = hash_value(arg.denom()); diff --git a/include/boost/multiprecision/tommath.hpp b/include/boost/multiprecision/tommath.hpp index 52db1b76f..5ed035d40 100644 --- a/include/boost/multiprecision/tommath.hpp +++ b/include/boost/multiprecision/tommath.hpp @@ -899,7 +899,7 @@ inline typename std::enable_if return eval_integer_modulus(x, boost::multiprecision::detail::unsigned_abs(val)); } -inline std::size_t hash_value(const tommath_int& val) +constexpr std::size_t hash_value(const tommath_int& val) { std::size_t result = 0; std::size_t len = val.data().used; From 40cf9e50603a27b073a3349bdefa7b838f550405 Mon Sep 17 00:00:00 2001 From: ckormanyos Date: Tue, 7 Apr 2026 23:01:55 +0200 Subject: [PATCH 2/3] Relax constexpr-ness of a std-function --- include/boost/multiprecision/concepts/mp_number_archetypes.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/multiprecision/concepts/mp_number_archetypes.hpp b/include/boost/multiprecision/concepts/mp_number_archetypes.hpp index 71ced92e4..69c5b9dd2 100644 --- a/include/boost/multiprecision/concepts/mp_number_archetypes.hpp +++ b/include/boost/multiprecision/concepts/mp_number_archetypes.hpp @@ -212,7 +212,7 @@ inline int eval_fpclassify(const number_backend_float_architype& arg) return BOOST_MP_FPCLASSIFY(arg.m_value); } -constexpr std::size_t hash_value(const number_backend_float_architype& v) +inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const number_backend_float_architype& v) { std::hash hasher; return hasher(v.m_value); From b0fe49f4f7d8e6734624d1996daba11f448cb46a Mon Sep 17 00:00:00 2001 From: ckormanyos Date: Tue, 7 Apr 2026 23:03:36 +0200 Subject: [PATCH 3/3] Correct old-style constexpr-ness --- include/boost/multiprecision/concepts/mp_number_archetypes.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/boost/multiprecision/concepts/mp_number_archetypes.hpp b/include/boost/multiprecision/concepts/mp_number_archetypes.hpp index 69c5b9dd2..4139b89cf 100644 --- a/include/boost/multiprecision/concepts/mp_number_archetypes.hpp +++ b/include/boost/multiprecision/concepts/mp_number_archetypes.hpp @@ -214,7 +214,8 @@ inline int eval_fpclassify(const number_backend_float_architype& arg) inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const number_backend_float_architype& v) { - std::hash hasher; + std::hash hasher { }; + return hasher(v.m_value); }