@@ -238,10 +238,22 @@ Base.isassigned(A::UpperOrLowerTriangular, i::Int, j::Int) =
238
238
Base. isstored (A:: UpperOrLowerTriangular , i:: Int , j:: Int ) =
239
239
_shouldforwardindex (A, i, j) ? Base. isstored (A. data, i, j) : false
240
240
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
245
257
246
258
_shouldforwardindex (U:: UpperTriangular , b:: BandIndex ) = b. band >= 0
247
259
_shouldforwardindex (U:: LowerTriangular , b:: BandIndex ) = b. band <= 0
@@ -250,62 +262,97 @@ _shouldforwardindex(U::UnitLowerTriangular, b::BandIndex) = b.band < 0
250
262
251
263
# these specialized getindex methods enable constant-propagation of the band
252
264
Base. @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
254
271
end
255
272
Base. @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
257
279
end
258
280
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" : " "
264
284
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
+ )
266
290
end
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)
269
292
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)" ))
271
294
end
272
295
273
296
@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)
277
298
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)
278
306
end
279
307
return A
280
308
end
281
309
282
310
@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)
288
312
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
289
324
end
290
325
return A
291
326
end
292
327
293
328
@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)
297
330
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)
298
338
end
299
339
return A
300
340
end
301
341
302
342
@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)
308
344
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
309
356
end
310
357
return A
311
358
end
@@ -559,7 +606,7 @@ for (T, UT) in ((:UpperTriangular, :UnitUpperTriangular), (:LowerTriangular, :Un
559
606
@eval @inline function _copy! (A:: $UT , B:: $T )
560
607
for dind in diagind (A, IndexStyle (A))
561
608
if A[dind] != B[dind]
562
- throw_nononeerror ( typeof (A), B[dind], Tuple (dind)... )
609
+ throw_nonuniterror ( nameof ( typeof (A) ), B[dind], Tuple (dind)... )
563
610
end
564
611
end
565
612
_copy! ($ T (parent (A)), B)
@@ -740,7 +787,7 @@ function _triscale!(A::UpperOrUnitUpperTriangular, B::UnitUpperTriangular, c::Nu
740
787
checksize1 (A, B)
741
788
_iszero_alpha (_add) && return _rmul_or_fill! (A, _add. beta)
742
789
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))
744
791
for i in firstindex (B. data,1 ): (j - 1 )
745
792
@inbounds _modify! (_add, B. data[i,j] * c, A. data, (i,j))
746
793
end
@@ -751,7 +798,7 @@ function _triscale!(A::UpperOrUnitUpperTriangular, c::Number, B::UnitUpperTriang
751
798
checksize1 (A, B)
752
799
_iszero_alpha (_add) && return _rmul_or_fill! (A, _add. beta)
753
800
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))
755
802
for i in firstindex (B. data,1 ): (j - 1 )
756
803
@inbounds _modify! (_add, c * B. data[i,j], A. data, (i,j))
757
804
end
@@ -782,7 +829,7 @@ function _triscale!(A::LowerOrUnitLowerTriangular, B::UnitLowerTriangular, c::Nu
782
829
checksize1 (A, B)
783
830
_iszero_alpha (_add) && return _rmul_or_fill! (A, _add. beta)
784
831
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))
786
833
for i in (j + 1 ): lastindex (B. data,1 )
787
834
@inbounds _modify! (_add, B. data[i,j] * c, A. data, (i,j))
788
835
end
@@ -793,7 +840,7 @@ function _triscale!(A::LowerOrUnitLowerTriangular, c::Number, B::UnitLowerTriang
793
840
checksize1 (A, B)
794
841
_iszero_alpha (_add) && return _rmul_or_fill! (A, _add. beta)
795
842
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))
797
844
for i in (j + 1 ): lastindex (B. data,1 )
798
845
@inbounds _modify! (_add, c * B. data[i,j], A. data, (i,j))
799
846
end
0 commit comments