Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ndigits: make base and pad keywords #27908

Merged
merged 2 commits into from
Jul 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1300,6 +1300,8 @@ Deprecated or removed
(along with other utilities mostly used at the interactive prompt, such as `edit`
and `less`) ([#27635]).

* `ndigits(n, b, [pad])` is deprecated in favor of `ndigits(n, base=b, pad=pad)` ([#27908]).

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

Expand Down
10 changes: 8 additions & 2 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1440,8 +1440,14 @@ end
@deprecate countlines(x, eol) countlines(x, eol = eol)
@deprecate PipeBuffer(data, maxsize) PipeBuffer(data, maxsize = maxsize)
@deprecate unsafe_wrap(T, pointer, dims, own) unsafe_wrap(T, pointer, dims, own = own)
@deprecate digits(n, base, pad) digits(n, base = base, pad = pad)
@deprecate digits(T, n, base, pad) digits(T, n, base = base, pad = pad)
@deprecate digits(n, base) digits(n, base = base)
@deprecate digits(n, base, pad) digits(n, base = base, pad = pad)
@deprecate digits(T::Type{<:Integer}, n, base) digits(T, n, base = base)
@deprecate digits(T::Type{<:Integer}, n, base, pad) digits(T, n, base = base, pad = pad)

#27908
@deprecate ndigits(n, base) ndigits(n, base=base)
@deprecate ndigits(n, base, pad) ndigits(n, base=base, pad=pad)

@deprecate print_with_color(color, args...; kwargs...) printstyled(args...; kwargs..., color=color)

Expand Down
8 changes: 4 additions & 4 deletions base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ function string(n::BigInt; base::Integer = 10, pad::Integer = 1)
base < 0 && return Base._base(Int(base), n, pad, (base>0) & (n.size<0))
2 <= base <= 62 || throw(ArgumentError("base must be 2 ≤ base ≤ 62, got $base"))
iszero(n) && pad < 1 && return ""
nd1 = ndigits(n, base)
nd1 = ndigits(n, base=base)
nd = max(nd1, pad)
sv = Base.StringVector(nd + isneg(n))
GC.@preserve sv MPZ.get_str!(pointer(sv) + nd - nd1, base, n)
Expand All @@ -618,7 +618,7 @@ function ndigits0zpb(x::BigInt, b::Integer)
MPZ.sizeinbase(x, b)
else
# non-base 2 mpz_sizeinbase might return an answer 1 too big
# use property that log(b, x) < ndigits(x, b) <= log(b, x) + 1
# use property that log(b, x) < ndigits(x, base=b) <= log(b, x) + 1
n = MPZ.sizeinbase(x, 2)
lb = log2(b) # assumed accurate to <1ulp (true for openlibm)
q,r = divrem(n,lb)
Expand All @@ -636,8 +636,8 @@ end

# 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, 2) - 1), x)
nextpow2(x::BigInt) = count_ones_abs(x) <= 1 ? x : flipsign!(ONE << ndigits(x, 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
32 changes: 16 additions & 16 deletions base/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -454,10 +454,6 @@ ndigits0z(x::BitSigned) = ndigits0z(unsigned(abs(x)))

ndigits0z(x::Integer) = ndigits0zpb(x, 10)

# TODO (when keywords args are fast): rename to ndigits and make pad a keyword
ndigits10(x::Integer, pad::Int=1) = max(pad, ndigits0z(x))
ndigits(x::Integer) = iszero(x) ? 1 : ndigits0z(x)

## ndigits with specified base ##

# The suffix "nb" stands for "negative base"
Expand Down Expand Up @@ -510,7 +506,7 @@ ndigits0zpb(x::Bool, b::Integer) = x % Int
ndigits0z(n::Integer, b::Integer=10)

Return 0 if `n == 0`, otherwise compute the number of digits in
integer `n` written in base `b` (i.e. equal to `ndigits(n, b)`
integer `n` written in base `b` (i.e. equal to `ndigits(n, base=b)`
in this case).
The base `b` must not be in `[-1, 0, 1]`.

Expand All @@ -519,7 +515,7 @@ The base `b` must not be in `[-1, 0, 1]`.
julia> Base.ndigits0z(0, 16)
0

julia> Base.ndigits(0, 16)
julia> Base.ndigits(0, base=16)
1

julia> Base.ndigits0z(0)
Expand All @@ -540,29 +536,33 @@ function ndigits0z(x::Integer, b::Integer)
elseif b > 1
ndigits0zpb(x, b)
else
throw(DomainError(b, "The base `b` must not be in `[-1, 0, 1]`."))
throw(DomainError(b, "The base must not be in `[-1, 0, 1]`."))
end
end

"""
ndigits(n::Integer, b::Integer=10)
ndigits(n::Integer; base::Integer=10, pad::Integer=1)

Compute the number of digits in integer `n` written in base `b`.
The base `b` must not be in `[-1, 0, 1]`.
Compute the number of digits in integer `n` written in base `base`
(`base` must not be in `[-1, 0, 1]`), optionally padded with zeros
to a specified size (the result will never be less than `pad`).

# Examples
```jldoctest
julia> ndigits(12345)
5

julia> ndigits(1022, 16)
julia> ndigits(1022, base=16)
3

julia> string(1022, base = 16)
julia> string(1022, base=16)
"3fe"

julia> ndigits(123, pad=5)
5
```
"""
ndigits(x::Integer, b::Integer, pad::Int=1) = max(pad, ndigits0z(x, b))
ndigits(x::Integer; base::Integer=10, pad::Int=1) = max(pad, ndigits0z(x, base))

## integer to string functions ##

Expand Down Expand Up @@ -591,7 +591,7 @@ function oct(x::Unsigned, pad::Int, neg::Bool)
end

function dec(x::Unsigned, pad::Int, neg::Bool)
i = neg + ndigits10(x, pad)
i = neg + ndigits(x, base=10, pad=pad)
a = StringVector(i)
while i > neg
a[i] = '0'+rem(x,10)
Expand Down Expand Up @@ -622,7 +622,7 @@ function _base(b::Int, x::Integer, pad::Int, neg::Bool)
(x >= 0) | (b < 0) || throw(DomainError(x, "For negative `x`, `b` must be negative."))
2 <= abs(b) <= 62 || throw(ArgumentError("base must satisfy 2 ≤ abs(base) ≤ 62, got $b"))
digits = abs(b) <= 36 ? base36digits : base62digits
i = neg + ndigits(x, b, pad)
i = neg + ndigits(x, base=b, pad=pad)
a = StringVector(i)
@inbounds while i > neg
if b > 0
Expand Down Expand Up @@ -732,7 +732,7 @@ digits(n::Integer; base::Integer = 10, pad::Integer = 1) =
digits(typeof(base), n, base = base, pad = pad)

function digits(T::Type{<:Integer}, n::Integer; base::Integer = 10, pad::Integer = 1)
digits!(zeros(T, ndigits(n, base, pad)), n, base = base)
digits!(zeros(T, ndigits(n, base=base, pad=pad)), n, base=base)
end

"""
Expand Down
2 changes: 1 addition & 1 deletion base/printf.jl
Original file line number Diff line number Diff line change
Expand Up @@ -917,7 +917,7 @@ decode_HEX(x::Integer) = decode_hex(x,HEX_symbols)

function decode(b::Int, x::BigInt)
neg = x.size < 0
pt = Base.ndigits(x, abs(b))
pt = Base.ndigits(x, base=abs(b))
digits = DIGITSs[Threads.threadid()]
length(digits) < pt+1 && resize!(digits, pt+1)
neg && (x.size = -x.size)
Expand Down
2 changes: 1 addition & 1 deletion stdlib/Random/src/generation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ end
function Sampler(::AbstractRNG, r::AbstractUnitRange{BigInt}, ::Repetition)
m = last(r) - first(r)
m < 0 && throw(ArgumentError("range must be non-empty"))
nd = ndigits(m, 2)
nd = ndigits(m, base=2)
nlimbs, highbits = divrem(nd, 8*sizeof(Limb))
highbits > 0 && (nlimbs += 1)
mask = highbits == 0 ? ~zero(Limb) : one(Limb)<<highbits - one(Limb)
Expand Down
6 changes: 3 additions & 3 deletions test/bigint.jl
Original file line number Diff line number Diff line change
Expand Up @@ -301,12 +301,12 @@ end
@test !any(ndigits_mismatch, 8192:9999)
end
# The following should not crash (#16579)
ndigits(big(rand(Int)), rand(63:typemax(Int)))
ndigits(big(rand(Int)), big(2)^rand(2:999))
ndigits(big(rand(Int)), base=rand(63:typemax(Int)))
ndigits(big(rand(Int)), base=big(2)^rand(2:999))

for x in big.([-20:20; rand(Int)])
for _base in -1:1
@test_throws DomainError ndigits(x, _base)
@test_throws DomainError ndigits(x, base=_base)
end
end

Expand Down
38 changes: 19 additions & 19 deletions test/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -104,42 +104,42 @@ end
end
@testset "ndigits/ndigits0z" begin
@testset "issue #8266" begin
@test ndigits(-15, 10) == 2
@test ndigits(-15, -10) == 2
@test ndigits(-1, 10) == 1
@test ndigits(-1, -10) == 2
@test ndigits(2, 10) == 1
@test ndigits(2, -10) == 1
@test ndigits(10, 10) == 2
@test ndigits(10, -10) == 3
@test ndigits(17, 10) == 2
@test ndigits(17, -10) == 3
@test ndigits(unsigned(17), -10) == 3
@test ndigits(-15, base=10) == 2
@test ndigits(-15, base=-10) == 2
@test ndigits(-1, base=10) == 1
@test ndigits(-1, base=-10) == 2
@test ndigits(2, base=10) == 1
@test ndigits(2, base=-10) == 1
@test ndigits(10, base=10) == 2
@test ndigits(10, base=-10) == 3
@test ndigits(17, base=10) == 2
@test ndigits(17, base=-10) == 3
@test ndigits(unsigned(17), base=-10) == 3

@test ndigits(146, -3) == 5
@test ndigits(146, base=-3) == 5
end
let (n, b) = rand(Int, 2)
-1 <= b <= 1 && (b = 2) # invalid bases
@test ndigits(n) == ndigits(big(n)) == ndigits(n, 10)
@test ndigits(n, b) == ndigits(big(n), b)
@test ndigits(n) == ndigits(big(n)) == ndigits(n, base=10)
@test ndigits(n, base=b) == ndigits(big(n), base=b)
end

for b in -1:1
@test_throws DomainError ndigits(rand(Int), b)
@test_throws DomainError ndigits(rand(Int), base=b)
end
@test ndigits(Int8(5)) == ndigits(5)

# issue #19367
@test ndigits(Int128(2)^64, 256) == 9
@test ndigits(Int128(2)^64, base=256) == 9

# test unsigned bases
@test ndigits(9, 0x2) == 4
@test ndigits(0x9, 0x2) == 4
@test ndigits(9, base=0x2) == 4
@test ndigits(0x9, base=0x2) == 4

# ndigits is defined for Bool
@test iszero([Base.ndigits0z(false, b) for b in [-20:-2;2:20]])
@test all(n -> n == 1, Base.ndigits0z(true, b) for b in [-20:-2;2:20])
@test all(n -> n == 1, ndigits(x, b) for b in [-20:-2;2:20] for x in [true, false])
@test all(n -> n == 1, ndigits(x, base=b) for b in [-20:-2;2:20] for x in [true, false])
end
@testset "bin/oct/dec/hex/bits" begin
@test string(UInt32('3'), base = 2) == "110011"
Expand Down