@@ -52,7 +52,7 @@ struct BlockSkylineSizes{BS<:NTuple{2,AbstractUnitRange{Int}}, LL<:AbstractVecto
52
52
u:: UU
53
53
end
54
54
55
- const BlockBandedSizes = BlockSkylineSizes{NTuple{2 ,BlockedUnitRange{Vector{Int}}}, Fill{Int,1 ,Tuple{OneTo{Int}}}, Fill{Int,1 ,Tuple{OneTo{Int}}},
55
+ const BlockBandedSizes = BlockSkylineSizes{NTuple{2 ,BlockedUnitRange{Vector{Int}}}, Fill{Int,1 ,Tuple{OneTo{Int}}}, Fill{Int,1 ,Tuple{OneTo{Int}}},
56
56
BandedMatrix{Int,Matrix{Int},OneTo{Int}}, Vector{Int}}
57
57
58
58
@@ -247,7 +247,7 @@ BlockBandedMatrix(A::AbstractMatrix) = convert(BlockBandedMatrix, A)
247
247
similar (A:: BlockSkylineMatrix , T:: Type = eltype (A), bs:: BlockSkylineSizes = A. block_sizes) =
248
248
BlockSkylineMatrix {T} (undef, bs)
249
249
250
- axes (A:: BlockSkylineMatrix ) = A. block_sizes. axes
250
+ axes (A:: BlockSkylineMatrix ) = A. block_sizes. axes
251
251
252
252
# ###############################
253
253
# BlockSkylineMatrix Interface #
@@ -390,7 +390,7 @@ const BlockBandedBlock{T} = SubArray{T,2,<:BlockSkylineMatrix,<:Tuple{<:BlockSli
390
390
391
391
392
392
# gives the columns of parent(V).data that encode the block
393
- _parent_blocks (V:: BlockBandedBlock ):: Tuple{Int,Int} =
393
+ _parent_blocks (V:: BlockBandedBlock ):: Tuple{Int,Int} =
394
394
first (first (parentindices (V)). block. n),first (last (parentindices (V)). block. n)
395
395
396
396
# #####################################
@@ -437,3 +437,132 @@ end
437
437
throw (BandError (A, J- K))
438
438
end
439
439
end
440
+
441
+ """
442
+ copy_accommodating_diagonals(A::BlockSkylineMatrix, diagonals::UnitRange{<:Integer})
443
+
444
+ Return copy of `A`, ensuring blocks are present covering the
445
+ `diagonals` as well.
446
+ """
447
+ function copy_accommodating_diagonals (A:: BlockSkylineMatrix , diagonals:: UnitRange{<:Integer} , :: Type{T} = eltype (A)) where T
448
+ checksquareblocks (A)
449
+ bs = A. block_sizes
450
+ l,u = bs. l,bs. u
451
+ ax = first (bs. axes)
452
+
453
+ if 0 ∈ diagonals
454
+ l = max .(l, 0 )
455
+ u = max .(u, 0 )
456
+ end
457
+
458
+ for d = extrema (diagonals)
459
+ d == 0 && continue # Already taken care of above
460
+ v = d > 0 ? u : l
461
+ # The j:th element of rows is the row index which the diagonal
462
+ # d covers in the j:th column.
463
+ rows = clamp .(ax .- d, 1 , last (ax))
464
+ for (j,i) in enumerate (rows)
465
+ # First we find which block the j:th element of the main
466
+ # diagonal would occupy.
467
+ md_block = findfirst (≥ (j), ax. lasts)
468
+
469
+ # Next we find which block covers row i
470
+ d_block = findfirst (≥ (i), ax. lasts)
471
+
472
+ # Finally, we increase the block-bandwidth as necessary
473
+ v[md_block] = max (v[md_block], abs (d_block- md_block))
474
+ end
475
+ end
476
+
477
+ BlockSkylineMatrix {T} (A, BlockSkylineSizes ((ax,ax), l, u))
478
+ end
479
+
480
+ for op in (:- , :+ )
481
+ @eval begin
482
+ function $op (A:: BlockSkylineMatrix , D:: Diagonal )
483
+ B = copy_accommodating_diagonals (A, 0 : 0 , Base. _return_type (+ , Tuple{eltype (A), eltype (D)}))
484
+ @inbounds for i in axes (A, 1 )
485
+ B[i,i] = $ op (B[i,i], D. diag[i])
486
+ end
487
+ B
488
+ end
489
+ function $op (D:: Diagonal , A:: BlockSkylineMatrix )
490
+ B = copy_accommodating_diagonals ($ op (A), 0 : 0 , Base. _return_type (+ , Tuple{eltype (A), eltype (D)}))
491
+ @inbounds for i in axes (A, 1 )
492
+ B[i,i] += D. diag[i]
493
+ end
494
+ B
495
+ end
496
+
497
+ function $op (A:: BlockSkylineMatrix , Bd:: Bidiagonal )
498
+ B = copy_accommodating_diagonals (A, Bd. uplo == ' U' ? (0 : 1 ) : (- 1 : 0 ),
499
+ Base. _return_type (+ , Tuple{eltype (A), eltype (Bd)}))
500
+ @inbounds for i in axes (A, 1 )
501
+ B[i,i] = $ op (B[i,i], Bd. dv[i])
502
+ end
503
+ @inbounds for i in 1 : size (A, 1 )- 1
504
+ Bd. uplo == ' U' && (B[i,i+ 1 ] = $ op (B[i,i+ 1 ], Bd. ev[i]))
505
+ Bd. uplo == ' L' && (B[i+ 1 ,i] = $ op (B[i+ 1 ,i], Bd. ev[i]))
506
+ end
507
+ B
508
+ end
509
+ function $op (Bd:: Bidiagonal , A:: BlockSkylineMatrix )
510
+ B = copy_accommodating_diagonals ($ op (A), Bd. uplo == ' U' ? (0 : 1 ) : (- 1 : 0 ),
511
+ Base. _return_type (+ , Tuple{eltype (A), eltype (Bd)}))
512
+ @inbounds for i in axes (A, 1 )
513
+ B[i,i] += Bd. dv[i]
514
+ end
515
+ @inbounds for i in 1 : size (A, 1 )- 1
516
+ Bd. uplo == ' U' && (B[i,i+ 1 ] += Bd. ev[i])
517
+ Bd. uplo == ' L' && (B[i+ 1 ,i] += Bd. ev[i])
518
+ end
519
+ B
520
+ end
521
+
522
+ function $op (A:: BlockSkylineMatrix , T:: Tridiagonal )
523
+ B = copy_accommodating_diagonals (A, - 1 : 1 , Base. _return_type (+ , Tuple{eltype (A), eltype (T)}))
524
+ @inbounds for i in axes (A, 1 )
525
+ B[i,i] = $ op (B[i,i], T. d[i])
526
+ end
527
+ @inbounds for i in 1 : size (A, 1 )- 1
528
+ B[i,i+ 1 ] = $ op (B[i,i+ 1 ], T. du[i])
529
+ B[i+ 1 ,i] = $ op (B[i+ 1 ,i], T. dl[i])
530
+ end
531
+ B
532
+ end
533
+ function $op (T:: Tridiagonal , A:: BlockSkylineMatrix )
534
+ B = copy_accommodating_diagonals ($ op (A), - 1 : 1 , Base. _return_type (+ , Tuple{eltype (A), eltype (T)}))
535
+ @inbounds for i in axes (A, 1 )
536
+ B[i,i] += T. d[i]
537
+ end
538
+ @inbounds for i in 1 : size (A, 1 )- 1
539
+ B[i,i+ 1 ] += T. du[i]
540
+ B[i+ 1 ,i] += T. dl[i]
541
+ end
542
+ B
543
+ end
544
+
545
+ function $op (A:: BlockSkylineMatrix , T:: SymTridiagonal )
546
+ B = copy_accommodating_diagonals (A, - 1 : 1 , Base. _return_type (+ , Tuple{eltype (A), eltype (T)}))
547
+ @inbounds for i in axes (A, 1 )
548
+ B[i,i] = $ op (B[i,i], T. dv[i])
549
+ end
550
+ @inbounds for i in 1 : size (A, 1 )- 1
551
+ B[i,i+ 1 ] = $ op (B[i,i+ 1 ], T. ev[i])
552
+ B[i+ 1 ,i] = $ op (B[i+ 1 ,i], T. ev[i])
553
+ end
554
+ B
555
+ end
556
+ function $op (T:: SymTridiagonal , A:: BlockSkylineMatrix )
557
+ B = copy_accommodating_diagonals ($ op (A), - 1 : 1 , Base. _return_type (+ , Tuple{eltype (A), eltype (T)}))
558
+ @inbounds for i in axes (A, 1 )
559
+ B[i,i] += T. dv[i]
560
+ end
561
+ @inbounds for i in 1 : size (A, 1 )- 1
562
+ B[i,i+ 1 ] += T. ev[i]
563
+ B[i+ 1 ,i] += T. ev[i]
564
+ end
565
+ B
566
+ end
567
+ end
568
+ end
0 commit comments