Skip to content

Commit e4f31f9

Browse files
committed
fix behavior and docs of nextpow and prevpow. closes #4819
1 parent 00d7813 commit e4f31f9

File tree

5 files changed

+45
-18
lines changed

5 files changed

+45
-18
lines changed

NEWS.md

+4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ Library improvements
2222
* `consume(p)` extended to `consume(p, args...)`, allowing it
2323
to optionally pass `args...` back to the producer ([#4775]).
2424

25+
* `nextpow` and `prevpow` now return the `a^n` values instead of the
26+
exponent `n` ([#4819])
27+
2528
Deprecated or removed
2629
---------------------
2730

@@ -32,6 +35,7 @@ Deprecated or removed
3235
[#4766]: https://github.com/JuliaLang/julia/issues/4766
3336
[#4782]: https://github.com/JuliaLang/julia/issues/4782
3437
[#4759]: https://github.com/JuliaLang/julia/issues/4759
38+
[#4819]: https://github.com/JuliaLang/julia/issues/4819
3539

3640

3741

base/combinatorics.jl

+4-4
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ function nextprod(a::Vector{Int}, x)
446446
end
447447
k = length(a)
448448
v = ones(Int, k) # current value of each counter
449-
mx = int(a.^nextpow(a, x)) # maximum value of each counter
449+
mx = int(nextpow(a, x)) # maximum value of each counter
450450
v[1] = mx[1] # start at first case that is >= x
451451
p::morebits(Int) = mx[1] # initial value of product in this case
452452
best = p
@@ -478,7 +478,7 @@ function nextprod(a::Vector{Int}, x)
478478
return int(best) # could overflow, but best to have predictable return type
479479
end
480480

481-
# For a list of integers i1, i2, i3, find the largest
481+
# For a list of integers i1, i2, i3, find the largest
482482
# i1^n1 * i2^n2 * i3^n3 <= x
483483
# for integer n1, n2, n3
484484
function prevprod(a::Vector{Int}, x)
@@ -487,8 +487,8 @@ function prevprod(a::Vector{Int}, x)
487487
end
488488
k = length(a)
489489
v = ones(Int, k) # current value of each counter
490-
mx = int(a.^nextpow(a, x)) # allow each counter to exceed p (sentinel)
491-
first = int(a[1]^prevpow(a[1], x)) # start at best case in first factor
490+
mx = int(nextpow(a, x)) # allow each counter to exceed p (sentinel)
491+
first = int(prevpow(a[1], x)) # start at best case in first factor
492492
v[1] = first
493493
p::morebits(Int) = first
494494
best = p

base/intfuncs.jl

+14-8
Original file line numberDiff line numberDiff line change
@@ -146,15 +146,21 @@ prevpow2(x::Integer) = oftype(x,x < 0 ? -prevpow2(unsigned(-x)) : prevpow2(unsig
146146

147147
ispow2(x::Integer) = ((x<=0) == (x&(x-1)))
148148

149-
# smallest integer n for which a^n >= x
150-
function nextpow(a, x)
151-
n = iceil(log(x) ./ log(a))
152-
return n - int(a.^(n-1) .>= x) # guard against roundoff error, e.g., with a=5 and x=125
149+
# smallest a^n >= x, with integer n
150+
function nextpow(a::Real, x::Real)
151+
(a <= 1 || x <= 0) && throw(DomainError())
152+
x <= 1 && return one(a)
153+
n = iceil(log(a, x))
154+
p = a^(n-1)
155+
# guard against roundoff error, e.g., with a=5 and x=125
156+
p >= x ? p : a^n
153157
end
154-
# largest integer n for which a^n <= x
155-
function prevpow(a, x)
156-
n = ifloor(log(x) ./ log(a))
157-
return n + int(a.^(n+1) .<= x)
158+
# largest a^n <= x, with integer n
159+
function prevpow(a::Real, x::Real)
160+
(a <= 1 || x < 1) && throw(DomainError())
161+
n = ifloor(log(a, x))
162+
p = a^(n+1)
163+
p <= x ? p : a^n
158164
end
159165

160166
# decimal digits in an unsigned integer

doc/stdlib/base.rst

+10-6
Original file line numberDiff line numberDiff line change
@@ -2657,19 +2657,23 @@ Mathematical Functions
26572657

26582658
.. function:: nextpow2(n)
26592659

2660-
Next power of two not less than ``n``
2660+
The smallest power of two not less than ``n``. Returns 0 for ``n==0``, and returns
2661+
``-nextpow2(-n)`` for negative arguments.
26612662

26622663
.. function:: prevpow2(n)
26632664

2664-
Previous power of two not greater than ``n``
2665+
The largest power of two not greater than ``n``. Returns 0 for ``n==0``, and returns
2666+
``-prevpow2(-n)`` for negative arguments.
26652667

2666-
.. function:: nextpow(a, n)
2668+
.. function:: nextpow(a, x)
26672669

2668-
Next power of ``a`` not less than ``n``
2670+
The smallest ``a^n`` not less than ``x``, where ``n`` is a non-negative integer.
2671+
``a`` must be greater than 1, and ``x`` must be greater than 0.
26692672

2670-
.. function:: prevpow(a, n)
2673+
.. function:: prevpow(a, x)
26712674

2672-
Previous power of ``a`` not greater than ``n``
2675+
The largest ``a^n`` not greater than ``x``, where ``n`` is a non-negative integer.
2676+
``a`` must be greater than 1, and ``x`` must not be less than 1.
26732677

26742678
.. function:: nextprod([k_1,k_2,...], n)
26752679

test/numbers.jl

+13
Original file line numberDiff line numberDiff line change
@@ -1563,3 +1563,16 @@ for i = -100:100
15631563
@test nextpow2(i) == nextpow2(big(i))
15641564
@test prevpow2(i) == prevpow2(big(i))
15651565
end
1566+
1567+
@test nextpow(2,1) == 1
1568+
@test prevpow(2,1) == 1
1569+
@test nextpow(3,243) == 243
1570+
@test prevpow(3,243) == 243
1571+
@test nextpow(3,241) == 243
1572+
@test prevpow(3,244) == 243
1573+
for a = -1:1
1574+
@test_throws nextpow(a, 2)
1575+
@test_throws prevpow(a, 2)
1576+
end
1577+
@test_throws nextpow(2,0)
1578+
@test_throws prevpow(2,0)

0 commit comments

Comments
 (0)