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

Julia 0.6 rewrite #121

Merged
merged 9 commits into from
Mar 24, 2017
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
10 changes: 5 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ os:
- linux
- osx
julia:
- 0.5
- 0.6
- nightly
notifications:
email: false
matrix:
allow_failures:
# matrix:
# allow_failures:
# - julia: nightly
- os: osx
# - os: osx
# uncomment the following lines to override the default test script
#script:
# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
# - julia -e 'Pkg.clone(pwd()); Pkg.build("StaticArrays"); Pkg.test("StaticArrays"; coverage=true)'
after_success:
- if [ $TRAVIS_JULIA_VERSION = "0.5" ] && [ $TRAVIS_OS_NAME = "linux" ]; then
- if [ $TRAVIS_JULIA_VERSION = "0.6" ] && [ $TRAVIS_OS_NAME = "linux" ]; then
julia -e 'cd(Pkg.dir("StaticArrays")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())';
fi
1 change: 0 additions & 1 deletion REQUIRE
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
julia 0.5
Compat 0.19.0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@compat is still used in test/fixed_size_arrays.jl, though it looks like that's now dead code

Copy link
Member Author

@andyferris andyferris Mar 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that file is not deleted because I think Simon Danisch will revive it sometime

4 changes: 2 additions & 2 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
environment:
matrix:
- JULIAVERSION: "julialang/bin/winnt/x86/0.5/julia-0.5-latest-win32.exe"
- JULIAVERSION: "julialang/bin/winnt/x64/0.5/julia-0.5-latest-win64.exe"
# - JULIAVERSION: "julialang/bin/winnt/x86/0.5/julia-0.5-latest-win32.exe"
# - JULIAVERSION: "julialang/bin/winnt/x64/0.5/julia-0.5-latest-win64.exe"
- JULIAVERSION: "julianightlies/bin/winnt/x86/julia-latest-win32.exe"
- JULIAVERSION: "julianightlies/bin/winnt/x64/julia-latest-win64.exe"

Expand Down
6 changes: 3 additions & 3 deletions src/FieldVector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ For example:
z::Float64
end
"""
@compat abstract type FieldVector{T} <: StaticVector{T} end
abstract type FieldVector{T} <: StaticVector{T} end

# Is this a good idea?? Should people just define constructors that accept tuples?
@inline (::Type{FV}){FV<:FieldVector}(x::Tuple) = FV(x...)

@pure Size{FV<:FieldVector}(::Type{FV}) = Size(nfields(FV))

@inline getindex(v::FieldVector, i::Integer) = getfield(v, i)
@inline setindex!(v::FieldVector, x, i::Integer) = setfield!(v, i, x)
@inline getindex(v::FieldVector, i::Int) = getfield(v, i)
@inline setindex!(v::FieldVector, x, i::Int) = setfield!(v, i, x)

# See #53
Base.cconvert{T}(::Type{Ptr{T}}, v::FieldVector) = Ref(v)
Expand Down
51 changes: 25 additions & 26 deletions src/ImmutableArrays.jl
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
module ImmutableArrays

using ..StaticArrays
using Compat

@compat Vector1{T} = SVector{1,T}
@compat Vector2{T} = SVector{2,T}
@compat Vector3{T} = SVector{3,T}
@compat Vector4{T} = SVector{4,T}

@compat Matrix1x1{T} = SMatrix{1,1,T,1}
@compat Matrix1x2{T} = SMatrix{1,2,T,2}
@compat Matrix1x3{T} = SMatrix{1,3,T,3}
@compat Matrix1x4{T} = SMatrix{1,4,T,4}

@compat Matrix2x1{T} = SMatrix{2,1,T,2}
@compat Matrix2x2{T} = SMatrix{2,2,T,4}
@compat Matrix2x3{T} = SMatrix{2,3,T,6}
@compat Matrix2x4{T} = SMatrix{2,4,T,8}

@compat Matrix3x1{T} = SMatrix{3,1,T,3}
@compat Matrix3x2{T} = SMatrix{3,2,T,6}
@compat Matrix3x3{T} = SMatrix{3,3,T,9}
@compat Matrix3x4{T} = SMatrix{3,4,T,12}

@compat Matrix4x1{T} = SMatrix{4,1,T,4}
@compat Matrix4x2{T} = SMatrix{4,2,T,8}
@compat Matrix4x3{T} = SMatrix{4,3,T,12}
@compat Matrix4x4{T} = SMatrix{4,4,T,16}

Vector1{T} = SVector{1,T}
Vector2{T} = SVector{2,T}
Vector3{T} = SVector{3,T}
Vector4{T} = SVector{4,T}

Matrix1x1{T} = SMatrix{1,1,T,1}
Matrix1x2{T} = SMatrix{1,2,T,2}
Matrix1x3{T} = SMatrix{1,3,T,3}
Matrix1x4{T} = SMatrix{1,4,T,4}

Matrix2x1{T} = SMatrix{2,1,T,2}
Matrix2x2{T} = SMatrix{2,2,T,4}
Matrix2x3{T} = SMatrix{2,3,T,6}
Matrix2x4{T} = SMatrix{2,4,T,8}

Matrix3x1{T} = SMatrix{3,1,T,3}
Matrix3x2{T} = SMatrix{3,2,T,6}
Matrix3x3{T} = SMatrix{3,3,T,9}
Matrix3x4{T} = SMatrix{3,4,T,12}

Matrix4x1{T} = SMatrix{4,1,T,4}
Matrix4x2{T} = SMatrix{4,2,T,8}
Matrix4x3{T} = SMatrix{4,3,T,12}
Matrix4x4{T} = SMatrix{4,4,T,16}

export Vector1, Vector2, Vector3, Vector4,
Matrix1x1, Matrix1x2, Matrix1x3, Matrix1x4,
Expand Down
14 changes: 7 additions & 7 deletions src/MArray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ end
@inline MArray(a::StaticArray) = MArray{size(typeof(a))}(Tuple(a))

# Some more advanced constructor-like functions
@inline eye{Size}(::Type{MArray{Size}}) = eye(MArray{Size,Float64})
@inline zeros{Size}(::Type{MArray{Size}}) = zeros(MArray{Size,Float64})
@inline ones{Size}(::Type{MArray{Size}}) = ones(MArray{Size,Float64})

@inline one(::Type{MArray{S}}) where {S} = one(MArray{S,Float64,length(S)})
@inline eye(::Type{MArray{S}}) where {S} = eye(MArray{S,Float64,length(S)})
@inline one(::Type{MArray{S,T}}) where {S,T} = one(MArray{S,T,length(S)})
@inline eye(::Type{MArray{S,T}}) where {S,T} = eye(MArray{S,T,length(S)})

####################
## MArray methods ##
Expand All @@ -99,13 +99,13 @@ end
@pure Size{S,T,N}(::Type{MArray{S,T,N}}) = Size(S)
@pure Size{S,T,N,L}(::Type{MArray{S,T,N,L}}) = Size(S)

function getindex(v::MArray, i::Integer)
function getindex(v::MArray, i::Int)
Base.@_inline_meta
v.data[i]
end

@propagate_inbounds setindex!{S,T}(v::MArray{S,T}, val, i::Integer) = setindex!(v, convert(T, val), i)
@inline function setindex!{S,T}(v::MArray{S,T}, val::T, i::Integer)
@propagate_inbounds setindex!{S,T}(v::MArray{S,T}, val, i::Int) = setindex!(v, convert(T, val), i)
@inline function setindex!{S,T}(v::MArray{S,T}, val::T, i::Int)
@boundscheck if i < 1 || i > length(v)
throw(BoundsError())
end
Expand Down
25 changes: 10 additions & 15 deletions src/MMatrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,27 +34,26 @@ type MMatrix{S1, S2, T, L} <: StaticMatrix{T}
end
end

@generated function check_MMatrix_params{S1,S2,L}(::Type{Val{S1}}, ::Type{Val{S2}}, T, ::Type{Val{L}})
if !(T <: DataType) # I think the way types are handled in generated fnctions might have changed in 0.5?
return :(error("MMatrix: Parameter T must be a DataType. Got $T"))
end
function check_MMatrix_params(::Type{Val{S1}}, ::Type{Val{S2}}, T, ::Type{Val{L}}) where {S1,S2,L}
throw(ArgumentError("MMatrix: Parameter T must be a Type. Got $T"))
end

@generated function check_MMatrix_params(::Type{Val{S1}}, ::Type{Val{S2}}, ::Type{T}, ::Type{Val{L}}) where {S1,S2,L,T}
if !isa(S1, Int) || !isa(S2, Int) || !isa(L, Int) || S1 < 0 || S2 < 0 || L < 0
return :(error("MMatrix: Sizes must be positive integers. Got $S1 × $S2 ($L elements)"))
throw(ArgumentError("MMatrix: Sizes must be positive integers. Got $S1 × $S2 ($L elements)"))
end

if S1*S2 == L
return nothing
else
str = "Size mismatch in MMatrix. S1 = $S1, S2 = $S2, but recieved $L elements"
return :(error($str))
throw(ArgumentError("Size mismatch in MMatrix. S1 = $S1, S2 = $S2, but recieved $L elements"))
end
end

@generated function (::Type{MMatrix{S1}}){S1,L}(x::NTuple{L})
S2 = div(L, S1)
if S1*S2 != L
error("Incorrect matrix sizes. $S1 does not divide $L elements")
throw(DimensionMismatch("Incorrect matrix sizes. $S1 does not divide $L elements"))
end
T = promote_tuple_eltype(x)

Expand Down Expand Up @@ -90,13 +89,9 @@ end
@inline convert{S1,S2,T}(::Type{MMatrix{S1,S2}}, a::StaticArray{T}) = MMatrix{S1,S2,T}(Tuple(a))
@inline MMatrix(a::StaticMatrix) = MMatrix{size(typeof(a),1),size(typeof(a),2)}(Tuple(a))


# Some more advanced constructor-like functions
@inline one{N}(::Type{MMatrix{N}}) = one(MMatrix{N,N})
@inline eye{N}(::Type{MMatrix{N}}) = eye(MMatrix{N,N})
@inline eye{N,M}(::Type{MMatrix{N,M}}) = eye(MMatrix{N,M,Float64})
@inline zeros{N,M}(::Type{MMatrix{N,M}}) = zeros(MMatrix{N,M,Float64})
@inline ones{N,M}(::Type{MMatrix{N,M}}) = ones(MMatrix{N,M,Float64})

#####################
## MMatrix methods ##
Expand All @@ -106,7 +101,7 @@ end
@pure Size{S1,S2,T}(::Type{MMatrix{S1,S2,T}}) = Size(S1, S2)
@pure Size{S1,S2,T,L}(::Type{MMatrix{S1,S2,T,L}}) = Size(S1, S2)

@propagate_inbounds function getindex{S1,S2,T}(m::MMatrix{S1,S2,T}, i::Integer)
@propagate_inbounds function getindex{S1,S2,T}(m::MMatrix{S1,S2,T}, i::Int)
#@boundscheck if i < 1 || i > length(m)
# throw(BoundsError(m,i))
#end
Expand All @@ -121,8 +116,8 @@ end
end
end

@propagate_inbounds setindex!{S1,S2,T}(m::MMatrix{S1,S2,T}, val, i::Integer) = setindex!(m, convert(T, val), i)
@propagate_inbounds function setindex!{S1,S2,T}(m::MMatrix{S1,S2,T}, val::T, i::Integer)
@propagate_inbounds setindex!{S1,S2,T}(m::MMatrix{S1,S2,T}, val, i::Int) = setindex!(m, convert(T, val), i)
@propagate_inbounds function setindex!{S1,S2,T}(m::MMatrix{S1,S2,T}, val::T, i::Int)
#@boundscheck if i < 1 || i > length(m)
# throw(BoundsError(m,i))
#end
Expand Down
6 changes: 3 additions & 3 deletions src/MVector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ end
@pure Size{S}(::Type{MVector{S}}) = Size(S)
@pure Size{S,T}(::Type{MVector{S,T}}) = Size(S)

@propagate_inbounds function getindex(v::MVector, i::Integer)
@propagate_inbounds function getindex(v::MVector, i::Int)
v.data[i]
end

# Mutating setindex!
@propagate_inbounds setindex!{S,T}(v::MVector{S,T}, val, i::Integer) = setindex!(v, convert(T, val), i)
@inline function setindex!{S,T}(v::MVector{S,T}, val::T, i::Integer)
@propagate_inbounds setindex!{S,T}(v::MVector{S,T}, val, i::Int) = setindex!(v, convert(T, val), i)
@inline function setindex!{S,T}(v::MVector{S,T}, val::T, i::Int)
@boundscheck if i < 1 || i > length(v)
throw(BoundsError())
end
Expand Down
10 changes: 5 additions & 5 deletions src/SArray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@ end
@inline SArray(a::StaticArray) = SArray{size(typeof(a))}(Tuple(a))

# Some more advanced constructor-like functions
@inline eye{Size}(::Type{SArray{Size}}) = eye(SArray{Size,Float64})
@inline zeros{Size}(::Type{SArray{Size}}) = zeros(SArray{Size,Float64})
@inline ones{Size}(::Type{SArray{Size}}) = ones(SArray{Size,Float64})

@inline one(::Type{SArray{S}}) where {S} = one(SArray{S,Float64,length(S)})
@inline eye(::Type{SArray{S}}) where {S} = eye(SArray{S,Float64,length(S)})
@inline one(::Type{SArray{S,T}}) where {S,T} = one(SArray{S,T,length(S)})
@inline eye(::Type{SArray{S,T}}) where {S,T} = eye(SArray{S,T,length(S)})

####################
## SArray methods ##
Expand All @@ -79,7 +79,7 @@ end
@pure Size{S,T,N}(::Type{SArray{S,T,N}}) = Size(S)
@pure Size{S,T,N,L}(::Type{SArray{S,T,N,L}}) = Size(S)

function getindex(v::SArray, i::Integer)
function getindex(v::SArray, i::Int)
Base.@_inline_meta
v.data[i]
end
Expand Down
42 changes: 9 additions & 33 deletions src/SMatrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,26 @@ immutable SMatrix{S1, S2, T, L} <: StaticMatrix{T}
end
end

@generated function check_smatrix_params{S1,S2,L}(::Type{Val{S1}}, ::Type{Val{S2}}, T, ::Type{Val{L}})
if !(T <: DataType) # I think the way types are handled in generated fnctions might have changed in 0.5?
return :(error("SMatrix: Parameter T must be a DataType. Got $T"))
end
function check_smatrix_params(::Type{Val{S1}}, ::Type{Val{S2}}, T, ::Type{Val{L}}) where {S1,S2,L}
throw(ArgumentError("SMatrix: Parameter T must be a Type. Got $T"))
end

@generated function check_smatrix_params(::Type{Val{S1}}, ::Type{Val{S2}}, ::Type{T}, ::Type{Val{L}}) where {S1,S2,L,T}
if !isa(S1, Int) || !isa(S2, Int) || !isa(L, Int) || S1 < 0 || S2 < 0 || L < 0
return :(error("SMatrix: Sizes must be positive integers. Got $S1 × $S2 ($L elements)"))
throw(ArgumentError("SMatrix: Sizes must be positive integers. Got $S1 × $S2 ($L elements)"))
end

if S1*S2 == L
return nothing
else
str = "Size mismatch in SMatrix. S1 = $S1, S2 = $S2, but recieved $L elements"
return :(error($str))
throw(ArgumentError("Size mismatch in SMatrix. S1 = $S1, S2 = $S2, but recieved $L elements"))
end
end

@generated function (::Type{SMatrix{S1}}){S1,L}(x::NTuple{L,Any})
S2 = div(L, S1)
if S1*S2 != L
error("Incorrect matrix sizes. $S1 does not divide $L elements")
throw(DimensionMismatch("Incorrect matrix sizes. $S1 does not divide $L elements"))
end
T = promote_tuple_eltype(x)

Expand All @@ -66,7 +65,7 @@ end
SMatrix{S1, S2, $T, L}(x)
end
end
@compat SMatrixNoType{S1, S2, L, T} = SMatrix{S1, S2, T, L}
SMatrixNoType{S1, S2, L, T} = SMatrix{S1, S2, T, L}
@generated function (::Type{SMatrixNoType{S1, S2, L}}){S1,S2,L}(x::NTuple{L,Any})
T = promote_tuple_eltype(x)
return quote
Expand All @@ -85,32 +84,9 @@ end
@inline convert{S1,S2,T}(::Type{SMatrix{S1,S2}}, a::StaticArray{T}) = SMatrix{S1,S2,T}(Tuple(a))
@inline SMatrix(a::StaticMatrix) = SMatrix{size(typeof(a),1),size(typeof(a),2)}(Tuple(a))

#=
@inline (::Type{SMatrix{S1}}){S1}(x1) = SMatrix{S1}((x1,))
@inline (::Type{SMatrix{S1}}){S1}(x1,x2) = SMatrix{S1}((x1,x2))
@inline (::Type{SMatrix{S1}}){S1}(x1,x2,x3) = SMatrix{S1}((x1,x2,x3))
@inline (::Type{SMatrix{S1}}){S1}(x1,x2,x3,x4) = SMatrix{S1}((x1,x2,x3,x4))
@inline (::Type{SMatrix{S1}}){S1}(x...) = SMatrix{S1}(x)

@inline (::Type{SMatrix{S1,S2}}){S1,S2}(x1) = SMatrix{S1,S2}((x1,))
@inline (::Type{SMatrix{S1,S2}}){S1,S2}(x1,x2) = SMatrix{S1,S2}((x1,x2))
@inline (::Type{SMatrix{S1,S2}}){S1,S2}(x1,x2,x3) = SMatrix{S1,S2}((x1,x2,x3))
@inline (::Type{SMatrix{S1,S2}}){S1,S2}(x1,x2,x3,x4) = SMatrix{S1,S2}((x1,x2,x3,x4))
@inline (::Type{SMatrix{S1,S2}}){S1,S2}(x...) = SMatrix{S1,S2}(x)

@inline (::Type{SMatrix{S1,S2,T}}){S1,S2,T}(x1) = SMatrix{S1,S2,T}((x1,))
@inline (::Type{SMatrix{S1,S2,T}}){S1,S2,T}(x1,x2) = SMatrix{S1,S2,T}((x1,x2))
@inline (::Type{SMatrix{S1,S2,T}}){S1,S2,T}(x1,x2,x3) = SMatrix{S1,S2,T}((x1,x2,x3))
@inline (::Type{SMatrix{S1,S2,T}}){S1,S2,T}(x1,x2,x3,x4) = SMatrix{S1,S2,T}((x1,x2,x3,x4))
@inline (::Type{SMatrix{S1,S2,T}}){S1,S2,T}(x...) = SMatrix{S1,S2,T}(x)
=#

# Some more advanced constructor-like functions
@inline one{N}(::Type{SMatrix{N}}) = one(SMatrix{N,N})
@inline eye{N}(::Type{SMatrix{N}}) = eye(SMatrix{N,N})
@inline eye{N,M}(::Type{SMatrix{N,M}}) = eye(SMatrix{N,M,Float64})
@inline zeros{N,M}(::Type{SMatrix{N,M}}) = zeros(SMatrix{N,M,Float64})
@inline ones{N,M}(::Type{SMatrix{N,M}}) = ones(SMatrix{N,M,Float64})

#####################
## SMatrix methods ##
Expand All @@ -120,7 +96,7 @@ end
@pure Size{S1,S2,T}(::Type{SMatrix{S1,S2,T}}) = Size(S1, S2)
@pure Size{S1,S2,T,L}(::Type{SMatrix{S1,S2,T,L}}) = Size(S1, S2)

function getindex(v::SMatrix, i::Integer)
function getindex(v::SMatrix, i::Int)
Base.@_inline_meta
v.data[i]
end
Expand Down
12 changes: 12 additions & 0 deletions src/SUnitRange.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# `Start` and `End` should be `Int`
struct SUnitRange{Start,End} <: StaticVector{Int}
end

@pure Size(::SUnitRange{Start, End}) where {Start,End} = Size(End-Start+1)

@pure @propagate_inbounds function getindex(x::SUnitRange{Start,End}, i::Int) where {Start, End}
@boundscheck if i < Start || i > End
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a vague memory that @boundscheck wasn't reliable with a general expression. It does work with a function call as the expression.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe worth looking into. Though I thought this pattern was used throughout Base.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is, but I think it's usually written as

@boundscheck checkbounds(A, i)

or something. IIRC I had problems when the expression given to @boundscheck wasn't a function call.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it looks like you've defined a static version of what I'm calling an IdentityRange or IdempotentRange, see JuliaArrays/IdentityRanges.jl#1 and JuliaLang/julia#21052. Just to check, you're aware that these are non-1 indices arrays you've defined here? If this is intentional, you should definitely define the indices function for them.

If that's not what you're intending, you should be checking against 1 <= i <= End - Start + 1 and then return i + Start - 1.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha thanks @timholy - these definitely are WIP. I think I'll split this off and put it on a branch for now.

These are just meant to be singleton array types, so that indices(SVector(1,2,3)) === SUnitRange{1,3}(). AFAICT IdentityRanges are meant to be a bit like a safe :? (How is it distinct from start:stop?)

I suppose that OneTo has been able to double-up for both purposes, for one-based arrays?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IdentityRanges are indeed a generalization of :, one that allows you to slice some or all of an axis while preserving the indices. As to how it differs from start:stop...if you're constructing a view v = view(a, s) with an AbstractVector s, the key identity is that v[i] == a[s[i]]. Since start:stop is a conventional UnitRange, it is indexed starting at 1, so v = view(a, start:stop) would be indexed starting at 1 no matter how a is indexed. In contrast, v = view(a, IdentityRange(start:stop)) would be indexed starting with start, no matter how a is indexed.

throw(BoundsError(x, i))
end
return i
end
4 changes: 2 additions & 2 deletions src/SVector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ immutable SVector{S, T} <: StaticVector{T}
end
end

@inline (::Type{SVector}){S}(x::NTuple{S}) = SVector{S}(x)
@inline (::Type{SVector}){S}(x::NTuple{S,Any}) = SVector{S}(x)
@inline (::Type{SVector{S}}){S, T}(x::NTuple{S,T}) = SVector{S,T}(x)
@inline (::Type{SVector{S}}){S, T <: Tuple}(x::T) = SVector{S,promote_tuple_eltype(T)}(x)

Expand All @@ -43,7 +43,7 @@ end
@pure Size{S}(::Type{SVector{S}}) = Size(S)
@pure Size{S,T}(::Type{SVector{S,T}}) = Size(S)

@propagate_inbounds function getindex(v::SVector, i::Integer)
@propagate_inbounds function getindex(v::SVector, i::Int)
v.data[i]
end

Expand Down
10 changes: 8 additions & 2 deletions src/Scalar.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ Construct a statically-sized 0-dimensional array that contains a single element,
"""
immutable Scalar{T} <: StaticArray{T,0}
data::T

Scalar{T}(x::AbstractArray) where {T} = new{T}(convert(T,x))
Scalar{T}(x::Tuple{T2}) where {T, T2} = new{T}(convert(T,x[1]))
Scalar{T}(x) where {T} = new{T}(convert(T, x))
end

@inline (::Type{Scalar{T}}){T}(x::Tuple{T}) = Scalar{T}(x[1])
@inline Scalar(x::Tuple{T}) where {T} = Scalar{T}(x[1])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's this indexing x[1] about?

Copy link
Member Author

@andyferris andyferris Mar 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The abstract constructors will go Scalar(x) -> Scalar((x,)) (the internal functions also give a tuple). This then goes to Scalar{T}(x::T), which is an inner constructor (and is more specific than other constructors).

@inline Scalar(a::AbstractArray) = Scalar{typeof(a)}(a)
@inline Scalar(a::AbstractScalar) = Scalar{eltype(a)}(a[]) # Do we want this to convert or wrap?

@pure Size(::Type{Scalar}) = Size()
@pure Size{T}(::Type{Scalar{T}}) = Size()
Expand All @@ -24,4 +30,4 @@ end
@inline Tuple(v::Scalar) = (v.data,)

# A lot more compact than the default array show
Base.show{T}(io::IO, ::MIME"text/plain", x::Scalar{T}) = print(io, "Scalar{$T}(", x.data, ")")
Base.show(io::IO, ::MIME"text/plain", x::Scalar{T}) where {T} = print(io, "Scalar{$T}(", x.data, ")")
Loading