Skip to content
1 change: 1 addition & 0 deletions base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ function base(b::Integer, n::BigInt)
end

function ndigits0z(x::BigInt, b::Integer=10)
b < 0 && throw(DomainError()) # TODO: make this work correctly.
# mpz_sizeinbase might return an answer 1 too big
n = int(ccall((:__gmpz_sizeinbase,:libgmp), Culong, (Ptr{BigInt}, Int32), &x, b))
abs(x) < big(b)^(n-1) ? n-1 : n
Expand Down
39 changes: 27 additions & 12 deletions base/intfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -158,29 +158,44 @@ ndigits0z(x::Integer) = ndigits0z(unsigned(abs(x)))

const ndigits_max_mul = WORD_SIZE==32 ? 69000000 : 290000000000000000

function ndigits0z(n::Unsigned, b::Int)
b == 2 && return (sizeof(n)<<3-leading_zeros(n))
b == 8 && return div((sizeof(n)<<3)-leading_zeros(n)+2,3)
b == 16 && return (sizeof(n)<<1)-(leading_zeros(n)>>2)
b == 10 && return ndigits0z(n)
function ndigits0znb(n::Int, b::Int)
d = 0
while ndigits_max_mul < n
n = div(n,b)
while n != 0
n = cld(n,b)
d += 1
end
m = 1
while m <= n
m *= b
d += 1
return d
end

function ndigits0z(n::Unsigned, b::Int)
d = 0
if b < 0
d = ndigits0znb(signed(n), b)
else
b == 2 && return (sizeof(n)<<3-leading_zeros(n))
b == 8 && return div((sizeof(n)<<3)-leading_zeros(n)+2,3)
b == 16 && return (sizeof(n)<<1)-(leading_zeros(n)>>2)
b == 10 && return ndigits0z(n)
while ndigits_max_mul < n
n = div(n,b)
d += 1
end
m = 1
while m <= n
m *= b
d += 1
end
end
return d
end
ndigits0z(x::Integer, b::Integer) = ndigits0z(unsigned(abs(x)),int(b))

ndigitsnb(x::Integer, b::Integer) = x==0 ? 1 : ndigits0znb(x, b)

ndigits(x::Unsigned, b::Integer) = x==0 ? 1 : ndigits0z(x,int(b))
ndigits(x::Unsigned) = x==0 ? 1 : ndigits0z(x)

ndigits(x::Integer, b::Integer) = ndigits(unsigned(abs(x)),int(b))
ndigits(x::Integer, b::Integer) = b >= 0 ? ndigits(unsigned(abs(x)),int(b)) : ndigitsnb(x, b)
ndigits(x::Integer) = ndigits(unsigned(abs(x)))

## integer to string functions ##
Expand Down
2 changes: 1 addition & 1 deletion test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ JULIAHOME = $(abspath ..)
include ../Make.inc

TESTS = all core keywordargs numbers strings unicode collections hashing \
remote iobuffer arrayops reduce reducedim \
remote iobuffer arrayops reduce reducedim intfuncs \
simdloop linalg blas fft dsp sparse bitarray random \
math functional bigint sorting statistics spawn parallel arpack file \
git pkg resolve suitesparse complex version pollfd mpfr broadcast \
Expand Down
16 changes: 16 additions & 0 deletions test/intfuncs.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# issue #8266

@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(146, -3) == 5