// Copyright Advanced Micro Devices, Inc., or its affiliates. // SPDX-License-Identifier: MIT #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace rocRoller { /** * \ingroup rocRoller * \addtogroup Utilities * @{ */ template constexpr T CeilDivide(T num, T den) { return (num + (den - 1)) / den; } template constexpr T RoundUpToMultiple(T val, T den) { return CeilDivide(val, den) * den; } template ::value>> constexpr T IsPrime(T val) { if(val < 2) return false; if(val < 4) return true; T end = sqrt(val); for(T i = 2; i <= end; i++) if(val % i == 0) return false; return true; } template ::value>> constexpr T NextPrime(T val) { if(val < 2) return 2; while(!IsPrime(val)) val++; return val; } template std::variant singleVariant(T value) { return std::variant(std::move(value)); } /** * Returns a copy of `sets`, with any sets that have elements in common * merged together. * * Postconditions: * - Union of return value sets is the same as the union of the input sets. * - No two sets in return value have any common elements. * - mergeSets(mergeSets(x)) == mergeSets(x) for any x. */ std::vector> mergeSets(std::vector> sets); inline std::string toString(int x) { return std::to_string(x); } template requires(!std::is_arithmetic_v) inline std::ostream& operator<<(std::ostream& stream, T const& x) { return stream << toString(x); } template void streamJoin(std::ostream& stream, Container const& c, Joiner const& j) { bool first = true; for(auto const& item : c) { if(!first) stream << j; stream << item; first = false; } } template inline std::ostream& operator<<(std::ostream& stream, std::set const& x) { stream << "set{"; streamJoin(stream, x, ", "); stream << "}"; return stream; } template inline std::ostream& operator<<(std::ostream& stream, std::unordered_set const& x) { stream << "set{"; streamJoin(stream, x, ", "); stream << "}"; return stream; } template inline std::ostream& operator<<(std::ostream& stream, std::pair const& x) { stream << "[" << x.first << ", " << x.second << "]"; return stream; } template inline std::ostream& operator<<(std::ostream& stream, std::vector const& xs) { auto iter = xs.begin(); stream << "["; if(iter != xs.end()) { stream << *iter; } iter++; for(; iter != xs.end(); iter++) { stream << ", " << *iter; } stream << "]"; return stream; } template inline void streamJoinTuple(std::ostream& stream, std::string const& sep, std::tuple const& tup) { if constexpr(Idx < sizeof...(Ts)) { stream << std::get(tup); if constexpr((Idx + 1) < (sizeof...(Ts))) { stream << sep; streamJoinTuple(stream, sep, tup); } } } template inline std::string concatenate_join(std::string const& sep, Ts const&... vals) { std::ostringstream msg; msg.setf(std::ios::showpoint); streamJoinTuple(msg, sep, std::forward_as_tuple(vals...)); return msg.str(); } template inline std::string concatenate(Ts const&... vals) { std::ostringstream msg; msg.setf(std::ios::showpoint); ((msg << (vals)), ...); return msg.str(); } template <> inline std::string concatenate(std::string const& val) { return val; } template inline std::string concatenate_if(Ts const&... vals) { if constexpr(!T_Enable) return ""; return concatenate(vals...); } class StreamRead { public: explicit StreamRead(std::string const& value, bool except = true); ~StreamRead(); bool read(std::istream& stream); private: std::string const& m_value; bool m_except; bool m_success = false; }; // inline std::istream & operator>>(std::istream & stream, StreamRead & value); inline std::istream& operator>>(std::istream& stream, StreamRead& value) { value.read(stream); return stream; } struct BitFieldGenerator { constexpr static uint32_t maxBitFieldWidth = 32; // Get the minimum width of the given maxVal in bits. constexpr static uint32_t ElementWidth(uint32_t maxVal) { return maxVal ? 1 + ElementWidth(maxVal >> 1) : 0; } // Get the bit mask for the element size in bits. constexpr static uint32_t BitMask(uint32_t elementWidth) { if(elementWidth == 1) return (uint32_t)0x1; return (BitMask(elementWidth - 1) << 1) | (uint32_t)0x1; } // Generate a 32 bit field containing val0 in the LSB, occupying the first // elementWidth bits. constexpr static uint32_t GenerateBitField(uint32_t elementWidth, uint32_t val0) { int mask = BitMask(elementWidth); return mask & val0; } // Generate a 32 bit field containing val0... valN in order starting from LSB, each // value occupying elementWidth bits of the field. template constexpr static uint32_t GenerateBitField(uint32_t elementWidth, uint32_t val0, ArgsT... valN) { int mask = BitMask(elementWidth); return (GenerateBitField(elementWidth, valN...) << elementWidth) | (mask & val0); } }; template Generator iota(T begin, T end, T inc) { for(; begin < end; begin += inc) co_yield begin; } template Generator iota(T begin, T end) { co_yield iota(begin, end, 1); } template Generator iota(T begin) { for(;; ++begin) co_yield begin; } inline constexpr auto Generated(auto gen) { return std::vector(gen.begin(), gen.end()); } /** * Returns true if begin...end represents a contiguous, increasing range of integer values. */ template inline bool IsContiguousRange(Iter begin, End end) { if(begin == end) return true; auto value = *begin; begin++; for(; begin != end; begin++) { if(*begin != value + 1) return false; value = *begin; } return true; } /** * Returns the product of the elements of the input. */ template inline auto product(T const& x) { using Value = std::decay_t; Value init = 1; return std::accumulate(x.cbegin(), x.cend(), init, std::multiplies()); } template constexpr inline bool contains(std::vector x, T val) { return std::any_of(x.begin(), x.end(), [val](T elem) { return elem == val; }); } // helper for visitor template struct overloaded : Ts... { // cppcheck-suppress syntaxError using Ts::operator()...; }; // explicit deduction template overloaded(Ts...) -> overloaded; /** * Converts a string value to an enum by comparing against each toString conversion. */ template T fromString(std::string const& str); /** * @brief Generate a set of valid string values for a CCountedEnum type. */ template std::set enumStrings(); template requires(std::default_initializable) std::string name() { T obj; return name(obj); } std::string escapeSymbolName(std::string name); std::vector readFile(std::string const&); template consteval size_t variantIndex() { static_assert(Index < std::variant_size_v); if constexpr(std::same_as>) { return Index; } else { return variantIndex(); } } /** * @} */ } // namespace rocRoller namespace std { template inline std::ostream& operator<<(std::ostream& stream, std::tuple const& tup) { stream << "["; rocRoller::streamJoinTuple(stream, ", ", tup); return stream << "]"; } template inline std::ostream& operator<<(std::ostream& stream, std::array const& array) { rocRoller::streamJoin(stream, array, ", "); return stream; } template inline std::ostream& operator<<(std::ostream& stream, std::set const& array) { stream << "{"; rocRoller::streamJoin(stream, array, ", "); stream << "}"; return stream; } template inline std::ostream& operator<<(std::ostream& stream, std::unordered_set const& array) { stream << "{"; rocRoller::streamJoin(stream, array, ", "); stream << "}"; return stream; } template inline std::ostream& operator<<(std::ostream& stream, std::vector const& array) { stream << "{"; rocRoller::streamJoin(stream, array, ", "); stream << "}"; return stream; } } #include