/* SPDX-License-Identifier: BSL-1.0 OR BSD-3-Clause */ #ifndef MPT_BASE_NUMERIC_HPP #define MPT_BASE_NUMERIC_HPP #include "mpt/base/detect_compiler.hpp" #include "mpt/base/namespace.hpp" #include "mpt/base/bit.hpp" #include "mpt/base/saturate_cast.hpp" #include #include #include namespace mpt { inline namespace MPT_INLINE_NS { template struct ModIfNotZeroImpl { template constexpr Tval mod(Tval x) { static_assert(std::numeric_limits::is_integer); static_assert(!std::numeric_limits::is_signed); static_assert(std::numeric_limits::is_integer); static_assert(!std::numeric_limits::is_signed); return static_cast(x % m); } }; template <> struct ModIfNotZeroImpl { template constexpr Tval mod(Tval x) { return x; } }; template <> struct ModIfNotZeroImpl { template constexpr Tval mod(Tval x) { return x; } }; template <> struct ModIfNotZeroImpl { template constexpr Tval mod(Tval x) { return x; } }; template <> struct ModIfNotZeroImpl { template constexpr Tval mod(Tval x) { return x; } }; // Returns x % m if m != 0, x otherwise. // i.e. "return (m == 0) ? x : (x % m);", but without causing a warning with stupid older compilers template constexpr Tval modulo_if_not_zero(Tval x) { return ModIfNotZeroImpl().mod(x); } // rounds x up to multiples of target template constexpr T align_up(T x, T target) { return ((x + (target - 1)) / target) * target; } // rounds x down to multiples of target template constexpr T align_down(T x, T target) { return (x / target) * target; } // Returns sign of a number (-1 for negative numbers, 1 for positive numbers, 0 for 0) template constexpr int signum(T value) { return (value > T(0)) - (value < T(0)); } } // namespace MPT_INLINE_NS } // namespace mpt #endif // MPT_BASE_ALGORITHM_HPP