From e7644522c85d9ed6a4bb3b5dfd5e40737403a6f6 Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Sun, 12 Dec 2021 16:35:53 -0600 Subject: [PATCH 1/9] fix overflow bug in prevpow --- base/intfuncs.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 29cf041cbcf7b..e15fa48ca194a 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -490,14 +490,15 @@ julia> prevpow(4, 16) 16 ``` """ -function prevpow(a::Real, x::Real) +function prevpow(a::Real, x::T) where T <: Real x < 1 && throw(DomainError(x, "`x` must be ≥ 1.")) # See comment in nextpos() for a == special case. a == 2 && isa(x, Integer) && return _prevpow2(x) a <= 1 && throw(DomainError(a, "`a` must be greater than 1.")) n = floor(Integer,log(a, x)) - p = a^(n+1) - p <= x ? p : a^n + p = a^n + wp = widemul(p,a) + wp <= x ? T(wp) : p end ## ndigits (number of digits) in base 10 ## From 4c9ffaff4e429fcd9c7e0ce7558f804d98d41352 Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Sun, 12 Dec 2021 16:38:05 -0600 Subject: [PATCH 2/9] add test --- test/intfuncs.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/intfuncs.jl b/test/intfuncs.jl index 0814229a5d41b..0564ea85ae45d 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -264,6 +264,7 @@ end @test prevpow(2, 3) == 2 @test prevpow(2, 4) == 4 @test prevpow(2, 5) == 4 + @test prevpow(10, 1234567890123456789)) == 1000000000000000000 @test_throws DomainError prevpow(0, 3) @test_throws DomainError prevpow(0, 3) end From b820458345ec664d9c12c15c642d6f3f743a0f0d Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Mon, 13 Dec 2021 09:30:33 -0500 Subject: [PATCH 3/9] fix test --- test/intfuncs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/intfuncs.jl b/test/intfuncs.jl index 0564ea85ae45d..991b844492a79 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -264,7 +264,7 @@ end @test prevpow(2, 3) == 2 @test prevpow(2, 4) == 4 @test prevpow(2, 5) == 4 - @test prevpow(10, 1234567890123456789)) == 1000000000000000000 + @test prevpow(10, 1234567890123456789) == 1000000000000000000 @test_throws DomainError prevpow(0, 3) @test_throws DomainError prevpow(0, 3) end From 66ed9dc0bcfc13efa04e5abf60bcb38a08a06e66 Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Mon, 13 Dec 2021 12:02:55 -0500 Subject: [PATCH 4/9] fix type stability --- base/intfuncs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index e15fa48ca194a..9c811aa041a8f 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -496,7 +496,7 @@ function prevpow(a::Real, x::T) where T <: Real a == 2 && isa(x, Integer) && return _prevpow2(x) a <= 1 && throw(DomainError(a, "`a` must be greater than 1.")) n = floor(Integer,log(a, x)) - p = a^n + p = T(a)^n wp = widemul(p,a) wp <= x ? T(wp) : p end From a3bb6c74aa7e91ff5f7e9a2ad6a2d4b1b8d27b36 Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Mon, 13 Dec 2021 12:18:57 -0500 Subject: [PATCH 5/9] use mul_with_overflow for integer types --- base/intfuncs.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 9c811aa041a8f..5a35b65ae102f 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -497,8 +497,12 @@ function prevpow(a::Real, x::T) where T <: Real a <= 1 && throw(DomainError(a, "`a` must be greater than 1.")) n = floor(Integer,log(a, x)) p = T(a)^n - wp = widemul(p,a) - wp <= x ? T(wp) : p + if a isa Integer && x isa Integer + wp, overflow = mul_with_overflow(T(a), x) + return overflow ? T(wp) : p + end + wp = p*a + return wp <= x ? T(wp) : p end ## ndigits (number of digits) in base 10 ## From 6f01b8898a1c8b888d89a486e68b959997579004 Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Mon, 13 Dec 2021 13:34:56 -0500 Subject: [PATCH 6/9] oops --- base/intfuncs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 5a35b65ae102f..98ad98f7c35b5 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -499,7 +499,7 @@ function prevpow(a::Real, x::T) where T <: Real p = T(a)^n if a isa Integer && x isa Integer wp, overflow = mul_with_overflow(T(a), x) - return overflow ? T(wp) : p + return overflow ? p : T(wp) end wp = p*a return wp <= x ? T(wp) : p From bef005f133e126dea7b75e615f059f2bc43e70f7 Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Mon, 13 Dec 2021 14:51:09 -0500 Subject: [PATCH 7/9] fix type issues --- base/intfuncs.jl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 98ad98f7c35b5..98351c4bb6870 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -490,19 +490,19 @@ julia> prevpow(4, 16) 16 ``` """ -function prevpow(a::Real, x::T) where T <: Real +function prevpow(a::T, x::Real) where T <: Real x < 1 && throw(DomainError(x, "`x` must be ≥ 1.")) # See comment in nextpos() for a == special case. a == 2 && isa(x, Integer) && return _prevpow2(x) a <= 1 && throw(DomainError(a, "`a` must be greater than 1.")) n = floor(Integer,log(a, x)) - p = T(a)^n - if a isa Integer && x isa Integer - wp, overflow = mul_with_overflow(T(a), x) - return overflow ? p : T(wp) + p = a^n + if a isa Integer + wp, overflow = mul_with_overflow(a, p) + return overflow ? p : wp end wp = p*a - return wp <= x ? T(wp) : p + return wp <= x ? wp : p end ## ndigits (number of digits) in base 10 ## From afaf6260bc324dae960cbcc4c02568597798e0fa Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Mon, 13 Dec 2021 14:52:29 -0500 Subject: [PATCH 8/9] update tests --- test/intfuncs.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/intfuncs.jl b/test/intfuncs.jl index 991b844492a79..4fc21c3bcf1b2 100644 --- a/test/intfuncs.jl +++ b/test/intfuncs.jl @@ -264,7 +264,9 @@ end @test prevpow(2, 3) == 2 @test prevpow(2, 4) == 4 @test prevpow(2, 5) == 4 - @test prevpow(10, 1234567890123456789) == 1000000000000000000 + @test prevpow(Int64(10), Int64(1234567890123456789)) === Int64(1000000000000000000) + @test prevpow(10, 101.0) === 100 + @test prevpow(10.0, 101) === 100.0 @test_throws DomainError prevpow(0, 3) @test_throws DomainError prevpow(0, 3) end From bbef44f94a9088e0603e61e5c573a6c7ffead800 Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Mon, 13 Dec 2021 15:09:24 -0500 Subject: [PATCH 9/9] fix --- base/intfuncs.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/intfuncs.jl b/base/intfuncs.jl index 98351c4bb6870..3c2d9b4beec7b 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -499,7 +499,7 @@ function prevpow(a::T, x::Real) where T <: Real p = a^n if a isa Integer wp, overflow = mul_with_overflow(a, p) - return overflow ? p : wp + return (wp <= x && !overflow) ? wp : p end wp = p*a return wp <= x ? wp : p