Fix Integer.sqrt
to never exceed actual value
`Integer.sqrt` uses `sqrt(3)` from libm for small values. This method must return a value less than or equal to the actual integer square root, but libm's sqrt does not always guarantee that. This change corrects that by decrementing the result if necessary. Fixes [Bug #21217]
This commit is contained in:
parent
e25889951f
commit
3a7b9ca93b
Notes:
git
2025-04-07 02:08:28 +00:00
@ -5978,7 +5978,11 @@ prefix##_isqrt(argtype n) \
|
||||
while ((t = n/x) < (argtype)x) x = (rettype)((x + t) >> 1); \
|
||||
return x; \
|
||||
} \
|
||||
return (rettype)sqrt(argtype##_TO_DOUBLE(n)); \
|
||||
rettype x = (rettype)sqrt(argtype##_TO_DOUBLE(n)); \
|
||||
/* libm sqrt may returns a larger approximation than actual. */ \
|
||||
/* Our isqrt always returns a smaller approximation. */ \
|
||||
if (x * x > n) x--; \
|
||||
return x; \
|
||||
}
|
||||
|
||||
#if SIZEOF_LONG*CHAR_BIT > DBL_MANT_DIG
|
||||
|
@ -708,6 +708,10 @@ class TestInteger < Test::Unit::TestCase
|
||||
assert_equal(x, Integer.sqrt(x ** 2), "[ruby-core:95453]")
|
||||
end
|
||||
|
||||
def test_bug_21217
|
||||
assert_equal(0x10000 * 2**10, Integer.sqrt(0x100000008 * 2**20))
|
||||
end
|
||||
|
||||
def test_fdiv
|
||||
assert_equal(1.0, 1.fdiv(1))
|
||||
assert_equal(0.5, 1.fdiv(2))
|
||||
|
Loading…
x
Reference in New Issue
Block a user