Skip to content

Commit

Permalink
bugfixes, updates, more tests; closes SciML#20
Browse files Browse the repository at this point in the history
  • Loading branch information
ranocha committed Oct 8, 2020
1 parent 0b2165c commit 24e6b20
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 40 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
*.jl.cov
*.jl.*.cov
*.jl.mem
Manifest.toml
5 changes: 3 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ os:
- linux
- osx
julia:
- 0.6
- nightly
- 1.0
- 1
# - nightly
matrix:
allow_failures:
- julia: nightly
Expand Down
13 changes: 13 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name = "EllipsisNotation"
uuid = "da5c29d0-fa7d-589e-88eb-ea29b0a81949"
authors = ["Chris Rackauckas <accounts@chrisrackauckas.com>"]
version = "0.4.0"

[compat]
julia = "1"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test"]
45 changes: 27 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,48 @@ using EllipsisNotation
# Example Usage

```julia
A = Array{Int}(2,4,2)
julia> A = Array{Int}(undef,2,4,2)

A[..,1] = [2 1 4 5
2 2 3 6]
julia> A[..,1] = [2 1 4 5
2 2 3 6]

A[..,2] = [3 2 6 5
3 2 6 6]
julia> A[..,2] = [3 2 6 5
3 2 6 6]

A[:,:,1] == [2 1 4 5
2 2 3 6] #true
julia> A[:,:,1] == [2 1 4 5
2 2 3 6]
true

A[1,..] = reshape([3 4
5 6
4 5
6 7],1,4,2) #v0.4 doesn't drop singleton dimension, v0.5 does
julia> A[1,..] = reshape([3 4
5 6
4 5
6 7],1,4,2) # drops singleton dimension

B = [3 4
5 6
4 5
6 7]
julia> B = [3 4
5 6
4 5
6 7]

B == reshape(A[1,..],4,2) #true
julia> B == reshape(A[1,..],4,2)
true

A[..,1,2] # Can do as many integers as you want on the end!
julia> A[..,1,2] # Can do as many integers as you want on the end!
```

For avoiding squeezing dimensions from slicing.
```julia-repl
```julia
julia> C = ones(3,3,3,3,3);
julia> size(C[1:1, .., 1:1])
(1, 3, 3, 3, 1)
```

Note: `..` slurps dimensions greedily, meaning that the first occurrence
of `..` in an index expression creates as many slices as possible. Other
instances of `..` afterwards are treated simply as slices. Usually, you
should only use one instance of `..` in an indexing expression to avoid
possible confusion.


# Acknowledgements

I would like to acknowledge M. Schauer for the `..` notation implementation.
Expand Down
51 changes: 42 additions & 9 deletions src/EllipsisNotation.jl
Original file line number Diff line number Diff line change
@@ -1,22 +1,55 @@
__precompile__()

"""
Implements the notation `..` for indexing arrays. It's similar to the Python
`...` in that it means 'all of the columns before (or after)'.
`..` slurps dimensions greedily, meaning that the first occurrence
of `..` in an index expression creates as many slices as possible. Other
instances of `..` afterwards are treated simply as slices. Usually, you
should only use one instance of `..` in an indexing expression to avoid
possible confusion.
# Example
```jldoctest
julia> A = Array{Int}(undef,2,4,2);
julia> A[..,1] = [2 1 4 5
2 2 3 6];
julia> A[..,2] = [3 2 6 5
3 2 6 6];
julia> A[:,:,1] == [2 1 4 5
2 2 3 6]
true
julia> A[1,..] = reshape([3 4
5 6
4 5
6 7],1,4,2) # drops singleton dimension
...
julia> B = [3 4
5 6
4 5
6 7];
julia> B == reshape(A[1,..],4,2)
true
```
"""
module EllipsisNotation

import Base: to_indices, tail

struct Ellipsis end
const .. = Ellipsis()

@inline fillcolons(inds, I) = fillcolons((), inds, I)

@inline fillcolons(colons, ::Tuple{}, ::Tuple{}) = colons
@noinline fillcolons(colons, ::Tuple{}, ::Tuple) = throw(ArgumentError("too many indices provided"))
@inline fillcolons(colons, t::NTuple{N, <:Any}, ::NTuple{N, <:Any}) where {N} = colons
@inline fillcolons(colons, t::Tuple, s::Tuple) = fillcolons((colons..., :), tail(t), s)

@inline function to_indices(A, inds, I::Tuple{Ellipsis, Vararg{Any, N}}) where N
@inline function to_indices(A, inds::NTuple{M, Any}, I::Tuple{Ellipsis, Vararg{Any, N}}) where {M,N}
# Align the remaining indices to the tail of the `inds`
colons = fillcolons(inds, tail(I))
colons = ntuple(n->Colon(), M-N)
to_indices(A, inds, (colons..., tail(I)...))
end

Expand Down
12 changes: 9 additions & 3 deletions test/basic.jl
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
A = Array{Int}(2,4,2)
A = Array{Int}(undef,2,4,2)

A[..,1] = [2 1 4 5
2 2 3 6]

A[..,2] = [3 2 6 5
3 2 6 6]
3 2 6 6]

@test A[:,:,1] == [2 1 4 5
2 2 3 6]

@test A[:,:,2] == [3 2 6 5
3 2 6 6]

@test A[:,..,1] == [2 1 4 5
2 2 3 6]

@test A[:,..,1] == [2 1 4 5
2 2 3 6]

A[1,..] = reshape([3 4
5 6
4 5
Expand All @@ -27,7 +33,7 @@ B = [3 4
@test A[:,1,2] == A[..,1,2] == @view A[..,1,2]

# [..]
C = zeros(B)
C = zero(B)

C[:] = B[..]
@test B == C
Expand Down
14 changes: 7 additions & 7 deletions test/more_generic.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
B = Array{Int}(2, 3, 4, 5, 6)
B = Array{Int}(undef, 2, 3, 4, 5, 6)

n = 0
for i5=1:6, i4=1:5, i3=1:4
n += 1
B[.., i3, i4, i5] = n
global n += 1
B[.., i3, i4, i5] .= n
end
# B => 2×3×4×5×6 Array{Int64,5}:
# [:, :, 1, 1, 1] =
Expand All @@ -23,12 +23,12 @@ end
@test B[1, 1, ..] == B[1, 1, :, :, :] == reshape(1:120, 4, 5, 6)
@test B[1, 1, .., 1] == B[1, 1, :, :, 1] == reshape(1:20, 4, 5)

C = Array{Int}(2, 3, 4, 5, 6)
C = Array{Int}(undef, 2, 3, 4, 5, 6)

n = 0
for i3=1:4, i2=1:3, i1=1:2
n += 1
C[i1, i2, i3, ..] = n
global n += 1
C[i1, i2, i3, ..] .= n
end
# C => 2×3×4×5×6 Array{Int64,5}:
# [:, :, 1, 1, 1] =
Expand All @@ -49,5 +49,5 @@ end
@test C[1, .., 1, 1] == C[1, :, :, 1, 1] == reshape(1:2:24, 3, 4)

D = ones(Int, 1, 2, 3, 4)
D[1, .., 2] = 2
D[1, .., 2] .= 2
@test D == [i1 == 1 && i4 == 2 ? 2 : 1 for i1=1:1, i2=1:2, i3=1:3, i4=1:4]
2 changes: 1 addition & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using EllipsisNotation
using Base.Test
using Test

include("basic.jl")
include("more_generic.jl")

0 comments on commit 24e6b20

Please sign in to comment.