@@ -230,10 +230,22 @@ Base.isassigned(A::UpperOrLowerTriangular, i::Int, j::Int) =
230
230
Base. isstored (A:: UpperOrLowerTriangular , i:: Int , j:: Int ) =
231
231
_shouldforwardindex (A, i, j) ? Base. isstored (A. data, i, j) : false
232
232
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
237
249
238
250
_shouldforwardindex (U:: UpperTriangular , b:: BandIndex ) = b. band >= 0
239
251
_shouldforwardindex (U:: LowerTriangular , b:: BandIndex ) = b. band <= 0
@@ -242,62 +254,97 @@ _shouldforwardindex(U::UnitLowerTriangular, b::BandIndex) = b.band < 0
242
254
243
255
# these specialized getindex methods enable constant-propagation of the band
244
256
Base. @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
246
263
end
247
264
Base. @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
249
271
end
250
272
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" : " "
256
276
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
+ )
258
282
end
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)
261
284
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)" ))
263
286
end
264
287
265
288
@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)
269
290
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)
270
298
end
271
299
return A
272
300
end
273
301
274
302
@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)
280
304
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
281
316
end
282
317
return A
283
318
end
284
319
285
320
@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)
289
322
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)
290
330
end
291
331
return A
292
332
end
293
333
294
334
@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)
300
336
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
301
348
end
302
349
return A
303
350
end
@@ -542,7 +589,7 @@ for (T, UT) in ((:UpperTriangular, :UnitUpperTriangular), (:LowerTriangular, :Un
542
589
@eval @inline function _copyto! (A:: $UT , B:: $T )
543
590
for dind in diagind (A, IndexStyle (A))
544
591
if A[dind] != B[dind]
545
- throw_nononeerror ( typeof (A), B[dind], Tuple (dind)... )
592
+ throw_nonuniterror ( nameof ( typeof (A) ), B[dind], Tuple (dind)... )
546
593
end
547
594
end
548
595
_copyto! ($ T (parent (A)), B)
@@ -696,7 +743,7 @@ function _triscale!(A::UpperOrUnitUpperTriangular, B::UnitUpperTriangular, c::Nu
696
743
checksize1 (A, B)
697
744
iszero (_add. alpha) && return _rmul_or_fill! (A, _add. beta)
698
745
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))
700
747
for i in firstindex (B. data,1 ): (j - 1 )
701
748
@inbounds _modify! (_add, B. data[i,j] * c, A. data, (i,j))
702
749
end
@@ -707,7 +754,7 @@ function _triscale!(A::UpperOrUnitUpperTriangular, c::Number, B::UnitUpperTriang
707
754
checksize1 (A, B)
708
755
iszero (_add. alpha) && return _rmul_or_fill! (A, _add. beta)
709
756
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))
711
758
for i in firstindex (B. data,1 ): (j - 1 )
712
759
@inbounds _modify! (_add, c * B. data[i,j], A. data, (i,j))
713
760
end
@@ -738,7 +785,7 @@ function _triscale!(A::LowerOrUnitLowerTriangular, B::UnitLowerTriangular, c::Nu
738
785
checksize1 (A, B)
739
786
iszero (_add. alpha) && return _rmul_or_fill! (A, _add. beta)
740
787
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))
742
789
for i in (j + 1 ): lastindex (B. data,1 )
743
790
@inbounds _modify! (_add, B. data[i,j] * c, A. data, (i,j))
744
791
end
@@ -749,7 +796,7 @@ function _triscale!(A::LowerOrUnitLowerTriangular, c::Number, B::UnitLowerTriang
749
796
checksize1 (A, B)
750
797
iszero (_add. alpha) && return _rmul_or_fill! (A, _add. beta)
751
798
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))
753
800
for i in (j + 1 ): lastindex (B. data,1 )
754
801
@inbounds _modify! (_add, c * B. data[i,j], A. data, (i,j))
755
802
end
0 commit comments