@@ -336,6 +336,116 @@ const _SpecialArrays = Union{}
336
336
337
337
promote_to_array_type (:: Tuple ) = Matrix
338
338
339
+ # promote_to_arrays(n,k, T, A...) promotes any UniformScaling matrices
340
+ # in A to matrices of type T and sizes given by n[k:end]. n is an array
341
+ # so that the same promotion code can be used for hvcat. We pass the type T
342
+ # so that we can re-use this code for sparse-matrix hcat etcetera.
343
+ promote_to_arrays_ (n:: Int , :: Type , a:: Number ) = a
344
+ promote_to_arrays_ (n:: Int , :: Type{Matrix} , J:: UniformScaling{T} ) where {T} = Matrix (J, n, n)
345
+ promote_to_arrays_ (n:: Int , :: Type , A:: AbstractArray ) = A
346
+ promote_to_arrays_ (n:: Int , :: Type , A:: AbstractQ ) = collect (A)
347
+ promote_to_arrays (n,k, :: Type ) = ()
348
+ promote_to_arrays (n,k, :: Type{T} , A) where {T} = (promote_to_arrays_ (n[k], T, A),)
349
+ promote_to_arrays (n,k, :: Type{T} , A, B) where {T} =
350
+ (promote_to_arrays_ (n[k], T, A), promote_to_arrays_ (n[k+ 1 ], T, B))
351
+ promote_to_arrays (n,k, :: Type{T} , A, B, C) where {T} =
352
+ (promote_to_arrays_ (n[k], T, A), promote_to_arrays_ (n[k+ 1 ], T, B), promote_to_arrays_ (n[k+ 2 ], T, C))
353
+ promote_to_arrays (n,k, :: Type{T} , A, B, Cs... ) where {T} =
354
+ (promote_to_arrays_ (n[k], T, A), promote_to_arrays_ (n[k+ 1 ], T, B), promote_to_arrays (n,k+ 2 , T, Cs... )... )
355
+
356
+ _us2number (A) = A
357
+ _us2number (J:: UniformScaling ) = J. λ
358
+
359
+ for (f, _f, dim, name) in ((:hcat , :_hcat , 1 , " rows" ), (:vcat , :_vcat , 2 , " cols" ))
360
+ @eval begin
361
+ @inline $ f (A:: Union{AbstractArray,AbstractQ,UniformScaling} ...) = $ _f (A... )
362
+ # if there's a Number present, J::UniformScaling must be 1x1-dimensional
363
+ @inline $ f (A:: Union{AbstractArray,AbstractQ,UniformScaling,Number} ...) = $ f (map (_us2number, A)... )
364
+ function $_f (A:: Union{AbstractArray,AbstractQ,UniformScaling,Number} ...; array_type = promote_to_array_type (A))
365
+ n = - 1
366
+ for a in A
367
+ if ! isa (a, UniformScaling)
368
+ require_one_based_indexing (a)
369
+ na = size (a,$ dim)
370
+ n >= 0 && n != na &&
371
+ throw (DimensionMismatch (string (" number of " , $ name,
372
+ " of each array must match (got " , n, " and " , na, " )" )))
373
+ n = na
374
+ end
375
+ end
376
+ n == - 1 && throw (ArgumentError ($ (" $f of only UniformScaling objects cannot determine the matrix size" )))
377
+ return cat (promote_to_arrays (fill (n, length (A)), 1 , array_type, A... )... , dims= Val (3 - $ dim))
378
+ end
379
+ end
380
+ end
381
+
382
+ hvcat (rows:: Tuple{Vararg{Int}} , A:: Union{AbstractArray,AbstractQ,UniformScaling} ...) = _hvcat (rows, A... )
383
+ hvcat (rows:: Tuple{Vararg{Int}} , A:: Union{AbstractArray,AbstractQ,UniformScaling,Number} ...) = _hvcat (rows, A... )
384
+ function _hvcat (rows:: Tuple{Vararg{Int}} , A:: Union{AbstractArray,AbstractQ,UniformScaling,Number} ...; array_type = promote_to_array_type (A))
385
+ require_one_based_indexing (A... )
386
+ nr = length (rows)
387
+ sum (rows) == length (A) || throw (ArgumentError (" mismatch between row sizes and number of arguments" ))
388
+ n = fill (- 1 , length (A))
389
+ needcols = false # whether we also need to infer some sizes from the column count
390
+ j = 0
391
+ for i = 1 : nr # infer UniformScaling sizes from row counts, if possible:
392
+ ni = - 1 # number of rows in this block-row, -1 indicates unknown
393
+ for k = 1 : rows[i]
394
+ if ! isa (A[j+ k], UniformScaling)
395
+ na = size (A[j+ k], 1 )
396
+ ni >= 0 && ni != na &&
397
+ throw (DimensionMismatch (" mismatch in number of rows" ))
398
+ ni = na
399
+ end
400
+ end
401
+ if ni >= 0
402
+ for k = 1 : rows[i]
403
+ n[j+ k] = ni
404
+ end
405
+ else # row consisted only of UniformScaling objects
406
+ needcols = true
407
+ end
408
+ j += rows[i]
409
+ end
410
+ if needcols # some sizes still unknown, try to infer from column count
411
+ nc = - 1
412
+ j = 0
413
+ for i = 1 : nr
414
+ nci = 0
415
+ rows[i] > 0 && n[j+ 1 ] == - 1 && (j += rows[i]; continue )
416
+ for k = 1 : rows[i]
417
+ nci += isa (A[j+ k], UniformScaling) ? n[j+ k] : size (A[j+ k], 2 )
418
+ end
419
+ nc >= 0 && nc != nci && throw (DimensionMismatch (" mismatch in number of columns" ))
420
+ nc = nci
421
+ j += rows[i]
422
+ end
423
+ nc == - 1 && throw (ArgumentError (" sizes of UniformScalings could not be inferred" ))
424
+ j = 0
425
+ for i = 1 : nr
426
+ if rows[i] > 0 && n[j+ 1 ] == - 1 # this row consists entirely of UniformScalings
427
+ nci, r = divrem (nc, rows[i])
428
+ r != 0 && throw (DimensionMismatch (" indivisible UniformScaling sizes" ))
429
+ for k = 1 : rows[i]
430
+ n[j+ k] = nci
431
+ end
432
+ end
433
+ j += rows[i]
434
+ end
435
+ end
436
+ Amat = promote_to_arrays (n, 1 , array_type, A... )
437
+ # We have two methods for promote_to_array_type, one returning Matrix and
438
+ # another one returning SparseMatrixCSC (in SparseArrays.jl). In the dense
439
+ # case, we cannot call hvcat for the promoted UniformScalings because this
440
+ # causes a stack overflow. In the sparse case, however, we cannot call
441
+ # typed_hvcat because we need a sparse output.
442
+ if array_type == Matrix
443
+ return typed_hvcat (promote_eltype (Amat... ), rows, Amat... )
444
+ else
445
+ return hvcat (rows, Amat... )
446
+ end
447
+ end
448
+
339
449
# factorizations
340
450
function cholesky (S:: RealHermSymComplexHerm{<:Real,<:SymTridiagonal} , :: NoPivot = NoPivot (); check:: Bool = true )
341
451
T = choltype (eltype (S))
0 commit comments