|
| 1 | + |
| 2 | +Base.axes(::TupleVector{N}) where N = _axes(Val(N)) |
| 3 | +@pure function _axes(::Val{sizes}) where {sizes} |
| 4 | + map(SOneTo, (sizes,)) |
| 5 | +end |
| 6 | +Base.axes(rv::LinearAlgebra.Adjoint{<:Any,<:Values}) = (SOneTo(1), axes(rv.parent)...) |
| 7 | +Base.axes(rv::LinearAlgebra.Transpose{<:Any,<:Values}) = (SOneTo(1), axes(rv.parent)...) |
| 8 | + |
| 9 | +# Base.strides is intentionally not defined for SArray, see PR #658 for discussion |
| 10 | +Base.strides(a::Variables) = Base.size_to_strides(1, size(a)...) |
| 11 | +Base.strides(a::FixedVector) = strides(a.v) |
| 12 | + |
| 13 | +Base.IndexStyle(::Type{T}) where {T<:TupleVector} = IndexLinear() |
| 14 | + |
| 15 | +similar_type(::SA) where {SA<:TupleVector} = similar_type(SA,eltype(SA)) |
| 16 | +similar_type(::Type{SA}) where {SA<:TupleVector} = similar_type(SA,eltype(SA)) |
| 17 | + |
| 18 | +similar_type(::SA,::Type{T}) where {SA<:TupleVector{N},T} where N = similar_type(SA,T,Val(N)) |
| 19 | +similar_type(::Type{SA},::Type{T}) where {SA<:TupleVector{N},T} where N = similar_type(SA,T,Val(N)) |
| 20 | + |
| 21 | +similar_type(::A,n::Val) where {A<:AbstractArray} = similar_type(A,eltype(A),n) |
| 22 | +similar_type(::Type{A},n::Val) where {A<:AbstractArray} = similar_type(A,eltype(A),n) |
| 23 | + |
| 24 | +similar_type(::A,::Type{T},n::Val) where {A<:AbstractArray,T} = similar_type(A,T,n) |
| 25 | + |
| 26 | +# We should be able to deal with SOneTo axes |
| 27 | +similar_type(s::SOneTo) = similar_type(typeof(s)) |
| 28 | +similar_type(::Type{SOneTo{n}}) where n = similar_type(SOneTo{n}, Int, Val(n)) |
| 29 | + |
| 30 | +# Default types |
| 31 | +# Generally, use SArray |
| 32 | +similar_type(::Type{A},::Type{T},n::Val) where {A<:AbstractArray,T} = default_similar_type(T,n) |
| 33 | +default_similar_type(::Type{T},::Val{N}) where {N,T} = Values{N,T} |
| 34 | + |
| 35 | +similar_type(::Type{SA},::Type{T},n::Val) where {SA<:Variables,T} = mutable_similar_type(T,n) |
| 36 | + |
| 37 | +mutable_similar_type(::Type{T},::Val{N}) where {N,T} = Variables{N,T} |
| 38 | + |
| 39 | +similar_type(::Type{<:FixedVector},::Type{T},n::Val) where T = sizedarray_similar_type(T,n) |
| 40 | +# Should FixedVector also be used for normal Array? |
| 41 | +#similar_type(::Type{<:Array},::Type{T},n::Val) where T = sizedarray_similar_type(T,n) |
| 42 | + |
| 43 | +sizedarray_similar_type(::Type{T},::Val{N}) where {N,T} = FixedVector{N,T} |
| 44 | + |
| 45 | +Base.similar(::SA) where {SA<:TupleVector} = similar(SA,eltype(SA)) |
| 46 | +Base.similar(::Type{SA}) where {SA<:TupleVector} = similar(SA,eltype(SA)) |
| 47 | + |
| 48 | +Base.similar(::SA,::Type{T}) where {SA<:TupleVector{N},T} where N = similar(SA,T,Val(N)) |
| 49 | +Base.similar(::Type{SA},::Type{T}) where {SA<:TupleVector{N},T} where N = similar(SA,T,Val(N)) |
| 50 | + |
| 51 | +# Cases where a Val is given as the dimensions |
| 52 | +Base.similar(::A,n::Val) where A<:AbstractArray = similar(A,eltype(A),n) |
| 53 | +Base.similar(::Type{A},n::Val) where A<:AbstractArray = similar(A,eltype(A),n) |
| 54 | + |
| 55 | +Base.similar(::A,::Type{T},n::Val) where {A<:AbstractArray,T} = similar(A,T,n) |
| 56 | + |
| 57 | +# defaults to built-in mutable types |
| 58 | +Base.similar(::Type{A},::Type{T},n::Val) where {A<:AbstractArray,T} = mutable_similar_type(T,n)(undef) |
| 59 | + |
| 60 | +# both FixedVector and Array return FixedVector |
| 61 | +Base.similar(::Type{SA},::Type{T},n::Val) where {SA<:FixedVector,T} = sizedarray_similar_type(T,n)(undef) |
| 62 | +Base.similar(::Type{A},::Type{T},n::Val) where {A<:Array,T} = sizedarray_similar_type(T,n)(undef) |
| 63 | + |
| 64 | +# Support tuples of mixtures of `SOneTo`s alongside the normal `Integer` and `OneTo` options |
| 65 | +# by simply converting them to either a tuple of Ints or a Val, re-dispatching to either one |
| 66 | +# of the above methods (in the case of Val) or a base fallback (in the case of Ints). |
| 67 | +const HeterogeneousShape = Union{Integer, Base.OneTo, SOneTo} |
| 68 | + |
| 69 | +Base.similar(A::AbstractArray, ::Type{T}, shape::Tuple{HeterogeneousShape, Vararg{HeterogeneousShape}}) where {T} = similar(A, T, homogenize_shape(shape)) |
| 70 | +Base.similar(::Type{A}, shape::Tuple{HeterogeneousShape, Vararg{HeterogeneousShape}}) where {A<:AbstractArray} = similar(A, homogenize_shape(shape)) |
| 71 | +# Use an Array for TupleVectors if we don't have a statically-known size |
| 72 | +Base.similar(::Type{A}, shape::Tuple{Int, Vararg{Int}}) where {A<:TupleVector} = Array{eltype(A)}(undef, shape) |
| 73 | + |
| 74 | +homogenize_shape(::Tuple{}) = () |
| 75 | +homogenize_shape(shape::Tuple{Vararg{SOneTo}}) = Val(prod(map(last, shape))) |
| 76 | +homogenize_shape(shape::Tuple{Vararg{HeterogeneousShape}}) = map(last, shape) |
| 77 | + |
| 78 | + |
| 79 | +@inline Base.copy(a::TupleVector) = typeof(a)(Tuple(a)) |
| 80 | +@inline Base.copy(a::FixedVector) = typeof(a)(copy(a.v)) |
| 81 | + |
| 82 | +@inline Base.reverse(v::Values) = typeof(v)(_reverse(v)) |
| 83 | + |
| 84 | +@generated function _reverse(v::Values{N,T}) where {N,T} |
| 85 | + return Expr(:tuple, (:(v[$i]) for i = N:(-1):1)...) |
| 86 | +end |
| 87 | + |
| 88 | +#-------------------------------------------------- |
| 89 | +# Concatenation |
| 90 | +@inline Base.vcat(a::TupleVectorLike) = a |
| 91 | +@inline Base.vcat(a::TupleVectorLike{N}, b::TupleVectorLike{M}) where {N,M} = _vcat(Val(N), Val(M), a, b) |
| 92 | +@inline Base.vcat(a::TupleVectorLike, b::TupleVectorLike, c::TupleVectorLike...) = vcat(vcat(a,b), vcat(c...)) |
| 93 | + |
| 94 | +@generated function _vcat(::Val{Sa}, ::Val{Sb}, a::TupleVectorLike, b::TupleVectorLike) where {Sa, Sb} |
| 95 | + |
| 96 | + # TODO cleanup? |
| 97 | + Snew = Sa + Sb |
| 98 | + exprs = vcat([:(a[$i]) for i = 1:Sa], |
| 99 | + [:(b[$i]) for i = 1:Sb]) |
| 100 | + return quote |
| 101 | + @_inline_meta |
| 102 | + @inbounds return similar_type(a, promote_type(eltype(a), eltype(b)), Val($Snew))(tuple($(exprs...))) |
| 103 | + end |
| 104 | +end |
| 105 | + |
| 106 | +#=@inline hcat(a::StaticVector) = similar_type(a, Size(Size(a)[1],1))(a) |
| 107 | +@inline hcat(a::StaticMatrixLike) = a |
| 108 | +@inline hcat(a::StaticVecOrMatLike, b::StaticVecOrMatLike) = _hcat(Size(a), Size(b), a, b) |
| 109 | +@inline hcat(a::StaticVecOrMatLike, b::StaticVecOrMatLike, c::StaticVecOrMatLike...) = hcat(hcat(a,b), hcat(c...)) |
| 110 | +
|
| 111 | +@generated function _hcat(::Size{Sa}, ::Size{Sb}, a::StaticVecOrMatLike, b::StaticVecOrMatLike) where {Sa, Sb} |
| 112 | + if Sa[1] != Sb[1] |
| 113 | + return :(throw(DimensionMismatch("Tried to hcat arrays of size $Sa and $Sb"))) |
| 114 | + end |
| 115 | +
|
| 116 | + exprs = vcat([:(a[$i]) for i = 1:prod(Sa)], |
| 117 | + [:(b[$i]) for i = 1:prod(Sb)]) |
| 118 | +
|
| 119 | + Snew = (Sa[1], Size(Sa)[2] + Size(Sb)[2]) |
| 120 | +
|
| 121 | + return quote |
| 122 | + @_inline_meta |
| 123 | + @inbounds return similar_type(a, promote_type(eltype(a), eltype(b)), Size($Snew))(tuple($(exprs...))) |
| 124 | + end |
| 125 | +end=# |
0 commit comments