|
| 1 | +// SPDX-License-Identifier: BSD-3-Clause |
| 2 | +// |
| 3 | +// Copyright(c) 2021 Intel Corporation. All rights reserved. |
| 4 | +// |
| 5 | +// Author: Shriram Shastry <malladi.sastry@linux.intel.com> |
| 6 | +// |
| 7 | +// |
| 8 | + |
| 9 | +/* Include Files */ |
| 10 | +#include <sof/math/base2log.h> |
| 11 | + |
| 12 | +/* Defines Constant*/ |
| 13 | +#define BASE2LOG_WRAP_SCHAR_BITS 0xFF |
| 14 | +#define BASE2LOG_UPPERBYTES 0xFFFFFF |
| 15 | +#define BASE2LOG_WORDLENGTH 0x1F |
| 16 | +/** |
| 17 | + * Base-2 logarithm log2(n) |
| 18 | + * |
| 19 | + * Y = (u) computes the base-2 logarithm of |
| 20 | + * u using lookup table. |
| 21 | + * input u must be scalar/real number and positive |
| 22 | + * |
| 23 | + * +------------------+-----------------+--------+--------+ |
| 24 | + * | u | y (returntype) | u | y | |
| 25 | + * +----+-----+-------+----+----+-------+--------+--------+ |
| 26 | + * |WLen| FLen|Signbit|WLen|FLen|Signbit| Qformat| Qformat| |
| 27 | + * +----+-----+-------+----+----+-------+--------+--------+ |
| 28 | + * | 32 | 0 | 0 | 32 | 16 | 0 | 32.0 | 16.16 | |
| 29 | + * +------------------+-----------------+--------+--------+ |
| 30 | + * |
| 31 | + * Arguments : uint32_t u |
| 32 | + * u input range [1 to 4294967295] |
| 33 | + * |
| 34 | + * Return Type : int32_t y |
| 35 | + * y output range [0 to 32] |
| 36 | + * |
| 37 | + */ |
| 38 | +int32_t base2_logarithm(uint32_t u) |
| 39 | +{ |
| 40 | + static const int32_t iv1[129] = { |
| 41 | + 0, 736, 1466, 2190, 2909, 3623, 4331, 5034, 5732, 6425, 7112, 7795, |
| 42 | + 8473, 9146, 9814, 10477, 11136, 11791, 12440, 13086, 13727, 14363, 14996, 15624, |
| 43 | + 16248, 16868, 17484, 18096, 18704, 19308, 19909, 20505, 21098, 21687, 22272, 22854, |
| 44 | + 23433, 24007, 24579, 25146, 25711, 26272, 26830, 27384, 27936, 28484, 29029, 29571, |
| 45 | + 30109, 30645, 31178, 31707, 32234, 32758, 33279, 33797, 34312, 34825, 35334, 35841, |
| 46 | + 36346, 36847, 37346, 37842, 38336, 38827, 39316, 39802, 40286, 40767, 41246, 41722, |
| 47 | + 42196, 42667, 43137, 43603, 44068, 44530, 44990, 45448, 45904, 46357, 46809, 47258, |
| 48 | + 47705, 48150, 48593, 49034, 49472, 49909, 50344, 50776, 51207, 51636, 52063, 52488, |
| 49 | + 52911, 53332, 53751, 54169, 54584, 54998, 55410, 55820, 56229, 56635, 57040, 57443, |
| 50 | + 57845, 58245, 58643, 59039, 59434, 59827, 60219, 60609, 60997, 61384, 61769, 62152, |
| 51 | + 62534, 62915, 63294, 63671, 64047, 64421, 64794, 65166, 65536}; |
| 52 | + static const int8_t iv[256] = { |
| 53 | + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, |
| 54 | + 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, |
| 55 | + 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 56 | + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, |
| 57 | + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 58 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 59 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 60 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 61 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; |
| 62 | + uint64_t v; |
| 63 | + uint32_t x; |
| 64 | + int32_t a_i; |
| 65 | + int32_t l1_i; |
| 66 | + int32_t s_v; |
| 67 | + int32_t l2_i; |
| 68 | + int32_t l3_i; |
| 69 | + int num_left_shifts; |
| 70 | + int shift_factor; |
| 71 | + unsigned int slice_temp; |
| 72 | + /* Skipping for-loop */ |
| 73 | + /* Unroll the loop so there will be no branching. */ |
| 74 | + /* Loop unroll execute 20% faster (CPU cycle count )than for loop */ |
| 75 | + /* Every iteration, look for leading zeros are in the high */ |
| 76 | + /* byte of V, and shift them out to the left. Continue with the */ |
| 77 | + /* shifted V for as many bytes as it has. */ |
| 78 | + /* The index is the high byte of the input plus 1 to make it a */ |
| 79 | + /* one-based index. */ |
| 80 | + /* Index into the number-of-leading-zeros lookup table. This lookup */ |
| 81 | + /* table takes in a byte and returns the number of leading zeros in the */ |
| 82 | + /* binary representation. */ |
| 83 | + shift_factor = iv[u >> 24]; |
| 84 | + /* Left-shift out all the leading zeros in the high byte. */ |
| 85 | + v = (uint64_t)u << shift_factor; |
| 86 | + /* Update the total number of left-shifts */ |
| 87 | + num_left_shifts = shift_factor; |
| 88 | + shift_factor = iv[v >> 24]; |
| 89 | + /* Left-shift out all the leading zeros in the high byte. */ |
| 90 | + v <<= shift_factor; |
| 91 | + /* Update the total number of left-shifts */ |
| 92 | + num_left_shifts += shift_factor; |
| 93 | + shift_factor = iv[v >> 24]; |
| 94 | + /* Left-shift out all the leading zeros in the high byte. */ |
| 95 | + v <<= shift_factor; |
| 96 | + /* Update the total number of left-shifts */ |
| 97 | + num_left_shifts += shift_factor; |
| 98 | + shift_factor = iv[v >> 24]; |
| 99 | + /* Left-shift out all the leading zeros in the high byte. */ |
| 100 | + /* Update the total number of left-shifts */ |
| 101 | + num_left_shifts += shift_factor; |
| 102 | + /* The input has been left-shifted so the most-significant-bit is a 1. */ |
| 103 | + /* Reinterpret the output as unsigned with one integer bit, so */ |
| 104 | + /* that 1 <= x < 2. */ |
| 105 | + x = (uint32_t)v << shift_factor; |
| 106 | + /* Let Q = int(u). Then u = Q*2^(-u_fraction_length), */ |
| 107 | + /* and x = Q*2^num_left_shifts * 2^(1-word_length). Therefore, */ |
| 108 | + /* u = x*2^n, where n is defined as: */ |
| 109 | + /* Extract the high byte of x */ |
| 110 | + /* Convert the high byte into an index for lookup table */ |
| 111 | + slice_temp = (v << shift_factor) >> 24; |
| 112 | + /* Interpolate between points. */ |
| 113 | + /* The upper byte was used for the index into lookup table */ |
| 114 | + /* The remaining bits make up the fraction between points. */ |
| 115 | + a_i = BASE2LOG_WORDLENGTH - num_left_shifts; |
| 116 | + a_i <<= 16; |
| 117 | + l1_i = iv1[(BASE2LOG_WRAP_SCHAR_BITS & ((x >> 24) + 129)) - 1]; |
| 118 | + s_v = a_i + l1_i; |
| 119 | + l2_i = iv1[(BASE2LOG_WRAP_SCHAR_BITS & (slice_temp + 130)) - 1]; |
| 120 | + l3_i = iv1[(slice_temp - 127) - 1]; |
| 121 | + return s_v + (((x & BASE2LOG_UPPERBYTES) * (int64_t)(l2_i - l3_i)) >> 24); |
| 122 | +} |
| 123 | + |
0 commit comments