Skip to content

Commit ea52f6f

Browse files
committed
rewrite diagm with Pair's
1 parent 93a38b7 commit ea52f6f

24 files changed

+131
-100
lines changed

NEWS.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,8 @@ Library improvements
313313

314314
* REPL Undo via Ctrl-/ and Ctrl-_
315315

316+
* `diagm` now accepts several diagonal index/vector pairs ([#24047]).
317+
316318
* New function `equalto(x)`, which returns a function that compares its argument to `x`
317319
using `isequal` ([#23812]).
318320

@@ -464,10 +466,16 @@ Deprecated or removed
464466
* The tuple-of-types form of `cfunction`, `cfunction(f, returntype, (types...))`, has been deprecated
465467
in favor of the tuple-type form `cfunction(f, returntype, Tuple{types...})` ([#23066]).
466468

469+
* `diagm(v::AbstractVector, k::Integer=0)` has been deprecated in favor of
470+
`diagm(k => v)` ([#24047]).
471+
472+
* `diagm(x::Number)` has been deprecated in favor of `fill(x, 1, 1)` ([#24047]).
473+
467474
* `diagm(A::SparseMatrixCSC)` has been deprecated in favor of
468475
`spdiagm(sparsevec(A))` ([#23341]).
469476

470-
* `diagm(A::BitMatrix)` has been deprecated, use `diagm(vec(A))` instead ([#23373]).
477+
* `diagm(A::BitMatrix)` has been deprecated, use `diagm(0 => vec(A))` or
478+
`BitMatrix(Diagonal(vec(A)))` instead ([#23373], [#24047]).
471479

472480
* `` (written as `\mscre<TAB>` or `\euler<TAB>`) is now the only (by default) exported
473481
name for Euler's number, and the type has changed from `Irrational{:e}` to

base/deprecated.jl

+14-1
Original file line numberDiff line numberDiff line change
@@ -1641,7 +1641,7 @@ import .LinAlg: diagm
16411641
@deprecate diagm(A::SparseMatrixCSC) sparse(Diagonal(sparsevec(A)))
16421642

16431643
# PR #23373
1644-
@deprecate diagm(A::BitMatrix) diagm(vec(A))
1644+
@deprecate diagm(A::BitMatrix) BitMatrix(Diagonal(vec(A)))
16451645

16461646
# PR 23341
16471647
@eval GMP @deprecate gmp_version() version() false
@@ -1870,6 +1870,19 @@ end
18701870
nothing
18711871
end
18721872

1873+
function diagm(v::BitVector)
1874+
depwarn(string("diagm(v::BitVector) is deprecated, use diagm(0 => v) or ",
1875+
"BitMatrix(Diagonal(v)) instead"), :diagm)
1876+
return BitMatrix(Diagonal(v))
1877+
end
1878+
function diagm(v::AbstractVector)
1879+
depwarn(string("diagm(v::AbstractVector) is deprecated, use diagm(0 => v) or ",
1880+
"Matrix(Diagonal(v)) instead"), :diagm)
1881+
return Matrix(Diagonal(v))
1882+
end
1883+
@deprecate diagm(v::AbstractVector, k::Integer) diagm(k => v)
1884+
@deprecate diagm(x::Number) fill(x, 1, 1)
1885+
18731886
# issue #20816
18741887
@deprecate strwidth textwidth
18751888
@deprecate charwidth textwidth

base/linalg/bitarray.jl

+1-10
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ function tril(B::BitMatrix, k::Integer=0)
7474
A
7575
end
7676

77-
## diag and related
77+
## diag
7878

7979
function diag(B::BitMatrix)
8080
n = minimum(size(B))
@@ -85,15 +85,6 @@ function diag(B::BitMatrix)
8585
v
8686
end
8787

88-
function diagm(v::BitVector)
89-
n = length(v)
90-
a = falses(n, n)
91-
for i=1:n
92-
a[i,i] = v[i]
93-
end
94-
a
95-
end
96-
9788
## norm and rank
9889

9990
svd(A::BitMatrix) = svd(float(A))

base/linalg/dense.jl

+33-11
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,8 @@ diagind(A::AbstractMatrix, k::Integer=0) = diagind(size(A,1), size(A,2), k)
246246
diag(M, k::Integer=0)
247247
248248
The `k`th diagonal of a matrix, as a vector.
249-
Use [`diagm`](@ref) to construct a diagonal matrix.
249+
250+
See also: [`diagm`](@ref)
250251
251252
# Examples
252253
```jldoctest
@@ -265,29 +266,50 @@ julia> diag(A,1)
265266
diag(A::AbstractMatrix, k::Integer=0) = A[diagind(A,k)]
266267

267268
"""
268-
diagm(v, k::Integer=0)
269+
diagm(kv::Pair{<:Integer,<:AbstractVector}...)
270+
271+
Construct a square matrix from `Pair`s of diagonals and vectors.
272+
Vector `kv.second` will be placed on the `kv.first` diagonal.
269273
270-
Construct a matrix by placing `v` on the `k`th diagonal. This constructs a full matrix; if
271-
you want a storage-efficient version with fast arithmetic, use [`Diagonal`](@ref) instead.
274+
See also: [`spdiagm`](@ref), [`Diagonal`](@ref)
272275
273276
# Examples
274277
```jldoctest
275-
julia> diagm([1,2,3],1)
278+
julia> diagm(1 => [1,2,3])
276279
4×4 Array{Int64,2}:
277280
0 1 0 0
278281
0 0 2 0
279282
0 0 0 3
280283
0 0 0 0
284+
285+
julia> diagm(1 => [1,2,3], -1 => [4,5])
286+
4×4 Array{Int64,2}:
287+
0 1 0 0
288+
4 0 2 0
289+
0 5 0 3
290+
0 0 0 0
281291
```
282292
"""
283-
function diagm(v::AbstractVector{T}, k::Integer=0) where T
284-
n = length(v) + abs(k)
285-
A = zeros(T,n,n)
286-
A[diagind(A,k)] = v
287-
A
293+
function diagm(kv::Pair{<:Integer,<:AbstractVector}...)
294+
A = diagm_container(kv...)
295+
for p in kv
296+
inds = diagind(A, p.first)
297+
for (i, val) in enumerate(p.second)
298+
A[inds[i]] = val
299+
end
300+
end
301+
return A
302+
end
303+
function diagm_container(kv::Pair{<:Integer,<:AbstractVector}...)
304+
T = promote_type(map(x -> eltype(x.second), kv)...)
305+
n = mapreduce(x -> length(x.second) + abs(x.first), max, kv)
306+
return zeros(T, n, n)
307+
end
308+
function diagm_container(kv::Pair{<:Integer,<:BitVector}...)
309+
n = mapreduce(x -> length(x.second) + abs(x.first), max, kv)
310+
return falses(n, n)
288311
end
289312

290-
diagm(x::Number) = (X = Matrix{typeof(x)}(1,1); X[1,1] = x; X)
291313

292314
function trace(A::Matrix{T}) where T
293315
n = checksquare(A)

base/linalg/diagonal.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ Diagonal{T}(V::AbstractVector) where {T} = Diagonal{T}(convert(AbstractVector{T}
5252
convert(::Type{Diagonal{T}}, D::Diagonal{T}) where {T} = D
5353
convert(::Type{Diagonal{T}}, D::Diagonal) where {T} = Diagonal{T}(convert(AbstractVector{T}, D.diag))
5454
convert(::Type{AbstractMatrix{T}}, D::Diagonal) where {T} = convert(Diagonal{T}, D)
55-
convert(::Type{Matrix}, D::Diagonal) = diagm(D.diag)
55+
convert(::Type{Matrix}, D::Diagonal) = diagm(0 => D.diag)
5656
convert(::Type{Array}, D::Diagonal) = convert(Matrix, D)
5757
full(D::Diagonal) = convert(Array, D)
5858

base/linalg/generic.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -739,13 +739,13 @@ of the [`eltype`](@ref) of `A`.
739739
julia> rank(eye(3))
740740
3
741741
742-
julia> rank(diagm([1, 0, 2]))
742+
julia> rank(0 => diagm([1, 0, 2]))
743743
2
744744
745-
julia> rank(diagm([1, 0.001, 2]), 0.1)
745+
julia> rank(diagm(0 => [1, 0.001, 2]), 0.1)
746746
2
747747
748-
julia> rank(diagm([1, 0.001, 2]), 0.00001)
748+
julia> rank(diagm(0 => [1, 0.001, 2]), 0.00001)
749749
3
750750
```
751751
"""

base/linalg/lapack.jl

+5-5
Original file line numberDiff line numberDiff line change
@@ -1161,17 +1161,17 @@ of `A`. `fact` may be `E`, in which case `A` will be equilibrated and copied
11611161
to `AF`; `F`, in which case `AF` and `ipiv` from a previous `LU` factorization
11621162
are inputs; or `N`, in which case `A` will be copied to `AF` and then
11631163
factored. If `fact = F`, `equed` may be `N`, meaning `A` has not been
1164-
equilibrated; `R`, meaning `A` was multiplied by `diagm(R)` from the left;
1165-
`C`, meaning `A` was multiplied by `diagm(C)` from the right; or `B`, meaning
1166-
`A` was multiplied by `diagm(R)` from the left and `diagm(C)` from the right.
1164+
equilibrated; `R`, meaning `A` was multiplied by `Diagonal(R)` from the left;
1165+
`C`, meaning `A` was multiplied by `Diagonal(C)` from the right; or `B`, meaning
1166+
`A` was multiplied by `Diagonal(R)` from the left and `Diagonal(C)` from the right.
11671167
If `fact = F` and `equed = R` or `B` the elements of `R` must all be positive.
11681168
If `fact = F` and `equed = C` or `B` the elements of `C` must all be positive.
11691169
11701170
Returns the solution `X`; `equed`, which is an output if `fact` is not `N`,
11711171
and describes the equilibration that was performed; `R`, the row equilibration
11721172
diagonal; `C`, the column equilibration diagonal; `B`, which may be overwritten
1173-
with its equilibrated form `diagm(R)*B` (if `trans = N` and `equed = R,B`) or
1174-
`diagm(C)*B` (if `trans = T,C` and `equed = C,B`); `rcond`, the reciprocal
1173+
with its equilibrated form `Diagonal(R)*B` (if `trans = N` and `equed = R,B`) or
1174+
`Diagonal(C)*B` (if `trans = T,C` and `equed = C,B`); `rcond`, the reciprocal
11751175
condition number of `A` after equilbrating; `ferr`, the forward error bound for
11761176
each solution vector in `X`; `berr`, the forward error bound for each solution
11771177
vector in `X`; and `work`, the reciprocal pivot growth factor.

base/linalg/svd.jl

+8-8
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ end
3232
Compute the singular value decomposition (SVD) of `A` and return an `SVD` object.
3333
3434
`U`, `S`, `V` and `Vt` can be obtained from the factorization `F` with `F[:U]`,
35-
`F[:S]`, `F[:V]` and `F[:Vt]`, such that `A = U*diagm(S)*Vt`.
35+
`F[:S]`, `F[:V]` and `F[:Vt]`, such that `A = U*Diagonal(S)*Vt`.
3636
The algorithm produces `Vt` and hence `Vt` is more efficient to extract than `V`.
3737
The singular values in `S` are sorted in descending order.
3838
@@ -52,7 +52,7 @@ julia> A = [1. 0. 0. 0. 2.; 0. 0. 3. 0. 0.; 0. 0. 0. 0. 0.; 0. 2. 0. 0. 0.]
5252
julia> F = svdfact(A)
5353
Base.LinAlg.SVD{Float64,Float64,Array{Float64,2}}([0.0 1.0 0.0 0.0; 1.0 0.0 0.0 0.0; 0.0 0.0 0.0 -1.0; 0.0 0.0 1.0 0.0], [3.0, 2.23607, 2.0, 0.0], [-0.0 0.0 … -0.0 0.0; 0.447214 0.0 … 0.0 0.894427; -0.0 1.0 … -0.0 0.0; 0.0 0.0 … 1.0 0.0])
5454
55-
julia> F[:U] * diagm(F[:S]) * F[:Vt]
55+
julia> F[:U] * Diagonal(F[:S]) * F[:Vt]
5656
4×5 Array{Float64,2}:
5757
1.0 0.0 0.0 0.0 2.0
5858
0.0 0.0 3.0 0.0 0.0
@@ -71,7 +71,7 @@ svdfact(x::Integer; thin::Bool=true) = svdfact(float(x), thin=thin)
7171
svd(A; thin::Bool=true) -> U, S, V
7272
7373
Computes the SVD of `A`, returning `U`, vector `S`, and `V` such that
74-
`A == U*diagm(S)*V'`. The singular values in `S` are sorted in descending order.
74+
`A == U*Diagonal(S)*V'`. The singular values in `S` are sorted in descending order.
7575
7676
If `thin=true` (default), a thin SVD is returned. For a ``M \\times N`` matrix
7777
`A`, `U` is ``M \\times M`` for a full SVD (`thin=false`) and
@@ -93,7 +93,7 @@ julia> A = [1. 0. 0. 0. 2.; 0. 0. 3. 0. 0.; 0. 0. 0. 0. 0.; 0. 2. 0. 0. 0.]
9393
julia> U, S, V = svd(A)
9494
([0.0 1.0 0.0 0.0; 1.0 0.0 0.0 0.0; 0.0 0.0 0.0 -1.0; 0.0 0.0 1.0 0.0], [3.0, 2.23607, 2.0, 0.0], [-0.0 0.447214 -0.0 0.0; 0.0 0.0 1.0 0.0; … ; -0.0 0.0 -0.0 1.0; 0.0 0.894427 0.0 0.0])
9595
96-
julia> U*diagm(S)*V'
96+
julia> U*Diagonal(S)*V'
9797
4×5 Array{Float64,2}:
9898
1.0 0.0 0.0 0.0 2.0
9999
0.0 0.0 3.0 0.0 0.0
@@ -266,17 +266,17 @@ function getindex(obj::GeneralizedSVD{T}, d::Symbol) where T
266266
elseif d == :D1
267267
m = size(obj.U, 1)
268268
if m - obj.k - obj.l >= 0
269-
return [eye(T, obj.k) zeros(T, obj.k, obj.l); zeros(T, obj.l, obj.k) diagm(obj.a[obj.k + 1:obj.k + obj.l]); zeros(T, m - obj.k - obj.l, obj.k + obj.l)]
269+
return [eye(T, obj.k) zeros(T, obj.k, obj.l); zeros(T, obj.l, obj.k) Diagonal(obj.a[obj.k + 1:obj.k + obj.l]); zeros(T, m - obj.k - obj.l, obj.k + obj.l)]
270270
else
271-
return [eye(T, m, obj.k) [zeros(T, obj.k, m - obj.k); diagm(obj.a[obj.k + 1:m])] zeros(T, m, obj.k + obj.l - m)]
271+
return [eye(T, m, obj.k) [zeros(T, obj.k, m - obj.k); Diagonal(obj.a[obj.k + 1:m])] zeros(T, m, obj.k + obj.l - m)]
272272
end
273273
elseif d == :D2
274274
m = size(obj.U, 1)
275275
p = size(obj.V, 1)
276276
if m - obj.k - obj.l >= 0
277-
return [zeros(T, obj.l, obj.k) diagm(obj.b[obj.k + 1:obj.k + obj.l]); zeros(T, p - obj.l, obj.k + obj.l)]
277+
return [zeros(T, obj.l, obj.k) Diagonal(obj.b[obj.k + 1:obj.k + obj.l]); zeros(T, p - obj.l, obj.k + obj.l)]
278278
else
279-
return [zeros(T, p, obj.k) [diagm(obj.b[obj.k + 1:m]); zeros(T, obj.k + p - m, m - obj.k)] [zeros(T, m - obj.k, obj.k + obj.l - m); eye(T, obj.k + p - m, obj.k + obj.l - m)]]
279+
return [zeros(T, p, obj.k) [Diagonal(obj.b[obj.k + 1:m]); zeros(T, obj.k + p - m, m - obj.k)] [zeros(T, m - obj.k, obj.k + obj.l - m); eye(T, obj.k + p - m, obj.k + obj.l - m)]]
280280
end
281281
elseif d == :R
282282
return obj.R

base/linalg/uniformscaling.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ function isapprox(J::UniformScaling,A::AbstractMatrix;
220220
rtol::Real=rtoldefault(promote_leaf_eltypes(A),eltype(J),atol),
221221
nans::Bool=false, norm::Function=vecnorm)
222222
n = checksquare(A)
223-
Jnorm = norm === vecnorm ? abs(J.λ)*sqrt(n) : (norm === Base.norm ? abs(J.λ) : norm(diagm(fill(J.λ, n))))
223+
Jnorm = norm === vecnorm ? abs(J.λ)*sqrt(n) : (norm === Base.norm ? abs(J.λ) : norm(Diagonal(fill(J.λ, n))))
224224
return norm(A - J) <= max(atol, rtol*max(norm(A), Jnorm))
225225
end
226226
isapprox(A::AbstractMatrix,J::UniformScaling;kwargs...) = isapprox(J,A;kwargs...)

test/arrayops.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ end
232232
tmp[rng...] = A[rng...]
233233
@test tmp == cat(3,zeros(Int,2,3),[0 0 0; 0 47 52],zeros(Int,2,3),[0 0 0; 0 127 132])
234234

235-
@test cat([1,2],1,2,3.,4.,5.) == diagm([1,2,3.,4.,5.])
235+
@test cat([1,2],1,2,3.,4.,5.) == diagm(0 => [1,2,3.,4.,5.])
236236
blk = [1 2;3 4]
237237
tmp = cat([1,3],blk,blk)
238238
@test tmp[1:2,1:2,1] == blk
@@ -2044,7 +2044,7 @@ end # module AutoRetType
20442044
@testset "concatenations of dense matrices/vectors yield dense matrices/vectors" begin
20452045
N = 4
20462046
densevec = ones(N)
2047-
densemat = diagm(ones(N))
2047+
densemat = diagm(0 => ones(N))
20482048
# Test that concatenations of homogeneous pairs of either dense matrices or dense vectors
20492049
# (i.e., Matrix-Matrix concatenations, and Vector-Vector concatenations) yield dense arrays
20502050
for densearray in (densevec, densemat)

test/bitarray.jl

+5-1
Original file line numberDiff line numberDiff line change
@@ -1402,7 +1402,11 @@ timesofar("cat")
14021402
@check_bit_operation qr(b1)
14031403

14041404
b1 = bitrand(v1)
1405-
@check_bit_operation diagm(b1) BitMatrix
1405+
@check_bit_operation diagm(0 => b1) BitMatrix
1406+
1407+
b1 = bitrand(v1)
1408+
b2 = bitrand(v1)
1409+
@check_bit_operation diagm(-1 => b1, 1 => b2) BitMatrix
14061410

14071411
b1 = bitrand(n1, n1)
14081412
@check_bit_operation diag(b1)

test/broadcast.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ for arr in (identity, as_sub)
135135
@test A == fill(7, 2, 2)
136136
A = arr(zeros(3,3))
137137
broadcast_setindex!(A, 10:12, 1:3, 1:3)
138-
@test A == diagm(10:12)
138+
@test A == diagm(0 => 10:12)
139139
@test_throws BoundsError broadcast_setindex!(A, 7, [1,-1], [1 2])
140140

141141
for f in ((==), (<) , (!=), (<=))

test/linalg/arnoldi.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ end
186186
# Ensure singular values from svds are in
187187
# the correct order
188188
@testset "singular values ordered correctly" begin
189-
B = sparse(diagm([1.0, 2.0, 34.0, 5.0, 6.0]))
189+
B = sparse(Diagonal([1.0, 2.0, 34.0, 5.0, 6.0]))
190190
S3 = svds(B, ritzvec=false, nsv=2)
191191
@test S3[1][:S] [34.0, 6.0]
192192
S4 = svds(B, nsv=2)

test/linalg/bidiag.jl

+6-6
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,12 @@ srand(1)
9797
@testset "Constructor and basic properties" begin
9898
@test size(T, 1) == size(T, 2) == n
9999
@test size(T) == (n, n)
100-
@test Array(T) == diagm(dv) + diagm(ev, uplo == :U ? 1 : -1)
100+
@test Array(T) == diagm(0 => dv, uplo == :U ? 1 : -1 => ev)
101101
@test Bidiagonal(Array(T), uplo) == T
102102
@test big.(T) == T
103-
@test Array(abs.(T)) == abs.(diagm(dv)) + abs.(diagm(ev, uplo == :U ? 1 : -1))
104-
@test Array(real(T)) == real(diagm(dv)) + real(diagm(ev, uplo == :U ? 1 : -1))
105-
@test Array(imag(T)) == imag(diagm(dv)) + imag(diagm(ev, uplo == :U ? 1 : -1))
103+
@test Array(abs.(T)) == abs.(diagm(0 => dv, uplo == :U ? 1 : -1 => ev))
104+
@test Array(real(T)) == real(diagm(0 => dv, uplo == :U ? 1 : -1 => ev))
105+
@test Array(imag(T)) == imag(diagm(0 => dv, uplo == :U ? 1 : -1 => ev))
106106
end
107107

108108
@testset for func in (conj, transpose, adjoint)
@@ -241,7 +241,7 @@ srand(1)
241241
Test.test_approx_eq_modphase(u1, u2)
242242
Test.test_approx_eq_modphase(v1, v2)
243243
end
244-
@test 0 vecnorm(u2*diagm(d2)*v2'-Tfull) atol=n*max(n^2*eps(relty),vecnorm(u1*diagm(d1)*v1'-Tfull))
244+
@test 0 vecnorm(u2*Diagonal(d2)*v2'-Tfull) atol=n*max(n^2*eps(relty),vecnorm(u1*Diagonal(d1)*v1'-Tfull))
245245
@inferred svdvals(T)
246246
@inferred svd(T)
247247
end
@@ -264,7 +264,7 @@ srand(1)
264264
TriSym = SymTridiagonal(T.dv, T.ev)
265265
@test Array(TriSym*T) Array(TriSym)*Array(T)
266266
# test pass-through of A_mul_B! for AbstractTriangular*Bidiagonal
267-
Tri = UpperTriangular(diagm(T.ev, 1))
267+
Tri = UpperTriangular(diagm(1 => T.ev))
268268
@test Array(Tri*T) Array(Tri)*Array(T)
269269
end
270270

test/linalg/blas.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ srand(100)
227227
bH = zeros(elty,2,n)
228228
bH[1,2:n] = ev
229229
bH[2,:] = dv
230-
fullH = diagm(dv) + diagm(conj(ev),-1) + diagm(ev,1)
230+
fullH = diagm(0 => dv, -1 => conj(ev), 1 => ev)
231231
@test BLAS.hbmv('U',1,bH,x) fullH*x
232232
end
233233
end

0 commit comments

Comments
 (0)