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

RFC: Introduce promotion mechanism for concatenation #20815

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
69 changes: 34 additions & 35 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1009,20 +1009,18 @@ replace_in_print_matrix(A::AbstractMatrix,i::Integer,j::Integer,s::AbstractStrin
replace_in_print_matrix(A::AbstractVector,i::Integer,j::Integer,s::AbstractString) = s

## Concatenation ##
eltypeof(x) = typeof(x)
eltypeof(x::AbstractArray) = eltype(x)

promote_eltypeof() = Bottom
promote_eltypeof(v1, vs...) = promote_type(eltypeof(v1), promote_eltypeof(vs...))

promote_eltype() = Bottom
promote_eltype(v1, vs...) = promote_type(eltype(v1), promote_eltype(vs...))

eltyped_vcat{T}(::Type{T}, args...) = typed_vcat(Array{T}, args...)
eltyped_hcat{T}(::Type{T}, args...) = typed_hcat(Array{T}, args...)
eltyped_hvcat{T}(::Type{T}, args...) = typed_hvcat(Array{T}, args...)

#TODO: ERROR CHECK
cat(catdim::Integer) = Array{Any,1}(0)

typed_vcat{T}(::Type{T}) = Array{T,1}(0)
typed_hcat{T}(::Type{T}) = Array{T,1}(0)
typed_vcat{T}(::Type{T}) = similar(T, 0)
typed_hcat{T}(::Type{T}) = similar(T, 0)

## cat: special cases
vcat{T}(X::T...) = T[ X[i] for i=1:length(X) ]
Expand All @@ -1032,18 +1030,17 @@ hcat{T<:Number}(X::T...) = T[ X[j] for i=1:1, j=1:length(X) ]

vcat(X::Number...) = hvcat_fill(Array{promote_typeof(X...)}(length(X)), X)
hcat(X::Number...) = hvcat_fill(Array{promote_typeof(X...)}(1,length(X)), X)
typed_vcat{T}(::Type{T}, X::Number...) = hvcat_fill(Array{T,1}(length(X)), X)
typed_hcat{T}(::Type{T}, X::Number...) = hvcat_fill(Array{T,2}(1,length(X)), X)
typed_vcat{T}(::Type{T}, X::Number...) = hvcat_fill(similar(T, length(X)), X)
typed_hcat{T}(::Type{T}, X::Number...) = hvcat_fill(similar(T, 1, length(X)), X)

vcat(V::AbstractVector...) = typed_vcat(promote_eltype(V...), V...)
vcat{T}(V::AbstractVector{T}...) = typed_vcat(T, V...)
vcat(V::AbstractVector...) = typed_vcat(promote_typeof_cat(V...), V...)

function typed_vcat{T}(::Type{T}, V::AbstractVector...)
n::Int = 0
for Vk in V
n += length(Vk)
end
a = similar(V[1], T, n)
a = similar(T, n)
pos = 1
for k=1:length(V)
Vk = V[k]
Expand All @@ -1054,8 +1051,7 @@ function typed_vcat{T}(::Type{T}, V::AbstractVector...)
a
end

hcat(A::AbstractVecOrMat...) = typed_hcat(promote_eltype(A...), A...)
hcat{T}(A::AbstractVecOrMat{T}...) = typed_hcat(T, A...)
hcat(A::AbstractVecOrMat...) = typed_hcat(promote_typeof_cat(A...), A...)

function typed_hcat{T}(::Type{T}, A::AbstractVecOrMat...)
nargs = length(A)
Expand All @@ -1071,7 +1067,7 @@ function typed_hcat{T}(::Type{T}, A::AbstractVecOrMat...)
nd = ndims(Aj)
ncols += (nd==2 ? size(Aj,2) : 1)
end
B = similar(A[1], T, nrows, ncols)
B = similar(T, nrows, ncols)
pos = 1
if dense
for k=1:nargs
Expand All @@ -1091,8 +1087,7 @@ function typed_hcat{T}(::Type{T}, A::AbstractVecOrMat...)
return B
end

vcat(A::AbstractMatrix...) = typed_vcat(promote_eltype(A...), A...)
vcat{T}(A::AbstractMatrix{T}...) = typed_vcat(T, A...)
vcat(A::AbstractMatrix...) = typed_vcat(promote_typeof_cat(A...), A...)

function typed_vcat{T}(::Type{T}, A::AbstractMatrix...)
nargs = length(A)
Expand All @@ -1103,7 +1098,7 @@ function typed_vcat{T}(::Type{T}, A::AbstractMatrix...)
throw(ArgumentError("number of columns of each array must match (got $(map(x->size(x,2), A)))"))
end
end
B = similar(A[1], T, nrows, ncols)
B = similar(T, nrows, ncols)
pos = 1
for k=1:nargs
Ak = A[k]
Expand All @@ -1125,9 +1120,6 @@ cat_size(A::AbstractArray, d) = size(A, d)
cat_indices(A, d) = OneTo(1)
cat_indices(A::AbstractArray, d) = indices(A, d)

cat_similar(A, T, shape) = Array{T}(shape)
cat_similar(A::AbstractArray, T, shape) = similar(A, T, shape)

cat_shape(dims, shape::Tuple) = shape
@inline cat_shape(dims, shape::Tuple, nshape::Tuple, shapes::Tuple...) =
cat_shape(dims, _cshp(dims, (), shape, nshape), shapes...)
Expand Down Expand Up @@ -1157,14 +1149,24 @@ _cs(d, concat, a, b) = concat ? (a + b) : (a == b ? a : throw(DimensionMismatch(
dims2cat{n}(::Type{Val{n}}) = ntuple(i -> (i == n), Val{n})
dims2cat(dims) = ntuple(i -> (i in dims), maximum(dims))

cat(dims, X...) = cat_t(dims, promote_eltypeof(X...), X...)
promote_type_cat(::Type{S}, ::Type{T}) where {S<:AbstractArray, T<:AbstractArray} =
Array{promote_type(eltype(S), eltype(T))}
promote_type_cat(::Type{T}, ::Type{Union{}}) where {T<:AbstractArray} =
Array{eltype(T)}

promote_typeof_cat{T<:AbstractArray}(v1::T) = T
promote_typeof_cat{T}(v1::T) = Array{T}
promote_typeof_cat{T<:AbstractArray}(v1::T, vs...) = promote_type_cat(T, promote_typeof_cat(vs...))
promote_typeof_cat{T}(v1::T, vs...) = promote_type_cat(Array{T}, promote_typeof_cat(vs...))

cat(dims, X...) = cat_t(dims, promote_typeof_cat(X...), X...)

function cat_t(dims, T::Type, X...)
catdims = dims2cat(dims)
shape = cat_shape(catdims, (), map(cat_size, X)...)
A = cat_similar(X[1], T, shape)
if T <: Number && countnz(catdims) > 1
fill!(A, zero(T))
A = similar(T, shape)
if eltype(T) <: Number && countnz(catdims) > 1
fill!(A, zero(eltype(T)))
end
return _cat(A, shape, catdims, X...)
end
Expand Down Expand Up @@ -1264,8 +1266,6 @@ hcat(X...) = cat(Val{2}, X...)
typed_vcat(T::Type, X...) = cat_t(Val{1}, T, X...)
typed_hcat(T::Type, X...) = cat_t(Val{2}, T, X...)

cat{T}(catdims, A::AbstractArray{T}...) = cat_t(catdims, T, A...)

# The specializations for 1 and 2 inputs are important
# especially when running with --inline=no, see #11158
vcat(A::AbstractArray) = cat(Val{1}, A)
Expand Down Expand Up @@ -1330,8 +1330,7 @@ julia> hvcat((2,2,2), a,b,c,d,e,f)
If the first argument is a single integer `n`, then all block rows are assumed to have `n`
block columns.
"""
hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractVecOrMat...) = typed_hvcat(promote_eltype(xs...), rows, xs...)
hvcat{T}(rows::Tuple{Vararg{Int}}, xs::AbstractVecOrMat{T}...) = typed_hvcat(T, rows, xs...)
hvcat(rows::Tuple{Vararg{Int}}, xs::AbstractVecOrMat...) = typed_hvcat(promote_typeof_cat(xs...), rows, xs...)

function typed_hvcat{T}(::Type{T}, rows::Tuple{Vararg{Int}}, as::AbstractVecOrMat...)
nbr = length(rows) # number of block rows
Expand All @@ -1348,7 +1347,7 @@ function typed_hvcat{T}(::Type{T}, rows::Tuple{Vararg{Int}}, as::AbstractVecOrMa
a += rows[i]
end

out = similar(as[1], T, nr, nc)
out = similar(T, nr, nc)

a = 1
r = 1
Expand Down Expand Up @@ -1377,7 +1376,7 @@ function typed_hvcat{T}(::Type{T}, rows::Tuple{Vararg{Int}}, as::AbstractVecOrMa
end

hvcat(rows::Tuple{Vararg{Int}}) = []
typed_hvcat{T}(::Type{T}, rows::Tuple{Vararg{Int}}) = Array{T,1}(0)
typed_hvcat{T}(::Type{T}, rows::Tuple{Vararg{Int}}) = similar(T, 0)

function hvcat{T<:Number}(rows::Tuple{Vararg{Int}}, xs::T...)
nr = length(rows)
Expand Down Expand Up @@ -1412,7 +1411,7 @@ function hvcat_fill(a::Array, xs::Tuple)
a
end

hvcat(rows::Tuple{Vararg{Int}}, xs::Number...) = typed_hvcat(promote_typeof(xs...), rows, xs...)
hvcat(rows::Tuple{Vararg{Int}}, xs::Number...) = typed_hvcat(Matrix{promote_typeof(xs...)}, rows, xs...)

function typed_hvcat{T}(::Type{T}, rows::Tuple{Vararg{Int}}, xs::Number...)
nr = length(rows)
Expand All @@ -1426,7 +1425,7 @@ function typed_hvcat{T}(::Type{T}, rows::Tuple{Vararg{Int}}, xs::Number...)
if nr*nc != len
throw(ArgumentError("argument count $(len) does not match specified shape $((nr,nc))"))
end
hvcat_fill(Array{T,2}(nr, nc), xs)
hvcat_fill(similar(T, nr, nc), xs)
end

# fallback definition of hvcat in terms of hcat and vcat
Expand All @@ -1449,7 +1448,7 @@ function typed_hvcat{T}(::Type{T}, rows::Tuple{Vararg{Int}}, as...)
rs[i] = typed_hcat(T, as[a:a-1+rows[i]]...)
a += rows[i]
end
T[rs...;]
eltype(T)[rs...;]
end

## Reductions and accumulates ##
Expand Down
2 changes: 2 additions & 0 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,8 @@ similar{T}(a::Array{T}, m::Int) = Array{T,1}(m)
similar{N}(a::Array, T::Type, dims::Dims{N}) = Array{T,N}(dims)
similar{T,N}(a::Array{T}, dims::Dims{N}) = Array{T,N}(dims)

similar{T,A<:Array{T},N}(::Type{A}, dims::Dims{N}) = Array{T, N}(dims)

# T[x...] constructs Array{T,1}
function getindex{T}(::Type{T}, vals...)
a = Array{T,1}(length(vals))
Expand Down
6 changes: 3 additions & 3 deletions base/sparse/sparse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import Base: @get!, acos, acosd, acot, acotd, acsch, asech, asin, asind, asinh,
broadcast, ceil, complex, cond, conj, convert, copy, copy!, ctranspose, diagm,
exp, expm1, factorize, find, findmax, findmin, findnz, float, full, getindex,
vcat, hcat, hvcat, cat, imag, indmax, ishermitian, kron, length, log, log1p, max, min,
maximum, minimum, norm, one, promote_eltype, real, reinterpret, reshape, rot180,
rotl90, rotr90, round, scale!, setindex!, similar, size, transpose, tril,
triu, vec, permute!, map, map!
maximum, minimum, norm, one, promote_eltype, promote_type_cat, promote_typeof_cat, real,
reinterpret, reshape, rot180, rotl90, rotr90, round, scale!, setindex!, similar, size,
transpose, tril, triu, vec, permute!, map, map!

import Base.Broadcast: broadcast_indices

Expand Down
2 changes: 1 addition & 1 deletion base/sparse/sparsematrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ function similar{Tv,Ti}(S::SparseMatrixCSC, ::Type{Tv}, ::Type{Ti})
SparseMatrixCSC(S.m, S.n, new_colptr, new_rowval, new_nzval)
end
@inline similar{Tv}(S::SparseMatrixCSC, ::Type{Tv}, d::Dims) = spzeros(Tv, d...)
@inline similar{Tv}(::Type{SparseMatrixCSC{Tv}}, d::Dims) = spzeros(Tv, d...)

# convert'ing between SparseMatrixCSC types
convert{Tv}(::Type{AbstractMatrix{Tv}}, A::SparseMatrixCSC{Tv}) = A
Expand Down Expand Up @@ -2938,7 +2939,6 @@ end
end
end


function hcat(X::SparseMatrixCSC...)
num = length(X)
mX = Int[ size(x, 1) for x in X ]
Expand Down
33 changes: 19 additions & 14 deletions base/sparse/sparsevector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -928,16 +928,25 @@ const _Symmetric_DenseArrays{T,A<:Matrix} = Symmetric{T,A}
const _Hermitian_DenseArrays{T,A<:Matrix} = Hermitian{T,A}
const _Triangular_DenseArrays{T,A<:Matrix} = Base.LinAlg.AbstractTriangular{T,A}
const _Annotated_DenseArrays = Union{_Triangular_DenseArrays, _Symmetric_DenseArrays, _Hermitian_DenseArrays}
const _Annotated_Typed_DenseArrays{T} = Union{_Triangular_DenseArrays{T}, _Symmetric_DenseArrays{T}, _Hermitian_DenseArrays{T}}

const _SparseConcatGroup = Union{Vector, Matrix, _SparseConcatArrays, _Annotated_SparseConcatArrays, _Annotated_DenseArrays}
const _DenseConcatGroup = Union{Vector, Matrix, _Annotated_DenseArrays}
const _TypedDenseConcatGroup{T} = Union{Vector{T}, Matrix{T}, _Annotated_Typed_DenseArrays{T}}

promote_type_cat(::Type{S}, ::Type{T}) where {S<:AbstractArray,
T<:Union{_SparseConcatArrays,_Annotated_SparseConcatArrays}} =
SparseMatrixCSC{promote_type(eltype(S), eltype(T))}
promote_type_cat(::Type{S}, ::Type{T}) where {S<:Union{_SparseConcatArrays,_Annotated_SparseConcatArrays},
T<:AbstractArray} =
SparseMatrixCSC{promote_type(eltype(S), eltype(T))}
promote_type_cat(::Type{S}, ::Type{T}) where {S<:Union{_SparseConcatArrays,_Annotated_SparseConcatArrays},
T<:Union{_SparseConcatArrays,_Annotated_SparseConcatArrays}} =
SparseMatrixCSC{promote_type(eltype(S), eltype(T))}

# Concatenations involving un/annotated sparse/special matrices/vectors should yield sparse arrays
function cat(catdims, Xin::_SparseConcatGroup...)
# FIXME: still needed? (same below)
X = map(x -> SparseMatrixCSC(issparse(x) ? x : sparse(x)), Xin)
T = promote_eltype(Xin...)
T = promote_typeof_cat(Xin...)
Base.cat_t(catdims, T, X...)
end
function hcat(Xin::_SparseConcatGroup...)
Expand Down Expand Up @@ -965,18 +974,14 @@ promote_to_array_type(A::Tuple{Vararg{Union{_SparseConcatGroup,UniformScaling}}}
promote_to_array_type(A::Tuple{Vararg{Union{_DenseConcatGroup,UniformScaling}}}) = (@_pure_meta; Matrix)
promote_to_arrays_(n::Int, ::Type{SparseMatrixCSC}, J::UniformScaling) = sparse(J, n, n)

# FIXME: these should be unnecessary now, and _DenseConcatGroup too
# Concatenations strictly involving un/annotated dense matrices/vectors should yield dense arrays
cat(catdims, xs::_DenseConcatGroup...) = Base.cat_t(catdims, promote_eltype(xs...), xs...)
vcat(A::Vector...) = Base.typed_vcat(promote_eltype(A...), A...)
vcat(A::_DenseConcatGroup...) = Base.typed_vcat(promote_eltype(A...), A...)
hcat(A::Vector...) = Base.typed_hcat(promote_eltype(A...), A...)
hcat(A::_DenseConcatGroup...) = Base.typed_hcat(promote_eltype(A...), A...)
hvcat(rows::Tuple{Vararg{Int}}, xs::_DenseConcatGroup...) = Base.typed_hvcat(promote_eltype(xs...), rows, xs...)
# For performance, specially handle the case where the matrices/vectors have homogeneous eltype
cat{T}(catdims, xs::_TypedDenseConcatGroup{T}...) = Base.cat_t(catdims, T, xs...)
vcat{T}(A::_TypedDenseConcatGroup{T}...) = Base.typed_vcat(T, A...)
hcat{T}(A::_TypedDenseConcatGroup{T}...) = Base.typed_hcat(T, A...)
hvcat{T}(rows::Tuple{Vararg{Int}}, xs::_TypedDenseConcatGroup{T}...) = Base.typed_hvcat(T, rows, xs...)
cat(catdims, xs::_DenseConcatGroup...) = Base.cat_t(catdims, promote_typeof_cat(xs...), xs...)
vcat(A::Vector...) = Base.typed_vcat(promote_typeof_cat(A...), A...)
vcat(A::_DenseConcatGroup...) = Base.typed_vcat(promote_typeof_cat(A...), A...)
hcat(A::Vector...) = Base.typed_hcat(promote_typeof_cat(A...), A...)
hcat(A::_DenseConcatGroup...) = Base.typed_hcat(promote_typeof_cat(A...), A...)
hvcat(rows::Tuple{Vararg{Int}}, xs::_DenseConcatGroup...) = Base.typed_hvcat(promote_typeof_cat(xs...), rows, xs...)


### math functions
Expand Down
6 changes: 3 additions & 3 deletions doc/src/devdocs/ast.md
Original file line number Diff line number Diff line change
Expand Up @@ -390,9 +390,9 @@ call. Finally, chains of comparisons have their own special expression structure
| Input | AST |
|:------------------------ |:------------------------------------ |
| `a[i]` | `(ref a i)` |
| `t[i;j]` | `(typed_vcat t i j)` |
| `t[i j]` | `(typed_hcat t i j)` |
| `t[a b; c d]` | `(typed_vcat t (row a b) (row c d))` |
| `t[i;j]` | `(eltyped_vcat t i j)` |
| `t[i j]` | `(eltyped_hcat t i j)` |
| `t[a b; c d]` | `(eltyped_vcat t (row a b) (row c d))` |
| `a{b}` | `(curly a b)` |
| `a{b;c}` | `(curly a (parameters c) b)` |
| `[x]` | `(vect x)` |
Expand Down
4 changes: 2 additions & 2 deletions src/julia-parser.scm
Original file line number Diff line number Diff line change
Expand Up @@ -1052,9 +1052,9 @@
(loop (list 'ref ex))
(case (car al)
((vect) (loop (list* 'ref ex (cdr al))))
((hcat) (loop (list* 'typed_hcat ex (cdr al))))
((hcat) (loop (list* 'eltyped_hcat ex (cdr al))))
((vcat)
(loop (list* 'typed_vcat ex (cdr al))))
(loop (list* 'eltyped_vcat ex (cdr al))))
((comprehension)
(loop (list* 'typed_comprehension ex (cdr al))))
(else (error "unknown parse-cat result (internal error)"))))))
Expand Down
16 changes: 8 additions & 8 deletions src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -1518,7 +1518,7 @@
,(expand-update-operator op op= (car e) rhs T))))
(else
(if (and (pair? lhs)
(not (memq (car lhs) '(|.| tuple vcat typed_hcat typed_vcat))))
(not (memq (car lhs) '(|.| tuple vcat eltyped_hcat eltyped_vcat))))
(error (string "invalid assignment location \"" (deparse lhs) "\"")))
(expand-update-operator- op op= lhs rhs declT))))

Expand Down Expand Up @@ -1914,9 +1914,9 @@
(iota (length lhss))
lhss)
(unnecessary ,xx))))))
((typed_hcat)
((eltyped_hcat)
(error "invalid spacing in left side of indexed assignment"))
((typed_vcat)
((eltyped_vcat)
(error "unexpected \";\" in left side of indexed assignment"))
((ref)
;; (= (ref a . idxs) rhs)
Expand Down Expand Up @@ -2210,10 +2210,10 @@
,.(apply append rows)))
`(call vcat ,@a))))))

'typed_hcat
(lambda (e) `(call (top typed_hcat) ,(expand-forms (cadr e)) ,.(map expand-forms (cddr e))))
'eltyped_hcat
(lambda (e) `(call (top eltyped_hcat) ,(expand-forms (cadr e)) ,.(map expand-forms (cddr e))))

'typed_vcat
'eltyped_vcat
(lambda (e)
(let ((t (cadr e))
(a (cddr e)))
Expand All @@ -2227,10 +2227,10 @@
(cdr x)
(list x)))
a)))
`(call (top typed_hvcat) ,t
`(call (top eltyped_hvcat) ,t
(tuple ,.(map length rows))
,.(apply append rows)))
`(call (top typed_vcat) ,t ,@a)))))
`(call (top eltyped_vcat) ,t ,@a)))))

'|'| (lambda (e) `(call ctranspose ,(expand-forms (cadr e))))
'|.'| (lambda (e) `(call transpose ,(expand-forms (cadr e))))
Expand Down
18 changes: 13 additions & 5 deletions test/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,16 @@ Base.convert{T,N }(::Type{TSlow{T,N}}, X::AbstractArray ) = begin
A
end

Base.promote_type_cat(::Type{S}, ::Type{T}) where {S<:TSlow, T<:AbstractArray} =
TSlow{promote_type(eltype(S), eltype(T))}
Base.promote_type_cat(::Type{S}, ::Type{T}) where {S<:AbstractArray, T<:TSlow} =
TSlow{promote_type(eltype(S), eltype(T))}
Base.promote_type_cat(::Type{S}, ::Type{T}) where {S<:TSlow, T<:TSlow} =
TSlow{promote_type(eltype(S), eltype(T))}

Base.size(A::TSlow) = A.dims
Base.similar{T}(A::TSlow, ::Type{T}, dims::Dims) = TSlow(T, dims)
Base.similar{T, A<:TSlow{T}}(::Type{A}, dims::Dims) = TSlow(T, dims)
import Base: IndexCartesian
Base.IndexStyle{A<:TSlow}(::Type{A}) = IndexCartesian()
# Until #11242 is merged, we need to define each dimension independently
Expand Down Expand Up @@ -560,9 +568,9 @@ function test_cat(::Type{TestAbstractArray})

@test vcat(B) == B
@test hcat(B) == B
@test Base.typed_hcat(Float64, B) == TSlow(b_float)
@test Base.typed_hcat(Float64, B, B) == TSlow(b2hcat)
@test Base.typed_hcat(Float64, B, B, B) == TSlow(b3hcat)
@test Base.eltyped_hcat(Float64, B) == TSlow(b_float)
@test Base.eltyped_hcat(Float64, B, B) == TSlow(b2hcat)
@test Base.eltyped_hcat(Float64, B, B, B) == TSlow(b3hcat)

@test vcat(B1, B2) == TSlow(vcat([1:24...], [1:25...]))
@test hcat(C1, C2) == TSlow([1 2 1 2 3; 3 4 4 5 6])
Expand All @@ -584,10 +592,10 @@ function test_cat(::Type{TestAbstractArray})

# check for shape mismatch
@test_throws ArgumentError hvcat((2, 2), 1, 2, 3, 4, 5)
@test_throws ArgumentError Base.typed_hvcat(Int, (2, 2), 1, 2, 3, 4, 5)
@test_throws ArgumentError Base.eltyped_hvcat(Int, (2, 2), 1, 2, 3, 4, 5)
# check for # of columns mismatch b/w rows
@test_throws ArgumentError hvcat((3, 2), 1, 2, 3, 4, 5, 6)
@test_throws ArgumentError Base.typed_hvcat(Int, (3, 2), 1, 2, 3, 4, 5, 6)
@test_throws ArgumentError Base.eltyped_hvcat(Int, (3, 2), 1, 2, 3, 4, 5, 6)

# 18395
@test isa(Any["a" 5; 2//3 1.0][2,1], Rational{Int})
Expand Down