@@ -52,7 +52,7 @@ struct BlockSkylineSizes{BS<:NTuple{2,AbstractUnitRange{Int}}, LL<:AbstractVecto
5252    u:: UU 
5353end 
5454
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}}},
5656                                            BandedMatrix{Int,Matrix{Int},OneTo{Int}}, Vector{Int}}
5757
5858
@@ -247,7 +247,7 @@ BlockBandedMatrix(A::AbstractMatrix) = convert(BlockBandedMatrix, A)
247247similar (A:: BlockSkylineMatrix , T:: Type = eltype (A), bs:: BlockSkylineSizes = A. block_sizes) = 
248248    BlockSkylineMatrix {T} (undef, bs)
249249
250- axes (A:: BlockSkylineMatrix ) =  A. block_sizes. axes     
250+ axes (A:: BlockSkylineMatrix ) =  A. block_sizes. axes
251251
252252# ###############################
253253#  BlockSkylineMatrix Interface #
@@ -390,7 +390,7 @@ const BlockBandedBlock{T} = SubArray{T,2,<:BlockSkylineMatrix,<:Tuple{<:BlockSli
390390
391391
392392#  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}  = 
394394    first (first (parentindices (V)). block. n),first (last (parentindices (V)). block. n)
395395
396396# #####################################
@@ -437,3 +437,147 @@ end
437437        throw (BandError (A, J- K))
438438    end 
439439end 
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