diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-04-11 07:34:56 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-04-11 07:34:56 +0200 |
commit | 8a134ec68075fc2fd415558bcf6a37cda3ff285f (patch) | |
tree | e6c4927ebcb071b6dcb6e9832ebe6d7f4b721461 | |
parent | 10673c44f11045a0c99b19f32930097e9b3ae148 (diff) | |
download | busybox-w32-8a134ec68075fc2fd415558bcf6a37cda3ff285f.tar.gz busybox-w32-8a134ec68075fc2fd415558bcf6a37cda3ff285f.tar.bz2 busybox-w32-8a134ec68075fc2fd415558bcf6a37cda3ff285f.zip |
libbb: move isqrt from factor, use it in diff too
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | coreutils/factor.c | 19 | ||||
-rw-r--r-- | editors/diff.c | 11 | ||||
-rw-r--r-- | include/libbb.h | 2 | ||||
-rw-r--r-- | libbb/isqrt.c | 60 |
4 files changed, 63 insertions, 29 deletions
diff --git a/coreutils/factor.c b/coreutils/factor.c index f910fdb44..11cc04f92 100644 --- a/coreutils/factor.c +++ b/coreutils/factor.c | |||
@@ -44,24 +44,7 @@ typedef unsigned long half_t; | |||
44 | #error Cant find an integer type which is half as wide as ullong | 44 | #error Cant find an integer type which is half as wide as ullong |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | /* Returns such x that x+1 > sqrt(N) */ | 47 | static half_t isqrt_odd(wide_t N) |
48 | static inline half_t isqrt(wide_t N) | ||
49 | { | ||
50 | half_t x; | ||
51 | unsigned shift; | ||
52 | |||
53 | shift = WIDE_BITS - 2; | ||
54 | x = 0; | ||
55 | do { | ||
56 | x = (x << 1) + 1; | ||
57 | if ((wide_t)x * x > (N >> shift)) | ||
58 | x--; /* whoops, that +1 was too much */ | ||
59 | shift -= 2; | ||
60 | } while ((int)shift >= 0); | ||
61 | return x; | ||
62 | } | ||
63 | |||
64 | static NOINLINE half_t isqrt_odd(wide_t N) | ||
65 | { | 48 | { |
66 | half_t s = isqrt(N); | 49 | half_t s = isqrt(N); |
67 | /* Subtract 1 from even s, odd s won't change: */ | 50 | /* Subtract 1 from even s, odd s won't change: */ |
diff --git a/editors/diff.c b/editors/diff.c index 0eb825cfb..3304edb26 100644 --- a/editors/diff.c +++ b/editors/diff.c | |||
@@ -295,17 +295,6 @@ static int search(const int *c, int k, int y, const struct cand *list) | |||
295 | } | 295 | } |
296 | } | 296 | } |
297 | 297 | ||
298 | static unsigned isqrt(unsigned n) | ||
299 | { | ||
300 | unsigned x = 1; | ||
301 | while (1) { | ||
302 | const unsigned y = x; | ||
303 | x = ((n / x) + x) >> 1; | ||
304 | if (x <= (y + 1) && x >= (y - 1)) | ||
305 | return x; | ||
306 | } | ||
307 | } | ||
308 | |||
309 | static void stone(const int *a, int n, const int *b, int *J, int pref) | 298 | static void stone(const int *a, int n, const int *b, int *J, int pref) |
310 | { | 299 | { |
311 | const unsigned isq = isqrt(n); | 300 | const unsigned isq = isqrt(n); |
diff --git a/include/libbb.h b/include/libbb.h index a2c699b54..04071639a 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -342,6 +342,8 @@ extern int *const bb_errno; | |||
342 | uint64_t bb_bswap_64(uint64_t x) FAST_FUNC; | 342 | uint64_t bb_bswap_64(uint64_t x) FAST_FUNC; |
343 | #endif | 343 | #endif |
344 | 344 | ||
345 | unsigned long FAST_FUNC isqrt(unsigned long long N); | ||
346 | |||
345 | unsigned long long monotonic_ns(void) FAST_FUNC; | 347 | unsigned long long monotonic_ns(void) FAST_FUNC; |
346 | unsigned long long monotonic_us(void) FAST_FUNC; | 348 | unsigned long long monotonic_us(void) FAST_FUNC; |
347 | unsigned long long monotonic_ms(void) FAST_FUNC; | 349 | unsigned long long monotonic_ms(void) FAST_FUNC; |
diff --git a/libbb/isqrt.c b/libbb/isqrt.c new file mode 100644 index 000000000..817b7d036 --- /dev/null +++ b/libbb/isqrt.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 Denys Vlasenko <vda.linux@googlemail.com> | ||
3 | * | ||
4 | * Licensed under GPLv2, see file LICENSE in this source tree. | ||
5 | */ | ||
6 | |||
7 | //kbuild:lib-y += isqrt.o | ||
8 | |||
9 | #ifndef ISQRT_TEST | ||
10 | # include "libbb.h" | ||
11 | #else | ||
12 | /* gcc -DISQRT_TEST -Wall -O2 isqrt.c -oisqrt && ./isqrt $((RANDOM*RANDOM)) */ | ||
13 | # include <stdlib.h> | ||
14 | # include <stdio.h> | ||
15 | # include <time.h> | ||
16 | # define FAST_FUNC /* nothing */ | ||
17 | #endif | ||
18 | |||
19 | /* Returns such x that x+1 > sqrt(N) */ | ||
20 | unsigned long FAST_FUNC isqrt(unsigned long long N) | ||
21 | { | ||
22 | unsigned long x; | ||
23 | unsigned shift; | ||
24 | #define LL_WIDTH_BITS (unsigned)(sizeof(N)*8) | ||
25 | |||
26 | shift = LL_WIDTH_BITS - 2; | ||
27 | x = 0; | ||
28 | do { | ||
29 | x = (x << 1) + 1; | ||
30 | if ((unsigned long long)x * x > (N >> shift)) | ||
31 | x--; /* whoops, that +1 was too much */ | ||
32 | shift -= 2; | ||
33 | } while ((int)shift >= 0); | ||
34 | return x; | ||
35 | } | ||
36 | |||
37 | #ifdef ISQRT_TEST | ||
38 | int main(int argc, char **argv) | ||
39 | { | ||
40 | unsigned long long n = argv[1] ? strtoull(argv[1], NULL, 0) : time(NULL); | ||
41 | for (;;) { | ||
42 | unsigned long h; | ||
43 | n--; | ||
44 | h = isqrt(n); | ||
45 | if (!(n & 0xffff)) | ||
46 | printf("isqrt(%llx)=%lx\n", n, h); | ||
47 | if ((unsigned long long)h * h > n) { | ||
48 | printf("BAD1: isqrt(%llx)=%lx\n", n, h); | ||
49 | return 1; | ||
50 | } | ||
51 | h++; | ||
52 | if ((unsigned long long)h * h != 0 /* this can overflow to 0 - not a bug */ | ||
53 | && (unsigned long long)h * h <= n) | ||
54 | { | ||
55 | printf("BAD2: isqrt(%llx)=%lx\n", n, h); | ||
56 | return 1; | ||
57 | } | ||
58 | } | ||
59 | } | ||
60 | #endif | ||