Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:41:00

0001 // Copyright (c) 2016-2025 Antony Polukhin
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 #ifndef BOOST_PFR_DETAIL_FUNCTIONAL_HPP
0007 #define BOOST_PFR_DETAIL_FUNCTIONAL_HPP
0008 #pragma once
0009 
0010 #include <boost/pfr/detail/config.hpp>
0011 
0012 #ifdef BOOST_PFR_HAS_STD_MODULE
0013 import std;
0014 #else
0015 #include <functional>
0016 #include <cstdint>
0017 #endif
0018 
0019 #include <boost/pfr/detail/sequence_tuple.hpp>
0020 
0021 namespace boost { namespace pfr { namespace detail {
0022     template <std::size_t I, std::size_t N>
0023     struct equal_impl {
0024         template <class T, class U>
0025         constexpr static bool cmp(const T& v1, const U& v2) noexcept {
0026             return ::boost::pfr::detail::sequence_tuple::get<I>(v1) == ::boost::pfr::detail::sequence_tuple::get<I>(v2)
0027                 && equal_impl<I + 1, N>::cmp(v1, v2);
0028         }
0029     };
0030 
0031     template <std::size_t N>
0032     struct equal_impl<N, N> {
0033         template <class T, class U>
0034         constexpr static bool cmp(const T&, const U&) noexcept {
0035             return T::size_v == U::size_v;
0036         }
0037     };
0038 
0039     template <std::size_t I, std::size_t N>
0040     struct not_equal_impl {
0041         template <class T, class U>
0042         constexpr static bool cmp(const T& v1, const U& v2) noexcept {
0043             return ::boost::pfr::detail::sequence_tuple::get<I>(v1) != ::boost::pfr::detail::sequence_tuple::get<I>(v2)
0044                 || not_equal_impl<I + 1, N>::cmp(v1, v2);
0045         }
0046     };
0047 
0048     template <std::size_t N>
0049     struct not_equal_impl<N, N> {
0050         template <class T, class U>
0051         constexpr static bool cmp(const T&, const U&) noexcept {
0052             return T::size_v != U::size_v;
0053         }
0054     };
0055 
0056     template <std::size_t I, std::size_t N>
0057     struct less_impl {
0058         template <class T, class U>
0059         constexpr static bool cmp(const T& v1, const U& v2) noexcept {
0060             return sequence_tuple::get<I>(v1) < sequence_tuple::get<I>(v2)
0061                 || (sequence_tuple::get<I>(v1) == sequence_tuple::get<I>(v2) && less_impl<I + 1, N>::cmp(v1, v2));
0062         }
0063     };
0064 
0065     template <std::size_t N>
0066     struct less_impl<N, N> {
0067         template <class T, class U>
0068         constexpr static bool cmp(const T&, const U&) noexcept {
0069             return T::size_v < U::size_v;
0070         }
0071     };
0072 
0073     template <std::size_t I, std::size_t N>
0074     struct less_equal_impl {
0075         template <class T, class U>
0076         constexpr static bool cmp(const T& v1, const U& v2) noexcept {
0077             return sequence_tuple::get<I>(v1) < sequence_tuple::get<I>(v2)
0078                 || (sequence_tuple::get<I>(v1) == sequence_tuple::get<I>(v2) && less_equal_impl<I + 1, N>::cmp(v1, v2));
0079         }
0080     };
0081 
0082     template <std::size_t N>
0083     struct less_equal_impl<N, N> {
0084         template <class T, class U>
0085         constexpr static bool cmp(const T&, const U&) noexcept {
0086             return T::size_v <= U::size_v;
0087         }
0088     };
0089 
0090     template <std::size_t I, std::size_t N>
0091     struct greater_impl {
0092         template <class T, class U>
0093         constexpr static bool cmp(const T& v1, const U& v2) noexcept {
0094             return sequence_tuple::get<I>(v1) > sequence_tuple::get<I>(v2)
0095                 || (sequence_tuple::get<I>(v1) == sequence_tuple::get<I>(v2) && greater_impl<I + 1, N>::cmp(v1, v2));
0096         }
0097     };
0098 
0099     template <std::size_t N>
0100     struct greater_impl<N, N> {
0101         template <class T, class U>
0102         constexpr static bool cmp(const T&, const U&) noexcept {
0103             return T::size_v > U::size_v;
0104         }
0105     };
0106 
0107     template <std::size_t I, std::size_t N>
0108     struct greater_equal_impl {
0109         template <class T, class U>
0110         constexpr static bool cmp(const T& v1, const U& v2) noexcept {
0111             return sequence_tuple::get<I>(v1) > sequence_tuple::get<I>(v2)
0112                 || (sequence_tuple::get<I>(v1) == sequence_tuple::get<I>(v2) && greater_equal_impl<I + 1, N>::cmp(v1, v2));
0113         }
0114     };
0115 
0116     template <std::size_t N>
0117     struct greater_equal_impl<N, N> {
0118         template <class T, class U>
0119         constexpr static bool cmp(const T&, const U&) noexcept {
0120             return T::size_v >= U::size_v;
0121         }
0122     };
0123 
0124     // Hash combine functions copied from Boost.ContainerHash
0125     // https://github.com/boostorg/container_hash/blob/171c012d4723c5e93cc7cffe42919afdf8b27dfa/include/boost/container_hash/hash.hpp#L311
0126     // that is based on Peter Dimov's proposal
0127     // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
0128     // issue 6.18.
0129     //
0130     // This also contains public domain code from MurmurHash. From the
0131     // MurmurHash header:
0132     //
0133     // MurmurHash3 was written by Austin Appleby, and is placed in the public
0134     // domain. The author hereby disclaims copyright to this source code.
0135     template <typename SizeT>
0136     constexpr void hash_combine(SizeT& seed, SizeT value) noexcept {
0137         seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2);
0138     }
0139 
0140     constexpr auto rotl(std::uint32_t x, std::uint32_t r) noexcept {
0141         return (x << r) | (x >> (32 - r));
0142     }
0143 
0144     constexpr void hash_combine(std::uint32_t& h1, std::uint32_t k1) noexcept {
0145           const std::uint32_t c1 = 0xcc9e2d51;
0146           const std::uint32_t c2 = 0x1b873593;
0147 
0148           k1 *= c1;
0149           k1 = detail::rotl(k1,15);
0150           k1 *= c2;
0151 
0152           h1 ^= k1;
0153           h1 = detail::rotl(h1,13);
0154           h1 = h1*5+0xe6546b64;
0155     }
0156 
0157 #if defined(INT64_MIN) && defined(UINT64_MAX)
0158     constexpr void hash_combine(std::uint64_t& h, std::uint64_t k) noexcept {
0159         const std::uint64_t m = 0xc6a4a7935bd1e995ULL;
0160         const int r = 47;
0161 
0162         k *= m;
0163         k ^= k >> r;
0164         k *= m;
0165 
0166         h ^= k;
0167         h *= m;
0168 
0169         // Completely arbitrary number, to prevent 0's
0170         // from hashing to 0.
0171         h += 0xe6546b64;
0172     }
0173 #endif
0174 
0175     template <typename T>
0176     auto compute_hash(const T& value, long /*priority*/)
0177         -> decltype(std::hash<T>()(value))
0178     {
0179         return std::hash<T>()(value);
0180     }
0181 
0182     template <typename T>
0183     std::size_t compute_hash(const T& /*value*/, int /*priority*/) {
0184         static_assert(sizeof(T) && false, "====================> Boost.PFR: std::hash not specialized for type T");
0185         return 0;
0186     }
0187 
0188     template <std::size_t I, std::size_t N>
0189     struct hash_impl {
0190         template <class T>
0191         constexpr static std::size_t compute(const T& val) noexcept {
0192             std::size_t h = detail::compute_hash( ::boost::pfr::detail::sequence_tuple::get<I>(val), 1L );
0193             detail::hash_combine(h, hash_impl<I + 1, N>::compute(val) );
0194             return h;
0195         }
0196     };
0197 
0198     template <std::size_t N>
0199     struct hash_impl<N, N> {
0200         template <class T>
0201         constexpr static std::size_t compute(const T&) noexcept {
0202             return 0;
0203         }
0204     };
0205 
0206 ///////////////////// Define min_element and to avoid inclusion of <algorithm>
0207     constexpr std::size_t min_size(std::size_t x, std::size_t y) noexcept {
0208         return x < y ? x : y;
0209     }
0210 
0211     template <template <std::size_t, std::size_t> class Visitor, class T, class U>
0212     constexpr bool binary_visit(const T& x, const U& y) {
0213         constexpr std::size_t fields_count_lhs = detail::fields_count<std::remove_reference_t<T>>();
0214         constexpr std::size_t fields_count_rhs = detail::fields_count<std::remove_reference_t<U>>();
0215         constexpr std::size_t fields_count_min = detail::min_size(fields_count_lhs, fields_count_rhs);
0216         typedef Visitor<0, fields_count_min> visitor_t;
0217 
0218 #if BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE
0219         return visitor_t::cmp(detail::tie_as_tuple(x), detail::tie_as_tuple(y));
0220 #else
0221         bool result = true;
0222         ::boost::pfr::detail::for_each_field_dispatcher(
0223             x,
0224             [&result, &y](const auto& lhs) {
0225                 constexpr std::size_t fields_count_rhs_ = detail::fields_count<std::remove_reference_t<U>>();
0226                 ::boost::pfr::detail::for_each_field_dispatcher(
0227                     y,
0228                     [&result, &lhs](const auto& rhs) {
0229                         result = visitor_t::cmp(lhs, rhs);
0230                     },
0231                     detail::make_index_sequence<fields_count_rhs_>{}
0232                 );
0233             },
0234             detail::make_index_sequence<fields_count_lhs>{}
0235         );
0236 
0237         return result;
0238 #endif
0239     }
0240 
0241 }}} // namespace boost::pfr::detail
0242 
0243 #endif // BOOST_PFR_DETAIL_FUNCTIONAL_HPP