From f7b4ebece6ec76289065c523bbc3a2856d3263ae Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Wed, 7 Sep 2022 23:24:20 +0200 Subject: [PATCH] fix issue #46665, `prod(::Array{BigInt})` (#46667) 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. --- base/gmp.jl | 8 ++++++-- test/gmp.jl | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index 5d3cabac87e40..8e0c51e6259d6 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -668,8 +668,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) diff --git a/test/gmp.jl b/test/gmp.jl index 1125f57b195b3..be11c70e5064f 100644 --- a/test/gmp.jl +++ b/test/gmp.jl @@ -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