Skip to content

Commit

Permalink
Merge pull request #329 from cppalliance/hash
Browse files Browse the repository at this point in the history
Add support for std::hash to decimal128
  • Loading branch information
mborland authored Nov 16, 2023
2 parents 02fde1b + f022c47 commit 9ded10d
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 8 deletions.
9 changes: 1 addition & 8 deletions include/boost/decimal/detail/emulated128.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ struct uint128
constexpr auto operator=(const boost::uint128_type& v) noexcept -> uint128& { *this = uint128(v); return *this; }
#endif

constexpr auto operator=(const uint128&) noexcept -> uint128&;
constexpr uint128& operator=(const uint128&) noexcept = default;

#undef SIGNED_ASSIGNMENT_OPERATOR
#undef UNSIGNED_ASSIGNMENT_OPERATOR
Expand Down Expand Up @@ -653,13 +653,6 @@ constexpr auto operator+(uint128 val) noexcept -> uint128
return val;
}

constexpr auto uint128::operator=(const uint128& v) noexcept -> uint128&
{
low = v.low;
high = v.high;
return *this;
}

constexpr auto operator==(uint128 lhs, uint128 rhs) noexcept -> bool
{
return lhs.high == rhs.high && lhs.low == rhs.low;
Expand Down
23 changes: 23 additions & 0 deletions include/boost/decimal/hash.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <boost/decimal/decimal32.hpp>
#include <boost/decimal/decimal64.hpp>
#include <boost/decimal/decimal128.hpp>
#include <functional>
#include <cstring>

Expand Down Expand Up @@ -38,6 +39,28 @@ struct hash<boost::decimal::decimal64>
}
};

#if __GNUC__ >= 8
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wclass-memaccess"
#endif

template <>
struct hash<boost::decimal::decimal128>
{
// Take the xor of the two words and hash that
auto operator()(const boost::decimal::decimal128& v) const noexcept -> std::size_t
{
boost::decimal::detail::uint128 bits;
std::memcpy(&bits, &v, sizeof(boost::decimal::detail::uint128));

return std::hash<std::uint64_t>{}(bits.high ^ bits.low);
}
};

#if __GNUC__ >= 8
# pragma GCC diagnostic pop
#endif

}

#endif //BOOST_DECIMAL_HASH_HPP
1 change: 1 addition & 0 deletions test/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ run test_fenv.cpp ;
run test_float_conversion.cpp ;
run test_frexp_ldexp.cpp ;
run test_git_issue_271.cpp ;
run test_hash.cpp ;
run test_literals.cpp ;
run test_log.cpp ;
run test_log1p.cpp ;
Expand Down
29 changes: 29 additions & 0 deletions test/test_hash.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2023 Matt Borland
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
//
// This is a toy example to make sure that the hashing compiles correctly

#include <boost/decimal.hpp>
#include <boost/core/lightweight_test.hpp>
#include <functional>

template <typename T>
void test_hash()
{
std::hash<T> hasher;
for (int i = 0; i < 100; ++i)
{
T dec_val(i);
BOOST_TEST_EQ(hasher(dec_val), hasher(dec_val));
}
}

int main()
{
test_hash<boost::decimal::decimal32>();
test_hash<boost::decimal::decimal64>();
test_hash<boost::decimal::decimal128>();

return boost::report_errors();
}

0 comments on commit 9ded10d

Please sign in to comment.