Skip to content

Commit a67e9e4

Browse files
committed
merge revision(s) 3a7b9ca: [Backport #21217]
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]
1 parent 5640fea commit a67e9e4

File tree

3 files changed

+10
-2
lines changed

3 files changed

+10
-2
lines changed

numeric.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5844,7 +5844,11 @@ prefix##_isqrt(argtype n) \
58445844
while ((t = n/x) < (argtype)x) x = (rettype)((x + t) >> 1); \
58455845
return x; \
58465846
} \
5847-
return (rettype)sqrt(argtype##_TO_DOUBLE(n)); \
5847+
rettype x = (rettype)sqrt(argtype##_TO_DOUBLE(n)); \
5848+
/* libm sqrt may returns a larger approximation than actual. */ \
5849+
/* Our isqrt always returns a smaller approximation. */ \
5850+
if (x * x > n) x--; \
5851+
return x; \
58485852
}
58495853

58505854
#if SIZEOF_LONG*CHAR_BIT > DBL_MANT_DIG

test/ruby/test_integer.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,10 @@ def test_square_root
709709
assert_equal(x, Integer.sqrt(x ** 2), "[ruby-core:95453]")
710710
end
711711

712+
def test_bug_21217
713+
assert_equal(0x10000 * 2**10, Integer.sqrt(0x100000008 * 2**20))
714+
end
715+
712716
def test_fdiv
713717
assert_equal(1.0, 1.fdiv(1))
714718
assert_equal(0.5, 1.fdiv(2))

version.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
1212
#define RUBY_VERSION_TEENY 7
1313
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
14-
#define RUBY_PATCHLEVEL 141
14+
#define RUBY_PATCHLEVEL 142
1515

1616
#include "ruby/version.h"
1717
#include "ruby/internal/abi.h"

0 commit comments

Comments
 (0)