Skip to content

Commit 1600208

Browse files
ShriramShastrylgirdwood
authored andcommitted
math: Add power scalar and base 2 log function
fix point math power function having negative and positive values of base and exponent as function argument. power_int32() support only integer base and exponential value and it does not support fractional values for base and exponent. fix point math base 2 logarithm function using a short lookup tables Signed-off-by: ShriramShastry <malladi.sastry@intel.com>
1 parent 70358b7 commit 1600208

File tree

13 files changed

+589
-0
lines changed

13 files changed

+589
-0
lines changed

src/include/sof/math/base2log.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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+
#ifndef __SOF_MATH_BASE_TWO_LOGARITHM_H__
10+
#define __SOF_MATH_BASE_TWO_LOGARITHM_H__
11+
12+
/* Include Files */
13+
#include <stdint.h>
14+
/* Function Declarations */
15+
int32_t base2_logarithm(uint32_t u);
16+
17+
#endif

src/include/sof/math/power.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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+
#ifndef __SOF_MATH_POWER_H__
9+
#define __SOF_MATH_POWER_H__
10+
11+
/* Include Files */
12+
#include <stdint.h>
13+
/* Function Declarations */
14+
int32_t power_int32(int32_t b, int32_t e);
15+
16+
#endif

src/math/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ if(CONFIG_MATH_DECIBELS)
1414
add_local_sources(sof decibels.c)
1515
endif()
1616

17+
if(CONFIG_POWER_FIXED)
18+
add_local_sources(sof power.c)
19+
endif()
20+
21+
if(CONFIG_BINARY_LOGARITHM_FIXED)
22+
add_local_sources(sof base2log.c)
23+
endif()
24+
1725
if(CONFIG_MATH_FIR)
1826
add_local_sources(sof fir_generic.c fir_hifi2ep.c fir_hifi3.c)
1927
endif()

src/math/Kconfig

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,28 @@ config CORDIC_FIXED
99
Select this to enable sin(), cos(), asin(), acos(),
1010
and cexp() functions as 16 bit and 32 bit versions.
1111

12+
config POWER_FIXED
13+
bool "Power function"
14+
default n
15+
help
16+
This option builds the 32 bit power_int32(). A power represents repeated
17+
multiplication of the same number. power_int32() calculates the power
18+
raised to the base value. The power function works for even, odd and
19+
fractional base and exponent argument.Operating range of power_int32()
20+
with base having values from -32 to + 32 . Exponent values range from
21+
-3 to +3. Power out MIN/MAX range is -/+32768.
22+
23+
24+
config BINARY_LOGARITHM_FIXED
25+
bool "Binary Logarithm function"
26+
default n
27+
help
28+
This option builds Binary Logarithm function (log2n) is the logarithm to
29+
the base 2. The binary logarithm of x is the power to which the number 2
30+
must be raised to obtain the value x. Base 2 logarithm function is implemented
31+
with a short lookup table. (log2n) operates for a range of 32 bit width size
32+
i.e. 1 to 4294967295.
33+
1234
config NUMBERS_GCD
1335
bool "Greatest common divisor"
1436
default n

src/math/base2log.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
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+

src/math/power.c

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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+
// Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
7+
//
8+
9+
/* Include Files */
10+
#include <sof/audio/format.h>
11+
#include <sof/trace/trace.h>
12+
#include <sof/math/power.h>
13+
#include <sof/lib/uuid.h>
14+
#include <ipc/trace.h>
15+
#include <user/trace.h>
16+
#include <stdint.h>
17+
18+
/* d23cf8d0-8dfe-497c-8202-5f909cf72735 */
19+
DECLARE_SOF_UUID("math_power", math_power_uuid, 0xd23cf8d0, 0x8dfe, 0x497c,
20+
0x82, 0x02, 0x5f, 0x90, 0x9c, 0xf7, 0x27, 0x35);
21+
22+
DECLARE_TR_CTX(math_power_tr, SOF_UUID(math_power_uuid), LOG_LEVEL_INFO);
23+
/* define constant */
24+
#define POWER_MAX_LIMIT 0x8000
25+
26+
/* Function Definitions */
27+
28+
/**
29+
* Arguments : int32_t b
30+
* base input range [-32 to +32]
31+
*
32+
* : int32_t e
33+
* exponent input range [ -3 to +3 ]
34+
*
35+
* Return Type : int32_t
36+
* power output range [-32768 to + 32768]
37+
* ATTENTION - FRACTIONAL EXPONENTIAL IS NOT SUPPORTED
38+
* +------------------+------------------+------------------+--------+--------+--------+
39+
* | base | exponent | power(returntype)| b | e | p |
40+
* +----+-----+-------+----+-----+-------+----+----+--------+--------+--------+--------+
41+
* |WLen| FLen|Signbit|WLen| FLen|Signbit|WLen|FLen|Signbit | Qformat| Qformat| Qformat|
42+
* +----+-----+-------+----+-----+-------+----+----+--------+--------+--------+--------+
43+
* | 32 | 25 | 1 | 32 | 29 | 1 | 32 | 15 | 1 | 6.26 | 2.30 | 16.16 |
44+
* +------------------+------------------+------------------+--------+--------+--------+
45+
*/
46+
int32_t power_int32(int32_t b, int32_t e)
47+
{
48+
int32_t i;
49+
int32_t k;
50+
int32_t multiplier;
51+
int32_t p;
52+
53+
p = POWER_MAX_LIMIT;
54+
55+
if (e < 0) {
56+
e = -e;
57+
if (b) {
58+
multiplier = (int32_t)((1LL << 50) / (int64_t)b);
59+
} else {
60+
multiplier = INT32_MAX;
61+
tr_err(&math_power_tr, "power_int32(): Divide by zero error.");
62+
}
63+
} else {
64+
multiplier = b;
65+
}
66+
i = e >> 29;
67+
for (k = 0; k < i; k++)
68+
p = sat_int32((((p * (int64_t)multiplier) >> 24) + 1) >> 1);
69+
70+
return p;
71+
}

test/cmocka/include/log2_tables.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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+
/* Include Files */
8+
#include <stdint.h>
9+
10+
/* Reference table generated by Matlab log2() */
11+
static const double log2_lookup_table[] = {
12+
0.0000000000000000, 25.3706434118312352, 26.3706433952040058, 26.9556058903827527,
13+
27.3706433868903893, 27.6925714801150313, 27.9556058848403417, 28.1779983053850174,
14+
28.3706433827335829, 28.5405683837140280, 28.6925714767895848, 28.8300750002372048,
15+
28.9556058820691362, 29.0710830992759028, 29.1779983030096979, 29.2775339764022569,
16+
29.3706433806551779, 29.4581062237394029, 29.5405683837140280, 29.6185708955208291,
17+
29.6925714767895848, 29.7629608045226277, 29.8300750002372048, 29.8942053375254808,
18+
29.9556058820691362, 30.0144995710118572, 30.0710830992759028, 30.1255308832035382,
19+
30.1779983030096979, 30.2286243759977573, 30.2775339764022569, 30.3248396911091014,
20+
30.3706433806551779, 30.4150374999506496, 30.4581062217832610, 30.4999263974219978,
21+
30.5405683818665565, 30.5800967460032638, 30.6185708937705954, 30.6560455991443810,
22+
30.6925714751268615, 30.7281953848170275, 30.7629608029390802, 30.7969081348255926,
23+
30.8300749987256388, 30.8624964763844254, 30.8942053360796365, 30.9252322316694972,
24+
30.9556058806835352, 30.9853532240493088, 31.0144995703467679, 31.0430687225044153,
25+
31.0710830986363931, 31.0985638350223041, 31.1255308825877144, 31.1520030939153152,
26+
31.1779983024158689, 31.2035333944917532, 31.2286243754244062, 31.2532864296295223,
27+
31.2775339758480158, 31.3013807177751282, 31.3248396905727375, 31.3479233036602380,
28+
31.3706433801355793, 31.3930111931400511, 31.4150374994467967, 31.4367325705235530,
29+
31.4581062212942228, 31.4791678368007908, 31.4999263969469325, 31.5203904994865773,
30+
31.5405683814046895, 31.5604679388234146, 31.5800967455538810, 31.5994620704028364,
31+
31.6185708933330361, 31.6374299205673069, 31.6560455987180411, 31.6744241280167067,
32+
31.6925714747111797, 31.7104933826930484, 31.7281953844114852, 31.7456828115263257,
33+
31.7629608029390802, 31.7800343162793943, 31.7969081348255926, 31.8135868759544458,
34+
31.8300749987256388, 31.8463768110377572, 31.8624964763844254, 31.8784380202372049,
35+
31.8942053360796365, 31.9098021911151051, 31.9252322316694972, 31.9404989883079118,
36+
31.9556058806835352, 31.9705562221352224, 31.9853532240493088, 31.9999999996640980};

0 commit comments

Comments
 (0)