Skip to content

Commit afc071d

Browse files
committed
Improve performance of derangement/subfactorial with simpler recursive formula and inplace computations
Use the simpler formula !n = n * !(n-1) + (-1)^n and use inplace operations on `BigInt`s to avoid allocations.
1 parent 53c5e71 commit afc071d

File tree

1 file changed

+9
-3
lines changed

1 file changed

+9
-3
lines changed

src/factorials.jl

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,17 @@ function derangement(n::Integer)
4444
elseif n <= 1
4545
return BigInt(1-n)
4646
end
47-
a, b = BigInt(1), BigInt(0)
47+
d = BigInt(0)
4848
for i in 2:n
49-
a, b = b, (i-1)*(a+b)
49+
# d = i * d + (iseven(i) ? 1 : -1)
50+
Base.GMP.MPZ.mul_ui!(d, i)
51+
if iseven(i)
52+
Base.GMP.MPZ.add_ui!(d, 1)
53+
else
54+
Base.GMP.MPZ.sub_ui!(d, 1)
55+
end
5056
end
51-
return b
57+
return d
5258
end
5359
const subfactorial = derangement
5460

0 commit comments

Comments
 (0)