Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:43:38

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