@@ -2126,28 +2126,34 @@ julia> hvncat(((3, 3), (3, 3), (6,)), true, a, b, c, d, e, f)
2126
2126
4 = elements in each 4d slice (4,)
2127
2127
=> shape = ((2, 1, 1), (3, 1), (4,), (4,)) with `rowfirst` = true
2128
2128
"""
2129
- hvncat (:: Tuple{} , :: Bool ) = []
2130
- hvncat (:: Tuple{} , :: Bool , xs... ) = []
2131
- hvncat (:: Tuple{Vararg{Any, 1}} , :: Bool , xs... ) = vcat (xs... ) # methods assume 2+ dimensions
2132
2129
hvncat (dimsshape:: Tuple , row_first:: Bool , xs... ) = _hvncat (dimsshape, row_first, xs... )
2133
2130
hvncat (dim:: Int , xs... ) = _hvncat (dim, true , xs... )
2134
2131
2135
- _hvncat (:: Union{Tuple, Int} , :: Bool ) = []
2132
+ _hvncat (dimsshape :: Union{Tuple, Int} , row_first :: Bool ) = _typed_hvncat (Any, dimsshape, row_first)
2136
2133
_hvncat (dimsshape:: Union{Tuple, Int} , row_first:: Bool , xs... ) = _typed_hvncat (promote_eltypeof (xs... ), dimsshape, row_first, xs... )
2137
2134
_hvncat (dimsshape:: Union{Tuple, Int} , row_first:: Bool , xs:: T... ) where T<: Number = _typed_hvncat (T, dimsshape, row_first, xs... )
2138
2135
_hvncat (dimsshape:: Union{Tuple, Int} , row_first:: Bool , xs:: Number... ) = _typed_hvncat (promote_typeof (xs... ), dimsshape, row_first, xs... )
2139
2136
_hvncat (dimsshape:: Union{Tuple, Int} , row_first:: Bool , xs:: AbstractArray... ) = _typed_hvncat (promote_eltype (xs... ), dimsshape, row_first, xs... )
2140
2137
_hvncat (dimsshape:: Union{Tuple, Int} , row_first:: Bool , xs:: AbstractArray{T} ...) where T = _typed_hvncat (T, dimsshape, row_first, xs... )
2141
2138
2142
- typed_hvncat (:: Type{T} , :: Tuple{} , :: Bool ) where T = Vector {T} ()
2143
- typed_hvncat (:: Type{T} , :: Tuple{} , :: Bool , xs... ) where T = Vector {T} ()
2144
- typed_hvncat (T:: Type , :: Tuple{Vararg{Any, 1}} , :: Bool , xs... ) = typed_vcat (T, xs... ) # methods assume 2+ dimensions
2145
2139
typed_hvncat (T:: Type , dimsshape:: Tuple , row_first:: Bool , xs... ) = _typed_hvncat (T, dimsshape, row_first, xs... )
2146
2140
typed_hvncat (T:: Type , dim:: Int , xs... ) = _typed_hvncat (T, Val (dim), xs... )
2147
2141
2148
- _typed_hvncat (:: Type{T} , :: Tuple{} , :: Bool ) where T = Vector {T} ()
2149
- _typed_hvncat (:: Type{T} , :: Tuple{} , :: Bool , xs... ) where T = Vector {T} ()
2150
- _typed_hvncat (:: Type{T} , :: Tuple{} , :: Bool , xs:: Number... ) where T = Vector {T} ()
2142
+ # 1-dimensional hvncat methods
2143
+
2144
+ _typed_hvncat (:: Type , :: Val{0} ) = _typed_hvncat_0d_only_one ()
2145
+ _typed_hvncat (T:: Type , :: Val{0} , x) = fill (convert (T, x))
2146
+ _typed_hvncat (T:: Type , :: Val{0} , x:: Number ) = fill (convert (T, x))
2147
+ _typed_hvncat (T:: Type , :: Val{0} , x:: AbstractArray ) = convert .(T, x)
2148
+ _typed_hvncat (:: Type , :: Val{0} , :: Any... ) = _typed_hvncat_0d_only_one ()
2149
+ _typed_hvncat (:: Type , :: Val{0} , :: Number... ) = _typed_hvncat_0d_only_one ()
2150
+ _typed_hvncat (:: Type , :: Val{0} , :: AbstractArray... ) = _typed_hvncat_0d_only_one ()
2151
+
2152
+ _typed_hvncat_0d_only_one () =
2153
+ throw (ArgumentError (" a 0-dimensional array may only contain exactly one element" ))
2154
+
2155
+ _typed_hvncat (:: Type{T} , :: Val{N} ) where {T, N} = Array {T, N} (undef, ntuple (x -> 0 , Val (N)))
2156
+
2151
2157
function _typed_hvncat (:: Type{T} , dims:: Tuple{Vararg{Int, N}} , row_first:: Bool , xs:: Number... ) where {T, N}
2152
2158
A = Array {T, N} (undef, dims... )
2153
2159
lengtha = length (A) # Necessary to store result because throw blocks are being deoptimized right now, which leads to excessive allocations
@@ -2185,14 +2191,13 @@ function hvncat_fill!(A::Array, row_first::Bool, xs::Tuple)
2185
2191
end
2186
2192
2187
2193
_typed_hvncat (T:: Type , dim:: Int , :: Bool , xs... ) = _typed_hvncat (T, Val (dim), xs... ) # catches from _hvncat type promoters
2188
- _typed_hvncat (:: Type{T} , :: Val ) where T = Vector {T} ()
2189
- _typed_hvncat (T:: Type , :: Val{N} , xs:: Number... ) where N = _typed_hvncat (T, (ntuple (x -> 1 , N - 1 )... , length (xs)), false , xs... )
2190
2194
function _typed_hvncat (:: Type{T} , :: Val{N} , as:: AbstractArray... ) where {T, N}
2191
2195
# optimization for arrays that can be concatenated by copying them linearly into the destination
2192
2196
# conditions: the elements must all have 1- or 0-length dimensions above N
2193
2197
for a ∈ as
2194
2198
ndims (a) <= N || all (x -> size (a, x) == 1 , (N + 1 ): ndims (a)) ||
2195
- return _typed_hvncat (T, (ntuple (x -> 1 , N - 1 )... , length (as)), false , as... )
2199
+ return _typed_hvncat (T, (ntuple (x -> 1 , N - 1 )... , length (as), 1 ), false , as... )
2200
+ # the extra 1 is to avoid an infinite cycle
2196
2201
end
2197
2202
2198
2203
nd = max (N, ndims (as[1 ]))
@@ -2246,6 +2251,31 @@ function _typed_hvncat(::Type{T}, ::Val{N}, as...) where {T, N}
2246
2251
return A
2247
2252
end
2248
2253
2254
+
2255
+ # 0-dimensional cases for balanced and unbalanced hvncat method
2256
+
2257
+ _typed_hvncat (T:: Type , :: Tuple{} , :: Bool , x... ) = _typed_hvncat (T, Val (0 ), x... )
2258
+ _typed_hvncat (T:: Type , :: Tuple{} , :: Bool , x:: Number... ) = _typed_hvncat (T, Val (0 ), x... )
2259
+
2260
+
2261
+ # balanced dimensions hvncat methods
2262
+
2263
+ _typed_hvncat (T:: Type , dims:: Tuple{Int} , :: Bool , as... ) = _typed_hvncat_1d (T, dims[1 ], Val (false ), as... )
2264
+ _typed_hvncat (T:: Type , dims:: Tuple{Int} , :: Bool , as:: Number... ) = _typed_hvncat_1d (T, dims[1 ], Val (false ), as... )
2265
+
2266
+ function _typed_hvncat_1d (:: Type{T} , ds:: Int , :: Val{row_first} , as... ) where {T, row_first}
2267
+ lengthas = length (as)
2268
+ ds > 0 ||
2269
+ throw (ArgumentError (" `dimsshape` argument must consist of positive integers" ))
2270
+ lengthas == ds ||
2271
+ throw (ArgumentError (" number of elements does not match `dimshape` argument; expected $ds , got $lengthas " ))
2272
+ if row_first
2273
+ return _typed_hvncat (T, Val (2 ), as... )
2274
+ else
2275
+ return _typed_hvncat (T, Val (1 ), as... )
2276
+ end
2277
+ end
2278
+
2249
2279
function _typed_hvncat (:: Type{T} , dims:: Tuple{Vararg{Int, N}} , row_first:: Bool , as... ) where {T, N}
2250
2280
d1 = row_first ? 2 : 1
2251
2281
d2 = row_first ? 1 : 2
@@ -2308,7 +2338,16 @@ function _typed_hvncat(::Type{T}, dims::Tuple{Vararg{Int, N}}, row_first::Bool,
2308
2338
return A
2309
2339
end
2310
2340
2311
- function _typed_hvncat (:: Type{T} , shape:: Tuple{Vararg{Tuple, N}} , row_first:: Bool , as... ) where {T, N}
2341
+
2342
+ # unbalanced dimensions hvncat methods
2343
+
2344
+ function _typed_hvncat (T:: Type , shape:: Tuple{Tuple} , row_first:: Bool , xs... )
2345
+ length (shape[1 ]) > 0 ||
2346
+ throw (ArgumentError (" each level of `shape` argument must have at least one value" ))
2347
+ return _typed_hvncat_1d (T, shape[1 ][1 ], Val (row_first), xs... )
2348
+ end
2349
+
2350
+ function _typed_hvncat (T:: Type , shape:: NTuple{N, Tuple} , row_first:: Bool , as... ) where {N}
2312
2351
d1 = row_first ? 2 : 1
2313
2352
d2 = row_first ? 1 : 2
2314
2353
shape = collect (shape) # saves allocations later
0 commit comments