// Copyright Advanced Micro Devices, Inc., or its affiliates. // SPDX-License-Identifier: MIT #pragma once #include #include #include #include namespace rocRoller { /** * \ingroup Utilities * \defgroup Comparison Comparison */ /** * \addtogroup Comparison * @{ */ /** * Lexicographically compares two lists of values, one pair of values at a * time. * * \return -1: The first list is lesser. * 1: The second list is lesser. * 0: The lists are equal. */ inline int LexicographicCompare() { return 0; } template inline int LexicographicCompare(A const& lhs, A const& rhs) { if(lhs < rhs) return -1; if(lhs > rhs) return 1; return 0; } template > inline int LexicographicCompare(A const& lhs, A const& rhs, Args const&... rest) { if(lhs < rhs) return -1; if(lhs > rhs) return 1; return LexicographicCompare(rest...); } /** * @brief Traits class which enables comparison operators to be implemented * based on a `compare()` function. * * Specializations must implement a `compare(lhs, rhs)` function which returns: * - -1: lhs is lesser * - 0: values are equal * - 1: rhs is lesser */ template struct Comparison { enum { implemented = false }; }; template ::implemented>::type> inline bool operator==(T const& lhs, U const& rhs) { return Comparison::compare(lhs, rhs) == 0; } template ::implemented>::type> inline bool operator!=(T const& lhs, U const& rhs) { return Comparison::compare(lhs, rhs) != 0; } template ::implemented>::type> inline bool operator<(T const& lhs, U const& rhs) { return Comparison::compare(lhs, rhs) < 0; } template ::implemented>::type> inline bool operator<=(T const& lhs, U const& rhs) { return Comparison::compare(lhs, rhs) <= 0; } template ::implemented>::type> inline bool operator>(T const& lhs, U const& rhs) { return Comparison::compare(lhs, rhs) > 0; } template ::implemented>::type> inline bool operator>=(T const& lhs, U const& rhs) { return Comparison::compare(lhs, rhs) >= 0; } /** * Combines a number of already-hashed values. */ template inline size_t combine_hashes(size_t a, Ts... rest) { return combine_hashes(a, combine_hashes(rest...)); } template <> inline size_t combine_hashes(size_t a, size_t b) { return b ^ (a + 0x9b9773e99e3779b9 + (b << 6) + (b >> 2)); } template inline size_t hash_combine(T const& val) { return std::hash()(val); } template inline size_t hash_combine(T const& val, Ts const&... more) { //size_t mine = sizeof(val); size_t mine = std::hash()(val); size_t rest = hash_combine(more...); //return mine + rest; return combine_hashes(mine, rest); } template inline size_t hash_combine_iter(Iter begin, Iter end) { size_t rv = 0; while(begin != end) { rv = combine_hashes(hash_combine(*begin), rv); begin++; } return rv; } template struct tuple_hash { using MyTuple = std::tuple; using TypeN = typename std::tuple_element::type; static size_t apply(std::tuple const& tup) { size_t mine = std::hash()(std::get(tup)); size_t rest = tuple_hash::apply(tup); return combine_hashes(mine, rest); } }; template struct tuple_hash<0, Types...> { using MyTuple = std::tuple; using Type0 = typename std::tuple_element<0, MyTuple>::type; static size_t apply(std::tuple const& tup) { return std::hash()(std::get<0>(tup)); } }; template size_t hash_tuple(std::tuple const& tup) { return tuple_hash::apply(tup); } /** * @} */ } // namespace rocRoller namespace std { template struct hash> { inline size_t operator()(tuple const& tup) const { return rocRoller::hash_tuple(tup); } }; } // namespace std