LCOV - code coverage report
Current view: top level - src/AH/Math - IncreaseBitDepth.hpp (source / functions) Coverage Total Hit
Test: 73449d9b107c772cf65493691543348214e5d5eb Lines: 100.0 % 21 21
Test Date: 2026-06-06 17:44:35 Functions: 96.9 % 65 63
Legend: Lines:     hit not hit

            Line data    Source code
       1              : #pragma once
       2              : 
       3              : #include <AH/STL/type_traits> // enable_if
       4              : #include <limits.h>           // CHAR_BIT
       5              : #include <stddef.h>           // size_t
       6              : 
       7              : BEGIN_AH_NAMESPACE
       8              : 
       9              : namespace detail {
      10              : 
      11              : template <size_t Bits_out, size_t Bits_in, class T_out, class T_in>
      12              : std::enable_if_t<(Bits_out <= 2 * Bits_in) && (Bits_out > Bits_in), T_out>
      13          101 : increaseBitDepthImpl(T_in in) {
      14          101 :     constexpr size_t leftShift = Bits_out - Bits_in;
      15          101 :     constexpr size_t rightShift = Bits_in - leftShift;
      16          101 :     return (static_cast<T_out>(in) << leftShift) | (in >> rightShift);
      17              : }
      18              : 
      19              : template <size_t Bits_out, size_t Bits_in, class T_out, class T_in>
      20            2 : std::enable_if_t<(Bits_out <= Bits_in), T_out> increaseBitDepthImpl(T_in in) {
      21            2 :     constexpr size_t rightShift = Bits_in - Bits_out;
      22            2 :     return static_cast<T_out>(in >> rightShift);
      23              : }
      24              : 
      25              : template <size_t Bits_out, size_t Bits_in, class T_out, class T_in>
      26              : std::enable_if_t<(Bits_out > 2 * Bits_in), T_out>
      27           38 : increaseBitDepthImpl(T_in in) {
      28           38 :     constexpr size_t leftShift = Bits_out - Bits_in;
      29           30 :     return (static_cast<T_out>(in) << leftShift) |
      30           38 :            increaseBitDepthImpl<leftShift, Bits_in, T_out>(in);
      31              : }
      32              : 
      33              : } // namespace detail
      34              : 
      35              : /// @addtogroup    AH_Math
      36              : /// @{
      37              : 
      38              : /**
      39              :  * @brief   Increase the bit depth of the given value from `Bits_in` bits wide
      40              :  *          to `Bits_out` bits wide, (approximately) evenly distributing the 
      41              :  *          error across the entire range, such that the error for each element
      42              :  *          is between -1 and +1.
      43              :  * 
      44              :  * @see @ref increaseBitDepthMiddle
      45              :  * 
      46              :  * For example, converting 3-bit numbers to 7-bit numbers would result in the
      47              :  * following:
      48              :  * 
      49              :  * | in (dec) | in (bin) | out (bin) | out (dec) | exact  | error |
      50              :  * |:--------:|:--------:|:---------:|:---------:|:------:|:-----:|
      51              :  * | 0        | 000      | 000'0000  | 0         | 0.00   | +0.00 |
      52              :  * | 1        | 001      | 001'0010  | 18        | 18.14  | +0.14 |
      53              :  * | 2        | 010      | 010'0100  | 36        | 36.29  | +0.29 |
      54              :  * | 3        | 011      | 011'0110  | 54        | 54.43  | +0.43 |
      55              :  * | 4        | 100      | 100'1001  | 73        | 72.57  | -0.43 |
      56              :  * | 5        | 101      | 101'1011  | 91        | 90.71  | -0.29 |
      57              :  * | 6        | 110      | 110'1101  | 109       | 108.86 | -0.14 |
      58              :  * | 7        | 111      | 111'1111  | 127       | 127.00 | +0.00 |
      59              :  *
      60              :  * The following is a comparison to the @ref increaseBitDepthMiddle function.
      61              :  *
      62              :  * @image html increase-bit-depth.svg
      63              :  *
      64              :  * @tparam  Bits_out 
      65              :  *          The number of bits of the output range.
      66              :  * @tparam  Bits_in 
      67              :  *          The number of bits of the input range.
      68              :  * @tparam  T_out 
      69              :  *          The type of the output (return type).
      70              :  * @tparam  T_in 
      71              :  *          The type of the input.
      72              :  * @param   in 
      73              :  *          The value to scale up.
      74              :  * @return  The scaled up value.
      75              :  */
      76              : template <size_t Bits_out, size_t Bits_in, class T_out, class T_in>
      77          103 : T_out increaseBitDepth(T_in in) {
      78              :     static_assert(Bits_in <= sizeof(T_in) * CHAR_BIT,
      79              :                   "Error: Bits_in > bits(T_in)");
      80              :     static_assert(Bits_out <= sizeof(T_out) * CHAR_BIT,
      81              :                   "Error: Bits_out > bits(T_out)");
      82          103 :     return detail::increaseBitDepthImpl<Bits_out, Bits_in, T_out>(in);
      83              : }
      84              : 
      85              : /**
      86              :  * @brief   Increase the bit depth of the given value from `Bits_in` bits wide
      87              :  *          to `Bits_out` bits wide, while ensuring that the middle of the input
      88              :  *          range maps exactly to the middle of the output range, i.e.
      89              :  *          @f$ 2^{\texttt{Bits\_in} - 1} @f$ maps to
      90              :  *          @f$ 2^{\texttt{Bits\_out} - 1} @f$.
      91              :  * 
      92              :  * @see @ref increaseBitDepth
      93              :  *
      94              :  * For example, converting 3-bit numbers to 7-bit numbers would result in the
      95              :  * following:
      96              :  * 
      97              :  * | in (dec) | in (bin) | out (bin) | out (dec) | exact  | error |
      98              :  * |:--------:|:--------:|:---------:|:---------:|:------:|:-----:|
      99              :  * | 0        | 000      | 000'0000  | 0         | 0.00   | +0.00 |
     100              :  * | 1        | 001      | 001'0000  | 16        | 18.14  | -2.14 |
     101              :  * | 2        | 010      | 010'0000  | 32        | 36.29  | -4.29 |
     102              :  * | 3        | 011      | 011'0000  | 48        | 54.43  | -6.43 |
     103              :  * | 4        | 100      | 100'0000  | 64        | 72.57  | -8.57 |
     104              :  * | 5        | 101      | 101'0101  | 85        | 90.71  | -5.71 |
     105              :  * | 6        | 110      | 110'1010  | 106       | 108.86 | -2.86 |
     106              :  * | 7        | 111      | 111'1111  | 127       | 127.00 | +0.00 |
     107              :  *
     108              :  * The following is a comparison to the @ref increaseBitDepth function.
     109              :  *
     110              :  * @image html increase-bit-depth.svg
     111              :  * 
     112              :  * @tparam  Bits_out 
     113              :  *          The number of bits of the output range.
     114              :  * @tparam  Bits_in 
     115              :  *          The number of bits of the input range.
     116              :  * @tparam  T_out 
     117              :  *          The type of the output (return type).
     118              :  * @tparam  T_in 
     119              :  *          The type of the input.
     120              :  * @param   in 
     121              :  *          The value to scale up.
     122              :  * @return  The scaled up value.
     123              :  */
     124              : template <size_t Bits_out, size_t Bits_in, class T_out, class T_in>
     125           20 : T_out increaseBitDepthMiddle(T_in in) {
     126              :     static_assert(Bits_in <= sizeof(T_in) * CHAR_BIT,
     127              :                   "Error: Bits_in > bits(T_in)");
     128              :     static_assert(Bits_out <= sizeof(T_out) * CHAR_BIT,
     129              :                   "Error: Bits_out > bits(T_out)");
     130           20 :     constexpr size_t leftShift = Bits_out - Bits_in;
     131           20 :     T_in half = T_in {1} << (Bits_in - 1);
     132           20 :     T_out out = static_cast<T_out>(in) << leftShift;
     133           20 :     if (in > half) {
     134            9 :         T_in repeat = in & (half - 1);
     135            9 :         out |= increaseBitDepth<leftShift, Bits_in - 1, T_out>(repeat);
     136              :     }
     137           20 :     return out;
     138              : }
     139              : 
     140              : /// @}
     141              : 
     142              : END_AH_NAMESPACE
        

Generated by: LCOV version 2.4-beta