Skip to content

Commit

Permalink
Deprecate nextpow2/prevpow2
Browse files Browse the repository at this point in the history
Base 2 is an important special case here, but we can just handle that
as a special case in the implementation of `nextpow` rather than
having a whole separate user facing function.
  • Loading branch information
Keno authored and JeffBezanson committed Jul 31, 2018
1 parent 749f073 commit 1f52ab6
Show file tree
Hide file tree
Showing 9 changed files with 38 additions and 62 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1352,6 +1352,8 @@ Deprecated or removed

* `sortrows`/`sortcols` have been deprecated in favor of the more general `sortslices`.

* `nextpow2`/`prevpow2` have been deprecated in favor of the more general `nextpow`/`prevpow` functions.

Command-line option changes
---------------------------

Expand Down
4 changes: 4 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1780,6 +1780,10 @@ end
@deprecate sortrows(A::AbstractMatrix; kws...) sortslices(A, dims=1, kws...)
@deprecate sortcols(A::AbstractMatrix; kws...) sortslices(A, dims=2, kws...)

# PR #28304
@deprecate nextpow2(x) nextpow(2, x)
@deprecate prevpow2(x) prevpow(2, x)

# END 0.7 deprecations

# BEGIN 1.0 deprecations
Expand Down
2 changes: 0 additions & 2 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -297,15 +297,13 @@ export
muladd,
nextfloat,
nextpow,
nextpow2,
nextprod,
numerator,
one,
oneunit,
powermod,
prevfloat,
prevpow,
prevpow2,
rad2deg,
rationalize,
real,
Expand Down
7 changes: 4 additions & 3 deletions base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import .Base: *, +, -, /, <, <<, >>, >>>, <=, ==, >, >=, ^, (~), (&), (|), xor,
binomial, cmp, convert, div, divrem, factorial, fld, gcd, gcdx, lcm, mod,
ndigits, promote_rule, rem, show, isqrt, string, powermod,
sum, trailing_zeros, trailing_ones, count_ones, tryparse_internal,
bin, oct, dec, hex, isequal, invmod, prevpow2, nextpow2, ndigits0zpb,
bin, oct, dec, hex, isequal, invmod, _prevpow2, _nextpow2, ndigits0zpb,
widen, signed, unsafe_trunc, trunc, iszero, isone, big, flipsign, signbit,
hastypemax

Expand Down Expand Up @@ -634,10 +634,11 @@ function ndigits0zpb(x::BigInt, b::Integer)
end
end

# Fast paths for nextpow(2, x::BigInt)
# below, ONE is always left-shifted by at least one digit, so a new BigInt is
# allocated, which can be safely mutated
prevpow2(x::BigInt) = -2 <= x <= 2 ? x : flipsign!(ONE << (ndigits(x, base=2) - 1), x)
nextpow2(x::BigInt) = count_ones_abs(x) <= 1 ? x : flipsign!(ONE << ndigits(x, base=2), x)
_prevpow2(x::BigInt) = -2 <= x <= 2 ? x : flipsign!(ONE << (ndigits(x, base=2) - 1), x)
_nextpow2(x::BigInt) = count_ones_abs(x) <= 1 ? x : flipsign!(ONE << ndigits(x, base=2), x)

Base.checked_abs(x::BigInt) = abs(x)
Base.checked_neg(x::BigInt) = -x
Expand Down
53 changes: 13 additions & 40 deletions base/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ function powermod(x::Integer, p::Integer, m::T) where T<:Integer
(m == 1 || m == -1) && return zero(m)
b = oftype(m,mod(x,m)) # this also checks for divide by zero

t = prevpow2(p)
t = prevpow(2, p)
r::T = 1
while true
if p >= t
Expand All @@ -309,43 +309,10 @@ end
# optimization: promote the modulus m to BigInt only once (cf. widemul in generic powermod above)
powermod(x::Integer, p::Integer, m::Union{Int128,UInt128}) = oftype(m, powermod(x, p, big(m)))

# smallest power of 2 >= x

"""
nextpow2(n::Integer)
The smallest power of two not less than `n`. Returns 0 for `n==0`, and returns
`-nextpow2(-n)` for negative arguments.
# Examples
```jldoctest
julia> nextpow2(16)
16
julia> nextpow2(17)
32
```
"""
nextpow2(x::Unsigned) = oneunit(x)<<((sizeof(x)<<3)-leading_zeros(x-oneunit(x)))
nextpow2(x::Integer) = reinterpret(typeof(x),x < 0 ? -nextpow2(unsigned(-x)) : nextpow2(unsigned(x)))

"""
prevpow2(n::Integer)
The largest power of two not greater than `n`. Returns 0 for `n==0`, and returns
`-prevpow2(-n)` for negative arguments.
# Examples
```jldoctest
julia> prevpow2(5)
4
julia> prevpow2(0)
0
```
"""
prevpow2(x::Unsigned) = one(x) << unsigned((sizeof(x)<<3)-leading_zeros(x)-1)
prevpow2(x::Integer) = reinterpret(typeof(x),x < 0 ? -prevpow2(unsigned(-x)) : prevpow2(unsigned(x)))
_nextpow2(x::Unsigned) = oneunit(x)<<((sizeof(x)<<3)-leading_zeros(x-oneunit(x)))
_nextpow2(x::Integer) = reinterpret(typeof(x),x < 0 ? -_nextpow2(unsigned(-x)) : _nextpow2(unsigned(x)))
_prevpow2(x::Unsigned) = one(x) << unsigned((sizeof(x)<<3)-leading_zeros(x)-1)
_prevpow2(x::Integer) = reinterpret(typeof(x),x < 0 ? -_prevpow2(unsigned(-x)) : _prevpow2(unsigned(x)))

"""
ispow2(n::Integer) -> Bool
Expand Down Expand Up @@ -387,8 +354,12 @@ julia> nextpow(4, 16)
See also [`prevpow`](@ref).
"""
function nextpow(a::Real, x::Real)
a <= 1 && throw(DomainError(a, "`a` must be greater than 1."))
x <= 0 && throw(DomainError(x, "`x` must be positive."))
# Special case fast path for x::Integer, a == 2.
# This is a very common case. Constant prop will make sure that a call site
# specified as `nextpow(2, x)` will get this special case inlined.
a == 2 && isa(x, Integer) && return _nextpow2(x)
a <= 1 && throw(DomainError(a, "`a` must be greater than 1."))
x <= 1 && return one(a)
n = ceil(Integer,log(a, x))
p = a^(n-1)
Expand Down Expand Up @@ -419,8 +390,10 @@ julia> prevpow(4, 16)
See also [`nextpow`](@ref).
"""
function prevpow(a::Real, x::Real)
a <= 1 && throw(DomainError(a, "`a` must be greater than 1."))
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
Expand Down
2 changes: 0 additions & 2 deletions doc/src/base/math.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,6 @@ Base.gcd
Base.lcm
Base.gcdx
Base.ispow2
Base.nextpow2
Base.prevpow2
Base.nextpow
Base.prevpow
Base.nextprod
Expand Down
4 changes: 2 additions & 2 deletions stdlib/Random/src/misc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ randsubseq(A::AbstractArray, p::Real) = randsubseq(GLOBAL_RNG, A, p)
## rand Less Than Masked 52 bits (helper function)

"Return a sampler generating a random `Int` (masked with `mask`) in ``[0, n)``, when `n <= 2^52`."
ltm52(n::Int, mask::Int=nextpow2(n)-1) = LessThan(n-1, Masked(mask, UInt52Raw(Int)))
ltm52(n::Int, mask::Int=nextpow(2, n)-1) = LessThan(n-1, Masked(mask, UInt52Raw(Int)))

## shuffle & shuffle!

Expand Down Expand Up @@ -183,7 +183,7 @@ function shuffle!(r::AbstractRNG, a::AbstractArray)
@assert !has_offset_axes(a)
n = length(a)
@assert n <= Int64(2)^52
mask = nextpow2(n) - 1
mask = nextpow(2, n) - 1
for i = n:-1:2
(mask >> 1) == i && (mask >>= 1)
j = 1 + rand(r, ltm52(i, mask))
Expand Down
3 changes: 1 addition & 2 deletions test/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,13 @@ end
@test powermod(2, -2, -5) == -1
end
@testset "nextpow/prevpow" begin
@test nextpow2(3) == 4
@test nextpow(2, 3) == 4
@test nextpow(2, 4) == 4
@test nextpow(2, 7) == 8
@test_throws DomainError nextpow(0, 3)
@test_throws DomainError nextpow(3, 0)

@test prevpow2(3) == 2
@test prevpow(2, 3) == 2
@test prevpow(2, 4) == 4
@test prevpow(2, 5) == 4
@test_throws DomainError prevpow(0, 3)
Expand Down
23 changes: 12 additions & 11 deletions test/numbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1909,20 +1909,21 @@ end
@test rem(typemin(Int),-1) == 0
@test mod(typemin(Int),-1) == 0
end
@testset "prevpow2/nextpow2" begin
@test nextpow2(0) == prevpow2(0) == 0
for i = -2:2
@test nextpow2(i) == prevpow2(i) == i
@testset "prevpow(2, _)/nextpow(2, _)" begin
for i = 1:2
@test nextpow(2, i) == prevpow(2, i) == i
end
@test nextpow2(56789) == -nextpow2(-56789) == 65536
@test prevpow2(56789) == -prevpow2(-56789) == 32768
for i = -100:100
@test nextpow2(i) == nextpow2(big(i))
@test prevpow2(i) == prevpow2(big(i))
@test nextpow(2, 56789) == 65536
@test_throws DomainError nextpow(2, -56789)
@test prevpow(2, 56789) == 32768
@test_throws DomainError prevpow(2, -56789)
for i = 1:100
@test nextpow(2, i) == nextpow(2, big(i))
@test prevpow(2, i) == prevpow(2, big(i))
end
for T in (Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64)
@test nextpow2(T(42)) === T(64)
@test prevpow2(T(42)) === T(32)
@test nextpow(2, T(42)) === T(64)
@test prevpow(2, T(42)) === T(32)
end
end
@testset "ispow2" begin
Expand Down

0 comments on commit 1f52ab6

Please sign in to comment.