Skip to content

Commit

Permalink
Implement svdx(Number, Number) (#22195)
Browse files Browse the repository at this point in the history
Make svd(x::Number) return numbers

Implement hash, isequal, and == for Factorizations
  • Loading branch information
andreasnoack authored Jun 4, 2017
1 parent 063e8f1 commit 0cc329e
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 1 deletion.
4 changes: 4 additions & 0 deletions base/linalg/factorization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ end
convert(::Type{Factorization{T}}, F::Factorization{T}) where {T} = F
inv(F::Factorization{T}) where {T} = A_ldiv_B!(F, eye(T, size(F,1)))

Base.hash(F::Factorization, h::UInt) = mapreduce(f -> hash(getfield(F, f)), hash, h, fieldnames(F))
Base.:(==)( F::T, G::T) where {T<:Factorization} = all(f -> getfield(F, f) == getfield(G, f), fieldnames(F))
Base.isequal(F::T, G::T) where {T<:Factorization} = all(f -> isequal(getfield(F, f), getfield(G, f)), fieldnames(F))

# With a real lhs and complex rhs with the same precision, we can reinterpret
# the complex rhs as a real rhs with twice the number of columns
function (\){T<:BlasReal}(F::Factorization{T}, B::VecOrMat{Complex{T}})
Expand Down
9 changes: 8 additions & 1 deletion base/linalg/svd.jl
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,11 @@ julia> U*diagm(S)*V'
0.0 2.0 0.0 0.0 0.0
```
"""
function svd(A::Union{Number, AbstractArray}; thin::Bool=true)
function svd(A::AbstractArray; thin::Bool=true)
F = svdfact(A, thin=thin)
F.U, F.S, F.Vt'
end
svd(x::Number; thin::Bool=true) = first.(svd(fill(x, 1, 1)))

function getindex(F::SVD, d::Symbol)
if d == :U
Expand Down Expand Up @@ -231,6 +232,10 @@ function svdfact(A::StridedMatrix{TA}, B::StridedMatrix{TB}) where {TA,TB}
S = promote_type(Float32, typeof(one(TA)/norm(one(TA))),TB)
return svdfact!(copy_oftype(A, S), copy_oftype(B, S))
end
# This method can be heavily optimized but it is probably not critical
# and might introduce bugs or inconsistencies relative to the 1x1 matrix
# version
svdfact(x::Number, y::Number) = svdfact(fill(x, 1, 1), fill(y, 1, 1))

"""
svd(A, B) -> U, V, Q, D1, D2, R0
Expand All @@ -245,6 +250,7 @@ function svd(A::AbstractMatrix, B::AbstractMatrix)
F = svdfact(A, B)
F[:U], F[:V], F[:Q], F[:D1], F[:D2], F[:R0]
end
svd(x::Number, y::Number) = first.(svd(fill(x, 1, 1), fill(y, 1, 1)))

function getindex(obj::GeneralizedSVD{T}, d::Symbol) where T
if d == :U
Expand Down Expand Up @@ -305,6 +311,7 @@ function svdvals(A::StridedMatrix{TA}, B::StridedMatrix{TB}) where {TA,TB}
S = promote_type(Float32, typeof(one(TA)/norm(one(TA))), TB)
return svdvals!(copy_oftype(A, S), copy_oftype(B, S))
end
svdvals(x::Number, y::Number) = abs(x/y)

# Conversion
convert(::Type{AbstractMatrix}, F::SVD) = (F.U * Diagonal(F.S)) * F.Vt
Expand Down
22 changes: 22 additions & 0 deletions test/linalg/svd.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,25 @@ a2img = randn(n,n)/2
end
end
end

@testset "Number input" begin
x, y = randn(2)
@test svdfact(x) == svdfact( fill(x, 1, 1))
@test svdvals(x) == first(svdvals(fill(x, 1, 1)))
@test svd(x) == first.(svd( fill(x, 1, 1)))
@test svdfact(x, y) == svdfact( fill(x, 1, 1), fill(y, 1, 1))
@test svdvals(x, y) == first(svdvals(fill(x, 1, 1), fill(y, 1, 1)))
@test svd(x, y) == first.(svd( fill(x, 1, 1), fill(y, 1, 1)))
end

@testset "isequal, ==, and hash" begin
x, y = rand(), NaN
Fx, Fy = svdfact(x), svdfact(y)
@test Fx == Fx
@test !(Fy == Fy)
@test isequal(Fy, Fy)
@test hash(Fx) == hash(Fx)
@test hash(Fx, UInt(1)) == hash(Fx, UInt(1))
@test hash(Fy) == hash(Fy)
@test hash(Fy, UInt(1)) == hash(Fy, UInt(1))
end

2 comments on commit 0cc329e

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Executing the daily benchmark build, I will reply here when finished:

@nanosoldier runbenchmarks(ALL, isdaily = true)

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @jrevels

Please sign in to comment.