diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/int_sqrt.c | 32 |
1 files changed, 19 insertions, 13 deletions
diff --git a/lib/int_sqrt.c b/lib/int_sqrt.c index fc2eeb7cb2ea..1ef4cc344977 100644 --- a/lib/int_sqrt.c +++ b/lib/int_sqrt.c | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Davidlohr Bueso <davidlohr.bueso@hp.com> | ||
3 | * | ||
4 | * Based on the shift-and-subtract algorithm for computing integer | ||
5 | * square root from Guy L. Steele. | ||
6 | */ | ||
1 | 7 | ||
2 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
3 | #include <linux/export.h> | 9 | #include <linux/export.h> |
@@ -10,23 +16,23 @@ | |||
10 | */ | 16 | */ |
11 | unsigned long int_sqrt(unsigned long x) | 17 | unsigned long int_sqrt(unsigned long x) |
12 | { | 18 | { |
13 | unsigned long op, res, one; | 19 | unsigned long b, m, y = 0; |
14 | 20 | ||
15 | op = x; | 21 | if (x <= 1) |
16 | res = 0; | 22 | return x; |
17 | 23 | ||
18 | one = 1UL << (BITS_PER_LONG - 2); | 24 | m = 1UL << (BITS_PER_LONG - 2); |
19 | while (one > op) | 25 | while (m != 0) { |
20 | one >>= 2; | 26 | b = y + m; |
27 | y >>= 1; | ||
21 | 28 | ||
22 | while (one != 0) { | 29 | if (x >= b) { |
23 | if (op >= res + one) { | 30 | x -= b; |
24 | op = op - (res + one); | 31 | y += m; |
25 | res = res + 2 * one; | ||
26 | } | 32 | } |
27 | res /= 2; | 33 | m >>= 2; |
28 | one /= 4; | ||
29 | } | 34 | } |
30 | return res; | 35 | |
36 | return y; | ||
31 | } | 37 | } |
32 | EXPORT_SYMBOL(int_sqrt); | 38 | EXPORT_SYMBOL(int_sqrt); |