@@ -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,147 @@ 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 , I:: UniformScaling )
483
+ B = copy_accommodating_diagonals (A, 0 : 0 , Base. _return_type (+ , Tuple{eltype (A), eltype (I)}))
484
+ @inbounds for i in axes (A, 1 )
485
+ B[i,i] = $ op (B[i,i], I. λ)
486
+ end
487
+ B
488
+ end
489
+ function $op (I:: UniformScaling , A:: BlockSkylineMatrix )
490
+ B = copy_accommodating_diagonals ($ op (A), 0 : 0 , Base. _return_type (+ , Tuple{eltype (A), eltype (I)}))
491
+ @inbounds for i in axes (A, 1 )
492
+ B[i,i] += I. λ
493
+ end
494
+ B
495
+ end
496
+
497
+ function $op (A:: BlockSkylineMatrix , D:: Diagonal )
498
+ B = copy_accommodating_diagonals (A, 0 : 0 , Base. _return_type (+ , Tuple{eltype (A), eltype (D)}))
499
+ @inbounds for i in axes (A, 1 )
500
+ B[i,i] = $ op (B[i,i], D. diag[i])
501
+ end
502
+ B
503
+ end
504
+ function $op (D:: Diagonal , A:: BlockSkylineMatrix )
505
+ B = copy_accommodating_diagonals ($ op (A), 0 : 0 , Base. _return_type (+ , Tuple{eltype (A), eltype (D)}))
506
+ @inbounds for i in axes (A, 1 )
507
+ B[i,i] += D. diag[i]
508
+ end
509
+ B
510
+ end
511
+
512
+ function $op (A:: BlockSkylineMatrix , Bd:: Bidiagonal )
513
+ B = copy_accommodating_diagonals (A, Bd. uplo == ' U' ? (0 : 1 ) : (- 1 : 0 ),
514
+ Base. _return_type (+ , Tuple{eltype (A), eltype (Bd)}))
515
+ @inbounds for i in axes (A, 1 )
516
+ B[i,i] = $ op (B[i,i], Bd. dv[i])
517
+ end
518
+ @inbounds for i in 1 : size (A, 1 )- 1
519
+ Bd. uplo == ' U' && (B[i,i+ 1 ] = $ op (B[i,i+ 1 ], Bd. ev[i]))
520
+ Bd. uplo == ' L' && (B[i+ 1 ,i] = $ op (B[i+ 1 ,i], Bd. ev[i]))
521
+ end
522
+ B
523
+ end
524
+ function $op (Bd:: Bidiagonal , A:: BlockSkylineMatrix )
525
+ B = copy_accommodating_diagonals ($ op (A), Bd. uplo == ' U' ? (0 : 1 ) : (- 1 : 0 ),
526
+ Base. _return_type (+ , Tuple{eltype (A), eltype (Bd)}))
527
+ @inbounds for i in axes (A, 1 )
528
+ B[i,i] += Bd. dv[i]
529
+ end
530
+ @inbounds for i in 1 : size (A, 1 )- 1
531
+ Bd. uplo == ' U' && (B[i,i+ 1 ] += Bd. ev[i])
532
+ Bd. uplo == ' L' && (B[i+ 1 ,i] += Bd. ev[i])
533
+ end
534
+ B
535
+ end
536
+
537
+ function $op (A:: BlockSkylineMatrix , T:: Tridiagonal )
538
+ B = copy_accommodating_diagonals (A, - 1 : 1 , Base. _return_type (+ , Tuple{eltype (A), eltype (T)}))
539
+ @inbounds for i in axes (A, 1 )
540
+ B[i,i] = $ op (B[i,i], T. d[i])
541
+ end
542
+ @inbounds for i in 1 : size (A, 1 )- 1
543
+ B[i,i+ 1 ] = $ op (B[i,i+ 1 ], T. du[i])
544
+ B[i+ 1 ,i] = $ op (B[i+ 1 ,i], T. dl[i])
545
+ end
546
+ B
547
+ end
548
+ function $op (T:: Tridiagonal , A:: BlockSkylineMatrix )
549
+ B = copy_accommodating_diagonals ($ op (A), - 1 : 1 , Base. _return_type (+ , Tuple{eltype (A), eltype (T)}))
550
+ @inbounds for i in axes (A, 1 )
551
+ B[i,i] += T. d[i]
552
+ end
553
+ @inbounds for i in 1 : size (A, 1 )- 1
554
+ B[i,i+ 1 ] += T. du[i]
555
+ B[i+ 1 ,i] += T. dl[i]
556
+ end
557
+ B
558
+ end
559
+
560
+ function $op (A:: BlockSkylineMatrix , T:: SymTridiagonal )
561
+ B = copy_accommodating_diagonals (A, - 1 : 1 , Base. _return_type (+ , Tuple{eltype (A), eltype (T)}))
562
+ @inbounds for i in axes (A, 1 )
563
+ B[i,i] = $ op (B[i,i], T. dv[i])
564
+ end
565
+ @inbounds for i in 1 : size (A, 1 )- 1
566
+ B[i,i+ 1 ] = $ op (B[i,i+ 1 ], T. ev[i])
567
+ B[i+ 1 ,i] = $ op (B[i+ 1 ,i], T. ev[i])
568
+ end
569
+ B
570
+ end
571
+ function $op (T:: SymTridiagonal , A:: BlockSkylineMatrix )
572
+ B = copy_accommodating_diagonals ($ op (A), - 1 : 1 , Base. _return_type (+ , Tuple{eltype (A), eltype (T)}))
573
+ @inbounds for i in axes (A, 1 )
574
+ B[i,i] += T. dv[i]
575
+ end
576
+ @inbounds for i in 1 : size (A, 1 )- 1
577
+ B[i,i+ 1 ] += T. ev[i]
578
+ B[i+ 1 ,i] += T. ev[i]
579
+ end
580
+ B
581
+ end
582
+ end
583
+ end
0 commit comments