Skip to content

Commit

Permalink
Major code reorganization
Browse files Browse the repository at this point in the history
- DROP 0.4 SUPPORT
- Import most of base/combinatorics.jl (Ref: JuliaLang/julia#13897)
- Move most of the special numbers to numbers.jl
- Put combinations, permutations and partitions in their own files
- Rename special numbers with ~num suffix. This renaming is particularly
  important for catalannum to avoid clashing with the Base.catalan
  irrational constant.
  • Loading branch information
jiahao committed Nov 6, 2015
1 parent d67c151 commit 2e56149
Show file tree
Hide file tree
Showing 9 changed files with 766 additions and 167 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Combinatorics

[![Combinatorics](http://pkg.julialang.org/badges/Combinatorics_0.3.svg)](http://pkg.julialang.org/?pkg=Combinatorics&ver=0.3)
[![Combinatorics](http://pkg.julialang.org/badges/Combinatorics_0.4.svg)](http://pkg.julialang.org/?pkg=Combinatorics&ver=0.4)
[![Build Status](https://travis-ci.org/JuliaLang/Combinatorics.jl.svg?branch=master)](https://travis-ci.org/JuliaLang/Combinatorics.jl)
[![Coverage Status](https://coveralls.io/repos/JuliaLang/Combinatorics.jl/badge.svg?branch=master&service=github)](https://coveralls.io/github/JuliaLang/Combinatorics.jl?branch=master)
Expand Down
2 changes: 1 addition & 1 deletion REQUIRE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
julia 0.4
julia 0.5-
Compat
Polynomials
Iterators
157 changes: 5 additions & 152 deletions src/Combinatorics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,158 +2,11 @@ module Combinatorics

using Compat, Polynomials, Iterators

import Base:combinations

export bell,
derangement,
doublefactorial,
fibonacci,
hyperfactorial,
jacobisymbol,
lassalle,
legendresymbol,
lucas,
multifactorial,
multinomial,
primorial,
stirlings1,
subfactorial

include("numbers.jl")
include("factorials.jl")
include("combinations.jl")
include("permutations.jl")
include("partitions.jl")
include("youngdiagrams.jl")

# Returns the n-th Bell number
function bell(bn::Integer)
if bn < 0
throw(DomainError())
else
n = BigInt(bn)
end
list = Array(BigInt, div(n*(n+1), 2))
list[1] = 1
for i = 2:n
beg = div(i*(i-1),2)
list[beg+1] = list[beg]
for j = 2:i
list[beg+j] = list[beg+j-1]+list[beg+j-i]
end
end
return list[end]
end

# Returns the n-th Catalan number
function catalan(bn::Integer)
if bn<0
throw(DomainError())
else
n = BigInt(bn)
end
div(binomial(2*n, n), (n + 1))
end

#generate combinations of all orders, chaining of order iterators is eager,
#but sequence at each order is lazy
combinations(a) = chain([combinations(a,k) for k=1:length(a)]...)

# The number of permutations of n with no fixed points (subfactorial)
function derangement(sn::Integer)
n = BigInt(sn)
return num(factorial(n)*sum([(-1)^k//factorial(k) for k=0:n]))
end
subfactorial(n::Integer) = derangement(n)

function doublefactorial(n::Integer)
if n < 0
throw(DomainError())
end
z = BigInt()
ccall((:__gmpz_2fac_ui, :libgmp), Void,
(Ptr{BigInt}, UInt), &z, @compat(UInt(n)))
return z
end

function fibonacci(n::Integer)
if n < 0
throw(DomainError())
end
z = BigInt()
ccall((:__gmpz_fib_ui, :libgmp), Void,
(Ptr{BigInt}, UInt), &z, @compat(UInt(n)))
return z
end

# Hyperfactorial
hyperfactorial(n::Integer) = prod([i^i for i = BigInt(2):n])

function jacobisymbol(a::Integer, b::Integer)
ba = BigInt(a)
bb = BigInt(b)
return ccall((:__gmpz_jacobi, :libgmp), Cint,
(Ptr{BigInt}, Ptr{BigInt}), &ba, &bb)
end

#Computes Lassalle's sequence
#OEIS entry A180874
function lassalle(m::Integer)
A = ones(BigInt,m)
for n=2:m
A[n]=(-1)^(n-1) * (catalan(n) + sum([(-1)^j*binomial(2n-1, 2j-1)*A[j]*catalan(n-j) for j=1:n-1]))
end
A[m]
end

function legendresymbol(a::Integer, b::Integer)
ba = BigInt(a)
bb = BigInt(b)
return ccall((:__gmpz_legendre, :libgmp), Cint,
(Ptr{BigInt}, Ptr{BigInt}), &ba, &bb)
end

function lucas(n::Integer)
if n < 0
throw(DomainError())
end
z = BigInt()
ccall((:__gmpz_lucnum_ui, :libgmp), Void,
(Ptr{BigInt}, UInt), &z, @compat(UInt(n)))
return z
end

function multifactorial(n::Integer, m::Integer)
if n < 0
throw(DomainError())
end
z = BigInt()
ccall((:__gmpz_mfac_uiui, :libgmp), Void,
(Ptr{BigInt}, UInt, UInt), &z, @compat(UInt(n)), @compat(UInt(m)))
return z
end

# Multinomial coefficient where n = sum(k)
function multinomial(k...)
s = 0
result = 1
for i in k
s += i
result *= binomial(s, i)
end
result
end

function primorial(n::Integer)
if n < 0
throw(DomainError())
end
z = BigInt()
ccall((:__gmpz_primorial_ui, :libgmp), Void,
(Ptr{BigInt}, UInt), &z, @compat(UInt(n)))
return z
end

# Returns s(n, k), the signed Stirling number of first kind
function stirlings1(n::Integer, k::Integer)
p = poly(0:(n-1))
p[n - k + 1]
end

end # module
end #module
51 changes: 51 additions & 0 deletions src/combinations.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
export combinations


#The Combinations iterator
import Base: start, next, done, length

immutable Combinations{T}
a::T
t::Int
end

start(c::Combinations) = [1:c.t;]
function next(c::Combinations, s)
comb = [c.a[si] for si in s]
if c.t == 0
# special case to generate 1 result for t==0
return (comb,[length(c.a)+2])
end
s = copy(s)
for i = length(s):-1:1
s[i] += 1
if s[i] > (length(c.a) - (length(s)-i))
continue
end
for j = i+1:endof(s)
s[j] = s[j-1]+1
end
break
end
(comb,s)
end
done(c::Combinations, s) = !isempty(s) && s[1] > length(c.a)-c.t+1

length(c::Combinations) = binomial(length(c.a),c.t)

eltype{T}(::Type{Combinations{T}}) = Vector{eltype(T)}



function combinations(a, t::Integer)
if t < 0
# generate 0 combinations for negative argument
t = length(a)+1
end
Combinations(a, t)
end

#generate combinations of all orders, chaining of order iterators is eager,
#but sequence at each order is lazy
combinations(a) = chain([combinations(a,k) for k=1:length(a)]...)

64 changes: 64 additions & 0 deletions src/factorials.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#Factorials and elementary coefficients

export
derangement,
subfactorial,
doublefactorial,
hyperfactorial,
multifactorial,
gamma,
primorial,
multinomial

# The number of permutations of n with no fixed points (subfactorial)
function derangement(sn::Integer)
n = BigInt(sn)
return num(factorial(n)*sum([(-1)^k//factorial(k) for k=0:n]))
end
subfactorial(n::Integer) = derangement(n)

function doublefactorial(n::Integer)
if n < 0
throw(DomainError())
end
z = BigInt()
ccall((:__gmpz_2fac_ui, :libgmp), Void,
(Ptr{BigInt}, UInt), &z, @compat(UInt(n)))
return z
end

# Hyperfactorial
hyperfactorial(n::Integer) = prod([i^i for i = BigInt(2):n])

function multifactorial(n::Integer, m::Integer)
if n < 0
throw(DomainError())
end
z = BigInt()
ccall((:__gmpz_mfac_uiui, :libgmp), Void,
(Ptr{BigInt}, UInt, UInt), &z, @compat(UInt(n)), @compat(UInt(m)))
return z
end

function primorial(n::Integer)
if n < 0
throw(DomainError())
end
z = BigInt()
ccall((:__gmpz_primorial_ui, :libgmp), Void,
(Ptr{BigInt}, UInt), &z, @compat(UInt(n)))
return z
end

#Multinomial coefficient where n = sum(k)
function multinomial(k...)
s = 0
result = 1
for i in k
s += i
result *= binomial(s, i)
end
result
end


91 changes: 91 additions & 0 deletions src/numbers.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#Special named numbers and symbols

export bellnum,
catalannum,
fibonaccinum,
jacobisymbol,
lassallenum,
legendresymbol,
lucasnum,
stirlings1

# Returns the n-th Bell number
function bellnum(bn::Integer)
if bn < 0
throw(DomainError())
else
n = BigInt(bn)
end
list = Array(BigInt, div(n*(n+1), 2))
list[1] = 1
for i = 2:n
beg = div(i*(i-1),2)
list[beg+1] = list[beg]
for j = 2:i
list[beg+j] = list[beg+j-1]+list[beg+j-i]
end
end
return list[end]
end

# Returns the n-th Catalan number
function catalannum(bn::Integer)
if bn<0
throw(DomainError())
else
n = BigInt(bn)
end
div(binomial(2*n, n), (n + 1))
end

function fibonaccinum(n::Integer)
if n < 0
throw(DomainError())
end
z = BigInt()
ccall((:__gmpz_fib_ui, :libgmp), Void,
(Ptr{BigInt}, UInt), &z, @compat(UInt(n)))
return z
end


function jacobisymbol(a::Integer, b::Integer)
ba = BigInt(a)
bb = BigInt(b)
return ccall((:__gmpz_jacobi, :libgmp), Cint,
(Ptr{BigInt}, Ptr{BigInt}), &ba, &bb)
end

#Computes Lassalle's sequence
#OEIS entry A180874
function lassallenum(m::Integer)
A = ones(BigInt,m)
for n=2:m
A[n]=(-1)^(n-1) * (catalannum(n) + sum([(-1)^j*binomial(2n-1, 2j-1)*A[j]*catalannum(n-j) for j=1:n-1]))
end
A[m]
end

function legendresymbol(a::Integer, b::Integer)
ba = BigInt(a)
bb = BigInt(b)
return ccall((:__gmpz_legendre, :libgmp), Cint,
(Ptr{BigInt}, Ptr{BigInt}), &ba, &bb)
end

function lucasnum(n::Integer)
if n < 0
throw(DomainError())
end
z = BigInt()
ccall((:__gmpz_lucnum_ui, :libgmp), Void,
(Ptr{BigInt}, UInt), &z, @compat(UInt(n)))
return z
end

# Returns s(n, k), the signed Stirling number of first kind
function stirlings1(n::Integer, k::Integer)
p = poly(0:(n-1))
p[n - k + 1]
end

Loading

0 comments on commit 2e56149

Please sign in to comment.