From 7246d22ce6059edd351f94de5f4673f2b97329d1 Mon Sep 17 00:00:00 2001 From: kshyatt Date: Wed, 22 Nov 2017 19:56:21 -0800 Subject: [PATCH] Even more linalg doctests and docs for svdvals! --- base/linalg/generic.jl | 25 ++++++ base/linalg/schur.jl | 22 +++++- base/linalg/svd.jl | 164 +++++++++++++++++++++++++++++++++++++++ base/linalg/transpose.jl | 50 ++++++++++++ doc/src/stdlib/linalg.md | 1 + 5 files changed, 261 insertions(+), 1 deletion(-) diff --git a/base/linalg/generic.jl b/base/linalg/generic.jl index 82d6f7d2d2a78..a88d7e886201a 100644 --- a/base/linalg/generic.jl +++ b/base/linalg/generic.jl @@ -1330,6 +1330,31 @@ det(x::Number) = x Log of absolute value of matrix determinant. Equivalent to `(log(abs(det(M))), sign(det(M)))`, but may provide increased accuracy and/or speed. + +# Examples +```jldoctest +julia> A = [-1. 0.; 0. 1.] +2×2 Array{Float64,2}: + -1.0 0.0 + 0.0 1.0 + +julia> det(A) +-1.0 + +julia> logabsdet(A) +(0.0, -1.0) + +julia> B = [2. 0.; 0. 1.] +2×2 Array{Float64,2}: + 2.0 0.0 + 0.0 1.0 + +julia> det(B) +2.0 + +julia> logabsdet(B) +(0.6931471805599453, 1.0) +``` """ logabsdet(A::AbstractMatrix) = logabsdet(lufact(A)) diff --git a/base/linalg/schur.jl b/base/linalg/schur.jl index f3b47900f3b70..989c72315c7ca 100644 --- a/base/linalg/schur.jl +++ b/base/linalg/schur.jl @@ -12,7 +12,27 @@ Schur(T::AbstractMatrix{Ty}, Z::AbstractMatrix{Ty}, values::Vector) where {Ty} = """ schurfact!(A::StridedMatrix) -> F::Schur -Same as [`schurfact`](@ref) but uses the input argument as workspace. +Same as [`schurfact`](@ref) but uses the input argument `A` as workspace. + +# Examples +```jldoctest +julia> A = [5. 7.; -2. -4.] +2×2 Array{Float64,2}: + 5.0 7.0 + -2.0 -4.0 + +julia> F = schurfact!(A) +Base.LinAlg.Schur{Float64,Array{Float64,2}} with factors T and Z: +[3.0 9.0; 0.0 -2.0] +[0.961524 0.274721; -0.274721 0.961524] +and values: +[3.0, -2.0] + +julia> A +2×2 Array{Float64,2}: + 3.0 9.0 + 0.0 -2.0 +``` """ schurfact!(A::StridedMatrix{<:BlasFloat}) = Schur(LinAlg.LAPACK.gees!('V', A)...) diff --git a/base/linalg/svd.jl b/base/linalg/svd.jl index de880d586a903..2672a432bd27c 100644 --- a/base/linalg/svd.jl +++ b/base/linalg/svd.jl @@ -15,6 +15,32 @@ SVD(U::AbstractArray{T}, S::Vector{Tr}, Vt::AbstractArray{T}) where {T,Tr} = SVD `svdfact!` is the same as [`svdfact`](@ref), but saves space by overwriting the input `A`, instead of creating a copy. + +# Examples +```jldoctest +julia> A = [1. 0. 0. 0. 2.; 0. 0. 3. 0. 0.; 0. 0. 0. 0. 0.; 0. 2. 0. 0. 0.] +4×5 Array{Float64,2}: + 1.0 0.0 0.0 0.0 2.0 + 0.0 0.0 3.0 0.0 0.0 + 0.0 0.0 0.0 0.0 0.0 + 0.0 2.0 0.0 0.0 0.0 + +julia> F = svdfact!(A); + +julia> F[:U] * Diagonal(F[:S]) * F[:Vt] +4×5 Array{Float64,2}: + 1.0 0.0 0.0 0.0 2.0 + 0.0 0.0 3.0 0.0 0.0 + 0.0 0.0 0.0 0.0 0.0 + 0.0 2.0 0.0 0.0 0.0 + +julia> A +4×5 Array{Float64,2}: + -2.23607 0.0 0.0 0.0 0.618034 + 0.0 -3.0 1.0 0.0 0.0 + 0.0 0.0 0.0 0.0 0.0 + 0.0 0.0 -2.0 0.0 0.0 +``` """ function svdfact!(A::StridedMatrix{T}; full::Bool = false, thin::Union{Bool,Void} = nothing) where T<:BlasFloat # DEPRECATION TODO: remove deprecated thin argument and associated logic after 0.7 @@ -260,6 +286,41 @@ end `svdfact!` is the same as [`svdfact`](@ref), but modifies the arguments `A` and `B` in-place, instead of making copies. + +# Examples +```jldoctest +julia> A = [1. 0.; 0. -1.] +2×2 Array{Float64,2}: + 1.0 0.0 + 0.0 -1.0 + +julia> B = [0. 1.; 1. 0.] +2×2 Array{Float64,2}: + 0.0 1.0 + 1.0 0.0 + +julia> F = svdfact!(A, B); + +julia> F[:U]*F[:D1]*F[:R0]*F[:Q]' +2×2 Array{Float64,2}: + 1.0 0.0 + 0.0 -1.0 + +julia> F[:V]*F[:D2]*F[:R0]*F[:Q]' +2×2 Array{Float64,2}: + 0.0 1.0 + 1.0 0.0 + +julia> A +2×2 Array{Float64,2}: + 1.41421 0.0 + 0.0 -1.41421 + +julia> B +2×2 Array{Float64,2}: + 1.0 -0.0 + 0.0 -1.0 +``` """ function svdfact!(A::StridedMatrix{T}, B::StridedMatrix{T}) where T<:BlasFloat # xggsvd3 replaced xggsvd in LAPACK 3.6.0 @@ -295,6 +356,31 @@ documentation for the [generalized SVD](http://www.netlib.org/lapack/lug/node36.html) and the [xGGSVD3](http://www.netlib.org/lapack/explore-html/d6/db3/dggsvd3_8f.html) routine which is called underneath (in LAPACK 3.6.0 and newer). + +# Examples +```jldoctest +julia> A = [1. 0.; 0. -1.] +2×2 Array{Float64,2}: + 1.0 0.0 + 0.0 -1.0 + +julia> B = [0. 1.; 1. 0.] +2×2 Array{Float64,2}: + 0.0 1.0 + 1.0 0.0 + +julia> F = svdfact(A, B); + +julia> F[:U]*F[:D1]*F[:R0]*F[:Q]' +2×2 Array{Float64,2}: + 1.0 0.0 + 0.0 -1.0 + +julia> F[:V]*F[:D2]*F[:R0]*F[:Q]' +2×2 Array{Float64,2}: + 0.0 1.0 + 1.0 0.0 +``` """ function svdfact(A::StridedMatrix{TA}, B::StridedMatrix{TB}) where {TA,TB} S = promote_type(Float32, typeof(one(TA)/norm(one(TA))),TB) @@ -313,6 +399,31 @@ factorization to a tuple. Direct use of `svdfact` is therefore generally more efficient. The function returns the generalized SVD of `A` and `B`, returning `U`, `V`, `Q`, `D1`, `D2`, and `R0` such that `A = U*D1*R0*Q'` and `B = V*D2*R0*Q'`. + +# Examples +```jldoctest +julia> A = [1. 0.; 0. -1.] +2×2 Array{Float64,2}: + 1.0 0.0 + 0.0 -1.0 + +julia> B = [0. 1.; 1. 0.] +2×2 Array{Float64,2}: + 0.0 1.0 + 1.0 0.0 + +julia> U, V, Q, D1, D2, R0 = svd(A, B); + +julia> U*D1*R0*Q' +2×2 Array{Float64,2}: + 1.0 0.0 + 0.0 -1.0 + +julia> V*D2*R0*Q' +2×2 Array{Float64,2}: + 0.0 1.0 + 1.0 0.0 +``` """ function svd(A::AbstractMatrix, B::AbstractMatrix) F = svdfact(A, B) @@ -360,6 +471,41 @@ function getindex(obj::GeneralizedSVD{T}, d::Symbol) where T end end +""" + svdvals!(A, B) + +Return the generalized singular values from the generalized singular value +decomposition of `A` and `B`, saving space by overwriting `A` and `B`. +See also [`svdfact`](@ref) and [`svdvals`](@ref). + +# Examples +```jldoctest +julia> A = [1. 0.; 0. -1.] +2×2 Array{Float64,2}: + 1.0 0.0 + 0.0 -1.0 + +julia> B = [0. 1.; 1. 0.] +2×2 Array{Float64,2}: + 0.0 1.0 + 1.0 0.0 + +julia> svdvals!(A, B) +2-element Array{Float64,1}: + 1.0 + 1.0 + +julia> A +2×2 Array{Float64,2}: + 1.41421 0.0 + 0.0 -1.41421 + +julia> B +2×2 Array{Float64,2}: + 1.0 -0.0 + 0.0 -1.0 +``` +""" function svdvals!(A::StridedMatrix{T}, B::StridedMatrix{T}) where T<:BlasFloat # xggsvd3 replaced xggsvd in LAPACK 3.6.0 if LAPACK.version() < v"3.6.0" @@ -376,6 +522,24 @@ svdvals(A::StridedMatrix{T},B::StridedMatrix{T}) where {T<:BlasFloat} = svdvals! Return the generalized singular values from the generalized singular value decomposition of `A` and `B`. See also [`svdfact`](@ref). + +# Examples +```jldoctest +julia> A = [1. 0.; 0. -1.] +2×2 Array{Float64,2}: + 1.0 0.0 + 0.0 -1.0 + +julia> B = [0. 1.; 1. 0.] +2×2 Array{Float64,2}: + 0.0 1.0 + 1.0 0.0 + +julia> svdvals(A, B) +2-element Array{Float64,1}: + 1.0 + 1.0 +``` """ function svdvals(A::StridedMatrix{TA}, B::StridedMatrix{TB}) where {TA,TB} S = promote_type(Float32, typeof(one(TA)/norm(one(TA))), TB) diff --git a/base/linalg/transpose.jl b/base/linalg/transpose.jl index d46e4a5d3a6b9..e5388fbdea948 100644 --- a/base/linalg/transpose.jl +++ b/base/linalg/transpose.jl @@ -12,6 +12,31 @@ Transpose array `src` and store the result in the preallocated array `dest`, whi have a size corresponding to `(size(src,2),size(src,1))`. No in-place transposition is supported and unexpected results will happen if `src` and `dest` have overlapping memory regions. + +# Examples +```jldoctest +julia> A = [3+2im 9+2im; 8+7im 4+6im] +2×2 Array{Complex{Int64},2}: + 3+2im 9+2im + 8+7im 4+6im + +julia> B = zeros(Complex{Int64}, 2, 2) +2×2 Array{Complex{Int64},2}: + 0+0im 0+0im + 0+0im 0+0im + +julia> transpose!(B, A); + +julia> B +2×2 Array{Complex{Int64},2}: + 3+2im 8+7im + 9+2im 4+6im + +julia> A +2×2 Array{Complex{Int64},2}: + 3+2im 9+2im + 8+7im 4+6im +``` """ transpose!(B::AbstractMatrix, A::AbstractMatrix) = transpose_f!(transpose, B, A) @@ -22,6 +47,31 @@ Conjugate transpose array `src` and store the result in the preallocated array ` should have a size corresponding to `(size(src,2),size(src,1))`. No in-place transposition is supported and unexpected results will happen if `src` and `dest` have overlapping memory regions. + +# Examples +```jldoctest +julia> A = [3+2im 9+2im; 8+7im 4+6im] +2×2 Array{Complex{Int64},2}: + 3+2im 9+2im + 8+7im 4+6im + +julia> B = zeros(Complex{Int64}, 2, 2) +2×2 Array{Complex{Int64},2}: + 0+0im 0+0im + 0+0im 0+0im + +julia> adjoint!(B, A); + +julia> B +2×2 Array{Complex{Int64},2}: + 3-2im 8-7im + 9-2im 4-6im + +julia> A +2×2 Array{Complex{Int64},2}: + 3+2im 9+2im + 8+7im 4+6im +``` """ adjoint!(B::AbstractMatrix, A::AbstractMatrix) = transpose_f!(adjoint, B, A) function transpose!(B::AbstractVector, A::AbstractMatrix) diff --git a/doc/src/stdlib/linalg.md b/doc/src/stdlib/linalg.md index b8c9fb13b8aec..977b5f6f3240d 100644 --- a/doc/src/stdlib/linalg.md +++ b/doc/src/stdlib/linalg.md @@ -64,6 +64,7 @@ Base.LinAlg.svdfact Base.LinAlg.svdfact! Base.LinAlg.svd Base.LinAlg.svdvals +Base.LinAlg.svdvals! Base.LinAlg.Givens Base.LinAlg.givens Base.LinAlg.triu