@@ -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 " cannot set index in the $Ts triangular part ($i, $j) of an $Tn matrix to a nonzero value ($x)" ))
277+ LazyString (
278+ lazy " cannot set index ($i, $j) in the $zero_half triangular part " ,
279+ lazy " of a$nstr $Tn matrix to a nonzero value ($x)" )
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 " cannot set index on the diagonal ($i, $j) of an $Tn matrix to a non-unit value ($x)" ))
285+ lazy " cannot set index ($i, $j) 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