Skip to content

Commit

Permalink
Merge pull request #61 from YingboMa/myb/idx
Browse files Browse the repository at this point in the history
Add explicit indices handling via NamedTuple
  • Loading branch information
ChrisRackauckas authored May 2, 2019
2 parents 3428d61 + 225516b commit 5e05c10
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 42 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ os:
- linux
- osx
julia:
- 1.0
- 1.1
- nightly
notifications:
email: false
Expand Down
36 changes: 36 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,28 @@ julia> B2 = SLArray(B; c=30 )
2 4
```

One can also specify the indices directly.
```julia
julia> EFG = @SLArray (2,2) (e=1:3, f=4, g=2:4);
julia> y = EFG(1.0,2.5,3.0,5.0)
2×2 SLArray{Tuple{2,2},Float64,2,4,(e = 1:3, f = 4, g = 2:4)}:
1.0 3.0
2.5 5.0

julia> y.g
3-element view(reshape(::StaticArrays.SArray{Tuple{2,2},Float64,2,4}, 4), 2:4) with eltype Float64:
2.5
3.0
5.0

julia> Arr = @SLArray (2, 2) (a = (2, :), b = 3);
julia> z = Arr(1, 2, 3, 4);
julia> z.a
2-element view(::StaticArrays.SArray{Tuple{2,2},Int64,2,4}, 2, :) with eltype Int64:
2
4
```

## LArrays

The `LArrays`s are fully mutable arrays with labels. There is no performance
Expand Down Expand Up @@ -120,6 +142,20 @@ julia> LArray((2,2); a=1, b=2, c=3, d=4) # need to specify size as first argumen
2 4
```

One can also specify the indices directly.
```julia
julia> z = @LArray [1.,2.,3.] (a = 1:2, b = 2:3);
julia> z.b
2-element view(::Array{Float64,1}, 2:3) with eltype Float64:
2.0
3.0
julia> z = @LArray [1 2; 3 4] (a = (2, :), b = 2:3);
julia> z.a
2-element view(::Array{Int64,2}, 2, :) with eltype Int64:
3
4
```

The labels of LArray and SLArray can be accessed
by function `symbols`, which returns a tuple of symbols.

Expand Down
50 changes: 22 additions & 28 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
environment:
matrix:
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/1.0/julia-1.0-latest-win32.exe"
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/1.0/julia-1.0-latest-win64.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe"
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe"

## uncomment the following lines to allow failures on nightly julia
## (tests will run but not make your overall status red)
#matrix:
# allow_failures:
# - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe"
# - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe"
- julia_version: 1.1

platform:
- x86 # 32-bit
- x64 # 64-bit

# # Uncomment the following lines to allow failures on nightly julia
# # (tests will run but not make your overall status red)
# matrix:
# allow_failures:
# - julia_version: nightly

branches:
only:
Expand All @@ -24,24 +24,18 @@ notifications:
on_build_status_changed: false

install:
- ps: "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12"
# If there's a newer build queued for the same PR, cancel this one
- ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | `
Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
throw "There are newer queued builds for this pull request, failing early." }
# Download most recent Julia Windows binary
- ps: (new-object net.webclient).DownloadFile(
$env:JULIA_URL,
"C:\projects\julia-binary.exe")
# Run installer silently, output to C:\projects\julia
- C:\projects\julia-binary.exe /S /D=C:\projects\julia
- ps: iex ((new-object net.webclient).DownloadString("https://raw.githubusercontent.com/JuliaCI/Appveyor.jl/version-1/bin/install.ps1"))

build_script:
# Need to convert from shallow to complete for Pkg.clone to work
- IF EXIST .git\shallow (git fetch --unshallow)
- C:\projects\julia\bin\julia -e "versioninfo();
Pkg.clone(pwd(), \"LabelledArrays\"); Pkg.build(\"LabelledArrays\")"
- echo "%JL_BUILD_SCRIPT%"
- C:\julia\bin\julia -e "%JL_BUILD_SCRIPT%"

test_script:
- C:\projects\julia\bin\julia -e "Pkg.test(\"LabelledArrays\")"
- echo "%JL_TEST_SCRIPT%"
- C:\julia\bin\julia -e "%JL_TEST_SCRIPT%"

# # Uncomment to support code coverage upload. Should only be enabled for packages
# # which would have coverage gaps without running on Windows
# on_success:
# - echo "%JL_CODECOV_SCRIPT%"
# - C:\julia\bin\julia -e "%JL_CODECOV_SCRIPT%"
28 changes: 24 additions & 4 deletions src/larray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,13 @@ end
end

@inline function Base.getindex(x::LArray,s::Symbol)
getindex(x,Val(s))
syms = symnames(typeof(x))
if syms isa NamedTuple
idxs = syms[s]
return idxs isa Tuple ? @views(x.__x[idxs...]) : @views(x.__x[idxs])
else
return getindex(x,Val(s))
end
end

@inline @generated function Base.getindex(x::LArray,::Val{s}) where s
Expand All @@ -67,12 +73,24 @@ end
end

@inline function Base.setindex!(x::LArray,v,s::Symbol)
syms = symnames(typeof(x))
if syms isa NamedTuple
idxs = syms[s]
return setindex!(x.__x, v, idxs)
else
setindex!(x,v,Val(s))
end
end

@inline @generated function Base.setindex!(x::LArray,y,::Val{s}) where s
idx = findfirst(y->y==s,symnames(x))
:(setindex!(getfield(x,:__x),y,$idx))
syms = symnames(x)
if syms isa NamedTuple
idxs = syms[s]
return :(setindex!(view(getfield(x,:__x), y, $idxs)))
else # Tuple
idx = findfirst(y->y==s,symnames(x))
return :(setindex!(getfield(x,:__x),y,$idx))
end
end

function Base.getindex(x::LArray,s::AbstractArray{Symbol,1})
Expand Down Expand Up @@ -121,6 +139,8 @@ For example:
a = @LArray Float64 (2,2) (:a,:b,:c,:d)
b = @LArray [1,2,3] (:a,:b,:c)
c = @LArray [1,2,3] (a=1:2, b=2:3)
d = @LArray [1 2; 3 4] (a=(2, :), b=2:3)
"""
macro LArray(vals,syms)
vals = esc(vals)
Expand Down Expand Up @@ -170,7 +190,7 @@ For example:
z = @LVector Float64 (:a,:b,:c,:d)
symbols(z) # NTuple{4,Symbol} == (:a, :b, :c, :d)
"""
symbols(::LArray{T,N,D,Syms}) where {T,N,D,Syms} = Syms
symbols(::LArray{T,N,D,Syms}) where {T,N,D,Syms} = Syms isa NamedTuple ? keys(Syms) : Syms


# copy constructors
Expand Down
19 changes: 15 additions & 4 deletions src/slarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,13 @@ symnames(::Type{SLArray{S,T,N,L,Syms}}) where {S,T,N,L,Syms} = Syms
s == :__x ? getfield(x,:__x) : x[s]
end
@inline function Base.getindex(x::SLArray,s::Symbol)
getindex(x,Val(s))
syms = symnames(typeof(x))
if syms isa NamedTuple
idxs = syms[s]
return idxs isa Tuple ? @views(x.__x[idxs...]) : @views(x.__x[idxs])
else
return getindex(x,Val(s))
end
end
@inline @generated function Base.getindex(x::SLArray,::Val{s}) where s
idx = findfirst(y->y==s,symnames(x))
Expand Down Expand Up @@ -116,18 +122,23 @@ x.a == 1.0
x.b == 2.5
x.c == x[3]
x.d == x[2,2]
EFG = @SLArray (2,2) (e=1:3, f=4, g=2:4)
y = EFG(1.0,2.5,3.0,5.0)
EFG = @SLArray (2,2) (e=(2, :), f=4, g=2:4)
```
"""
macro SLArray(dims,syms)
dims isa Expr && (dims = dims.args)
syms = esc(syms)
quote
SLArray{Tuple{$dims...},$syms}
end
end

macro SLArray(T,dims,syms)
dims isa Expr && (dims = dims.args)
syms = esc(syms)
quote
SLArray{Tuple{$dims...},$T,$(length(dims)),$(prod(dims)),$syms}
end
Expand Down Expand Up @@ -155,7 +166,7 @@ x.c == x[3]
macro SLVector(syms)
syms = esc(syms)
quote
n = length($syms)
n = $syms isa NamedTuple ? maximum(map(maximum, $syms)) : length($syms)
SLArray{Tuple{n},$syms}
end
end
Expand All @@ -164,7 +175,7 @@ macro SLVector(T,syms)
T = esc(T)
syms = esc(syms)
quote
n = length($syms)
n = $syms isa NamedTuple ? maximum(map(maximum, $syms)) : length($syms)
SLArray{Tuple{n},$T,1,n,$syms}
end
end
Expand All @@ -179,4 +190,4 @@ For example:
z = SLVector(a=1, b=2, c=3)
symbols(z) # Tuple{Symbol,Symbol,Symbol} == (:a, :b, :c)
"""
symbols(::SLArray{S,T,N,L,Syms}) where {S,T,N,L,Syms} = Syms
symbols(::SLArray{S,T,N,L,Syms}) where {S,T,N,L,Syms} = Syms isa NamedTuple ? keys(Syms) : Syms
23 changes: 18 additions & 5 deletions test/larrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,21 @@ end
@test zs[[:c,:a]] == [3.,1.]
end






@testset "Explicit indices" begin
z = @LArray [1.,2.,3.] (a = 1:2, b = 3)
@test z.a isa SubArray
@test z.a == [1, 2.]
z.a = [100, 200.]
@test z.a == [100, 200.]
@test z.b === 3.
z.b = 1000.
@test z.b === 1000.
z = @LArray [1.,2.,3.] (a = 1:2, b = 1:3)
@test z.b === view(z.__x, 1:3)
z = @LArray [1.,2.] (a = 1, b = 2)
@test z.a === 1.0
@test z.b === 2.0
@test symbols(z) === (:a, :b)
z = @LArray [1 2; 3 4] (a = (2, :), b = 2:3)
@test z.a == [3, 4]
end
19 changes: 19 additions & 0 deletions test/slarrays.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,22 @@ end
ret = symbols(z)
@test ret == (:a,:b,:c)
end

@testset "Explicit indices" begin
Arr = @SLVector (a = 1:2, b = 3)
z = Arr(1.,2.,3.)
@test z.a isa SubArray
@test z.a == [1, 2.]
@test z.b === 3.
Arr = @SLVector (a = 1:2, b = 2:3)
z = Arr(1.,2.,3.)
@test z.b == [2, 3.]
Arr = @SLVector (a = 1, b = 2)
z = Arr(1, 2)
@test z.a === 1
@test z.b === 2
@test symbols(z) === (:a, :b)
Arr = @SLArray (2, 2) (a = (2, :), b = 3)
z = Arr(1, 2, 3, 4)
@test z.a == [2, 4]
end

0 comments on commit 5e05c10

Please sign in to comment.