diff --git a/src/FixedSizeArrays.jl b/src/FixedSizeArrays.jl index d1252afe..dd1bcf04 100644 --- a/src/FixedSizeArrays.jl +++ b/src/FixedSizeArrays.jl @@ -87,14 +87,15 @@ end macro fixed_vector(name, parent) esc(quote - immutable $(name){S, T} <: $(parent){T} + immutable $(name){S, T} <: $(parent){S, T} data::NTuple{S, T} - function $(name)(x::NTuple{S,T}) - new(x) + function (::Type{$(name){S, T}}){S, T}(x::NTuple{S,T}) + new{S, T}(x) end - function $(name)(x::NTuple{S}) - new(StaticArrays.convert_ntuple(T, x)) + + function (::Type{$(name){S, T}}){S, T}(x::NTuple{S,Any}) + new{S, T}(StaticArrays.convert_ntuple(T, x)) end end # Array constructor @@ -122,6 +123,19 @@ macro fixed_vector(name, parent) @inline function (::Type{$(name){S}}){S, T <: Tuple}(x::T) $(name){S, StaticArrays.promote_tuple_eltype(T)}(x) end + (::Type{$(name){S, T}}){S, T}(x::StaticVector) = $(name){S, T}(Tuple(x)) + @generated function (::Type{$(name){S, T}}){S, T}(x::$(name)) + idx = [:(x[$i]) for i = 1:S] + quote + $($(name)){S, T}($(idx...)) + end + end + @generated function convert{S, T}(::Type{$(name){S, T}}, x::$(name)) + idx = [:(x[$i]) for i = 1:S] + quote + $($(name)){S, T}($(idx...)) + end + end @generated function (::Type{SV}){SV <: $(name)}(x::StaticVector) len = size_or(SV, size(x))[1] if length(x) == len @@ -134,36 +148,34 @@ macro fixed_vector(name, parent) end end - Base.@pure StaticArrays.Size{S}(::Type{$(name){S}}) = Size(S) + Base.@pure StaticArrays.Size{S}(::Type{$(name){S, Any}}) = Size(S) Base.@pure StaticArrays.Size{S,T}(::Type{$(name){S, T}}) = Size(S) - Base.@propagate_inbounds function Base.getindex(v::$(name), i::Integer) + Base.@propagate_inbounds function Base.getindex{S, T}(v::$(name){S, T}, i::Int) v.data[i] end @inline Base.Tuple(v::$(name)) = v.data @inline Base.convert{S, T}(::Type{$(name){S, T}}, x::NTuple{S, T}) = $(name){S, T}(x) - @inline Base.convert{SV <: $(name)}(::Type{SV}, x::StaticVector) = SV(x) + @inline Base.convert(::Type{$(name)}, x::StaticVector) = SV(x) @inline function Base.convert{S, T}(::Type{$(name){S, T}}, x::Tuple) $(name){S, T}(convert(NTuple{S, T}, x)) end - @generated function StaticArrays.similar_type{SV <: $(name), T,S}(::Type{SV}, ::Type{T}, s::Size{S}) + @generated function StaticArrays.similar_type{SV <: $(name), T, S}(::Type{SV}, ::Type{T}, s::Size{S}) if length(S) === 1 $(name){S[1], T} else StaticArrays.default_similar_type(T,s(),Val{length(S)}) end end - - + size_or(::Type{$(name)}, or) = or eltype_or(::Type{$(name)}, or) = or - eltype_or{T}(::Type{$(name){TypeVar(:S), T}}, or) = T - eltype_or{S}(::Type{$(name){S, TypeVar(:T)}}, or) = or + eltype_or{T}(::Type{$(name){S, T} where S}, or) = T + eltype_or{S}(::Type{$(name){S, T} where T}, or) = or eltype_or{S, T}(::Type{$(name){S, T}}, or) = T - size_or(::Type{$(name)}, or) = or - size_or{T}(::Type{$(name){TypeVar(:S), T}}, or) = or - size_or{S}(::Type{$(name){S, TypeVar(:T)}}, or) = (S,) + size_or{T}(::Type{$(name){S, T} where S}, or) = or + size_or{S}(::Type{$(name){S, T} where T}, or) = Size{(S,)}() size_or{S, T}(::Type{$(name){S, T}}, or) = (S,) end) end diff --git a/src/StaticArrays.jl b/src/StaticArrays.jl index b9cc3164..8a63748a 100644 --- a/src/StaticArrays.jl +++ b/src/StaticArrays.jl @@ -94,7 +94,7 @@ include("eigen.jl") include("cholesky.jl") include("deque.jl") -#include("FixedSizeArrays.jl") # Currently defunct +include("FixedSizeArrays.jl") include("ImmutableArrays.jl") end # module diff --git a/src/broadcast.jl b/src/broadcast.jl index ed0e5486..c0d0a3d8 100644 --- a/src/broadcast.jl +++ b/src/broadcast.jl @@ -8,6 +8,10 @@ _broadcast(f, broadcast_sizes(a...), a...) end +@propagate_inbounds function broadcast{T}(f::Function, a::Type{T}, x::StaticArray) + _broadcast(f, (Size(), Size(x)), T, x) +end + @inline broadcast_sizes(a...) = _broadcast_sizes((), a...) @inline _broadcast_sizes(t::Tuple) = t @inline _broadcast_sizes(t::Tuple, a::StaticArray, as...) = _broadcast_sizes((t..., Size(a)), as...) @@ -23,7 +27,7 @@ function broadcasted_index(oldsize, newindex) return sub2ind(oldsize, index...) end -@generated function _broadcast(f, s::Tuple{Vararg{Size}}, a::Union{Number, StaticArray}...) +@generated function _broadcast(f, s::Tuple{Vararg{Size}}, a...) first_staticarray = 0 for i = 1:length(a) if a[i] <: StaticArray @@ -57,7 +61,7 @@ end current_ind = ones(Int, length(newsize)) while more - exprs_vals = [(a[i] <: Number ? :(a[$i]) : :(a[$i][$(broadcasted_index(sizes[i], current_ind))])) for i = 1:length(sizes)] + exprs_vals = [(!(a[i] <: AbstractArray) ? :(a[$i]) : :(a[$i][$(broadcasted_index(sizes[i], current_ind))])) for i = 1:length(sizes)] exprs[current_ind...] = :(f($(exprs_vals...))) # increment current_ind (maybe use CartesianRange?) @@ -77,7 +81,7 @@ end end end - eltype_exprs = [:(eltype($t)) for t ∈ a] + eltype_exprs = [t <: AbstractArray ? :($(eltype(t))) : :($t) for t ∈ a] newtype_expr = :(Core.Inference.return_type(f, Tuple{$(eltype_exprs...)})) return quote diff --git a/src/indexing.jl b/src/indexing.jl index ffe7761e..d04f0d60 100644 --- a/src/indexing.jl +++ b/src/indexing.jl @@ -14,6 +14,7 @@ end @generated function _getindex_scalar(::Size{S}, a::StaticArray, inds::Int...) where S stride = 1 + ind_expr = :() for i ∈ 1:length(inds) if i == 1 ind_expr = :(inds[1]) @@ -34,6 +35,7 @@ end @generated function _setindex!_scalar(::Size{S}, a::StaticArray, value, inds::Int...) where S stride = 1 + ind_expr = :() for i ∈ 1:length(inds) if i == 1 ind_expr = :(inds[1]) diff --git a/src/util.jl b/src/util.jl index a472e256..68fa4a33 100644 --- a/src/util.jl +++ b/src/util.jl @@ -50,11 +50,11 @@ end @generated function check_array_parameters{Size,T,N,L}(::Type{Size}, ::Type{T}, ::Type{Val{N}}, ::Type{Val{L}}) if !all(x->isa(x, Int), Size.parameters) - throw(ArgumentError("Static Array parameter Size must be a tuple of Ints (e.g. `SArray{Tuple{3,3}}` or `SMatrix{3,3}`).")) + return :(throw(ArgumentError("Static Array parameter Size must be a tuple of Ints (e.g. `SArray{Tuple{3,3}}` or `SMatrix{3,3}`)."))) end if L != tuple_prod(Size) || L < 0 || tuple_minimum(Size) < 0 || tuple_length(Size) != N - throw(ArgumentError("Size mismatch in Static Array parameters. Got size $Size, dimension $N and length $L.")) + return :(throw(ArgumentError("Size mismatch in Static Array parameters. Got size $Size, dimension $N and length $L."))) end return nothing diff --git a/test/fixed_size_arrays.jl b/test/fixed_size_arrays.jl index f5fc3e25..d6bf8b24 100644 --- a/test/fixed_size_arrays.jl +++ b/test/fixed_size_arrays.jl @@ -5,38 +5,39 @@ using Base.Test import StaticArrays.FixedSizeArrays: @fixed_vector -@compat const Vec1d = Vec{1, Float64} -@compat const Vec2d = Vec{2, Float64} -@compat const Vec3d = Vec{3, Float64} -@compat const Vec4d = Vec{4, Float64} -@compat const Vec3f = Vec{3, Float32} +const Vec1d = Vec{1, Float64} +const Vec2d = Vec{2, Float64} +const Vec3d = Vec{3, Float64} +const Vec4d = Vec{4, Float64} +const Vec3f = Vec{3, Float32} -@compat const Mat2d = Mat{2,2, Float64, 4} -@compat const Mat3d = Mat{3,3, Float64, 9} -@compat const Mat4d = Mat{4,4, Float64, 16} +const Mat2d = Mat{2,2, Float64, 4} +const Mat3d = Mat{3,3, Float64, 9} +const Mat4d = Mat{4,4, Float64, 16} -immutable RGB{T} <: FieldVector{T} +immutable RGB{T} <: FieldVector{3, T} x::T y::T z::T end + RGB{T}(x::T) = RGB{T}(x, x, x) (::RGB{T}){T}(r, g, b) = RGB{T}(T(r), T(g), T(b)) (::RGB{T}){T}(r::Real) = RGB(T(r), T(r), T(r)) StaticArrays.similar_type{SV <: RGB, T}(::Type{SV}, ::Type{T}, ::Size{(3,)}) = RGB{T} # TODO find equivalent in StaticArrays -# testset "scalar nan" begin -# for (p, r) in ( -# (Point{2, Float32}(NaN, 1), true), -# (Point{2, Float64}(1, NaN), true), -# (Vec{11, Float64}(NaN), true), -# (Point{2, Float32}(1, 1), false), -# (RGB{Float32}(NaN), true), -# ) -# @fact isnan(p) == r -# end -# end +@testset "scalar nan" begin + for (p, r) in ( + (Point{2, Float32}(NaN, 1), true), + (Point{2, Float64}(1, NaN), true), + (Vec{11, Float64}(NaN), true), + (Point{2, Float32}(1, 1), false), + (RGB{Float32}(NaN, NaN, NaN), true), + ) + @test any(isnan, p) == r + end +end # methods I needed to define: @@ -124,8 +125,8 @@ rand(Mat{4,2, Int}) @test typeof(rand(Mat{4,2, Int})) == Mat{4,2, Int, 8} @test typeof(rand(Vec{7, Int})) == Vec{7, Int} -@test typeof(rand(-20f0:0.192f0:230f0, Mat4d)) == Mat4d -@test typeof(rand(-20f0:0.192f0:230f0, Mat{4,21,Float32})) == Mat{4,21,Float32, 4*21} +# @test typeof(rand(-20f0:0.192f0:230f0, Mat4d)) == Mat4d +# @test typeof(rand(-20f0:0.192f0:230f0, Mat{4,21,Float32})) == Mat{4,21,Float32, 4*21} @test typeof(rand(Vec4d, 5,5)) == Matrix{Vec4d} #end @@ -206,13 +207,13 @@ map(-, Vec(1,2,3)) map(+, Vec(1,2,3), Vec(1,1, 1)) (+).(Vec(1,2,3), 1.0) v1 = Vec3d(1,2,3) -@test v1[(2,1)] == Vec2d(2,1) +@test v1[Vec(2,1)] == Vec2d(2,1) @test @inferred(-v1) == Vec(-1.0,-2.0,-3.0) @test isa(-v1, Vec3d) == true @test @inferred(v1 ./ v1) == Vec3d(1.0,1.0,1.0) @test (<).(Vec(1,3), Vec(2,2)) === Vec{2,Bool}(true, false) - +# v1 = Vec(1.0,2.0,3.0) v2 = Vec(6.0,5.0,4.0) vi = Vec(1,2,3) @@ -379,10 +380,9 @@ const unaryOps = ( # vec-vec and vec-scalar const binaryOps = ( - .+, .-, .*, ./, .\, - .==, .!=, .<, .<=, .>, .>=, +, -, + +, -, *, /, \, + ==, !=, <, <=, >, >=, min, max, - atan2, besselj, bessely, hankelh1, hankelh2, besseli, besselk, beta, lbeta ) @@ -400,7 +400,7 @@ const binaryOps = ( @testset "$op with $v1 and $v2" begin try # really bad tests, but better than nothing... if applicable(op, v1[1], v2[1]) && typeof(op(v1[1], v2[1])) == eltype(v1) - r = op(v1, v2) + r = op.(v1, v2) for j=1:length(v1) @test r[j] == op(v1[j], v2[j]) end @@ -417,7 +417,7 @@ const binaryOps = ( @testset "$op with $t" begin try if applicable(op, t[1]) && typeof(op(t[1])) == eltype(t) - v = op(t) + v = op.(t) for i=1:length(v) @test v[i] == op(t[i]) end diff --git a/test/runtests.jl b/test/runtests.jl index 54fd7023..47b2502a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -25,5 +25,5 @@ using Base.Test include("solve.jl") # Strange inference / world-age error include("eigen.jl") include("deque.jl") - #include("fixed_size_arrays.jl") + include("fixed_size_arrays.jl") end