Skip to content

Commit af86581

Browse files
singalsukv2019i
authored andcommitted
Math: Add 32-bit square root function sofm_sqrt_int32()
This patch adds a higher precision 32-bit fractional integer square root function to SOF math library. The algorithm uses a lookup table for initial value and two iterations with Newton-Raphson method to improve the accuracy. Both input and output format is Q2.30. The format was chosen to match complex to polar conversions numbers range for Q1.31 complex values. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
1 parent 66534d3 commit af86581

3 files changed

Lines changed: 77 additions & 1 deletion

File tree

src/include/sof/math/sqrt.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,16 @@
1717
* @return Calculated square root of n in Q4.12 format, from 0 to 4.0.
1818
*/
1919
uint16_t sofm_sqrt_int16(uint16_t u);
20+
21+
/**
22+
* sofm_sqrt_int32() - Calculate 32-bit fractional square root function.
23+
* @param n Input value in Q2.30 format, from 0 to 2.0.
24+
* @return Calculated square root of n in Q2.30 format.
25+
*
26+
* The input range of square root function is matched with Q1.31
27+
* complex numbers range where the magnitude squared can be to 2.0.
28+
* The function returns zero for non-positive input values.
29+
*/
30+
int32_t sofm_sqrt_int32(int32_t n);
31+
2032
#endif /* __SOF_MATH_SQRT_H__ */

src/math/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ if(CONFIG_MATH_LUT_SINE_FIXED)
1616
endif()
1717

1818
if(CONFIG_SQRT_FIXED)
19-
list(APPEND base_files sqrt_int16.c)
19+
list(APPEND base_files sqrt_int16.c sqrt_int32.c)
2020
endif()
2121

2222
if(CONFIG_MATH_EXP)

src/math/sqrt_int32.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// SPDX-License-Identifier: BSD-3-Clause
2+
//
3+
// Copyright(c) 2026 Intel Corporation.
4+
//
5+
// Author: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
6+
//
7+
8+
#include <sof/math/sqrt.h>
9+
#include <rtos/symbol.h>
10+
#include <stdint.h>
11+
12+
/* Lookup table for square root for initial value in iteration,
13+
* created with Octave commands:
14+
*
15+
* arg=((1:64) * 2^25) / 2^30; lut = int32(sqrt(arg) * 2^30);
16+
* fmt=['static const int32_t sqrt_int32_lut[] = {' repmat(' %d,',1, numel(lut)-1) ' %d};\n'];
17+
* fprintf(fmt, lut)
18+
*/
19+
static const int32_t sqrt_int32_lut[] = {
20+
189812531, 268435456, 328764948, 379625062, 424433723, 464943848, 502196753,
21+
536870912, 569437594, 600239927, 629536947, 657529896, 684378814, 710213460,
22+
735140772, 759250125, 782617115, 805306368, 827373642, 848867446, 869830292,
23+
890299688, 910308921, 929887697, 949062656, 967857801, 986294844, 1004393507,
24+
1022171763, 1039646051, 1056831447, 1073741824, 1090389977, 1106787739, 1122946079,
25+
1138875187, 1154584553, 1170083026, 1185378878, 1200479854, 1215393219, 1230125796,
26+
1244684005, 1259073893, 1273301169, 1287371222, 1301289153, 1315059792, 1328687719,
27+
1342177280, 1355532607, 1368757628, 1381856086, 1394831545, 1407687407, 1420426919,
28+
1433053185, 1445569171, 1457977717, 1470281545, 1482483261, 1494585366, 1506590260,
29+
1518500250
30+
};
31+
32+
/* sofm_sqrt_int32() - Calculate 32-bit fractional square root function. */
33+
int32_t sofm_sqrt_int32(int32_t n)
34+
{
35+
uint64_t n_shifted;
36+
uint32_t x;
37+
int shift;
38+
39+
if (n < 1)
40+
return 0;
41+
42+
/* Scale input argument with 2^n, where n is even.
43+
* Scale calculated sqrt() with 2^(-n/2).
44+
*/
45+
shift = (__builtin_clz(n) - 1) & ~1; /* Make even by clearing LSB */
46+
n = n << shift;
47+
shift >>= 1; /* Divide by 2 for sqrt shift compensation */
48+
49+
/* For Q2.30 divide */
50+
n_shifted = (uint64_t)n << 30;
51+
52+
/* Get initial guess from LUT, idx = 0 .. 63 */
53+
x = sqrt_int32_lut[n >> 25];
54+
55+
/* Iterate x(n+1) = 1/2 * (x(n) + N / x(n))
56+
* N is argument for square root
57+
* x(n) is initial guess. Do two iterations.
58+
*/
59+
x = (uint32_t)(((n_shifted / x + x) + 1) >> 1);
60+
x = (uint32_t)(((n_shifted / x + x) + 1) >> 1);
61+
62+
return (int32_t)(x >> shift);
63+
}
64+
EXPORT_SYMBOL(sofm_sqrt_int32);

0 commit comments

Comments
 (0)