• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37527

pending completion
#37527

push

local

web-flow
make `IRShow.method_name` inferrable (#49607)

18 of 18 new or added lines in 3 files covered. (100.0%)

68710 of 81829 relevant lines covered (83.97%)

33068903.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.68
/stdlib/LinearAlgebra/src/uniformscaling.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
import Base: copy, adjoint, getindex, show, transpose, one, zero, inv,
4
             hcat, vcat, hvcat, ^
5

6
"""
7
    UniformScaling{T<:Number}
8

9
Generically sized uniform scaling operator defined as a scalar times
10
the identity operator, `λ*I`. Although without an explicit `size`, it
11
acts similarly to a matrix in many cases and includes support for some
12
indexing. See also [`I`](@ref).
13

14
!!! compat "Julia 1.6"
15
     Indexing using ranges is available as of Julia 1.6.
16

17
# Examples
18
```jldoctest
19
julia> J = UniformScaling(2.)
20
UniformScaling{Float64}
21
2.0*I
22

23
julia> A = [1. 2.; 3. 4.]
24
2×2 Matrix{Float64}:
25
 1.0  2.0
26
 3.0  4.0
27

28
julia> J*A
29
2×2 Matrix{Float64}:
30
 2.0  4.0
31
 6.0  8.0
32

33
julia> J[1:2, 1:2]
34
2×2 Matrix{Float64}:
35
 2.0  0.0
36
 0.0  2.0
37
```
38
"""
39
struct UniformScaling{T<:Number}
40
    λ::T
7,078✔
41
end
42

43
"""
44
    I
45

46
An object of type [`UniformScaling`](@ref), representing an identity matrix of any size.
47

48
# Examples
49
```jldoctest
50
julia> fill(1, (5,6)) * I == fill(1, (5,6))
51
true
52

53
julia> [1 2im 3; 1im 2 3] * I
54
2×3 Matrix{Complex{Int64}}:
55
 1+0im  0+2im  3+0im
56
 0+1im  2+0im  3+0im
57
```
58
"""
59
const I = UniformScaling(true)
60

61
"""
62
    (I::UniformScaling)(n::Integer)
63

64
Construct a `Diagonal` matrix from a `UniformScaling`.
65

66
!!! compat "Julia 1.2"
67
     This method is available as of Julia 1.2.
68

69
# Examples
70
```jldoctest
71
julia> I(3)
72
3×3 Diagonal{Bool, Vector{Bool}}:
73
 1  ⋅  ⋅
74
 ⋅  1  ⋅
75
 ⋅  ⋅  1
76

77
julia> (0.7*I)(3)
78
3×3 Diagonal{Float64, Vector{Float64}}:
79
 0.7   ⋅    ⋅
80
  ⋅   0.7   ⋅
81
  ⋅    ⋅   0.7
82
```
83
"""
84
(I::UniformScaling)(n::Integer) = Diagonal(fill(I.λ, n))
40,379✔
85

86
eltype(::Type{UniformScaling{T}}) where {T} = T
5,217✔
87
ndims(J::UniformScaling) = 2
2✔
88
Base.has_offset_axes(::UniformScaling) = false
57✔
89
getindex(J::UniformScaling, i::Integer,j::Integer) = ifelse(i==j,J.λ,zero(J.λ))
2✔
90

91
getindex(J::UniformScaling, n::Integer, m::AbstractVector{<:Integer}) = getindex(J, m, n)
10✔
92
function getindex(J::UniformScaling{T}, n::AbstractVector{<:Integer}, m::Integer) where T
16✔
93
    v = zeros(T, axes(n))
86✔
94
    @inbounds for (i,ii) in pairs(n)
32✔
95
        if ii == m
86✔
96
            v[i] = J.λ
12✔
97
        end
98
    end
156✔
99
    return v
16✔
100
end
101

102
function getindex(J::UniformScaling{T}, n::AbstractVector{<:Integer}, m::AbstractVector{<:Integer}) where T
44✔
103
    A = zeros(T, axes(n)..., axes(m)...)
428✔
104
    @inbounds for (j,jj) in pairs(m), (i,ii) in pairs(n)
196✔
105
        if ii == jj
556✔
106
            A[i,j] = J.λ
92✔
107
        end
108
    end
664✔
109
    return A
44✔
110
end
111

112
function show(io::IO, ::MIME"text/plain", J::UniformScaling)
2✔
113
    s = "$(J.λ)"
2✔
114
    if occursin(r"\w+\s*[\+\-]\s*\w+", s)
2✔
115
        s = "($s)"
1✔
116
    end
117
    print(io, typeof(J), "\n$s*I")
2✔
118
end
119
copy(J::UniformScaling) = UniformScaling(J.λ)
11✔
120

121
Base.convert(::Type{UniformScaling{T}}, J::UniformScaling) where {T} = UniformScaling(convert(T, J.λ))::UniformScaling{T}
1✔
122

123
conj(J::UniformScaling) = UniformScaling(conj(J.λ))
4✔
124
real(J::UniformScaling) = UniformScaling(real(J.λ))
2✔
125
imag(J::UniformScaling) = UniformScaling(imag(J.λ))
2✔
126

127
transpose(J::UniformScaling) = J
1✔
128
adjoint(J::UniformScaling) = UniformScaling(conj(J.λ))
18✔
129

130
one(::Type{UniformScaling{T}}) where {T} = UniformScaling(one(T))
6✔
131
one(J::UniformScaling{T}) where {T} = one(UniformScaling{T})
3✔
132
oneunit(::Type{UniformScaling{T}}) where {T} = UniformScaling(oneunit(T))
×
133
oneunit(J::UniformScaling{T}) where {T} = oneunit(UniformScaling{T})
×
134
zero(::Type{UniformScaling{T}}) where {T} = UniformScaling(zero(T))
9✔
135
zero(J::UniformScaling{T}) where {T} = zero(UniformScaling{T})
7✔
136

137
isdiag(::UniformScaling) = true
1✔
138
istriu(::UniformScaling) = true
1✔
139
istril(::UniformScaling) = true
1✔
140
issymmetric(::UniformScaling) = true
2✔
141
ishermitian(J::UniformScaling) = isreal(J.λ)
2✔
142
isposdef(J::UniformScaling) = isposdef(J.λ)
8✔
143

144
(+)(J::UniformScaling, x::Number) = J.λ + x
1✔
145
(+)(x::Number, J::UniformScaling) = x + J.λ
16,157✔
146
(-)(J::UniformScaling, x::Number) = J.λ - x
1,063✔
147
(-)(x::Number, J::UniformScaling) = x - J.λ
1✔
148

149
(+)(J::UniformScaling)                      = UniformScaling(+J.λ)
1✔
150
(+)(J1::UniformScaling, J2::UniformScaling) = UniformScaling(J1.λ+J2.λ)
4✔
151
(+)(B::BitArray{2}, J::UniformScaling)      = Array(B) + J
2✔
152
(+)(J::UniformScaling, B::BitArray{2})      = J + Array(B)
2✔
153
(+)(J::UniformScaling, A::AbstractMatrix)   = A + J
204✔
154

155
(-)(J::UniformScaling)                      = UniformScaling(-J.λ)
1,110✔
156
(-)(J1::UniformScaling, J2::UniformScaling) = UniformScaling(J1.λ-J2.λ)
5✔
157
(-)(B::BitArray{2}, J::UniformScaling)      = Array(B) - J
2✔
158
(-)(J::UniformScaling, B::BitArray{2})      = J - Array(B)
2✔
159
(-)(A::AbstractMatrix, J::UniformScaling)   = A + (-J)
1,065✔
160

161
# matrix functions
162
for f in ( :exp,   :log,
163
           :expm1, :log1p,
164
           :sqrt,  :cbrt,
165
           :sin,   :cos,   :tan,
166
           :asin,  :acos,  :atan,
167
           :csc,   :sec,   :cot,
168
           :acsc,  :asec,  :acot,
169
           :sinh,  :cosh,  :tanh,
170
           :asinh, :acosh, :atanh,
171
           :csch,  :sech,  :coth,
172
           :acsch, :asech, :acoth )
173
    @eval Base.$f(J::UniformScaling) = UniformScaling($f(J.λ))
54✔
174
end
175

176
# Unit{Lower/Upper}Triangular matrices become {Lower/Upper}Triangular under
177
# addition with a UniformScaling
178
for (t1, t2) in ((:UnitUpperTriangular, :UpperTriangular),
179
                 (:UnitLowerTriangular, :LowerTriangular))
180
    @eval begin
181
        function (+)(UL::$t1, J::UniformScaling)
12✔
182
            ULnew = copymutable_oftype(UL.data, Base.promote_op(+, eltype(UL), typeof(J)))
24✔
183
            for i in axes(ULnew, 1)
24✔
184
                ULnew[i,i] = one(ULnew[i,i]) + J
36✔
185
            end
60✔
186
            return ($t2)(ULnew)
12✔
187
        end
188
    end
189
end
190

191
# Adding a complex UniformScaling to the diagonal of a Hermitian
192
# matrix breaks the hermiticity, if the UniformScaling is non-real.
193
# However, to preserve type stability, we do not special-case a
194
# UniformScaling{<:Complex} that happens to be real.
195
function (+)(A::Hermitian, J::UniformScaling{<:Complex})
52✔
196
    TS = Base.promote_op(+, eltype(A), typeof(J))
104✔
197
    B = copytri!(copymutable_oftype(parent(A), TS), A.uplo, true)
436✔
198
    for i in diagind(B)
104✔
199
        B[i] = A[i] + J
436✔
200
    end
820✔
201
    return B
52✔
202
end
203

204
function (-)(J::UniformScaling{<:Complex}, A::Hermitian)
4✔
205
    TS = Base.promote_op(+, eltype(A), typeof(J))
8✔
206
    B = copytri!(copymutable_oftype(parent(A), TS), A.uplo, true)
12✔
207
    B .= .-B
8✔
208
    for i in diagind(B)
8✔
209
        B[i] = J - A[i]
12✔
210
    end
20✔
211
    return B
4✔
212
end
213

214
function (+)(A::AbstractMatrix, J::UniformScaling)
1,977✔
215
    checksquare(A)
1,977✔
216
    B = copymutable_oftype(A, Base.promote_op(+, eltype(A), typeof(J)))
3,908✔
217
    for i in intersect(axes(A,1), axes(A,2))
3,954✔
218
        @inbounds B[i,i] += J
11,226✔
219
    end
20,025✔
220
    return B
1,977✔
221
end
222

223
function (-)(J::UniformScaling, A::AbstractMatrix)
342✔
224
    checksquare(A)
342✔
225
    B = convert(AbstractMatrix{Base.promote_op(+, eltype(A), typeof(J))}, -A)
537✔
226
    for i in intersect(axes(A,1), axes(A,2))
684✔
227
        @inbounds B[i,i] += J
1,303✔
228
    end
2,114✔
229
    return B
342✔
230
end
231

232
inv(J::UniformScaling) = UniformScaling(inv(J.λ))
2✔
233
opnorm(J::UniformScaling, p::Real=2) = opnorm(J.λ, p)
2✔
234

235
pinv(J::UniformScaling) = ifelse(iszero(J.λ),
5✔
236
                          UniformScaling(zero(inv(J.λ))),  # type stability
237
                          UniformScaling(inv(J.λ)))
238

239
function det(J::UniformScaling{T}) where T
6✔
240
    if isone(J.λ)
6✔
241
        one(T)
3✔
242
    elseif iszero(J.λ)
3✔
243
        zero(T)
2✔
244
    else
245
        throw(ArgumentError("Determinant of UniformScaling is only well-defined when λ = 0 or 1."))
1✔
246
    end
247
end
248

249
function tr(J::UniformScaling{T}) where T
5✔
250
    if iszero(J.λ)
5✔
251
        zero(T)
4✔
252
    else
253
        throw(ArgumentError("Trace of UniformScaling is only well-defined when λ = 0"))
1✔
254
    end
255
end
256

257
*(J1::UniformScaling, J2::UniformScaling) = UniformScaling(J1.λ*J2.λ)
2✔
258
*(B::BitArray{2}, J::UniformScaling) = *(Array(B), J::UniformScaling)
2✔
259
*(J::UniformScaling, B::BitArray{2}) = *(J::UniformScaling, Array(B))
2✔
260
*(A::AbstractMatrix, J::UniformScaling) = A*J.λ
79✔
261
*(v::AbstractVector, J::UniformScaling) = reshape(v, length(v), 1) * J
1✔
262
*(J::UniformScaling, A::AbstractVecOrMat) = J.λ*A
68✔
263
*(x::Number, J::UniformScaling) = UniformScaling(x*J.λ)
7,005✔
264
*(J::UniformScaling, x::Number) = UniformScaling(J.λ*x)
4✔
265

266
/(J1::UniformScaling, J2::UniformScaling) = J2.λ == 0 ? throw(SingularException(1)) : UniformScaling(J1.λ/J2.λ)
2✔
267
/(J::UniformScaling, A::AbstractMatrix) =
36✔
268
    (invA = inv(A); lmul!(J.λ, convert(AbstractMatrix{promote_type(eltype(J),eltype(invA))}, invA)))
44✔
269
/(A::AbstractMatrix, J::UniformScaling) = J.λ == 0 ? throw(SingularException(1)) : A/J.λ
48✔
270
/(v::AbstractVector, J::UniformScaling) = reshape(v, length(v), 1) / J
2✔
271

272
/(J::UniformScaling, x::Number) = UniformScaling(J.λ/x)
3✔
273

274
\(J1::UniformScaling, J2::UniformScaling) = J1.λ == 0 ? throw(SingularException(1)) : UniformScaling(J1.λ\J2.λ)
2✔
275
\(J::UniformScaling, A::AbstractVecOrMat) = J.λ == 0 ? throw(SingularException(1)) : J.λ\A
53✔
276
\(A::AbstractMatrix, J::UniformScaling) =
44✔
277
    (invA = inv(A); rmul!(convert(AbstractMatrix{promote_type(eltype(invA),eltype(J))}, invA), J.λ))
52✔
278
\(F::Factorization, J::UniformScaling) = F \ J(size(F,1))
22✔
279

280
\(x::Number, J::UniformScaling) = UniformScaling(x\J.λ)
2✔
281

282
@inline mul!(C::AbstractMatrix, A::AbstractMatrix, J::UniformScaling, alpha::Number, beta::Number) =
3✔
283
    mul!(C, A, J.λ, alpha, beta)
284
@inline mul!(C::AbstractVecOrMat, J::UniformScaling, B::AbstractVecOrMat, alpha::Number, beta::Number) =
3✔
285
    mul!(C, J.λ, B, alpha, beta)
286

287
function mul!(out::AbstractMatrix{T}, a::Number, B::UniformScaling, α::Number, β::Number) where {T}
3,406✔
288
    checksquare(out)
3,406✔
289
    if iszero(β)  # zero contribution of the out matrix
3,406✔
290
        fill!(out, zero(T))
9✔
291
    elseif !isone(β)
3,405✔
292
        rmul!(out, β)
3✔
293
    end
294
    s = convert(T, a*B.λ*α)
3,406✔
295
    if !iszero(s)
3,406✔
296
        @inbounds for i in diagind(out)
6,810✔
297
            out[i] += s
8,903✔
298
        end
14,401✔
299
    end
300
    return out
3,406✔
301
end
302
@inline mul!(out::AbstractMatrix, A::UniformScaling, b::Number, α::Number, β::Number)=
1✔
303
    mul!(out, A.λ, UniformScaling(b), α, β)
304
rmul!(A::AbstractMatrix, J::UniformScaling) = rmul!(A, J.λ)
1✔
305
lmul!(J::UniformScaling, B::AbstractVecOrMat) = lmul!(J.λ, B)
1✔
306
rdiv!(A::AbstractMatrix, J::UniformScaling) = rdiv!(A, J.λ)
1✔
307
ldiv!(J::UniformScaling, B::AbstractVecOrMat) = ldiv!(J.λ, B)
1✔
308
ldiv!(Y::AbstractVecOrMat, J::UniformScaling, B::AbstractVecOrMat) = (Y .= J.λ .\ B)
1✔
309

310
Broadcast.broadcasted(::typeof(*), x::Number,J::UniformScaling) = UniformScaling(x*J.λ)
1✔
311
Broadcast.broadcasted(::typeof(*), J::UniformScaling,x::Number) = UniformScaling(J.λ*x)
1✔
312

313
Broadcast.broadcasted(::typeof(/), J::UniformScaling,x::Number) = UniformScaling(J.λ/x)
1✔
314

315
Broadcast.broadcasted(::typeof(\), x::Number,J::UniformScaling) = UniformScaling(x\J.λ)
1✔
316

317
(^)(J::UniformScaling, x::Number) = UniformScaling((J.λ)^x)
3✔
318
Base.literal_pow(::typeof(^), J::UniformScaling, x::Val) = UniformScaling(Base.literal_pow(^, J.λ, x))
2✔
319

320
Broadcast.broadcasted(::typeof(^), J::UniformScaling, x::Number) = UniformScaling(J.λ^x)
2✔
321
function Broadcast.broadcasted(::typeof(Base.literal_pow), ::typeof(^), J::UniformScaling, x::Val)
1✔
322
    UniformScaling(Base.literal_pow(^, J.λ, x))
1✔
323
end
324

325
==(J1::UniformScaling,J2::UniformScaling) = (J1.λ == J2.λ)
43✔
326

327
## equality comparison with UniformScaling
328
==(J::UniformScaling, A::AbstractMatrix) = A == J
16✔
329
function ==(A::AbstractMatrix, J::UniformScaling)
17✔
330
    require_one_based_indexing(A)
17✔
331
    size(A, 1) == size(A, 2) || return false
19✔
332
    iszero(J.λ) && return iszero(A)
15✔
333
    isone(J.λ) && return isone(A)
11✔
334
    return A == J.λ*one(A)
6✔
335
end
336
function ==(A::StridedMatrix, J::UniformScaling)
16✔
337
    size(A, 1) == size(A, 2) || return false
18✔
338
    iszero(J.λ) && return iszero(A)
14✔
339
    isone(J.λ) && return isone(A)
10✔
340
    for j in axes(A, 2), i in axes(A, 1)
16✔
341
        ifelse(i == j, A[i, j] == J.λ, iszero(A[i, j])) || return false
28✔
342
    end
24✔
343
    return true
2✔
344
end
345

346
isequal(A::AbstractMatrix, J::UniformScaling) = false
1✔
347
isequal(J::UniformScaling, A::AbstractMatrix) = false
1✔
348

349
function isapprox(J1::UniformScaling{T}, J2::UniformScaling{S};
4✔
350
            atol::Real=0, rtol::Real=Base.rtoldefault(T,S,atol), nans::Bool=false) where {T<:Number,S<:Number}
351
    isapprox(J1.λ, J2.λ, rtol=rtol, atol=atol, nans=nans)
4✔
352
end
353
function isapprox(J::UniformScaling, A::AbstractMatrix;
166✔
354
                  atol::Real = 0,
355
                  rtol::Real = Base.rtoldefault(promote_leaf_eltypes(A), eltype(J), atol),
356
                  nans::Bool = false, norm::Function = norm)
357
    n = checksquare(A)
83✔
358
    normJ = norm === opnorm             ? abs(J.λ) :
83✔
359
            norm === LinearAlgebra.norm ? abs(J.λ) * sqrt(n) :
360
                                          norm(Diagonal(fill(J.λ, n)))
361
    return norm(A - J) <= max(atol, rtol * max(norm(A), normJ))
83✔
362
end
363
isapprox(A::AbstractMatrix, J::UniformScaling; kwargs...) = isapprox(J, A; kwargs...)
50✔
364

365
"""
366
    copyto!(dest::AbstractMatrix, src::UniformScaling)
367

368
Copies a [`UniformScaling`](@ref) onto a matrix.
369

370
!!! compat "Julia 1.1"
371
    In Julia 1.0 this method only supported a square destination matrix. Julia 1.1. added
372
    support for a rectangular matrix.
373
"""
374
function copyto!(A::AbstractMatrix, J::UniformScaling)
46✔
375
    require_one_based_indexing(A)
46✔
376
    fill!(A, 0)
983✔
377
    λ = J.λ
46✔
378
    for i = 1:min(size(A,1),size(A,2))
92✔
379
        @inbounds A[i,i] = λ
208✔
380
    end
370✔
381
    return A
46✔
382
end
383

384
function copyto!(A::Diagonal, J::UniformScaling)
×
385
    A.diag .= J.λ
×
386
    return A
×
387
end
388
function copyto!(A::Union{Bidiagonal, SymTridiagonal}, J::UniformScaling)
6✔
389
    A.ev .= 0
10✔
390
    A.dv .= J.λ
12✔
391
    return A
6✔
392
end
393
function copyto!(A::Tridiagonal, J::UniformScaling)
3✔
394
    A.dl .= 0
5✔
395
    A.du .= 0
5✔
396
    A.d .= J.λ
6✔
397
    return A
3✔
398
end
399

400
function cond(J::UniformScaling{T}) where T
2✔
401
    onereal = inv(one(real(J.λ)))
2✔
402
    return J.λ ≠ zero(T) ? onereal : oftype(onereal, Inf)
2✔
403
end
404

405
# promote_to_arrays(n,k, T, A...) promotes any UniformScaling matrices
406
# in A to matrices of type T and sizes given by n[k:end].  n is an array
407
# so that the same promotion code can be used for hvcat.  We pass the type T
408
# so that we can re-use this code for sparse-matrix hcat etcetera.
409
promote_to_arrays_(n::Int, ::Type, a::Number) = a
4✔
410
promote_to_arrays_(n::Int, ::Type{Matrix}, J::UniformScaling{T}) where {T} = Matrix(J, n, n)
115✔
411
promote_to_arrays_(n::Int, ::Type, A::AbstractVecOrMat) = A
144✔
412
promote_to_arrays(n,k, ::Type) = ()
×
413
promote_to_arrays(n,k, ::Type{T}, A) where {T} = (promote_to_arrays_(n[k], T, A),)
×
414
promote_to_arrays(n,k, ::Type{T}, A, B) where {T} =
109✔
415
    (promote_to_arrays_(n[k], T, A), promote_to_arrays_(n[k+1], T, B))
416
promote_to_arrays(n,k, ::Type{T}, A, B, C) where {T} =
7✔
417
    (promote_to_arrays_(n[k], T, A), promote_to_arrays_(n[k+1], T, B), promote_to_arrays_(n[k+2], T, C))
418
promote_to_arrays(n,k, ::Type{T}, A, B, Cs...) where {T} =
32✔
419
    (promote_to_arrays_(n[k], T, A), promote_to_arrays_(n[k+1], T, B), promote_to_arrays(n,k+2, T, Cs...)...)
420
promote_to_array_type(A::Tuple{Vararg{Union{AbstractVecOrMat,UniformScaling,Number}}}) = Matrix
×
421

422
_us2number(A) = A
8✔
423
_us2number(J::UniformScaling) = J.λ
4✔
424

425
for (f, _f, dim, name) in ((:hcat, :_hcat, 1, "rows"), (:vcat, :_vcat, 2, "cols"))
426
    @eval begin
427
        @inline $f(A::Union{AbstractVecOrMat,UniformScaling}...) = $_f(A...)
104✔
428
        # if there's a Number present, J::UniformScaling must be 1x1-dimensional
429
        @inline $f(A::Union{AbstractVecOrMat,UniformScaling,Number}...) = $f(map(_us2number, A)...)
4✔
430
        function $_f(A::Union{AbstractVecOrMat,UniformScaling,Number}...; array_type = promote_to_array_type(A))
208✔
431
            n = -1
104✔
432
            for a in A
104✔
433
                if !isa(a, UniformScaling)
213✔
434
                    require_one_based_indexing(a)
97✔
435
                    na = size(a,$dim)
97✔
436
                    n >= 0 && n != na &&
97✔
437
                        throw(DimensionMismatch(string("number of ", $name,
438
                            " of each array must match (got ", n, " and ", na, ")")))
439
                    n = na
97✔
440
                end
441
            end
313✔
442
            n == -1 && throw(ArgumentError($("$f of only UniformScaling objects cannot determine the matrix size")))
104✔
443
            return cat(promote_to_arrays(fill(n, length(A)), 1, array_type, A...)..., dims=Val(3-$dim))
96✔
444
        end
445
    end
446
end
447

448
hvcat(rows::Tuple{Vararg{Int}}, A::Union{AbstractVecOrMat,UniformScaling}...) = _hvcat(rows, A...)
18✔
449
hvcat(rows::Tuple{Vararg{Int}}, A::Union{AbstractVecOrMat,UniformScaling,Number}...) = _hvcat(rows, A...)
4✔
450
function _hvcat(rows::Tuple{Vararg{Int}}, A::Union{AbstractVecOrMat,UniformScaling,Number}...; array_type = promote_to_array_type(A))
44✔
451
    require_one_based_indexing(A...)
22✔
452
    nr = length(rows)
22✔
453
    sum(rows) == length(A) || throw(ArgumentError("mismatch between row sizes and number of arguments"))
22✔
454
    n = fill(-1, length(A))
108✔
455
    needcols = false # whether we also need to infer some sizes from the column count
22✔
456
    j = 0
22✔
457
    for i = 1:nr # infer UniformScaling sizes from row counts, if possible:
22✔
458
        ni = -1 # number of rows in this block-row, -1 indicates unknown
54✔
459
        for k = 1:rows[i]
108✔
460
            if !isa(A[j+k], UniformScaling)
108✔
461
                na = size(A[j+k], 1)
51✔
462
                ni >= 0 && ni != na &&
51✔
463
                    throw(DimensionMismatch("mismatch in number of rows"))
464
                ni = na
51✔
465
            end
466
        end
162✔
467
        if ni >= 0
54✔
468
            for k = 1:rows[i]
70✔
469
                n[j+k] = ni
77✔
470
            end
119✔
471
        else # row consisted only of UniformScaling objects
472
            needcols = true
19✔
473
        end
474
        j += rows[i]
54✔
475
    end
86✔
476
    if needcols # some sizes still unknown, try to infer from column count
22✔
477
        nc = -1
14✔
478
        j = 0
14✔
479
        for i = 1:nr
14✔
480
            nci = 0
37✔
481
            rows[i] > 0 && n[j+1] == -1 && (j += rows[i]; continue)
56✔
482
            for k = 1:rows[i]
36✔
483
                nci += isa(A[j+k], UniformScaling) ? n[j+k] : size(A[j+k], 2)
72✔
484
            end
68✔
485
            nc >= 0 && nc != nci && throw(DimensionMismatch("mismatch in number of columns"))
18✔
486
            nc = nci
18✔
487
            j += rows[i]
18✔
488
        end
60✔
489
        nc == -1 && throw(ArgumentError("sizes of UniformScalings could not be inferred"))
14✔
490
        j = 0
12✔
491
        for i = 1:nr
12✔
492
            if rows[i] > 0 && n[j+1] == -1 # this row consists entirely of UniformScalings
33✔
493
                nci, r = divrem(nc, rows[i])
30✔
494
                r != 0 && throw(DimensionMismatch("indivisible UniformScaling sizes"))
15✔
495
                for k = 1:rows[i]
30✔
496
                    n[j+k] = nci
25✔
497
                end
35✔
498
            end
499
            j += rows[i]
33✔
500
        end
54✔
501
    end
502
    Amat = promote_to_arrays(n, 1, array_type, A...)
20✔
503
    # We have two methods for promote_to_array_type, one returning Matrix and
504
    # another one returning SparseMatrixCSC (in SparseArrays.jl). In the dense
505
    # case, we cannot call hvcat for the promoted UniformScalings because this
506
    # causes a stack overflow. In the sparse case, however, we cannot call
507
    # typed_hvcat because we need a sparse output.
508
    if array_type == Matrix
20✔
509
        return typed_hvcat(promote_eltype(Amat...), rows, Amat...)
9✔
510
    else
511
        return hvcat(rows, Amat...)
11✔
512
    end
513
end
514

515
## Matrix construction from UniformScaling
516
function Matrix{T}(s::UniformScaling, dims::Dims{2}) where {T}
11,028✔
517
    A = zeros(T, dims)
401,916,005✔
518
    v = T(s.λ)
14,120✔
519
    for i in diagind(dims...)
21,579✔
520
        @inbounds A[i] = v
492,026✔
521
    end
973,401✔
522
    return A
11,028✔
523
end
524
Matrix{T}(s::UniformScaling, m::Integer, n::Integer) where {T} = Matrix{T}(s, Dims((m, n)))
4,591✔
525
Matrix(s::UniformScaling, m::Integer, n::Integer) = Matrix(s, Dims((m, n)))
4,904✔
526
Matrix(s::UniformScaling, dims::Dims{2}) = Matrix{eltype(s)}(s, dims)
4,952✔
527
Array{T}(s::UniformScaling, dims::Dims{2}) where {T} = Matrix{T}(s, dims)
×
528
Array{T}(s::UniformScaling, m::Integer, n::Integer) where {T} = Matrix{T}(s, m, n)
2✔
529
Array(s::UniformScaling, m::Integer, n::Integer) = Matrix(s, m, n)
4✔
530
Array(s::UniformScaling, dims::Dims{2}) = Matrix(s, dims)
×
531

532
dot(A::AbstractMatrix, J::UniformScaling) = dot(tr(A), J.λ)
4✔
533
dot(J::UniformScaling, A::AbstractMatrix) = dot(J.λ, tr(A))
2✔
534

535
dot(x::AbstractVector, J::UniformScaling, y::AbstractVector) = dot(x, J.λ, y)
2✔
536
dot(x::AbstractVector, a::Number, y::AbstractVector) = sum(t -> dot(t[1], a, t[2]), zip(x, y))
2✔
537
dot(x::AbstractVector, a::Union{Real,Complex}, y::AbstractVector) = a*dot(x, y)
1✔
538

539
# muladd
540
Base.muladd(A::UniformScaling, B::UniformScaling, z::UniformScaling) =
1✔
541
    UniformScaling(A.λ * B.λ + z.λ)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc