From e11f2ffac0f2df6af23de1a1c872ee799dfb07ca Mon Sep 17 00:00:00 2001 From: Rafael Fourquet Date: Wed, 7 Sep 2022 12:54:44 +0200 Subject: [PATCH] fix issue #46665, `prod(::Array{BigInt})` 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