Skip to content

Commit

Permalink
fix issue #46665, prod(::Array{BigInt}) (#46667)
Browse files Browse the repository at this point in the history
The way we were counting the number of bits was assigning a negative number
to `0`, which could lead to a negative total number of bits. Better to just
exit early in this case.
Also, the estimate was slightly off because we were counting the number of leading
zeros in the least significant limb, instead of the most significant.

(cherry picked from commit f7b4ebe)
  • Loading branch information
rfourquet authored and KristofferC committed Sep 16, 2022
1 parent 237c92d commit 3fa8073
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 2 deletions.
8 changes: 6 additions & 2 deletions base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -667,8 +667,12 @@ function prod(arr::AbstractArray{BigInt})
# to account for the rounding to limbs in MPZ.mul!
# (BITS_PER_LIMB-1 would typically be enough, to which we add
# 1 for the initial multiplication by init=1 in foldl)
nbits = GC.@preserve arr sum(arr; init=BITS_PER_LIMB) do x
abs(x.size) * BITS_PER_LIMB - leading_zeros(unsafe_load(x.d))
nbits = BITS_PER_LIMB
for x in arr
iszero(x) && return zero(BigInt)
xsize = abs(x.size)
lz = GC.@preserve x leading_zeros(unsafe_load(x.d, xsize))
nbits += xsize * BITS_PER_LIMB - lz
end
init = BigInt(; nbits)
MPZ.set_si!(init, 1)
Expand Down
1 change: 1 addition & 0 deletions test/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ let a, b
@test 0 == sum(BigInt[]) isa BigInt
@test prod(b) == foldl(*, b)
@test 1 == prod(BigInt[]) isa BigInt
@test prod(BigInt[0, 0, 0]) == 0 # issue #46665
end

@testset "Iterated arithmetic" begin
Expand Down

0 comments on commit 3fa8073

Please sign in to comment.