@@ -230,10 +230,22 @@ Base.isassigned(A::UpperOrLowerTriangular, i::Int, j::Int) =
230230Base. isstored (A:: UpperOrLowerTriangular , i:: Int , j:: Int ) = 
231231    _shouldforwardindex (A, i, j) ?  Base. isstored (A. data, i, j) :  false 
232232
233- @propagate_inbounds  getindex (A:: Union{UnitLowerTriangular{T}, UnitUpperTriangular{T}} , i:: Int , j:: Int ) where  {T} = 
234-     _shouldforwardindex (A, i, j) ?  A. data[i,j] :  ifelse (i ==  j, oneunit (T), zero (T))
235- @propagate_inbounds  getindex (A:: Union{LowerTriangular, UpperTriangular} , i:: Int , j:: Int ) = 
236-     _shouldforwardindex (A, i, j) ?  A. data[i,j] :  diagzero (A,i,j)
233+ @propagate_inbounds  function  getindex (A:: Union{UnitLowerTriangular{T}, UnitUpperTriangular{T}} , i:: Int , j:: Int ) where  {T}
234+     if  _shouldforwardindex (A, i, j)
235+         A. data[i,j]
236+     else 
237+         @boundscheck  checkbounds (A, i, j)
238+         ifelse (i ==  j, oneunit (T), zero (T))
239+     end 
240+ end 
241+ @propagate_inbounds  function  getindex (A:: Union{LowerTriangular, UpperTriangular} , i:: Int , j:: Int )
242+     if  _shouldforwardindex (A, i, j)
243+         A. data[i,j]
244+     else 
245+         @boundscheck  checkbounds (A, i, j)
246+         @inbounds  diagzero (A,i,j)
247+     end 
248+ end 
237249
238250_shouldforwardindex (U:: UpperTriangular , b:: BandIndex ) =  b. band >=  0 
239251_shouldforwardindex (U:: LowerTriangular , b:: BandIndex ) =  b. band <=  0 
@@ -242,62 +254,97 @@ _shouldforwardindex(U::UnitLowerTriangular, b::BandIndex) = b.band < 0
242254
243255#  these specialized getindex methods enable constant-propagation of the band
244256Base. @constprop  :aggressive  @propagate_inbounds  function  getindex (A:: Union{UnitLowerTriangular{T}, UnitUpperTriangular{T}} , b:: BandIndex ) where  {T}
245-     _shouldforwardindex (A, b) ?  A. data[b] :  ifelse (b. band ==  0 , oneunit (T), zero (T))
257+     if  _shouldforwardindex (A, b)
258+         A. data[b]
259+     else 
260+         @boundscheck  checkbounds (A, b)
261+         ifelse (b. band ==  0 , oneunit (T), zero (T))
262+     end 
246263end 
247264Base. @constprop  :aggressive  @propagate_inbounds  function  getindex (A:: Union{LowerTriangular, UpperTriangular} , b:: BandIndex )
248-     _shouldforwardindex (A, b) ?  A. data[b] :  diagzero (A. data, b)
265+     if  _shouldforwardindex (A, b)
266+         A. data[b]
267+     else 
268+         @boundscheck  checkbounds (A, b)
269+         @inbounds  diagzero (A, b)
270+     end 
249271end 
250272
251- _zero_triangular_half_str (T:: Type ) =  T <:  UpperOrUnitUpperTriangular  ?  " lower" :  " upper" 
252- 
253- @noinline  function  throw_nonzeroerror (T:: DataType , @nospecialize (x), i, j)
254-     Ts =  _zero_triangular_half_str (T)
255-     Tn =  nameof (T)
273+ @noinline  function  throw_nonzeroerror (Tn:: Symbol , @nospecialize (x), i, j)
274+     zero_half =  Tn in  (:UpperTriangular , :UnitUpperTriangular ) ?  " lower" :  " upper" 
275+     nstr =  Tn ===  :UpperTriangular  ?  " n" :  " " 
256276    throw (ArgumentError (
257-         lazy "" 
277+         LazyString (
278+             lazy "" 
279+             lazy "" 
280+         )
281+     )
258282end 
259- @noinline  function  throw_nononeerror (T:: DataType , @nospecialize (x), i, j)
260-     Tn =  nameof (T)
283+ @noinline  function  throw_nonuniterror (Tn:: Symbol , @nospecialize (x), i, j)
261284    throw (ArgumentError (
262-         lazy "on the diagonal  ($i, $j) of an  $Tn matrix to a non-unit value ($x)" 
285+         lazy "on the diagonal  of a  $Tn matrix to a non-unit value ($x)" 
263286end 
264287
265288@propagate_inbounds  function  setindex! (A:: UpperTriangular , x, i:: Integer , j:: Integer )
266-     if  i >  j
267-         iszero (x) ||  throw_nonzeroerror (typeof (A), x, i, j)
268-     else 
289+     if  _shouldforwardindex (A, i, j)
269290        A. data[i,j] =  x
291+     else 
292+         @boundscheck  checkbounds (A, i, j)
293+         #  the value must be convertible to the eltype for setindex! to be meaningful
294+         #  however, the converted value is unused, and the compiler is free to remove
295+         #  the conversion if the call is guaranteed to succeed
296+         convert (eltype (A), x)
297+         iszero (x) ||  throw_nonzeroerror (nameof (typeof (A)), x, i, j)
270298    end 
271299    return  A
272300end 
273301
274302@propagate_inbounds  function  setindex! (A:: UnitUpperTriangular , x, i:: Integer , j:: Integer )
275-     if  i >  j
276-         iszero (x) ||  throw_nonzeroerror (typeof (A), x, i, j)
277-     elseif  i ==  j
278-         x ==  oneunit (x) ||  throw_nononeerror (typeof (A), x, i, j)
279-     else 
303+     if  _shouldforwardindex (A, i, j)
280304        A. data[i,j] =  x
305+     else 
306+         @boundscheck  checkbounds (A, i, j)
307+         #  the value must be convertible to the eltype for setindex! to be meaningful
308+         #  however, the converted value is unused, and the compiler is free to remove
309+         #  the conversion if the call is guaranteed to succeed
310+         convert (eltype (A), x)
311+         if  i ==  j #  diagonal
312+             x ==  oneunit (eltype (A)) ||  throw_nonuniterror (nameof (typeof (A)), x, i, j)
313+         else 
314+             iszero (x) ||  throw_nonzeroerror (nameof (typeof (A)), x, i, j)
315+         end 
281316    end 
282317    return  A
283318end 
284319
285320@propagate_inbounds  function  setindex! (A:: LowerTriangular , x, i:: Integer , j:: Integer )
286-     if  i <  j
287-         iszero (x) ||  throw_nonzeroerror (typeof (A), x, i, j)
288-     else 
321+     if  _shouldforwardindex (A, i, j)
289322        A. data[i,j] =  x
323+     else 
324+         @boundscheck  checkbounds (A, i, j)
325+         #  the value must be convertible to the eltype for setindex! to be meaningful
326+         #  however, the converted value is unused, and the compiler is free to remove
327+         #  the conversion if the call is guaranteed to succeed
328+         convert (eltype (A), x)
329+         iszero (x) ||  throw_nonzeroerror (nameof (typeof (A)), x, i, j)
290330    end 
291331    return  A
292332end 
293333
294334@propagate_inbounds  function  setindex! (A:: UnitLowerTriangular , x, i:: Integer , j:: Integer )
295-     if  i <  j
296-         iszero (x) ||  throw_nonzeroerror (typeof (A), x, i, j)
297-     elseif  i ==  j
298-         x ==  oneunit (x) ||  throw_nononeerror (typeof (A), x, i, j)
299-     else 
335+     if  _shouldforwardindex (A, i, j)
300336        A. data[i,j] =  x
337+     else 
338+         @boundscheck  checkbounds (A, i, j)
339+         #  the value must be convertible to the eltype for setindex! to be meaningful
340+         #  however, the converted value is unused, and the compiler is free to remove
341+         #  the conversion if the call is guaranteed to succeed
342+         convert (eltype (A), x)
343+         if  i ==  j  #  diagonal
344+             x ==  oneunit (eltype (A)) ||  throw_nonuniterror (nameof (typeof (A)), x, i, j)
345+         else 
346+             iszero (x) ||  throw_nonzeroerror (nameof (typeof (A)), x, i, j)
347+         end 
301348    end 
302349    return  A
303350end 
@@ -542,7 +589,7 @@ for (T, UT) in ((:UpperTriangular, :UnitUpperTriangular), (:LowerTriangular, :Un
542589    @eval  @inline  function  _copyto! (A:: $UT , B:: $T )
543590        for  dind in  diagind (A, IndexStyle (A))
544591            if  A[dind] !=  B[dind]
545-                 throw_nononeerror ( typeof (A), B[dind], Tuple (dind)... )
592+                 throw_nonuniterror ( nameof ( typeof (A) ), B[dind], Tuple (dind)... )
546593            end 
547594        end 
548595        _copyto! ($ T (parent (A)), B)
@@ -696,7 +743,7 @@ function _triscale!(A::UpperOrUnitUpperTriangular, B::UnitUpperTriangular, c::Nu
696743    checksize1 (A, B)
697744    iszero (_add. alpha) &&  return  _rmul_or_fill! (A, _add. beta)
698745    for  j in  axes (B. data,2 )
699-         @inbounds  _modify! (_add, c, A, (j,j))
746+         @inbounds  _modify! (_add, B[ BandIndex ( 0 ,j)]  *   c, A, (j,j))
700747        for  i in  firstindex (B. data,1 ): (j -  1 )
701748            @inbounds  _modify! (_add, B. data[i,j] *  c, A. data, (i,j))
702749        end 
@@ -707,7 +754,7 @@ function _triscale!(A::UpperOrUnitUpperTriangular, c::Number, B::UnitUpperTriang
707754    checksize1 (A, B)
708755    iszero (_add. alpha) &&  return  _rmul_or_fill! (A, _add. beta)
709756    for  j in  axes (B. data,2 )
710-         @inbounds  _modify! (_add, c, A, (j,j))
757+         @inbounds  _modify! (_add, c  *  B[ BandIndex ( 0 ,j)] , A, (j,j))
711758        for  i in  firstindex (B. data,1 ): (j -  1 )
712759            @inbounds  _modify! (_add, c *  B. data[i,j], A. data, (i,j))
713760        end 
@@ -738,7 +785,7 @@ function _triscale!(A::LowerOrUnitLowerTriangular, B::UnitLowerTriangular, c::Nu
738785    checksize1 (A, B)
739786    iszero (_add. alpha) &&  return  _rmul_or_fill! (A, _add. beta)
740787    for  j in  axes (B. data,2 )
741-         @inbounds  _modify! (_add, c, A, (j,j))
788+         @inbounds  _modify! (_add, B[ BandIndex ( 0 ,j)]  *   c, A, (j,j))
742789        for  i in  (j +  1 ): lastindex (B. data,1 )
743790            @inbounds  _modify! (_add, B. data[i,j] *  c, A. data, (i,j))
744791        end 
@@ -749,7 +796,7 @@ function _triscale!(A::LowerOrUnitLowerTriangular, c::Number, B::UnitLowerTriang
749796    checksize1 (A, B)
750797    iszero (_add. alpha) &&  return  _rmul_or_fill! (A, _add. beta)
751798    for  j in  axes (B. data,2 )
752-         @inbounds  _modify! (_add, c, A, (j,j))
799+         @inbounds  _modify! (_add, c  *  B[ BandIndex ( 0 ,j)] , A, (j,j))
753800        for  i in  (j +  1 ): lastindex (B. data,1 )
754801            @inbounds  _modify! (_add, c *  B. data[i,j], A. data, (i,j))
755802        end 
0 commit comments