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