Line data Source code
1 : #pragma once 2 : 3 : #include <AH/Settings/Warnings.hpp> 4 : AH_DIAGNOSTIC_WERROR() // Enable errors on warnings 5 : 6 : #include <AH/STL/type_traits> // enable_if 7 : #include <limits.h> // CHAR_BIT 8 : #include <stddef.h> // size_t 9 : 10 : BEGIN_AH_NAMESPACE 11 : 12 : template <size_t Bits_out, size_t Bits_in, class T_out, class T_in> 13 : std::enable_if_t<(Bits_out <= 2 * Bits_in), T_out> 14 94 : increaseBitDepthImpl(T_in in) { 15 94 : constexpr size_t leftShift = Bits_out - Bits_in; 16 94 : constexpr size_t rightShift = Bits_in - leftShift; 17 94 : return (T_out(in) << leftShift) | (in >> rightShift); 18 : } 19 : 20 : template <size_t Bits_out, size_t Bits_in, class T_out, class T_in> 21 : std::enable_if_t<(Bits_out > 2 * Bits_in), T_out> 22 8 : increaseBitDepthImpl(T_in in) { 23 8 : constexpr size_t leftShift = Bits_out - Bits_in; 24 0 : return (T_out(in) << leftShift) | 25 8 : increaseBitDepthImpl<leftShift, Bits_in, T_out>(in); 26 : } 27 : 28 : /// @addtogroup AH_Math 29 : /// @{ 30 : 31 : /** 32 : * @brief Increase the bit depth of the given value from `Bits_in` bits wide 33 : * to `Bits_out` bits wide, (approximately) evenly distributing the 34 : * error across the entire range, such that the error for each element 35 : * is between -1 and +1. 36 : * 37 : * For example, converting 3-bit numbers to 7-bit numbers would result in the 38 : * following: 39 : * 40 : * | in (dec) | in (bin) | out (bin) | out (dec) | exact | error | 41 : * |:--------:|:--------:|:---------:|:---------:|:------:|:-----:| 42 : * | 0 | 000 | 000'0000 | 0 | 0.00 | +0.00 | 43 : * | 1 | 001 | 001'0010 | 18 | 18.14 | +0.14 | 44 : * | 2 | 010 | 010'0100 | 36 | 36.29 | +0.29 | 45 : * | 3 | 011 | 011'0110 | 54 | 54.43 | +0.43 | 46 : * | 4 | 100 | 100'1001 | 73 | 72.57 | -0.43 | 47 : * | 5 | 101 | 101'1011 | 91 | 90.71 | -0.29 | 48 : * | 6 | 110 | 110'1101 | 109 | 108.86 | -0.14 | 49 : * | 7 | 111 | 111'1111 | 127 | 127.00 | +0.00 | 50 : * 51 : * @tparam Bits_out 52 : * The number of bits of the output range. 53 : * @tparam Bits_in 54 : * The number of bits of the input range. 55 : * @tparam T_out 56 : * The type of the output (return type). 57 : * @tparam T_in 58 : * The type of the input. 59 : * @param in 60 : * The value to scale up. 61 : * @return The scaled up value. 62 : */ 63 : template <size_t Bits_out, size_t Bits_in, class T_out, class T_in> 64 94 : T_out increaseBitDepth(T_in in) { 65 : static_assert(Bits_in <= sizeof(T_in) * CHAR_BIT, 66 : "Error: Bits_in > bits(T_in)"); 67 : static_assert(Bits_out <= sizeof(T_out) * CHAR_BIT, 68 : "Error: Bits_out > bits(T_out)"); 69 94 : return increaseBitDepthImpl<Bits_out, Bits_in, T_out>(in); 70 : } 71 : 72 : /// @} 73 : 74 : END_AH_NAMESPACE 75 : 76 : AH_DIAGNOSTIC_POP()