Skip to content

Commit

Permalink
Implement arithmetic, min, and max on cartesian indexes
Browse files Browse the repository at this point in the history
These allow many more algorithms to be written
  • Loading branch information
timholy committed Dec 17, 2014
1 parent 8521fe2 commit b888f5b
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 20 deletions.
2 changes: 2 additions & 0 deletions base/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export
BitArray,
BitMatrix,
BitVector,
CartesianIndex,
CFILE,
Cmd,
Colon,
Expand All @@ -54,6 +55,7 @@ export
FloatRange,
Hermitian,
UniformScaling,
IndexIterator,
InsertionSort,
IntSet,
IO,
Expand Down
27 changes: 20 additions & 7 deletions base/multidimensional.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
### Multidimensional iterators
module IteratorsMD

import Base: start, _start, done, next, getindex, setindex!, linearindexing
import Base: start, _start, done, next, getindex, setindex!, linearindexing, min, max
import Base: @nref, @ncall, @nif, @nexprs, LinearFast, LinearSlow

export eachindex
export CartesianIndex, IndexIterator, eachindex

# Traits for linear indexing
linearindexing(::BitArray) = LinearFast()
Expand Down Expand Up @@ -55,18 +55,15 @@ end
end

# indexing
getindex(index::CartesianIndex, i::Integer) = getfield(index, i)

stagedfunction getindex{N}(A::AbstractArray, index::CartesianIndex{N})
:(@nref $N A d->getfield(index,d))
end
stagedfunction setindex!{N}(A::AbstractArray, v, index::CartesianIndex{N})
:((@nref $N A d->getfield(index,d)) = v)
end

# Prevent an ambiguity warning
gen_cartesian(1) # to make sure the next two lines are valid
next(R::StepRange, state::(Bool, CartesianIndex{1})) = R[state[2].I_1], (state[2].I_1==length(R), CartesianIndex_1(state[2].I_1+1))
next{T}(R::UnitRange{T}, state::(Bool, CartesianIndex{1})) = R[state[2].I_1], (state[2].I_1==length(R), CartesianIndex_1(state[2].I_1+1))

# iteration
eachindex(A::AbstractArray) = IndexIterator(size(A))

Expand All @@ -90,6 +87,11 @@ stagedfunction _start{T,N}(A::AbstractArray{T,N}, ::LinearSlow)
end
end

# Prevent an ambiguity warning
gen_cartesian(1) # to make sure the next two lines are valid
next(R::StepRange, state::(Bool, CartesianIndex{1})) = R[state[2].I_1], (state[2].I_1==length(R), CartesianIndex_1(state[2].I_1+1))
next{T}(R::UnitRange{T}, state::(Bool, CartesianIndex{1})) = R[state[2].I_1], (state[2].I_1==length(R), CartesianIndex_1(state[2].I_1+1))

stagedfunction next{T,N}(A::AbstractArray{T,N}, state::(Bool, CartesianIndex{N}))
indextype, _ = gen_cartesian(N)
finishedex = (N==0 ? true : :(getfield(newindex, $N) > size(A, $N)))
Expand Down Expand Up @@ -123,6 +125,17 @@ done(R::FloatRange, state::(Bool, CartesianIndex{1})) = state[1]
done{T,N}(A::AbstractArray{T,N}, state::(Bool, CartesianIndex{N})) = state[1]
done{N}(iter::IndexIterator{N}, state::(Bool, CartesianIndex{N})) = state[1]

# arithmetic, min/max
for op in (:+, :-, :min, :max)
@eval begin
stagedfunction ($op){N}(I1::CartesianIndex{N}, I2::CartesianIndex{N})
indextype, _ = gen_cartesian(N)
args = [:($($op)(getfield(I1, $d),getfield(I2, $d))) for d = 1:N]
:($indextype($(args...)))
end
end
end

end # IteratorsMD

using .IteratorsMD
Expand Down
36 changes: 23 additions & 13 deletions test/arrayops.jl
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,20 @@ b718cbc = 5
@test b718cbc[1.0] == 5
@test_throws InexactError b718cbc[1.1]

#6828 - size of specific dimensions
a = Array(Float64, 10)
@test size(a) == (10,)
@test size(a, 1) == 10
@test size(a,2,1) == (1,10)
a = Array(Float64, 2,3)
@test size(a) == (2,3)
@test size(a,4,3,2,1) == (1,1,3,2)
@test size(a,1,2) == (2,3)
a = Array(Float64, 9,8,7,6,5,4,3,2,1)
@test size(a,1,1) == (9,9)
@test size(a,4) == 6
@test size(a,9,8,7,6,5,4,3,2,19,8,7,6,5,4,3,2,1) == (1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,9)

# Multidimensional iterators
for a in ([1:5], reshape([2]))
counter = 0
Expand Down Expand Up @@ -917,16 +931,12 @@ a = ones(5,0)
b = sub(a, :, :)
@test mdsum(b) == 0

#6828 - size of specific dimensions
a = Array(Float64, 10)
@test size(a) == (10,)
@test size(a, 1) == 10
@test size(a,2,1) == (1,10)
a = Array(Float64, 2,3)
@test size(a) == (2,3)
@test size(a,4,3,2,1) == (1,1,3,2)
@test size(a,1,2) == (2,3)
a = Array(Float64, 9,8,7,6,5,4,3,2,1)
@test size(a,1,1) == (9,9)
@test size(a,4) == 6
@test size(a,9,8,7,6,5,4,3,2,19,8,7,6,5,4,3,2,1) == (1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,9)
I1 = CartesianIndex((2,3,0))
I2 = CartesianIndex((-1,5,2))
@test I1 + I2 == CartesianIndex((1,8,2))
@test I2 + I1 == CartesianIndex((1,8,2))
@test I1 - I2 == CartesianIndex((3,-2,-2))
@test I2 - I1 == CartesianIndex((-3,2,2))

@test min(CartesianIndex((2,3)), CartesianIndex((5,2))) == CartesianIndex((2,2))
@test max(CartesianIndex((2,3)), CartesianIndex((5,2))) == CartesianIndex((5,3))

0 comments on commit b888f5b

Please sign in to comment.