Skip to content

Commit c0ce76c

Browse files
authored
improve effects of factorial (#54320)
1 parent 685f527 commit c0ce76c

File tree

3 files changed

+29
-27
lines changed

3 files changed

+29
-27
lines changed

base/Base.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,9 @@ using .ScopedValues
406406
include("logging.jl")
407407
using .CoreLogging
408408

409+
# metaprogramming
410+
include("meta.jl")
411+
409412
include("env.jl")
410413

411414
# functions defined in Random
@@ -495,9 +498,6 @@ include("irrationals.jl")
495498
include("mathconstants.jl")
496499
using .MathConstants: ℯ, π, pi
497500

498-
# metaprogramming
499-
include("meta.jl")
500-
501501
# Stack frames and traces
502502
include("stacktraces.jl")
503503
using .StackTraces

base/combinatorics.jl

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,30 @@
22

33
# Factorials
44

5-
const _fact_table64 = Vector{Int64}(undef, 20)
6-
_fact_table64[1] = 1
7-
for n in 2:20
8-
_fact_table64[n] = _fact_table64[n-1] * n
5+
const _fact_table64 = let _fact_table64 = Vector{Int64}(undef, 20)
6+
_fact_table64[1] = 1
7+
for n in 2:20
8+
_fact_table64[n] = _fact_table64[n-1] * n
9+
end
10+
Tuple(_fact_table64)
911
end
1012

11-
const _fact_table128 = Vector{UInt128}(undef, 34)
12-
_fact_table128[1] = 1
13-
for n in 2:34
14-
_fact_table128[n] = _fact_table128[n-1] * n
13+
const _fact_table128 = let _fact_table128 = Vector{UInt128}(undef, 34)
14+
_fact_table128[1] = 1
15+
for n in 2:34
16+
_fact_table128[n] = _fact_table128[n-1] * n
17+
end
18+
Tuple(_fact_table128)
1519
end
1620

17-
function factorial_lookup(n::Integer, table, lim)
18-
n < 0 && throw(DomainError(n, "`n` must not be negative."))
19-
n > lim && throw(OverflowError(string(n, " is too large to look up in the table; consider using `factorial(big(", n, "))` instead")))
20-
n == 0 && return one(n)
21-
@inbounds f = table[n]
21+
function factorial_lookup(
22+
n::Union{Checked.SignedInt,Checked.UnsignedInt},
23+
table::Union{NTuple{20,Int64},NTuple{34,UInt128}}, lim::Int)
24+
idx = Int(n)
25+
idx < 0 && throw(DomainError(n, "`n` must not be negative."))
26+
idx > lim && throw(OverflowError(lazy"$n is too large to look up in the table; consider using `factorial(big($n))` instead"))
27+
idx == 0 && return one(n)
28+
f = getfield(table, idx)
2229
return oftype(n, f)
2330
end
2431

test/combinatorics.jl

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,17 +77,12 @@ end
7777
end
7878

7979
@testset "factorial" begin
80-
@test factorial(7) == 5040
81-
@test factorial(Int8(7)) == 5040
82-
@test factorial(UInt8(7)) == 5040
83-
@test factorial(Int16(7)) == 5040
84-
@test factorial(UInt16(7)) == 5040
85-
@test factorial(Int32(7)) == 5040
86-
@test factorial(UInt32(7)) == 5040
87-
@test factorial(Int64(7)) == 5040
88-
@test factorial(UInt64(7)) == 5040
89-
@test factorial(Int128(7)) == 5040
90-
@test factorial(UInt128(7)) == 5040
80+
for T = Base.uniontypes(Union{Base.Checked.SignedInt,Base.Checked.UnsignedInt})
81+
@testset let T = T
82+
@test factorial(T(7)) == 5040
83+
@test Core.Compiler.is_foldable(Base.infer_effects(factorial, (T,)))
84+
end
85+
end
9186
@test factorial(0) == 1
9287
@test_throws DomainError factorial(-1)
9388
@test factorial(Int64(20)) == 2432902008176640000

0 commit comments

Comments
 (0)