#pragma once #include #include #include #include BEGIN_AH_NAMESPACE /// Divide by N using the default division operator, without explicit rounding /// This should be used for floating point types. For integers, prefer using /// @ref round_div_unsigned_int and @ref round_div_signed_int. template struct round_div_default { static T div(T val) { return val / N; } }; /// Divide an unsigned integer by N, rounding the result. template struct round_div_unsigned_int { static T div(T val) { return (val + (N / 2)) / N; static_assert(std::is_unsigned::value && std::is_integral::value, "This function is only valid for unsigned integers"); } }; /// Divide a signed integer by N, rounding the result. template struct round_div_signed_int { static T div(T val) { T offset = val >= 0 ? (N / 2) : (-N / 2); return (val + offset) / N; } }; /// Select the right rounding division operator, depending on whether T is a /// signed or unsigned integer. template struct round_div_int : std::conditional::value, round_div_signed_int, round_div_unsigned_int>::type {}; /// Select the right rounding division operator, depending on whether T is an /// integer or not. template struct round_div_helper : std::conditional::value, round_div_int, round_div_default>::type {}; /// Divide a number by N and round the result. Uses different specializations /// for integers to implement efficient rounding. template T round_div(T val) { return round_div_helper::div(val); } END_AH_NAMESPACE