Skip to content

Commit 2ad84aa

Browse files
Improve factorial(n, k) performance for BigInt (#149)
* Improve `factorial(n, k)` performance for `BigInt` Use in-place operations from `Base.GMP.MPZ` to reduce allocations. * Add tests for `factorial(::BigInt, ::BigInt)` * Avoid mutating first input of `factorial(::BigInt, ::BigInt)` Co-authored-by: Chengyu Han <[email protected]> --------- Co-authored-by: Chengyu Han <[email protected]>
1 parent 9bcadfa commit 2ad84aa

File tree

2 files changed

+15
-0
lines changed

2 files changed

+15
-0
lines changed

src/factorials.jl

+12
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,18 @@ function Base.factorial(n::T, k::T) where T<:Integer
2828
end
2929
return f
3030
end
31+
function Base.factorial(n::BigInt, k::BigInt)
32+
if k < 0 || n < 0 || k > n
33+
throw(DomainError((n, k), "n and k must be nonnegative with k ≤ n"))
34+
end
35+
f = BigInt(1)
36+
n = deepcopy(n) # avoid mutating input
37+
while n > k
38+
Base.GMP.MPZ.mul!(f, n)
39+
Base.GMP.MPZ.sub_ui!(n, 1)
40+
end
41+
return f
42+
end
3143
Base.factorial(n::Integer, k::Integer) = factorial(promote(n, k)...)
3244

3345

test/factorials.jl

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
@test_throws DomainError factorial(3, 7)
44
@test_throws DomainError factorial(-3, -7)
55
@test_throws DomainError factorial(-7, -3)
6+
@test_throws DomainError factorial(big"3", big"7")
7+
@test_throws DomainError factorial(big"-3", big"7")
8+
@test_throws DomainError factorial(big"3", big"-7")
69
#JuliaLang/julia#9943
710
@test factorial(big(100), (80)) == 1303995018204712451095685346159820800000
811
#JuliaLang/julia#9950

0 commit comments

Comments
 (0)