diff --git a/base/intfuncs.jl b/base/intfuncs.jl index f1e404ec77359..a85f37724b800 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -309,3 +309,10 @@ function digits{T<:Integer}(n::Integer, base::T=10, pad::Int=1) end isqrt(x::Integer) = oftype(x, trunc(sqrt(x))) + +function isqrt(x::Union(Int64,Uint64,Int128,Uint128)) + s = oftype(x, trunc(sqrt(x))) + # fix with a Newton iteration, since conversion to float discards + # too many bits. + (s + div(x,s)) >> 1 +end diff --git a/doc/stdlib/base.rst b/doc/stdlib/base.rst index 4d111b6e9d81a..8894ecf0afa09 100644 --- a/doc/stdlib/base.rst +++ b/doc/stdlib/base.rst @@ -2551,9 +2551,9 @@ Mathematical Functions Return :math:`\sqrt{x}`. Throws ``DomainError`` for negative ``Real`` arguments. Use complex negative arguments instead. -.. function:: isqrt(x) +.. function:: isqrt(n) - Integer square root. + Integer square root: the largest integer ``m`` such that ``m*m <= n``. .. function:: cbrt(x) diff --git a/test/math.jl b/test/math.jl index 22ae859e166d3..2903713f03edf 100644 --- a/test/math.jl +++ b/test/math.jl @@ -173,3 +173,7 @@ end # Ensure subnormal flags functions don't segfault @test any(ccall("jl_zero_subnormals", Uint8, (Uint8,), 1) .== [0x00 0x01]) @test any(ccall("jl_zero_subnormals", Uint8, (Uint8,), 0) .== [0x00 0x01]) + +# isqrt (issue #4884) +@test isqrt(9223372030926249000) == 3037000498 +@test isqrt(typemax(Int128)) == int128("13043817825332782212")