Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add explicit indices handling via NamedTuple #61

Merged
merged 6 commits into from
May 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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