mirror of https://gerrit.osmocom.org/libosmocore
Add osmo_isqrt32() to compute 32bit integer square root
Change-Id: I2b96db6e037e72e92317fec874877e473a1cf909
This commit is contained in:
parent
dfb0b97f55
commit
15a5f8de00
|
@ -128,4 +128,6 @@ const char *osmo_escape_str_buf(const char *str, int in_len, char *buf, size_t b
|
|||
const char *osmo_quote_str(const char *str, int in_len);
|
||||
const char *osmo_quote_str_buf(const char *str, int in_len, char *buf, size_t bufsize);
|
||||
|
||||
uint32_t osmo_isqrt32(uint32_t x);
|
||||
|
||||
/*! @} */
|
||||
|
|
40
src/utils.c
40
src/utils.c
|
@ -592,4 +592,44 @@ const char *osmo_quote_str(const char *str, int in_len)
|
|||
return osmo_quote_str_buf(str, in_len, namebuf, sizeof(namebuf));
|
||||
}
|
||||
|
||||
/*! perform an integer square root operation on unsigned 32bit integer.
|
||||
* This implementation is taken from "Hacker's Delight" Figure 11-1 "Integer square root, Newton's
|
||||
* method", which can also be found at http://www.hackersdelight.org/hdcodetxt/isqrt.c.txt */
|
||||
uint32_t osmo_isqrt32(uint32_t x)
|
||||
{
|
||||
uint32_t x1;
|
||||
int s, g0, g1;
|
||||
|
||||
if (x <= 1)
|
||||
return x;
|
||||
|
||||
s = 1;
|
||||
x1 = x - 1;
|
||||
if (x1 > 0xffff) {
|
||||
s = s + 8;
|
||||
x1 = x1 >> 16;
|
||||
}
|
||||
if (x1 > 0xff) {
|
||||
s = s + 4;
|
||||
x1 = x1 >> 8;
|
||||
}
|
||||
if (x1 > 0xf) {
|
||||
s = s + 2;
|
||||
x1 = x1 >> 4;
|
||||
}
|
||||
if (x1 > 0x3) {
|
||||
s = s + 1;
|
||||
}
|
||||
|
||||
g0 = 1 << s; /* g0 = 2**s */
|
||||
g1 = (g0 + (x >> s)) >> 1; /* g1 = (g0 + x/g0)/2 */
|
||||
|
||||
/* converges after four to five divisions for arguments up to 16,785,407 */
|
||||
while (g1 < g0) {
|
||||
g0 = g1;
|
||||
g1 = (g0 + (x/g0)) >> 1;
|
||||
}
|
||||
return g0;
|
||||
}
|
||||
|
||||
/*! @} */
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
|
||||
static void hexdump_test(void)
|
||||
{
|
||||
|
@ -425,6 +426,26 @@ static void str_quote_test(void)
|
|||
printf("'%s'\n", osmo_quote_str_buf(NULL, -1, out_buf, 10));
|
||||
}
|
||||
|
||||
static void isqrt_test(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("\nTesting integer square-root\n");
|
||||
srand(time(NULL));
|
||||
for (i = 0; i < 1024; i++) {
|
||||
uint16_t x;
|
||||
uint32_t r = rand();
|
||||
if (RAND_MAX < UINT16_MAX)
|
||||
x = r * (UINT16_MAX/RAND_MAX);
|
||||
else
|
||||
x = r;
|
||||
uint32_t sq = x*x;
|
||||
uint32_t y = osmo_isqrt32(sq);
|
||||
if (y != x)
|
||||
printf("ERROR: x=%u, sq=%u, osmo_isqrt(%u) = %u\n", x, sq, sq, y);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
static const struct log_info log_info = {};
|
||||
|
@ -437,5 +458,6 @@ int main(int argc, char **argv)
|
|||
bcd_test();
|
||||
str_escape_test();
|
||||
str_quote_test();
|
||||
isqrt_test();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -137,3 +137,5 @@ NOT passed through. '"printable"'
|
|||
'<buf-too-small>'
|
||||
- NULL string becomes a "NULL" literal:
|
||||
'NULL'
|
||||
|
||||
Testing integer square-root
|
||||
|
|
Loading…
Reference in New Issue