mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
If an input number x for int_sqrt64() has the highest bit set, then fls64(x) is 64. (1UL << 64) is an overflow and breaks the algorithm. Subtracting 1 is a better guess for the initial value of m anyway and that's what also done in int_sqrt() implicitly [*]. [*] Note how int_sqrt() uses __fls() with two underscores, which already returns the proper raw bit number. In contrast, int_sqrt64() used fls64(), and that returns bit numbers illogically starting at 1, because of error handling for the "no bits set" case. Will points out that he bug probably is due to a copy-and-paste error from the regular int_sqrt() case. Change-Id: I5be5be3e03ddbe68cc8025a64698bbb49c57c3a5 Acked-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Florian La Roche <Florian.LaRoche@googlemail.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Yousef Algadri <yusufgadrie@gmail.com> Signed-off-by: Richard Raya <rdxzv.dev@gmail.com>
71 lines
1.1 KiB
C
71 lines
1.1 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (C) 2013 Davidlohr Bueso <davidlohr.bueso@hp.com>
|
|
*
|
|
* Based on the shift-and-subtract algorithm for computing integer
|
|
* square root from Guy L. Steele.
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/export.h>
|
|
#include <linux/bitops.h>
|
|
|
|
/**
|
|
* int_sqrt - computes the integer square root
|
|
* @x: integer of which to calculate the sqrt
|
|
*
|
|
* Computes: floor(sqrt(x))
|
|
*/
|
|
unsigned long int_sqrt(unsigned long x)
|
|
{
|
|
unsigned long b, m, y = 0;
|
|
|
|
if (x <= 1)
|
|
return x;
|
|
|
|
m = 1UL << (__fls(x) & ~1UL);
|
|
while (m != 0) {
|
|
b = y + m;
|
|
y >>= 1;
|
|
|
|
if (x >= b) {
|
|
x -= b;
|
|
y += m;
|
|
}
|
|
m >>= 2;
|
|
}
|
|
|
|
return y;
|
|
}
|
|
EXPORT_SYMBOL(int_sqrt);
|
|
|
|
#if BITS_PER_LONG < 64
|
|
/**
|
|
* int_sqrt64 - strongly typed int_sqrt function when minimum 64 bit input
|
|
* is expected.
|
|
* @x: 64bit integer of which to calculate the sqrt
|
|
*/
|
|
u32 int_sqrt64(u64 x)
|
|
{
|
|
u64 b, m, y = 0;
|
|
|
|
if (x <= ULONG_MAX)
|
|
return int_sqrt((unsigned long) x);
|
|
|
|
m = 1ULL << ((fls64(x) - 1) & ~1ULL);
|
|
while (m != 0) {
|
|
b = y + m;
|
|
y >>= 1;
|
|
|
|
if (x >= b) {
|
|
x -= b;
|
|
y += m;
|
|
}
|
|
m >>= 2;
|
|
}
|
|
|
|
return y;
|
|
}
|
|
EXPORT_SYMBOL(int_sqrt64);
|
|
#endif
|