@@ -87,32 +87,7 @@ default_svd_alg(A) = DivideAndConquer()
87
87
svd!(A; full::Bool = false, alg::Algorithm = default_svd_alg(A)) -> SVD
88
88
89
89
`svd!` is the same as [`svd`](@ref), but saves space by
90
- overwriting the input `A`, instead of creating a copy.
91
-
92
- # Examples
93
- ```jldoctest
94
- julia> A = [1. 0. 0. 0. 2.; 0. 0. 3. 0. 0.; 0. 0. 0. 0. 0.; 0. 2. 0. 0. 0.]
95
- 4×5 Array{Float64,2}:
96
- 1.0 0.0 0.0 0.0 2.0
97
- 0.0 0.0 3.0 0.0 0.0
98
- 0.0 0.0 0.0 0.0 0.0
99
- 0.0 2.0 0.0 0.0 0.0
100
-
101
- julia> F = svd!(A);
102
-
103
- julia> F.U * Diagonal(F.S) * F.Vt
104
- 4×5 Array{Float64,2}:
105
- 1.0 0.0 0.0 0.0 2.0
106
- 0.0 0.0 3.0 0.0 0.0
107
- 0.0 0.0 0.0 0.0 0.0
108
- 0.0 2.0 0.0 0.0 0.0
109
-
110
- julia> A
111
- 4×5 Array{Float64,2}:
112
- -2.23607 0.0 0.0 0.0 0.618034
113
- 0.0 -3.0 1.0 0.0 0.0
114
- 0.0 0.0 0.0 0.0 0.0
115
- 0.0 0.0 -2.0 0.0 0.0
90
+ overwriting the input `A`, instead of creating a copy. See documentation of [`svd`](@ref) for details.
116
91
```
117
92
"""
118
93
function svd! (A:: StridedMatrix{T} ; full:: Bool = false , alg:: Algorithm = default_svd_alg (A)) where T<: BlasFloat
@@ -161,25 +136,21 @@ Another (typically slower but more accurate) option is `alg = QRIteration()`.
161
136
162
137
# Examples
163
138
```jldoctest
164
- julia> A = [1. 0. 0. 0. 2.; 0. 0. 3. 0. 0.; 0. 0. 0. 0. 0.; 0. 2. 0. 0. 0.]
165
- 4×5 Array{Float64,2}:
166
- 1.0 0.0 0.0 0.0 2.0
167
- 0.0 0.0 3.0 0.0 0.0
168
- 0.0 0.0 0.0 0.0 0.0
169
- 0.0 2.0 0.0 0.0 0.0
139
+ julia> A = rand(4,3);
170
140
171
- julia> F = svd(A);
141
+ julia> F = svd(A); # Store the Factorization Object
172
142
173
- julia> F.U * Diagonal(F.S) * F.Vt
174
- 4×5 Array{Float64,2}:
175
- 1.0 0.0 0.0 0.0 2.0
176
- 0.0 0.0 3.0 0.0 0.0
177
- 0.0 0.0 0.0 0.0 0.0
178
- 0.0 2.0 0.0 0.0 0.0
143
+ julia> A ≈ F.U * Diagonal(F.S) * F.Vt
144
+ true
179
145
180
- julia> u, s, v = F; # destructuring via iteration
146
+ julia> U, S, V = F; # destructuring via iteration
181
147
182
- julia> u == F.U && s == F.S && v == F.V
148
+ julia> A ≈ U * Diagonal(S) * V'
149
+ true
150
+
151
+ julia> Uonly, = svd(A); # Store U only
152
+
153
+ julia> Uonly == U
183
154
true
184
155
```
185
156
"""
@@ -217,29 +188,6 @@ Base.propertynames(F::SVD, private::Bool=false) =
217
188
218
189
Return the singular values of `A`, saving space by overwriting the input.
219
190
See also [`svdvals`](@ref) and [`svd`](@ref).
220
-
221
- # Examples
222
- ```jldoctest
223
- julia> A = [1. 0. 0. 0. 2.; 0. 0. 3. 0. 0.; 0. 0. 0. 0. 0.; 0. 2. 0. 0. 0.]
224
- 4×5 Array{Float64,2}:
225
- 1.0 0.0 0.0 0.0 2.0
226
- 0.0 0.0 3.0 0.0 0.0
227
- 0.0 0.0 0.0 0.0 0.0
228
- 0.0 2.0 0.0 0.0 0.0
229
-
230
- julia> svdvals!(A)
231
- 4-element Array{Float64,1}:
232
- 3.0
233
- 2.23606797749979
234
- 2.0
235
- 0.0
236
-
237
- julia> A
238
- 4×5 Array{Float64,2}:
239
- -2.23607 0.0 0.0 0.0 0.618034
240
- 0.0 -3.0 1.0 0.0 0.0
241
- 0.0 0.0 0.0 0.0 0.0
242
- 0.0 0.0 -2.0 0.0 0.0
243
191
```
244
192
"""
245
193
svdvals! (A:: StridedMatrix{T} ) where {T<: BlasFloat } = isempty (A) ? zeros (real (T), 0 ) : LAPACK. gesdd! (' N' , A)[2 ]
@@ -409,41 +357,7 @@ Base.iterate(S::GeneralizedSVD, ::Val{:done}) = nothing
409
357
svd!(A, B) -> GeneralizedSVD
410
358
411
359
`svd!` is the same as [`svd`](@ref), but modifies the arguments
412
- `A` and `B` in-place, instead of making copies.
413
-
414
- # Examples
415
- ```jldoctest
416
- julia> A = [1. 0.; 0. -1.]
417
- 2×2 Array{Float64,2}:
418
- 1.0 0.0
419
- 0.0 -1.0
420
-
421
- julia> B = [0. 1.; 1. 0.]
422
- 2×2 Array{Float64,2}:
423
- 0.0 1.0
424
- 1.0 0.0
425
-
426
- julia> F = svd!(A, B);
427
-
428
- julia> F.U*F.D1*F.R0*F.Q'
429
- 2×2 Array{Float64,2}:
430
- 1.0 0.0
431
- 0.0 -1.0
432
-
433
- julia> F.V*F.D2*F.R0*F.Q'
434
- 2×2 Array{Float64,2}:
435
- 0.0 1.0
436
- 1.0 0.0
437
-
438
- julia> A
439
- 2×2 Array{Float64,2}:
440
- 1.41421 0.0
441
- 0.0 -1.41421
442
-
443
- julia> B
444
- 2×2 Array{Float64,2}:
445
- 1.0 -0.0
446
- 0.0 -1.0
360
+ `A` and `B` in-place, instead of making copies. See documentation of [`svd`](@ref) for details.
447
361
```
448
362
"""
449
363
function svd! (A:: StridedMatrix{T} , B:: StridedMatrix{T} ) where T<: BlasFloat
@@ -458,12 +372,11 @@ end
458
372
svd (A:: StridedMatrix{T} , B:: StridedMatrix{T} ) where {T<: BlasFloat } = svd! (copy (A),copy (B))
459
373
460
374
"""
375
+
461
376
svd(A, B) -> GeneralizedSVD
462
377
463
378
Compute the generalized SVD of `A` and `B`, returning a `GeneralizedSVD` factorization
464
- object `F`, such that `A = F.U*F.D1*F.R0*F.Q'` and `B = F.V*F.D2*F.R0*F.Q'`.
465
-
466
- For an M-by-N matrix `A` and P-by-N matrix `B`,
379
+ object `F` such that `[A;B] = [F.U * F.D1; F.V * F.D2] * F.R0 * F.Q'`
467
380
468
381
- `U` is a M-by-M orthogonal matrix,
469
382
- `V` is a P-by-P orthogonal matrix,
@@ -477,35 +390,36 @@ For an M-by-N matrix `A` and P-by-N matrix `B`,
477
390
478
391
Iterating the decomposition produces the components `U`, `V`, `Q`, `D1`, `D2`, and `R0`.
479
392
480
- The entries of `F.D1` and `F.D2` are related, as explained in the LAPACK
481
- documentation for the
482
- [generalized SVD](http://www.netlib.org/lapack/lug/node36.html) and the
483
- [xGGSVD3](http://www.netlib.org/lapack/explore-html/d6/db3/dggsvd3_8f.html)
484
- routine which is called underneath (in LAPACK 3.6.0 and newer).
393
+ The generalized SVD is used in applications such as when one wants to compare how much belongs
394
+ to `A` vs. how much belongs to `B`, as in human vs yeast genome, or signal vs noise, or between
395
+ clusters vs within clusters. (See Edelman and Wang for discussion: https://arxiv.org/abs/1901.00485)
396
+
397
+ It decomposes `[A; B]` into `[UC; VS]H`, where `[UC; VS]` is a natural orthogonal basis for the
398
+ column space of `[A; B]`, and `H = RQ'` is a natural non-orthogonal basis for the rowspace of `[A;B]`,
399
+ where the top rows are most closely attributed to the `A` matrix, and the bottom to the `B` matrix.
400
+ The multi-cosine/sine matrices `C` and `S` provide a multi-measure of how much `A` vs how much `B`,
401
+ and `U` and `V` provide directions in which these are measured.
485
402
486
403
# Examples
487
404
```jldoctest
488
- julia> A = [1. 0.; 0. -1.]
489
- 2×2 Array{Float64,2}:
490
- 1.0 0.0
491
- 0.0 -1.0
492
-
493
- julia> B = [0. 1.; 1. 0.]
494
- 2×2 Array{Float64,2}:
495
- 0.0 1.0
496
- 1.0 0.0
405
+ julia> A = randn(3,2); B=randn(4,2);
497
406
498
407
julia> F = svd(A, B);
499
408
500
- julia> F.U*F.D1*F.R0*F.Q'
501
- 2×2 Array{Float64,2}:
502
- 1.0 0.0
503
- 0.0 -1.0
409
+ julia> U,V,Q,C,S,R = F;
504
410
505
- julia> F.V*F.D2*F.R0*F.Q'
506
- 2×2 Array{Float64,2}:
507
- 0.0 1.0
508
- 1.0 0.0
411
+ julia> H = R*Q';
412
+
413
+ julia> [A; B] ≈ [U*C; V*S]*H
414
+ true
415
+
416
+ julia> [A; B] ≈ [F.U*F.D1; F.V*F.D2]*F.R0*F.Q'
417
+ true
418
+
419
+ julia> Uonly, = svd(A,B);
420
+
421
+ julia> U == Uonly
422
+ true
509
423
```
510
424
"""
511
425
function svd (A:: StridedMatrix{TA} , B:: StridedMatrix{TB} ) where {TA,TB}
582
496
Return the generalized singular values from the generalized singular value
583
497
decomposition of `A` and `B`, saving space by overwriting `A` and `B`.
584
498
See also [`svd`](@ref) and [`svdvals`](@ref).
585
-
586
- # Examples
587
- ```jldoctest
588
- julia> A = [1. 0.; 0. -1.]
589
- 2×2 Array{Float64,2}:
590
- 1.0 0.0
591
- 0.0 -1.0
592
-
593
- julia> B = [0. 1.; 1. 0.]
594
- 2×2 Array{Float64,2}:
595
- 0.0 1.0
596
- 1.0 0.0
597
-
598
- julia> svdvals!(A, B)
599
- 2-element Array{Float64,1}:
600
- 1.0
601
- 1.0
602
-
603
- julia> A
604
- 2×2 Array{Float64,2}:
605
- 1.41421 0.0
606
- 0.0 -1.41421
607
-
608
- julia> B
609
- 2×2 Array{Float64,2}:
610
- 1.0 -0.0
611
- 0.0 -1.0
612
499
```
613
500
"""
614
501
function svdvals! (A:: StridedMatrix{T} , B:: StridedMatrix{T} ) where T<: BlasFloat
0 commit comments