Diagonal and identity
Prefer structured LinearAlgebra types over materializing a full matrix.
Wrap a 1D NDArray in Diagonal for scale / solve / inverse along a diagonal. Use LinearAlgebra.I (UniformScaling) for A + I, D + I, and A * I. D + I stays a Diagonal. A + I returns a dense NDArray.
using LinearAlgebra
using cuNumeric
d = cuNumeric.ones(Float32, 64)
D = Diagonal(d) # preferred: keep diagonal structure
A = cuNumeric.rand(Float32, 64, 64)
v = cuNumeric.rand(Float32, 64)
y = D * v # scale a vector
B = D * A # scale rows
X = D \ A # scale rows by 1 ./ d
Di = D + I # still Diagonal
C = A + I # dense NDArraySupported Diagonal{<:NDArray} APIs {#Supported-Diagonal{:NDArray}-APIs}
These paths stay on-device (no host densify for the math). RHS / other operands must be NDArray unless noted.
Construction / display
Diagonal(v::NDArray{<:Any,1}): wrap without copyingDiagonal(A::NDArray{<:Any,2}):Diagonal(diag(A))Matrix(D)/Matrix{T}(D): densify to a hostMatrix(conversion only)show: densifies.diagfor printing only
Multiply / divide / inverse
D * A,A * D,D * vfor 2D / 1DNDArraymul!,lmul!,rmul!withNDArrayD \ B,A / D,ldiv!,rdiv!withNDArrayinv(D): reciprocal on-device. Zeros become Inf (noSingularException)det(D):CNScalarproduct of the diagonal
NDArray ± Diagonal
A + D,D + A,A - D,D - Afor square 2DNDArray
UniformScaling (I)
NDArray{T}(I, m, n)/NDArray(I, …),copyto!(A, I),one(A),oneunit(A)A ± I,A * I,I * AD ± I,D * I,I * D,copyto!(D, I):D ± IstaysDiagonal
Broadcast
Structure- or zero-preserving broadcasts on
Diagonal(e.g.D .* c,D .*= c,D .+ D) lower to 1D broadcast on.diagDensifying out-of-place broadcasts (e.g.
D .+ 1,D .+ A) materialize a denseNDArray, matching Base’s densify-to-MatrixbehaviorIn-place densifying writes into
Diagonal(e.g.D .+= 1,D .+= A) still throwArgumentError(off-diagonal / densify), matching Base
Eigen / reductions / predicates / norms
eigvals(D),eigen(D),eigvecs(D): unsorted. Values are a copy of the diagonal (NDArray), vectors areNDArrayidentity. Keywordsortbyis not supported on this method.tr,sum,prod,maximum,minimum:CNScalar(not a Julia scalar)iszero,isone,istriu,istril,ishermitian,issymmetric,isposdef: 0DNDArray{Bool}opnorm(D)/opnorm(D, p)forp ∈ {1, 2, Inf}:CNScalarnorm(D)/norm(D, p)for finitepor±Inf:CNScalar. Off-diagonal elements are zero.cond(D)/cond(D, p)forp ∈ {1, 2, Inf}:CNScalarlogdet(D)for realDiagonalonly:CNScalar
Helpers on dense NDArray
cuNumeric.diag/LinearAlgebra.diag(2D → 1D),cuNumeric.diagonal(two axes of anN-D array → rankN-1),cuNumeric.trace/LinearAlgebra.tr(2D square → 0D)iszero(A): all elements== zero(T)→ 0DNDArray{Bool}isone(A): square 2D vs_eye(T, n)→ 0DNDArray{Bool}(non-square →false)
Unsupported / fallthrough
Other LinearAlgebra operations on Diagonal{<:NDArray} (for example svd, svdvals, pinv, logabsdet, complex logdet, kron, cholesky, host AbstractArray RHS for \ / / / ldiv! / rdiv!, or eigen(...; sortby)) are not specially implemented. They fall through to Base and typically fail with the package’s scalar-indexing error (NDArray does not support scalar indexing without @allowscalar). There are no “not implemented” ArgumentError stubs for these.
Only densify when you truly need a full identity matrix:
E = NDArray{Float32}(I, 64, 64) # dense identity
copyto!(A, I) # fill an existing array
E2 = one(A) # same shape / eltype as AAvoid building a dense identity (or densifying D with Matrix(D)) just to scale or shift. Prefer Diagonal and I instead. There is no public eye.