Mercurial > octave
comparison libinterp/corefcn/gsvd.cc @ 22235:63b41167ef1e
gsvd: new function imported from Octave-Forge linear-algebra package.
* libinterp/corefcn/gsvd.cc: New function to the interpreter. Imported
from the linear-algebra package.
* CmplxGSVD.cc, CmplxGSVD.h, dbleGSVD.cc, dbleGSVD.h: new classes
imported from the linear-algebra package to compute gsvd of Matrix
and ComplexMatrix.
* liboctave/operators/mx-defs.h, liboctave/operators/mx-ext.h: use new
classes.
* libinterp/corefcn/module.mk, liboctave/numeric/module.mk: Add to the
* scripts/help/__unimplemented__.m: Remove "gsvd" from list.
* doc/interpreter/linalg.txi: Add to manual.
build system.
* NEWS: Add function to list of new functions for 4.2.
author | Barbara Locsi <locsi.barbara@gmail.com> |
---|---|
date | Thu, 04 Aug 2016 07:50:31 +0200 |
parents | |
children | 065a44375723 |
comparison
equal
deleted
inserted
replaced
22234:66dd260512a4 | 22235:63b41167ef1e |
---|---|
1 // Copyright (C) 1996, 1997 John W. Eaton | |
2 // Copyright (C) 2006, 2010 Pascal Dupuis <Pascal.Dupuis@uclouvain.be> | |
3 // | |
4 // This program is free software; you can redistribute it and/or modify it under | |
5 // the terms of the GNU General Public License as published by the Free Software | |
6 // Foundation; either version 3 of the License, or (at your option) any later | |
7 // version. | |
8 // | |
9 // This program is distributed in the hope that it will be useful, but WITHOUT | |
10 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | |
12 // details. | |
13 // | |
14 // You should have received a copy of the GNU General Public License along with | |
15 // this program; if not, see <http://www.gnu.org/licenses/>. | |
16 | |
17 #ifdef HAVE_CONFIG_H | |
18 # include <config.h> | |
19 #endif | |
20 | |
21 #include "defun.h" | |
22 #include "error.h" | |
23 #include "gripes.h" | |
24 #include "pr-output.h" | |
25 #include "utils.h" | |
26 #include "ovl.h" | |
27 | |
28 #include "CmplxGSVD.h" | |
29 #include "dbleGSVD.h" | |
30 | |
31 DEFUN (gsvd, args, nargout, | |
32 doc: /* -*- texinfo -*- | |
33 @deftypefn {Loadable Function} {@var{s} =} gsvd (@var{a}, @var{b}) | |
34 @deftypefnx {Loadable Function} {[@var{u}, @var{v}, @var{c}, @var{s}, @var{x} [, @var{r}]] =} gsvd (@var{a}, @var{b}) | |
35 @cindex generalised singular value decomposition | |
36 Compute the generalised singular value decomposition of (@var{a}, @var{b}): | |
37 @iftex | |
38 @tex | |
39 $$ | |
40 U^H A X = [I 0; 0 C] [0 R] | |
41 V^H B X = [0 S; 0 0] [0 R] | |
42 C*C + S*S = eye(columns(A)) | |
43 I and 0 are padding matrices of suitable size | |
44 R is upper triangular | |
45 $$ | |
46 @end tex | |
47 @end iftex | |
48 @ifinfo | |
49 | |
50 @example | |
51 u' * a * x = [I 0; 0 c] * [0 r] | |
52 v' * b * x = [0 s; 0 0] * [0 r] | |
53 c * c + s * s = eye(columns(a)) | |
54 I and 0 are padding matrices of suitable size | |
55 r is upper triangular | |
56 @end example | |
57 @end ifinfo | |
58 | |
59 The function @code{gsvd} normally returns the vector of generalised singular | |
60 values | |
61 @iftex | |
62 @tex | |
63 diag(C)./diag(S). | |
64 @end tex | |
65 @end iftex | |
66 @ifinfo | |
67 diag(r)./diag(s). | |
68 @end ifinfo | |
69 If asked for five return values, it computes | |
70 @iftex | |
71 @tex | |
72 $U$, $V$, and $X$. | |
73 @end tex | |
74 @end iftex | |
75 @ifinfo | |
76 U, V, and X. | |
77 @end ifinfo | |
78 With a sixth output argument, it also returns | |
79 @iftex | |
80 @tex | |
81 R, | |
82 @end tex | |
83 @end iftex | |
84 @ifinfo | |
85 r, | |
86 @end ifinfo | |
87 The common upper triangular right term. Other authors, like S. Van Huffel, | |
88 define this transformation as the simulatenous diagonalisation of the | |
89 input matrices, this can be achieved by multiplying | |
90 @iftex | |
91 @tex | |
92 X | |
93 @end tex | |
94 @end iftex | |
95 @ifinfo | |
96 x | |
97 @end ifinfo | |
98 by the inverse of | |
99 @iftex | |
100 @tex | |
101 [I 0; 0 R]. | |
102 @end tex | |
103 @end iftex | |
104 @ifinfo | |
105 [I 0; 0 r]. | |
106 @end ifinfo | |
107 | |
108 For example, | |
109 | |
110 @example | |
111 gsvd (hilb (3), [1 2 3; 3 2 1]) | |
112 @end example | |
113 | |
114 @noindent | |
115 returns | |
116 | |
117 @example | |
118 ans = | |
119 | |
120 0.1055705 | |
121 0.0031759 | |
122 @end example | |
123 | |
124 @noindent | |
125 and | |
126 | |
127 @example | |
128 [u, v, c, s, x, r] = gsvd (hilb (3), [1 2 3; 3 2 1]) | |
129 @end example | |
130 | |
131 @noindent | |
132 returns | |
133 | |
134 @example | |
135 u = | |
136 | |
137 -0.965609 0.240893 0.097825 | |
138 -0.241402 -0.690927 -0.681429 | |
139 -0.096561 -0.681609 0.725317 | |
140 | |
141 v = | |
142 | |
143 -0.41974 0.90765 | |
144 -0.90765 -0.41974 | |
145 | |
146 c = | |
147 | |
148 0.10499 0.00000 | |
149 0.00000 0.00318 | |
150 | |
151 s = | |
152 0.99447 0.00000 | |
153 0.00000 0.99999 | |
154 x = | |
155 | |
156 0.408248 0.902199 0.139179 | |
157 -0.816497 0.429063 -0.386314 | |
158 0.408248 -0.044073 -0.911806 | |
159 | |
160 r = | |
161 -0.14093 -1.24345 0.43737 | |
162 0.00000 -3.90043 2.57818 | |
163 0.00000 0.00000 -2.52599 | |
164 | |
165 @end example | |
166 | |
167 The code is a wrapper to the corresponding Lapack dggsvd and zggsvd routines. | |
168 | |
169 @end deftypefn */) | |
170 { | |
171 octave_value_list retval; | |
172 | |
173 int nargin = args.length (); | |
174 | |
175 if (nargin < 2 || nargin > 2 || (nargout > 1 && (nargout < 5 || nargout > 6))) | |
176 { | |
177 print_usage (); | |
178 return retval; | |
179 } | |
180 | |
181 octave_value argA = args(0), argB = args(1); | |
182 | |
183 octave_idx_type nr = argA.rows (); | |
184 octave_idx_type nc = argA.columns (); | |
185 | |
186 // octave_idx_type nn = argB.rows (); | |
187 octave_idx_type np = argB.columns (); | |
188 | |
189 if (nr == 0 || nc == 0) | |
190 { | |
191 if (nargout == 5) | |
192 retval = ovl (identity_matrix (nc, nc), identity_matrix (nc, nc), | |
193 Matrix (nr, nc), identity_matrix (nr, nr), | |
194 identity_matrix (nr, nr)); | |
195 else if (nargout == 6) | |
196 retval = ovl (identity_matrix (nc, nc), identity_matrix (nc, nc), | |
197 Matrix (nr, nc), identity_matrix (nr, nr), | |
198 identity_matrix (nr, nr), | |
199 identity_matrix (nr, nr)); | |
200 else | |
201 retval = ovl (Matrix (0, 1)); | |
202 } | |
203 else | |
204 { | |
205 if ((nc != np)) | |
206 { | |
207 print_usage (); | |
208 return retval; | |
209 } | |
210 | |
211 GSVD::type type = ((nargout == 0 || nargout == 1) | |
212 ? GSVD::sigma_only | |
213 : (nargout > 5) ? GSVD::std : GSVD::economy ); | |
214 | |
215 if (argA.is_real_type () && argB.is_real_type ()) | |
216 { | |
217 Matrix tmpA = argA.matrix_value (); | |
218 Matrix tmpB = argB.matrix_value (); | |
219 | |
220 if (! error_state) | |
221 { | |
222 if (tmpA.any_element_is_inf_or_nan ()) | |
223 { | |
224 error ("gsvd: cannot take GSVD of matrix containing Inf or NaN values"); | |
225 return retval; | |
226 } | |
227 | |
228 if (tmpB.any_element_is_inf_or_nan ()) | |
229 { | |
230 error ("gsvd: cannot take GSVD of matrix containing Inf or NaN values"); | |
231 return retval; | |
232 } | |
233 | |
234 GSVD result (tmpA, tmpB, type); | |
235 | |
236 // DiagMatrix sigma = result.singular_values (); | |
237 | |
238 if (nargout == 0 || nargout == 1) | |
239 { | |
240 DiagMatrix sigA = result.singular_values_A (); | |
241 DiagMatrix sigB = result.singular_values_B (); | |
242 for (int i = sigA.rows() - 1; i >=0; i--) | |
243 sigA.dgxelem(i) /= sigB.dgxelem(i); | |
244 retval = ovl (sigA.diag()); | |
245 } | |
246 else | |
247 { | |
248 if (nargout > 5) | |
249 retval = ovl (result.left_singular_matrix_A (), | |
250 result.left_singular_matrix_B (), | |
251 result.singular_values_A (), | |
252 result.singular_values_B (), | |
253 result.right_singular_matrix (), | |
254 result.R_matrix ()); | |
255 else | |
256 retval = ovl (result.left_singular_matrix_A (), | |
257 result.left_singular_matrix_B (), | |
258 result.singular_values_A (), | |
259 result.singular_values_B (), | |
260 result.right_singular_matrix ()); | |
261 } | |
262 } | |
263 } | |
264 else if (argA.is_complex_type () || argB.is_complex_type ()) | |
265 { | |
266 ComplexMatrix ctmpA = argA.complex_matrix_value (); | |
267 ComplexMatrix ctmpB = argB.complex_matrix_value (); | |
268 | |
269 if (! error_state) | |
270 { | |
271 if (ctmpA.any_element_is_inf_or_nan ()) | |
272 { | |
273 error ("gsvd: cannot take GSVD of matrix containing Inf or NaN values"); | |
274 return retval; | |
275 } | |
276 if (ctmpB.any_element_is_inf_or_nan ()) | |
277 { | |
278 error ("gsvd: cannot take GSVD of matrix containing Inf or NaN values"); | |
279 return retval; | |
280 } | |
281 | |
282 ComplexGSVD result (ctmpA, ctmpB, type); | |
283 | |
284 // DiagMatrix sigma = result.singular_values (); | |
285 | |
286 if (nargout == 0 || nargout == 1) | |
287 { | |
288 DiagMatrix sigA = result.singular_values_A (); | |
289 DiagMatrix sigB = result.singular_values_B (); | |
290 for (int i = sigA.rows() - 1; i >=0; i--) | |
291 sigA.dgxelem(i) /= sigB.dgxelem(i); | |
292 retval = ovl (sigA.diag()); | |
293 } | |
294 else | |
295 { | |
296 if (nargout > 5) | |
297 retval = ovl (result.left_singular_matrix_A (), | |
298 result.left_singular_matrix_B (), | |
299 result.singular_values_A (), | |
300 result.singular_values_B (), | |
301 result.right_singular_matrix (), | |
302 result.R_matrix ()); | |
303 else | |
304 retval = ovl (result.left_singular_matrix_A (), | |
305 result.left_singular_matrix_B (), | |
306 result.singular_values_A (), | |
307 result.singular_values_B (), | |
308 result.right_singular_matrix ()); | |
309 } | |
310 } | |
311 } | |
312 else | |
313 { | |
314 gripe_wrong_type_arg ("gsvd", argA); | |
315 gripe_wrong_type_arg ("gsvd", argB); | |
316 return retval; | |
317 } | |
318 } | |
319 | |
320 return retval; | |
321 } | |
322 | |
323 /* | |
324 %# a few tests for gsvd.m | |
325 %!shared A, A0, B, B0, U, V, C, S, X, R, D1, D2 | |
326 | |
327 %! A0=randn(5, 3); B0=diag([1 2 4]); | |
328 %! A = A0; B = B0; | |
329 %! # disp('Full rank, 5x3 by 3x3 matrices'); | |
330 %! # disp([rank(A) rank(B) rank([A' B'])]); | |
331 %! [U, V, C, S, X, R] = gsvd(A, B); | |
332 %! D1 = zeros(5, 3); D1(1:3, 1:3) = C; | |
333 %! D2 = S; | |
334 %!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6) | |
335 %!assert(norm((U'*A*X)-D1*R) <= 1e-6) | |
336 %!assert(norm((V'*B*X)-D2*R) <= 1e-6) | |
337 | |
338 %! # disp('A 5x3 full rank, B 3x3 rank deficient'); | |
339 %! B(2, 2) = 0; | |
340 %! [U, V, C, S, X, R] = gsvd(A, B); | |
341 %! D1 = zeros(5, 3); D1(1, 1) = 1; D1(2:3, 2:3) = C; | |
342 %! D2 = [zeros(2, 1) S; zeros(1, 3)]; | |
343 %!assert(norm(diag(C).^2+diag(S).^2 - ones(2, 1)) <= 1e-6) | |
344 %!assert(norm((U'*A*X)-D1*R) <= 1e-6) | |
345 %!assert(norm((V'*B*X)-D2*R) <= 1e-6) | |
346 | |
347 %! # disp('A 5x3 rank deficient, B 3x3 full rank'); | |
348 %! B = B0; | |
349 %! A(:, 3) = 2*A(:, 1) - A(:, 2); | |
350 %! [U, V, C, S, X, R] = gsvd(A, B); | |
351 %! D1 = zeros(5, 3); D1(1:3, 1:3) = C; | |
352 %! D2 = S; | |
353 %!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6) | |
354 %!assert(norm((U'*A*X)-D1*R) <= 1e-6) | |
355 %!assert(norm((V'*B*X)-D2*R) <= 1e-6) | |
356 | |
357 %! # disp("A 5x3, B 3x3, [A' B'] rank deficient"); | |
358 %! B(:, 3) = 2*B(:, 1) - B(:, 2); | |
359 %! [U, V, C, S, X, R] = gsvd(A, B); | |
360 %! D1 = zeros(5, 2); D1(1:2, 1:2) = C; | |
361 %! D2 = [S; zeros(1, 2)]; | |
362 %!assert(norm(diag(C).^2+diag(S).^2 - ones(2, 1)) <= 1e-6) | |
363 %!assert(norm((U'*A*X)-D1*[zeros(2, 1) R]) <= 1e-6) | |
364 %!assert(norm((V'*B*X)-D2*[zeros(2, 1) R]) <= 1e-6) | |
365 | |
366 %! # now, A is 3x5 | |
367 %! A = A0.'; B0=diag([1 2 4 8 16]); B = B0; | |
368 %! # disp('Full rank, 3x5 by 5x5 matrices'); | |
369 %! # disp([rank(A) rank(B) rank([A' B'])]); | |
370 | |
371 %! [U, V, C, S, X, R] = gsvd(A, B); | |
372 %! D1 = [C zeros(3,2)]; | |
373 %! D2 = [S zeros(3,2); zeros(2, 3) eye(2)]; | |
374 %!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6) | |
375 %!assert(norm((U'*A*X)-D1*R) <= 1e-6) | |
376 %!assert(norm((V'*B*X)-D2*R) <= 1e-6) | |
377 | |
378 %! # disp('A 5x3 full rank, B 5x5 rank deficient'); | |
379 %! B(2, 2) = 0; | |
380 %! # disp([rank(A) rank(B) rank([A' B'])]); | |
381 | |
382 %! [U, V, C, S, X, R] = gsvd(A, B); | |
383 %! D1 = zeros(3, 5); D1(1, 1) = 1; D1(2:3, 2:3) = C; | |
384 %! D2 = zeros(5, 5); D2(1:2, 2:3) = S; D2(3:4, 4:5) = eye(2); | |
385 %!assert(norm(diag(C).^2+diag(S).^2 - ones(2, 1)) <= 1e-6) | |
386 %!assert(norm((U'*A*X)-D1*R) <= 1e-6) | |
387 %!assert(norm((V'*B*X)-D2*R) <= 1e-6) | |
388 | |
389 %! # disp('A 3x5 rank deficient, B 5x5 full rank'); | |
390 %! B = B0; | |
391 %! A(3, :) = 2*A(1, :) - A(2, :); | |
392 %! # disp([rank(A) rank(B) rank([A' B'])]); | |
393 %! [U, V, C, S, X, R] = gsvd(A, B); | |
394 %! D1 = zeros(3, 5); D1(1:3, 1:3) = C; | |
395 %! D2 = zeros(5, 5); D2(1:3, 1:3) = S; D2(4:5, 4:5) = eye(2); | |
396 %!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6) | |
397 %!assert(norm((U'*A*X)-D1*R) <= 1e-6) | |
398 %!assert(norm((V'*B*X)-D2*R) <= 1e-6) | |
399 | |
400 %! # disp("A 5x3, B 5x5, [A' B'] rank deficient"); | |
401 %! A = A0.'; B = B0.'; | |
402 %! A(:, 3) = 2*A(:, 1) - A(:, 2); | |
403 %! B(:, 3) = 2*B(:, 1) - B(:, 2); | |
404 %! # disp([rank(A) rank(B) rank([A' B'])]); | |
405 %! [U, V, C, S, X, R]=gsvd(A, B); | |
406 %! D1 = zeros(3, 4); D1(1:3, 1:3) = C; | |
407 %! D2 = eye(4); D2(1:3, 1:3) = S; D2(5,:) = 0; | |
408 %!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6) | |
409 %!assert(norm((U'*A*X)-D1*[zeros(4, 1) R]) <= 1e-6) | |
410 %!assert(norm((V'*B*X)-D2*[zeros(4, 1) R]) <= 1e-6) | |
411 | |
412 %! A0 = A0 +j * randn(5, 3); B0 = B0=diag([1 2 4]) + j*diag([4 -2 -1]); | |
413 %! A = A0; B = B0; | |
414 %! # disp('Complex: Full rank, 5x3 by 3x3 matrices'); | |
415 %! # disp([rank(A) rank(B) rank([A' B'])]); | |
416 %! [U, V, C, S, X, R] = gsvd(A, B); | |
417 %! D1 = zeros(5, 3); D1(1:3, 1:3) = C; | |
418 %! D2 = S; | |
419 %!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6) | |
420 %!assert(norm((U'*A*X)-D1*R) <= 1e-6) | |
421 %!assert(norm((V'*B*X)-D2*R) <= 1e-6) | |
422 | |
423 %! # disp('Complex: A 5x3 full rank, B 3x3 rank deficient'); | |
424 %! B(2, 2) = 0; | |
425 %! # disp([rank(A) rank(B) rank([A' B'])]); | |
426 | |
427 %! [U, V, C, S, X, R] = gsvd(A, B); | |
428 %! D1 = zeros(5, 3); D1(1, 1) = 1; D1(2:3, 2:3) = C; | |
429 %! D2 = [zeros(2, 1) S; zeros(1, 3)]; | |
430 %!assert(norm(diag(C).^2+diag(S).^2 - ones(2, 1)) <= 1e-6) | |
431 %!assert(norm((U'*A*X)-D1*R) <= 1e-6) | |
432 %!assert(norm((V'*B*X)-D2*R) <= 1e-6) | |
433 | |
434 %! # disp('Complex: A 5x3 rank deficient, B 3x3 full rank'); | |
435 %! B = B0; | |
436 %! A(:, 3) = 2*A(:, 1) - A(:, 2); | |
437 %! # disp([rank(A) rank(B) rank([A' B'])]); | |
438 %! [U, V, C, S, X, R] = gsvd(A, B); | |
439 %! D1 = zeros(5, 3); D1(1:3, 1:3) = C; | |
440 %! D2 = S; | |
441 %!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6) | |
442 %!assert(norm((U'*A*X)-D1*R) <= 1e-6) | |
443 %!assert(norm((V'*B*X)-D2*R) <= 1e-6) | |
444 | |
445 %! # disp("Complex: A 5x3, B 3x3, [A' B'] rank deficient"); | |
446 %! B(:, 3) = 2*B(:, 1) - B(:, 2); | |
447 %! # disp([rank(A) rank(B) rank([A' B'])]); | |
448 %! [U, V, C, S, X, R] = gsvd(A, B); | |
449 %! D1 = zeros(5, 2); D1(1:2, 1:2) = C; | |
450 %! D2 = [S; zeros(1, 2)]; | |
451 %!assert(norm(diag(C).^2+diag(S).^2 - ones(2, 1)) <= 1e-6) | |
452 %!assert(norm((U'*A*X)-D1*[zeros(2, 1) R]) <= 1e-6) | |
453 %!assert(norm((V'*B*X)-D2*[zeros(2, 1) R]) <= 1e-6) | |
454 | |
455 %! # now, A is 3x5 | |
456 %! A = A0.'; B0=diag([1 2 4 8 16])+j*diag([-5 4 -3 2 -1]); | |
457 %! B = B0; | |
458 %! # disp('Complex: Full rank, 3x5 by 5x5 matrices'); | |
459 %! # disp([rank(A) rank(B) rank([A' B'])]); | |
460 %! [U, V, C, S, X, R] = gsvd(A, B); | |
461 %! D1 = [C zeros(3,2)]; | |
462 %! D2 = [S zeros(3,2); zeros(2, 3) eye(2)]; | |
463 %!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6) | |
464 %!assert(norm((U'*A*X)-D1*R) <= 1e-6) | |
465 %!assert(norm((V'*B*X)-D2*R) <= 1e-6) | |
466 | |
467 %! # disp('Complex: A 5x3 full rank, B 5x5 rank deficient'); | |
468 %! B(2, 2) = 0; | |
469 %! # disp([rank(A) rank(B) rank([A' B'])]); | |
470 %! [U, V, C, S, X, R] = gsvd(A, B); | |
471 %! D1 = zeros(3, 5); D1(1, 1) = 1; D1(2:3, 2:3) = C; | |
472 %! D2 = zeros(5,5); D2(1:2, 2:3) = S; D2(3:4, 4:5) = eye(2); | |
473 %!assert(norm(diag(C).^2+diag(S).^2 - ones(2, 1)) <= 1e-6) | |
474 %!assert(norm((U'*A*X)-D1*R) <= 1e-6) | |
475 %!assert(norm((V'*B*X)-D2*R) <= 1e-6) | |
476 | |
477 %! # disp('Complex: A 3x5 rank deficient, B 5x5 full rank'); | |
478 %! B = B0; | |
479 %! A(3, :) = 2*A(1, :) - A(2, :); | |
480 %! # disp([rank(A) rank(B) rank([A' B'])]); | |
481 %! [U, V, C, S, X, R] = gsvd(A, B); | |
482 %! D1 = zeros(3, 5); D1(1:3, 1:3) = C; | |
483 %! D2 = zeros(5,5); D2(1:3, 1:3) = S; D2(4:5, 4:5) = eye(2); | |
484 %!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6) | |
485 %!assert(norm((U'*A*X)-D1*R) <= 1e-6) | |
486 %!assert(norm((V'*B*X)-D2*R) <= 1e-6) | |
487 | |
488 %! # disp("Complex: A 5x3, B 5x5, [A' B'] rank deficient"); | |
489 %! A = A0.'; B = B0.'; | |
490 %! A(:, 3) = 2*A(:, 1) - A(:, 2); | |
491 %! B(:, 3) = 2*B(:, 1) - B(:, 2); | |
492 %! # disp([rank(A) rank(B) rank([A' B'])]); | |
493 %! [U, V, C, S, X, R]=gsvd(A, B); | |
494 %! D1 = zeros(3, 4); D1(1:3, 1:3) = C; | |
495 %! D2 = eye(4); D2(1:3, 1:3) = S; D2(5,:) = 0; | |
496 %!assert(norm(diag(C).^2+diag(S).^2 - ones(3, 1)) <= 1e-6) | |
497 %!assert(norm((U'*A*X)-D1*[zeros(4, 1) R]) <= 1e-6) | |
498 %!assert(norm((V'*B*X)-D2*[zeros(4, 1) R]) <= 1e-6) | |
499 | |
500 */ |