Add: julia-0.6.2
Former-commit-id: ccc667cf67d569f3fb3df39aa57c2134755a7551
This commit is contained in:
283
julia-0.6.2/share/julia/base/linalg/uniformscaling.jl
Normal file
283
julia-0.6.2/share/julia/base/linalg/uniformscaling.jl
Normal file
@@ -0,0 +1,283 @@
|
||||
# This file is a part of Julia. License is MIT: https://julialang.org/license
|
||||
|
||||
import Base: copy, ctranspose, getindex, show, transpose, one, zero, inv,
|
||||
hcat, vcat, hvcat
|
||||
import Base.LinAlg: SingularException
|
||||
|
||||
struct UniformScaling{T<:Number}
|
||||
λ::T
|
||||
end
|
||||
|
||||
"""
|
||||
I
|
||||
|
||||
An object of type `UniformScaling`, representing an identity matrix of any size.
|
||||
|
||||
# Example
|
||||
|
||||
```jldoctest
|
||||
julia> ones(5, 6) * I == ones(5, 6)
|
||||
true
|
||||
|
||||
julia> [1 2im 3; 1im 2 3] * I
|
||||
2×3 Array{Complex{Int64},2}:
|
||||
1+0im 0+2im 3+0im
|
||||
0+1im 2+0im 3+0im
|
||||
```
|
||||
"""
|
||||
const I = UniformScaling(1)
|
||||
|
||||
eltype(::Type{UniformScaling{T}}) where {T} = T
|
||||
ndims(J::UniformScaling) = 2
|
||||
getindex(J::UniformScaling, i::Integer,j::Integer) = ifelse(i==j,J.λ,zero(J.λ))
|
||||
|
||||
function show(io::IO, J::UniformScaling)
|
||||
s = "$(J.λ)"
|
||||
if ismatch(r"\w+\s*[\+\-]\s*\w+", s)
|
||||
s = "($s)"
|
||||
end
|
||||
print(io, "$(typeof(J))\n$s*I")
|
||||
end
|
||||
copy(J::UniformScaling) = UniformScaling(J.λ)
|
||||
|
||||
transpose(J::UniformScaling) = J
|
||||
ctranspose(J::UniformScaling) = UniformScaling(conj(J.λ))
|
||||
|
||||
one(::Type{UniformScaling{T}}) where {T} = UniformScaling(one(T))
|
||||
one(J::UniformScaling{T}) where {T} = one(UniformScaling{T})
|
||||
oneunit(::Type{UniformScaling{T}}) where {T} = UniformScaling(oneunit(T))
|
||||
oneunit(J::UniformScaling{T}) where {T} = oneunit(UniformScaling{T})
|
||||
zero(::Type{UniformScaling{T}}) where {T} = UniformScaling(zero(T))
|
||||
zero(J::UniformScaling{T}) where {T} = zero(UniformScaling{T})
|
||||
|
||||
istriu(::UniformScaling) = true
|
||||
istril(::UniformScaling) = true
|
||||
issymmetric(::UniformScaling) = true
|
||||
ishermitian(J::UniformScaling) = isreal(J.λ)
|
||||
|
||||
(+)(J1::UniformScaling, J2::UniformScaling) = UniformScaling(J1.λ+J2.λ)
|
||||
(+)(B::BitArray{2}, J::UniformScaling) = Array(B) + J
|
||||
(+)(J::UniformScaling, B::BitArray{2}) = J + Array(B)
|
||||
(+)(J::UniformScaling, A::AbstractMatrix) = A + J
|
||||
|
||||
(-)(J::UniformScaling) = UniformScaling(-J.λ)
|
||||
(-)(J1::UniformScaling, J2::UniformScaling) = UniformScaling(J1.λ-J2.λ)
|
||||
(-)(B::BitArray{2}, J::UniformScaling) = Array(B) - J
|
||||
(-)(J::UniformScaling, B::BitArray{2}) = J - Array(B)
|
||||
|
||||
for (t1, t2) in ((:UnitUpperTriangular, :UpperTriangular),
|
||||
(:UnitLowerTriangular, :LowerTriangular))
|
||||
for op in (:+,:-)
|
||||
@eval begin
|
||||
($op)(UL::$t2, J::UniformScaling) = ($t2)(($op)(UL.data, J))
|
||||
|
||||
function ($op)(UL::$t1, J::UniformScaling)
|
||||
ULnew = copy_oftype(UL.data, promote_type(eltype(UL), eltype(J)))
|
||||
for i = 1:size(ULnew, 1)
|
||||
ULnew[i,i] = ($op)(1, J.λ)
|
||||
end
|
||||
return ($t2)(ULnew)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function (-)(J::UniformScaling, UL::Union{UpperTriangular,UnitUpperTriangular})
|
||||
ULnew = similar(full(UL), promote_type(eltype(J), eltype(UL)))
|
||||
n = size(ULnew, 1)
|
||||
ULold = UL.data
|
||||
for j = 1:n
|
||||
for i = 1:j - 1
|
||||
ULnew[i,j] = -ULold[i,j]
|
||||
end
|
||||
if isa(UL, UnitUpperTriangular)
|
||||
ULnew[j,j] = J.λ - 1
|
||||
else
|
||||
ULnew[j,j] = J.λ - ULold[j,j]
|
||||
end
|
||||
end
|
||||
return UpperTriangular(ULnew)
|
||||
end
|
||||
function (-)(J::UniformScaling, UL::Union{LowerTriangular,UnitLowerTriangular})
|
||||
ULnew = similar(full(UL), promote_type(eltype(J), eltype(UL)))
|
||||
n = size(ULnew, 1)
|
||||
ULold = UL.data
|
||||
for j = 1:n
|
||||
if isa(UL, UnitLowerTriangular)
|
||||
ULnew[j,j] = J.λ - 1
|
||||
else
|
||||
ULnew[j,j] = J.λ - ULold[j,j]
|
||||
end
|
||||
for i = j + 1:n
|
||||
ULnew[i,j] = -ULold[i,j]
|
||||
end
|
||||
end
|
||||
return LowerTriangular(ULnew)
|
||||
end
|
||||
|
||||
function (+)(A::AbstractMatrix{TA}, J::UniformScaling{TJ}) where {TA,TJ}
|
||||
n = checksquare(A)
|
||||
B = similar(A, promote_type(TA,TJ))
|
||||
copy!(B,A)
|
||||
@inbounds for i = 1:n
|
||||
B[i,i] += J.λ
|
||||
end
|
||||
B
|
||||
end
|
||||
|
||||
function (-)(A::AbstractMatrix{TA}, J::UniformScaling{TJ}) where {TA,TJ<:Number}
|
||||
n = checksquare(A)
|
||||
B = similar(A, promote_type(TA,TJ))
|
||||
copy!(B, A)
|
||||
@inbounds for i = 1:n
|
||||
B[i,i] -= J.λ
|
||||
end
|
||||
B
|
||||
end
|
||||
function (-)(J::UniformScaling{TJ}, A::AbstractMatrix{TA}) where {TA,TJ<:Number}
|
||||
n = checksquare(A)
|
||||
B = convert(AbstractMatrix{promote_type(TJ,TA)}, -A)
|
||||
@inbounds for j = 1:n
|
||||
B[j,j] += J.λ
|
||||
end
|
||||
B
|
||||
end
|
||||
|
||||
inv(J::UniformScaling) = UniformScaling(inv(J.λ))
|
||||
|
||||
*(J1::UniformScaling, J2::UniformScaling) = UniformScaling(J1.λ*J2.λ)
|
||||
*(B::BitArray{2}, J::UniformScaling) = *(Array(B), J::UniformScaling)
|
||||
*(J::UniformScaling, B::BitArray{2}) = *(J::UniformScaling, Array(B))
|
||||
*(A::AbstractMatrix, J::UniformScaling) = A*J.λ
|
||||
*(J::UniformScaling, A::AbstractVecOrMat) = J.λ*A
|
||||
*(x::Number, J::UniformScaling) = UniformScaling(x*J.λ)
|
||||
*(J::UniformScaling, x::Number) = UniformScaling(J.λ*x)
|
||||
|
||||
/(J1::UniformScaling, J2::UniformScaling) = J2.λ == 0 ? throw(SingularException(1)) : UniformScaling(J1.λ/J2.λ)
|
||||
/(J::UniformScaling, A::AbstractMatrix) = scale!(J.λ, inv(A))
|
||||
/(A::AbstractMatrix, J::UniformScaling) = J.λ == 0 ? throw(SingularException(1)) : A/J.λ
|
||||
|
||||
/(J::UniformScaling, x::Number) = UniformScaling(J.λ/x)
|
||||
|
||||
\(J1::UniformScaling, J2::UniformScaling) = J1.λ == 0 ? throw(SingularException(1)) : UniformScaling(J1.λ\J2.λ)
|
||||
\(A::Union{Bidiagonal{T},AbstractTriangular{T}}, J::UniformScaling) where {T<:Number} = scale!(inv(A), J.λ)
|
||||
\(J::UniformScaling, A::AbstractVecOrMat) = J.λ == 0 ? throw(SingularException(1)) : J.λ\A
|
||||
\(A::AbstractMatrix, J::UniformScaling) = scale!(inv(A), J.λ)
|
||||
|
||||
\(x::Number, J::UniformScaling) = UniformScaling(x\J.λ)
|
||||
|
||||
broadcast(::typeof(*), x::Number,J::UniformScaling) = UniformScaling(x*J.λ)
|
||||
broadcast(::typeof(*), J::UniformScaling,x::Number) = UniformScaling(J.λ*x)
|
||||
|
||||
broadcast(::typeof(/), J::UniformScaling,x::Number) = UniformScaling(J.λ/x)
|
||||
|
||||
==(J1::UniformScaling,J2::UniformScaling) = (J1.λ == J2.λ)
|
||||
|
||||
function isapprox(J1::UniformScaling{T}, J2::UniformScaling{S};
|
||||
rtol::Real=Base.rtoldefault(T,S), atol::Real=0, nans::Bool=false) where {T<:Number,S<:Number}
|
||||
isapprox(J1.λ, J2.λ, rtol=rtol, atol=atol, nans=nans)
|
||||
end
|
||||
|
||||
function copy!(A::AbstractMatrix, J::UniformScaling)
|
||||
size(A,1)==size(A,2) || throw(DimensionMismatch("a UniformScaling can only be copied to a square matrix"))
|
||||
fill!(A, 0)
|
||||
λ = J.λ
|
||||
for i = 1:size(A,1)
|
||||
@inbounds A[i,i] = λ
|
||||
end
|
||||
return A
|
||||
end
|
||||
|
||||
function cond(J::UniformScaling{T}) where T
|
||||
onereal = inv(one(real(J.λ)))
|
||||
return J.λ ≠ zero(T) ? onereal : oftype(onereal, Inf)
|
||||
end
|
||||
|
||||
# promote_to_arrays(n,k, T, A...) promotes any UniformScaling matrices
|
||||
# in A to matrices of type T and sizes given by n[k:end]. n is an array
|
||||
# so that the same promotion code can be used for hvcat. We pass the type T
|
||||
# so that we can re-use this code for sparse-matrix hcat etcetera.
|
||||
promote_to_arrays_(n::Int, ::Type{Matrix}, J::UniformScaling{T}) where {T} = copy!(Matrix{T}(n,n), J)
|
||||
promote_to_arrays_(n::Int, ::Type, A::AbstractVecOrMat) = A
|
||||
promote_to_arrays(n,k, ::Type) = ()
|
||||
promote_to_arrays(n,k, ::Type{T}, A) where {T} = (promote_to_arrays_(n[k], T, A),)
|
||||
promote_to_arrays(n,k, ::Type{T}, A, B) where {T} =
|
||||
(promote_to_arrays_(n[k], T, A), promote_to_arrays_(n[k+1], T, B))
|
||||
promote_to_arrays(n,k, ::Type{T}, A, B, C) where {T} =
|
||||
(promote_to_arrays_(n[k], T, A), promote_to_arrays_(n[k+1], T, B), promote_to_arrays_(n[k+2], T, C))
|
||||
promote_to_arrays(n,k, ::Type{T}, A, B, Cs...) where {T} =
|
||||
(promote_to_arrays_(n[k], T, A), promote_to_arrays_(n[k+1], T, B), promote_to_arrays(n,k+2, T, Cs...)...)
|
||||
promote_to_array_type(A::Tuple{Vararg{Union{AbstractVecOrMat,UniformScaling}}}) = Matrix
|
||||
|
||||
for (f,dim,name) in ((:hcat,1,"rows"), (:vcat,2,"cols"))
|
||||
@eval begin
|
||||
function $f(A::Union{AbstractVecOrMat,UniformScaling}...)
|
||||
n = 0
|
||||
for a in A
|
||||
if !isa(a, UniformScaling)
|
||||
na = size(a,$dim)
|
||||
n > 0 && n != na &&
|
||||
throw(DimensionMismatch(string("number of ", $name,
|
||||
" of each array must match (got ", n, " and ", na, ")")))
|
||||
n = na
|
||||
end
|
||||
end
|
||||
n == 0 && throw(ArgumentError($("$f of only UniformScaling objects cannot determine the matrix size")))
|
||||
return $f(promote_to_arrays(fill(n,length(A)),1, promote_to_array_type(A), A...)...)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function hvcat(rows::Tuple{Vararg{Int}}, A::Union{AbstractVecOrMat,UniformScaling}...)
|
||||
nr = length(rows)
|
||||
sum(rows) == length(A) || throw(ArgumentError("mismatch between row sizes and number of arguments"))
|
||||
n = zeros(Int, length(A))
|
||||
needcols = false # whether we also need to infer some sizes from the column count
|
||||
j = 0
|
||||
for i = 1:nr # infer UniformScaling sizes from row counts, if possible:
|
||||
ni = 0 # number of rows in this block-row
|
||||
for k = 1:rows[i]
|
||||
if !isa(A[j+k], UniformScaling)
|
||||
na = size(A[j+k], 1)
|
||||
ni > 0 && ni != na &&
|
||||
throw(DimensionMismatch("mismatch in number of rows"))
|
||||
ni = na
|
||||
end
|
||||
end
|
||||
if ni > 0
|
||||
for k = 1:rows[i]
|
||||
n[j+k] = ni
|
||||
end
|
||||
else # row consisted only of UniformScaling objects
|
||||
needcols = true
|
||||
end
|
||||
j += rows[i]
|
||||
end
|
||||
if needcols # some sizes still unknown, try to infer from column count
|
||||
nc = j = 0
|
||||
for i = 1:nr
|
||||
nci = 0
|
||||
rows[i] > 0 && n[j+1] == 0 && continue # column count unknown in this row
|
||||
for k = 1:rows[i]
|
||||
nci += isa(A[j+k], UniformScaling) ? n[j+k] : size(A[j+k], 2)
|
||||
end
|
||||
nc > 0 && nc != nci && throw(DimensionMismatch("mismatch in number of columns"))
|
||||
nc = nci
|
||||
j += rows[i]
|
||||
end
|
||||
nc == 0 && throw(ArgumentError("sizes of UniformScalings could not be inferred"))
|
||||
j = 0
|
||||
for i = 1:nr
|
||||
if rows[i] > 0 && n[j+1] == 0 # this row consists entirely of UniformScalings
|
||||
nci = nc ÷ rows[i]
|
||||
nci * rows[i] != nc && throw(DimensionMismatch("indivisible UniformScaling sizes"))
|
||||
for k = 1:rows[i]
|
||||
n[j+k] = nci
|
||||
end
|
||||
end
|
||||
j += rows[i]
|
||||
end
|
||||
end
|
||||
return hvcat(rows, promote_to_arrays(n,1, promote_to_array_type(A), A...)...)
|
||||
end
|
||||
Reference in New Issue
Block a user