Skip to content

Commit

Permalink
Specialize isperm and invperm on tuples of lengths 0, 1, and 2
Browse files Browse the repository at this point in the history
This speeds up construction of PermutedDimsArrays
  • Loading branch information
timholy committed Jun 24, 2016
1 parent 54bc917 commit 8146e9b
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 1 deletion.
9 changes: 9 additions & 0 deletions base/combinatorics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ function isperm(A)
true
end

isperm(p::Tuple{}) = true
isperm(p::Tuple{Int}) = p[1] == 1
isperm(p::Tuple{Int,Int}) = ((p[1] == 1) & (p[2] == 2)) | ((p[1] == 2) & (p[2] == 1))

function permute!!{T<:Integer}(a, p::AbstractVector{T})
count = 0
start = 0
Expand Down Expand Up @@ -147,6 +151,11 @@ function invperm(a::AbstractVector)
end
b
end

function invperm(p::Union{Tuple{},Tuple{Int},Tuple{Int,Int}})
isperm(p) || throw(ArgumentError("argument is not a permutation"))
p # in dimensions 0-2, every permutation is its own inverse
end
invperm(a::Tuple) = (invperm([a...])...,)

#XXX This function should be moved to Combinatorics.jl but is currently used by Base.DSP.
Expand Down
1 change: 0 additions & 1 deletion base/permuteddimsarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ immutable PermutedDimsArray{T,N,perm,iperm,AA<:AbstractArray} <: AbstractArray{T
dims::NTuple{N,Int}

function PermutedDimsArray(data::AA)
# TODO optimize isperm & invperm for low dimensions?
(isa(perm, NTuple{N,Int}) && isa(iperm, NTuple{N,Int})) || error("perm and iperm must both be NTuple{$N,Int}")
isperm(perm) || throw(ArgumentError(string(perm, " is not a valid permutation of dimensions 1:", N)))
all(map(d->iperm[perm[d]]==d, 1:N)) || throw(ArgumentError(string(perm, " and ", iperm, " must be inverses")))
Expand Down
12 changes: 12 additions & 0 deletions test/combinatorics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@
p = shuffle([1:1000;])
@test isperm(p)
@test all(invperm(invperm(p)) .== p)
@test isperm(()) == true
@test isperm((1,)) == true
@test isperm((2,)) == false
@test isperm((1,2)) == true
@test isperm((2,1)) == true
@test isperm((2,2)) == false
@test isperm((1,3)) == false
@test invperm(()) == ()
@test invperm((1,)) == (1,)
@test invperm((1,2)) == (1,2)
@test invperm((2,1)) == (2,1)
@test_throws ArgumentError invperm((1,3))

push!(p, 1)
@test !isperm(p)
Expand Down

0 comments on commit 8146e9b

Please sign in to comment.