@@ -238,10 +238,22 @@ Base.isassigned(A::UpperOrLowerTriangular, i::Int, j::Int) =
238238Base. isstored (A:: UpperOrLowerTriangular , i:: Int , j:: Int ) =
239239 _shouldforwardindex (A, i, j) ? Base. isstored (A. data, i, j) : false
240240
241- @propagate_inbounds getindex (A:: Union{UnitLowerTriangular{T}, UnitUpperTriangular{T}} , i:: Int , j:: Int ) where {T} =
242- _shouldforwardindex (A, i, j) ? A. data[i,j] : ifelse (i == j, oneunit (T), zero (T))
243- @propagate_inbounds getindex (A:: Union{LowerTriangular, UpperTriangular} , i:: Int , j:: Int ) =
244- _shouldforwardindex (A, i, j) ? A. data[i,j] : diagzero (A,i,j)
241+ @propagate_inbounds function getindex (A:: Union{UnitLowerTriangular{T}, UnitUpperTriangular{T}} , i:: Int , j:: Int ) where {T}
242+ if _shouldforwardindex (A, i, j)
243+ A. data[i,j]
244+ else
245+ @boundscheck checkbounds (A, i, j)
246+ ifelse (i == j, oneunit (T), zero (T))
247+ end
248+ end
249+ @propagate_inbounds function getindex (A:: Union{LowerTriangular, UpperTriangular} , i:: Int , j:: Int )
250+ if _shouldforwardindex (A, i, j)
251+ A. data[i,j]
252+ else
253+ @boundscheck checkbounds (A, i, j)
254+ @inbounds diagzero (A,i,j)
255+ end
256+ end
245257
246258_shouldforwardindex (U:: UpperTriangular , b:: BandIndex ) = b. band >= 0
247259_shouldforwardindex (U:: LowerTriangular , b:: BandIndex ) = b. band <= 0
@@ -250,62 +262,97 @@ _shouldforwardindex(U::UnitLowerTriangular, b::BandIndex) = b.band < 0
250262
251263# these specialized getindex methods enable constant-propagation of the band
252264Base. @constprop :aggressive @propagate_inbounds function getindex (A:: Union{UnitLowerTriangular{T}, UnitUpperTriangular{T}} , b:: BandIndex ) where {T}
253- _shouldforwardindex (A, b) ? A. data[b] : ifelse (b. band == 0 , oneunit (T), zero (T))
265+ if _shouldforwardindex (A, b)
266+ A. data[b]
267+ else
268+ @boundscheck checkbounds (A, b)
269+ ifelse (b. band == 0 , oneunit (T), zero (T))
270+ end
254271end
255272Base. @constprop :aggressive @propagate_inbounds function getindex (A:: Union{LowerTriangular, UpperTriangular} , b:: BandIndex )
256- _shouldforwardindex (A, b) ? A. data[b] : diagzero (A. data, b)
273+ if _shouldforwardindex (A, b)
274+ A. data[b]
275+ else
276+ @boundscheck checkbounds (A, b)
277+ @inbounds diagzero (A, b)
278+ end
257279end
258280
259- _zero_triangular_half_str (T:: Type ) = T <: UpperOrUnitUpperTriangular ? " lower" : " upper"
260-
261- @noinline function throw_nonzeroerror (T:: DataType , @nospecialize (x), i, j)
262- Ts = _zero_triangular_half_str (T)
263- Tn = nameof (T)
281+ @noinline function throw_nonzeroerror (Tn:: Symbol , @nospecialize (x), i, j)
282+ zero_half = Tn in (:UpperTriangular , :UnitUpperTriangular ) ? " lower" : " upper"
283+ nstr = Tn === :UpperTriangular ? " n" : " "
264284 throw (ArgumentError (
265- lazy " cannot set index in the $Ts triangular part ($i, $j) of an $Tn matrix to a nonzero value ($x)" ))
285+ LazyString (
286+ lazy " cannot set index ($i, $j) in the $zero_half triangular part " ,
287+ lazy " of a$nstr $Tn matrix to a nonzero value ($x)" )
288+ )
289+ )
266290end
267- @noinline function throw_nononeerror (T:: DataType , @nospecialize (x), i, j)
268- Tn = nameof (T)
291+ @noinline function throw_nonuniterror (Tn:: Symbol , @nospecialize (x), i, j)
269292 throw (ArgumentError (
270- lazy " cannot set index on the diagonal ($i, $j) of an $Tn matrix to a non-unit value ($x)" ))
293+ lazy " cannot set index ($i, $j) on the diagonal of a $Tn matrix to a non-unit value ($x)" ))
271294end
272295
273296@propagate_inbounds function setindex! (A:: UpperTriangular , x, i:: Integer , j:: Integer )
274- if i > j
275- iszero (x) || throw_nonzeroerror (typeof (A), x, i, j)
276- else
297+ if _shouldforwardindex (A, i, j)
277298 A. data[i,j] = x
299+ else
300+ @boundscheck checkbounds (A, i, j)
301+ # the value must be convertible to the eltype for setindex! to be meaningful
302+ # however, the converted value is unused, and the compiler is free to remove
303+ # the conversion if the call is guaranteed to succeed
304+ convert (eltype (A), x)
305+ iszero (x) || throw_nonzeroerror (nameof (typeof (A)), x, i, j)
278306 end
279307 return A
280308end
281309
282310@propagate_inbounds function setindex! (A:: UnitUpperTriangular , x, i:: Integer , j:: Integer )
283- if i > j
284- iszero (x) || throw_nonzeroerror (typeof (A), x, i, j)
285- elseif i == j
286- x == oneunit (x) || throw_nononeerror (typeof (A), x, i, j)
287- else
311+ if _shouldforwardindex (A, i, j)
288312 A. data[i,j] = x
313+ else
314+ @boundscheck checkbounds (A, i, j)
315+ # the value must be convertible to the eltype for setindex! to be meaningful
316+ # however, the converted value is unused, and the compiler is free to remove
317+ # the conversion if the call is guaranteed to succeed
318+ convert (eltype (A), x)
319+ if i == j # diagonal
320+ x == oneunit (eltype (A)) || throw_nonuniterror (nameof (typeof (A)), x, i, j)
321+ else
322+ iszero (x) || throw_nonzeroerror (nameof (typeof (A)), x, i, j)
323+ end
289324 end
290325 return A
291326end
292327
293328@propagate_inbounds function setindex! (A:: LowerTriangular , x, i:: Integer , j:: Integer )
294- if i < j
295- iszero (x) || throw_nonzeroerror (typeof (A), x, i, j)
296- else
329+ if _shouldforwardindex (A, i, j)
297330 A. data[i,j] = x
331+ else
332+ @boundscheck checkbounds (A, i, j)
333+ # the value must be convertible to the eltype for setindex! to be meaningful
334+ # however, the converted value is unused, and the compiler is free to remove
335+ # the conversion if the call is guaranteed to succeed
336+ convert (eltype (A), x)
337+ iszero (x) || throw_nonzeroerror (nameof (typeof (A)), x, i, j)
298338 end
299339 return A
300340end
301341
302342@propagate_inbounds function setindex! (A:: UnitLowerTriangular , x, i:: Integer , j:: Integer )
303- if i < j
304- iszero (x) || throw_nonzeroerror (typeof (A), x, i, j)
305- elseif i == j
306- x == oneunit (x) || throw_nononeerror (typeof (A), x, i, j)
307- else
343+ if _shouldforwardindex (A, i, j)
308344 A. data[i,j] = x
345+ else
346+ @boundscheck checkbounds (A, i, j)
347+ # the value must be convertible to the eltype for setindex! to be meaningful
348+ # however, the converted value is unused, and the compiler is free to remove
349+ # the conversion if the call is guaranteed to succeed
350+ convert (eltype (A), x)
351+ if i == j # diagonal
352+ x == oneunit (eltype (A)) || throw_nonuniterror (nameof (typeof (A)), x, i, j)
353+ else
354+ iszero (x) || throw_nonzeroerror (nameof (typeof (A)), x, i, j)
355+ end
309356 end
310357 return A
311358end
@@ -559,7 +606,7 @@ for (T, UT) in ((:UpperTriangular, :UnitUpperTriangular), (:LowerTriangular, :Un
559606 @eval @inline function _copy! (A:: $UT , B:: $T )
560607 for dind in diagind (A, IndexStyle (A))
561608 if A[dind] != B[dind]
562- throw_nononeerror ( typeof (A), B[dind], Tuple (dind)... )
609+ throw_nonuniterror ( nameof ( typeof (A) ), B[dind], Tuple (dind)... )
563610 end
564611 end
565612 _copy! ($ T (parent (A)), B)
@@ -740,7 +787,7 @@ function _triscale!(A::UpperOrUnitUpperTriangular, B::UnitUpperTriangular, c::Nu
740787 checksize1 (A, B)
741788 _iszero_alpha (_add) && return _rmul_or_fill! (A, _add. beta)
742789 for j in axes (B. data,2 )
743- @inbounds _modify! (_add, c, A, (j,j))
790+ @inbounds _modify! (_add, B[ BandIndex ( 0 ,j)] * c, A, (j,j))
744791 for i in firstindex (B. data,1 ): (j - 1 )
745792 @inbounds _modify! (_add, B. data[i,j] * c, A. data, (i,j))
746793 end
@@ -751,7 +798,7 @@ function _triscale!(A::UpperOrUnitUpperTriangular, c::Number, B::UnitUpperTriang
751798 checksize1 (A, B)
752799 _iszero_alpha (_add) && return _rmul_or_fill! (A, _add. beta)
753800 for j in axes (B. data,2 )
754- @inbounds _modify! (_add, c, A, (j,j))
801+ @inbounds _modify! (_add, c * B[ BandIndex ( 0 ,j)] , A, (j,j))
755802 for i in firstindex (B. data,1 ): (j - 1 )
756803 @inbounds _modify! (_add, c * B. data[i,j], A. data, (i,j))
757804 end
@@ -782,7 +829,7 @@ function _triscale!(A::LowerOrUnitLowerTriangular, B::UnitLowerTriangular, c::Nu
782829 checksize1 (A, B)
783830 _iszero_alpha (_add) && return _rmul_or_fill! (A, _add. beta)
784831 for j in axes (B. data,2 )
785- @inbounds _modify! (_add, c, A, (j,j))
832+ @inbounds _modify! (_add, B[ BandIndex ( 0 ,j)] * c, A, (j,j))
786833 for i in (j + 1 ): lastindex (B. data,1 )
787834 @inbounds _modify! (_add, B. data[i,j] * c, A. data, (i,j))
788835 end
@@ -793,7 +840,7 @@ function _triscale!(A::LowerOrUnitLowerTriangular, c::Number, B::UnitLowerTriang
793840 checksize1 (A, B)
794841 _iszero_alpha (_add) && return _rmul_or_fill! (A, _add. beta)
795842 for j in axes (B. data,2 )
796- @inbounds _modify! (_add, c, A, (j,j))
843+ @inbounds _modify! (_add, c * B[ BandIndex ( 0 ,j)] , A, (j,j))
797844 for i in (j + 1 ): lastindex (B. data,1 )
798845 @inbounds _modify! (_add, c * B. data[i,j], A. data, (i,j))
799846 end
0 commit comments