Skip to content

Commit ca3fbf1

Browse files
authored
fix type instability in binomial (#43283)
1 parent 728cba3 commit ca3fbf1

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

base/intfuncs.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,7 +1047,7 @@ function binomial(n::T, k::T) where T<:Integer
10471047
k < 0 && return zero(T)
10481048
sgn = one(T)
10491049
if n < 0
1050-
n = -n + k -1
1050+
n = -n + k - one(T)
10511051
if isodd(k)
10521052
sgn = -sgn
10531053
end
@@ -1058,15 +1058,15 @@ function binomial(n::T, k::T) where T<:Integer
10581058
if k > (n>>1)
10591059
k = (n - k)
10601060
end
1061-
x::T = nn = n - k + 1
1062-
nn += 1
1063-
rr = 2
1061+
x = nn = n - k + one(T)
1062+
nn += one(T)
1063+
rr = T(2)
10641064
while rr <= k
10651065
xt = div(widemul(x, nn), rr)
10661066
x = xt % T
10671067
x == xt || throw(OverflowError("binomial($n0, $k0) overflows"))
1068-
rr += 1
1069-
nn += 1
1068+
rr += one(T)
1069+
nn += one(T)
10701070
end
1071-
convert(T, copysign(x, sgn))
1071+
copysign(x, sgn)
10721072
end

test/intfuncs.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,3 +487,17 @@ end
487487
ci = code_typed(() -> 14 // 21)[][1]
488488
@test ci.code == Any[Core.ReturnNode(2 // 3)]
489489
end
490+
@testset "binomial" begin
491+
for T in (Int8, Int16, Int32, Int64)
492+
for x in rand(-isqrt(typemax(T)):isqrt(typemax(T)), 1000)
493+
@test binomial(x,T(1)) == x
494+
x>=0 && @test binomial(x,x-T(1)) == x
495+
@test binomial(x,T(2)) == div(x*(x-1), 2)
496+
x>=0 && @test binomial(x,x-T(2)) == div(x*(x-1), 2)
497+
end
498+
@test @inferred(binomial(one(T),one(T))) isa T
499+
end
500+
for x in ((false,false), (false,true), (true,false), (true,true))
501+
@test binomial(x...) == (x != (false,true))
502+
end
503+
end

0 commit comments

Comments
 (0)