From Code to Community: Sponsoring The Perl and Raku Conference 2025 Learn more

#!/usr/bin/ruby
# Daniel "Trizen" Șuteu
# License: GPLv3
# Date: 27 September 2016
# The inverse of n factorial, based on the inverse of Stirling's approximation.
define τ = Num.tau
define e = Num.e
define S = τ.sqrt.ln
define T = τ.root(-2*e)
func inv_fac_W(n) {
var l = (n.ln - S)
l / lambert_w(l / e) - 1/2
}
func inv_fac_lgrt(n) {
lgrt(T * n.root(e)) * e - 1/2
}
var tests = [
[3, 6],
[4, 24],
[5, 120],
[10, 3628800],
[15, 1307674368000],
]
for n,f in tests {
var a = inv_fac_W(f)
var b = inv_fac_lgrt(f)
printf("F(%2s!) =~ (%.10g, %.10g)\n", n, a, b)
if (a.round(-20) != b.round(-20)) {
die "#{a} != #{b}"
}
if (a.round(0) != n) {
die "a=#{a} is incorrect!"
}
}
var x = inv_fac_W(-123456789)
var y = inv_fac_lgrt(-123456789)
assert_eq(x.round(-20), y.round(-20))
assert((sqrt(2*Num.pi*x) * (x/e)**x) / -123456789 -> is_between(0.9, 0.99))