Mercurial > octave
changeset 22576:cdbf931c2024
maint: merge stable to default.
author | Carnë Draug <carandraug@octave.org> |
---|---|
date | Sat, 01 Oct 2016 20:35:36 +0100 |
parents | 17f6ed063c69 (current diff) 726f32d9fd92 (diff) |
children | 98eeed41f372 |
files | libinterp/corefcn/__gsvd__.cc scripts/linear-algebra/gsvd.m |
diffstat | 8 files changed, 481 insertions(+), 458 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/corefcn/__gsvd__.cc Fri Sep 30 17:45:22 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,350 +0,0 @@ -// Copyright (C) 2016 Barbara Lócsi -// Copyright (C) 2006, 2010 Pascal Dupuis <Pascal.Dupuis@uclouvain.be> -// Copyright (C) 1996, 1997 John W. Eaton -// -// This program is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free Software -// Foundation; either version 3 of the License, or (at your option) any later -// version. -// -// This program is distributed in the hope that it will be useful, but WITHOUT -// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more -// details. -// -// You should have received a copy of the GNU General Public License along with -// this program; if not, see <http://www.gnu.org/licenses/>. - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#include "dMatrix.h" -#include "CMatrix.h" -#include "dDiagMatrix.h" -#include "gsvd.h" - -#include "defun.h" -#include "defun-int.h" -#include "error.h" -#include "errwarn.h" -#include "utils.h" -#include "ovl.h" -#include "ov.h" - - -template <typename T> -static typename octave::math::gsvd<T>::Type -gsvd_type (int nargout) -{ - return ((nargout == 0 || nargout == 1) - ? octave::math::gsvd<T>::Type::sigma_only - : (nargout > 5) ? octave::math::gsvd<T>::Type::std - : octave::math::gsvd<T>::Type::economy); -} - -// Named like this to avoid conflicts with the gsvd class. -template <typename T> -static octave_value_list -function_gsvd (const T& A, const T& B, const octave_idx_type nargout) -{ - octave::math::gsvd<T> result (A, B, gsvd_type<T> (nargout)); - - octave_value_list retval (nargout); - if (nargout < 2) - { - DiagMatrix sigA = result.singular_values_A (); - DiagMatrix sigB = result.singular_values_B (); - for (int i = sigA.rows () - 1; i >= 0; i--) - sigA.dgxelem(i) /= sigB.dgxelem(i); - retval(0) = sigA.diag (); - } - else - { - retval(0) = result.left_singular_matrix_A (); - retval(1) = result.left_singular_matrix_B (); - if (nargout > 2) - retval(2) = result.right_singular_matrix (); - if (nargout > 3) - retval(3) = result.singular_values_A (); - if (nargout > 4) - retval(4) = result.singular_values_B (); - if (nargout > 5) - retval(5) = result.R_matrix (); - } - return retval; -} - -DEFUN (__gsvd__, args, nargout, - doc: /* -*- texinfo -*- -@deftypefn {} {@var{s} =} __gsvd__ (@var{a}, @var{b}) -@deftypefnx {} {[@var{u}, @var{v}, @var{x}, @var{c}, @var{s}, @var{r}] =} __gsvd__ (@var{a}, @var{b}) -Undocumented internal function. -@end deftypefn */) -{ - if (args.length () != 2) - print_usage (); - - octave_value_list retval; - - octave_value argA = args(0); - octave_value argB = args(1); - - octave_idx_type nr = argA.rows (); - octave_idx_type nc = argA.columns (); - - octave_idx_type np = argB.columns (); - - // This "special" case should be handled in the gsvd class, not here - if (nr == 0 || nc == 0) - { - retval = octave_value_list (nargout); - if (nargout < 2) // S = gsvd (A, B) - retval(0) = Matrix (0, 1); - else // [U, V, X, C, S, R] = gsvd (A, B) - { - retval(0) = identity_matrix (nc, nc); - retval(1) = identity_matrix (nc, nc); - if (nargout > 2) - retval(2) = identity_matrix (nr, nr); - if (nargout > 3) - retval(3) = Matrix (nr, nc); - if (nargout > 4) - retval(4) = identity_matrix (nr, nr); - if (nargout > 5) - retval(5) = identity_matrix (nr, nr); - } - } - else - { - if (nc != np) - print_usage (); - - if (argA.is_real_type () && argB.is_real_type ()) - { - Matrix tmpA = argA.matrix_value (); - Matrix tmpB = argB.matrix_value (); - - // FIXME: This code is still using error_state - if (! error_state) - { - if (tmpA.any_element_is_inf_or_nan ()) - error ("gsvd: B cannot have Inf or NaN values"); - if (tmpB.any_element_is_inf_or_nan ()) - error ("gsvd: B cannot have Inf or NaN values"); - - retval = function_gsvd (tmpA, tmpB, nargout); - } - } - else if (argA.is_complex_type () || argB.is_complex_type ()) - { - ComplexMatrix ctmpA = argA.complex_matrix_value (); - ComplexMatrix ctmpB = argB.complex_matrix_value (); - - if (! error_state) - { - if (ctmpA.any_element_is_inf_or_nan ()) - error ("gsvd: A cannot have Inf or NaN values"); - if (ctmpB.any_element_is_inf_or_nan ()) - error ("gsvd: B cannot have Inf or NaN values"); - - retval = function_gsvd (ctmpA, ctmpB, nargout); - } - } - else - error ("gsvd: A and B must be real or complex matrices"); - } - - return retval; -} - -/* -## FIXME: All tests are commented out for the 4.2.0 release. -## The m-file gsvd.m needs to be replaced with C++ code that achieves Matlab -## compatible outputs, and the BIST tests need to be updated to reflect the new -## outputs. - -## a few tests for gsvd.m -%!#shared A, A0, B, B0, U, V, C, S, X, R, D1, D2 -%! A0 = randn (5, 3); -%! B0 = diag ([1 2 4]); -%! A = A0; -%! B = B0; - -## A (5x3) and B (3x3) are full rank -%!#test -%! [U, V, X, C, S, R] = gsvd (A, B); -%! D1 = zeros (5, 3); D1(1:3, 1:3) = C; -%! D2 = S; -%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); -%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); -%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); - -## A: 5x3 full rank, B: 3x3 rank deficient -%!#test -%! B(2, 2) = 0; -%! [U, V, X, C, S, R] = gsvd (A, B); -%! D1 = zeros (5, 3); D1(1, 1) = 1; D1(2:3, 2:3) = C; -%! D2 = [zeros(2, 1) S; zeros(1, 3)]; -%! assert (norm (diag (C).^2 + diag (S).^2 - ones (2, 1)) <= 1e-6); -%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); -%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); - -## A: 5x3 rank deficient, B: 3x3 full rank -%!#test -%! B = B0; -%! A(:, 3) = 2*A(:, 1) - A(:, 2); -%! [U, V, X, C, S, R] = gsvd (A, B); -%! D1 = zeros(5, 3); D1(1:3, 1:3) = C; -%! D2 = S; -%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); -%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); -%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); - -## A and B are both rank deficient -%!#test -%! B(:, 3) = 2*B(:, 1) - B(:, 2); -%! [U, V, X, C, S, R] = gsvd (A, B); -%! D1 = zeros(5, 2); D1(1:2, 1:2) = C; -%! D2 = [S; zeros(1, 2)]; -%! assert (norm (diag (C).^2 + diag (S).^2 - ones (2, 1)) <= 1e-6); -%! assert (norm ((U'*A*X) - D1*[zeros(2, 1) R]) <= 1e-6); -%! assert (norm ((V'*B*X) - D2*[zeros(2, 1) R]) <= 1e-6); - -## A (now 3x5) and B (now 5x5) are full rank -%!#test -%! A = A0.'; -%! B0 = diag ([1 2 4 8 16]); -%! B = B0; -%! [U, V, X, C, S, R] = gsvd (A, B); -%! D1 = [C zeros(3,2)]; -%! D2 = [S zeros(3,2); zeros(2, 3) eye(2)]; -%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); -%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); -%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); - -## A: 3x5 full rank, B: 5x5 rank deficient -%!#test -%! B(2, 2) = 0; -%! [U, V, X, C, S, R] = gsvd (A, B); -%! D1 = zeros(3, 5); D1(1, 1) = 1; D1(2:3, 2:3) = C; -%! D2 = zeros(5, 5); D2(1:2, 2:3) = S; D2(3:4, 4:5) = eye (2); -%! assert (norm (diag (C).^2 + diag (S).^2 - ones (2, 1)) <= 1e-6); -%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); -%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); - -## A: 3x5 rank deficient, B: 5x5 full rank -%!#test -%! B = B0; -%! A(3, :) = 2*A(1, :) - A(2, :); -%! [U, V, X, C, S, R] = gsvd (A, B); -%! D1 = zeros (3, 5); D1(1:3, 1:3) = C; -%! D2 = zeros (5, 5); D2(1:3, 1:3) = S; D2(4:5, 4:5) = eye (2); -%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); -%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); -%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); - -## A and B are both rank deficient -%!#test -%! A = A0.'; B = B0.'; -%! A(:, 3) = 2*A(:, 1) - A(:, 2); -%! B(:, 3) = 2*B(:, 1) - B(:, 2); -%! [U, V, X, C, S, R]=gsvd (A, B); -%! D1 = zeros(3, 4); D1(1:3, 1:3) = C; -%! D2 = eye (4); D2(1:3, 1:3) = S; D2(5,:) = 0; -%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); -%! assert (norm ((U'*A*X) - D1*[zeros(4, 1) R]) <= 1e-6); -%! assert (norm ((V'*B*X) - D2*[zeros(4, 1) R]) <= 1e-6); - -## A: 5x3 complex full rank, B: 3x3 complex full rank -%!#test -%! A0 = A0 + j*randn (5, 3); -%! B0 = diag ([1 2 4]) + j*diag ([4 -2 -1]); -%! A = A0; -%! B = B0; -%! [U, V, X, C, S, R] = gsvd (A, B); -%! D1 = zeros(5, 3); D1(1:3, 1:3) = C; -%! D2 = S; -%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); -%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); -%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); - -## A: 5x3 complex full rank, B: 3x3 complex rank deficient -%!#test -%! B(2, 2) = 0; -%! [U, V, X, C, S, R] = gsvd (A, B); -%! D1 = zeros(5, 3); D1(1, 1) = 1; D1(2:3, 2:3) = C; -%! D2 = [zeros(2, 1) S; zeros(1, 3)]; -%! assert (norm (diag (C).^2 + diag (S).^2 - ones (2, 1)) <= 1e-6); -%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); -%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); - -## A: 5x3 complex rank deficient, B: 3x3 complex full rank -%!#test -%! B = B0; -%! A(:, 3) = 2*A(:, 1) - A(:, 2); -%! [U, V, X, C, S, R] = gsvd (A, B); -%! D1 = zeros(5, 3); D1(1:3, 1:3) = C; -%! D2 = S; -%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); -%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); -%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); - -## A (5x3) and B (3x3) are both complex rank deficient -%!#test -%! B(:, 3) = 2*B(:, 1) - B(:, 2); -%! [U, V, X, C, S, R] = gsvd (A, B); -%! D1 = zeros(5, 2); D1(1:2, 1:2) = C; -%! D2 = [S; zeros(1, 2)]; -%! assert (norm (diag (C).^2 + diag (S).^2 - ones (2, 1)) <= 1e-6); -%! assert (norm ((U'*A*X) - D1*[zeros(2, 1) R]) <= 1e-6); -%! assert (norm ((V'*B*X) - D2*[zeros(2, 1) R]) <= 1e-6); - -## A (now 3x5) complex and B (now 5x5) complex are full rank -## now, A is 3x5 -%!#test -%! A = A0.'; -%! B0 = diag ([1 2 4 8 16]) + j*diag ([-5 4 -3 2 -1]); -%! B = B0; -%! [U, V, X, C, S, R] = gsvd (A, B); -%! D1 = [C zeros(3,2)]; -%! D2 = [S zeros(3,2); zeros(2, 3) eye(2)]; -%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); -%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); -%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); - -## A: 3x5 complex full rank, B: 5x5 complex rank deficient -%!#test -%! B(2, 2) = 0; -%! [U, V, X, C, S, R] = gsvd (A, B); -%! D1 = zeros(3, 5); D1(1, 1) = 1; D1(2:3, 2:3) = C; -%! D2 = zeros(5,5); D2(1:2, 2:3) = S; D2(3:4, 4:5) = eye (2); -%! assert (norm (diag (C).^2 + diag (S).^2 - ones (2, 1)) <= 1e-6); -%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); -%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); - -## A: 3x5 complex rank deficient, B: 5x5 complex full rank -%!#test -%! B = B0; -%! A(3, :) = 2*A(1, :) - A(2, :); -%! [U, V, X, C, S, R] = gsvd (A, B); -%! D1 = zeros(3, 5); D1(1:3, 1:3) = C; -%! D2 = zeros(5,5); D2(1:3, 1:3) = S; D2(4:5, 4:5) = eye (2); -%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); -%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); -%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); - -## A and B are both complex rank deficient -%!#test -%! A = A0.'; -%! B = B0.'; -%! A(:, 3) = 2*A(:, 1) - A(:, 2); -%! B(:, 3) = 2*B(:, 1) - B(:, 2); -%! [U, V, X, C, S, R] = gsvd (A, B); -%! D1 = zeros(3, 4); D1(1:3, 1:3) = C; -%! D2 = eye (4); D2(1:3, 1:3) = S; D2(5,:) = 0; -%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); -%! assert (norm ((U'*A*X) - D1*[zeros(4, 1) R]) <= 1e-6); -%! assert (norm ((V'*B*X) - D2*[zeros(4, 1) R]) <= 1e-6); -*/ -
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/corefcn/gsvd.cc Sat Oct 01 20:35:36 2016 +0100 @@ -0,0 +1,465 @@ +// Copyright (C) 2016 Barbara Lócsi +// Copyright (C) 2006, 2010 Pascal Dupuis <Pascal.Dupuis@uclouvain.be> +// Copyright (C) 1996, 1997 John W. Eaton +// +// This program is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation; either version 3 of the License, or (at your option) any later +// version. +// +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +// details. +// +// You should have received a copy of the GNU General Public License along with +// this program; if not, see <http://www.gnu.org/licenses/>. + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "dMatrix.h" +#include "CMatrix.h" +#include "dDiagMatrix.h" +#include "gsvd.h" + +#include "defun.h" +#include "defun-int.h" +#include "error.h" +#include "errwarn.h" +#include "utils.h" +#include "ovl.h" +#include "ov.h" + + +template <typename T> +static typename octave::math::gsvd<T>::Type +gsvd_type (int nargout) +{ + return ((nargout == 0 || nargout == 1) + ? octave::math::gsvd<T>::Type::sigma_only + : (nargout > 5) ? octave::math::gsvd<T>::Type::std + : octave::math::gsvd<T>::Type::economy); +} + +// Named like this to avoid conflicts with the gsvd class. +template <typename T> +static octave_value_list +function_gsvd (const T& A, const T& B, const octave_idx_type nargout) +{ + octave::math::gsvd<T> result (A, B, gsvd_type<T> (nargout)); + + octave_value_list retval (nargout); + if (nargout < 2) + { + DiagMatrix sigA = result.singular_values_A (); + DiagMatrix sigB = result.singular_values_B (); + for (int i = sigA.rows () - 1; i >= 0; i--) + sigA.dgxelem(i) /= sigB.dgxelem(i); + retval(0) = sigA.diag (); + } + else + { + retval(0) = result.left_singular_matrix_A (); + retval(1) = result.left_singular_matrix_B (); + if (nargout > 2) + retval(2) = result.right_singular_matrix (); + if (nargout > 3) + retval(3) = result.singular_values_A (); + if (nargout > 4) + retval(4) = result.singular_values_B (); + if (nargout > 5) + retval(5) = result.R_matrix (); + } + return retval; +} + +DEFUN (gsvd, args, nargout, + doc: /* -*- texinfo -*- +@deftypefn {} {@var{s} =} gsvd (@var{a}, @var{b}) +@deftypefnx {} {[@var{u}, @var{v}, @var{x}, @var{c}, @var{s}, @var{r}] =} gsvd (@var{a}, @var{b}) +@cindex generalized singular value decomposition +Compute the generalized singular value decomposition of (@var{a}, @var{b}): +@tex +$$ + U^H A X = [I 0; 0 C] [0 R] + V^H B X = [0 S; 0 0] [0 R] + C*C + S*S = eye (columns (A)) + I and 0 are padding matrices of suitable size + R is upper triangular +$$ +@end tex +@ifinfo + +@example +@group +u' * a * x = [I 0; 0 c] * [0 r] +v' * b * x = [0 s; 0 0] * [0 r] +c * c + s * s = eye (columns (a)) +I and 0 are padding matrices of suitable size +r is upper triangular +@end group +@end example + +@end ifinfo + +The function @code{gsvd} normally returns the vector of generalized singular +values +@tex +diag (C) ./ diag (S). +@end tex +@ifinfo +diag (r) ./ diag (s). +@end ifinfo +If asked for five return values, it computes +@tex +$U$, $V$, and $X$. +@end tex +@ifinfo +U, V, and X. +@end ifinfo +With a sixth output argument, it also returns +@tex +R, +@end tex +@ifinfo +r, +@end ifinfo +The common upper triangular right term. Other authors, like +@nospell{S. Van Huffel}, define this transformation as the simultaneous +diagonalization of the input matrices, this can be achieved by multiplying +@tex +X +@end tex +@ifinfo +x +@end ifinfo +by the inverse of +@tex +[I 0; 0 R]. +@end tex +@ifinfo +[I 0; 0 r]. +@end ifinfo + +For example, + +@example +gsvd (hilb (3), [1 2 3; 3 2 1]) + +@result{} + 0.1055705 + 0.0031759 +@end example + +@noindent +and + +@example +[u, v, c, s, x, r] = gsvd (hilb (3), [1 2 3; 3 2 1]) +@result{} + +u = + + -0.965609 0.240893 0.097825 + -0.241402 -0.690927 -0.681429 + -0.096561 -0.681609 0.725317 + +v = + + -0.41974 0.90765 + -0.90765 -0.41974 + +x = + + 0.408248 0.902199 0.139179 + -0.816497 0.429063 -0.386314 + 0.408248 -0.044073 -0.911806 + +c = + + 0.10499 0.00000 + 0.00000 0.00318 + +s = + 0.99447 0.00000 + 0.00000 0.99999 + +r = + -0.14093 -1.24345 0.43737 + 0.00000 -3.90043 2.57818 + 0.00000 0.00000 -2.52599 + +@end example + +The code is a wrapper to the corresponding @sc{lapack} dggsvd and zggsvd +routines. + +@end deftypefn */) +{ + if (args.length () != 2) + print_usage (); + + octave_value_list retval; + + octave_value argA = args(0); + octave_value argB = args(1); + + octave_idx_type nr = argA.rows (); + octave_idx_type nc = argA.columns (); + + octave_idx_type np = argB.columns (); + + // This "special" case should be handled in the gsvd class, not here + if (nr == 0 || nc == 0) + { + retval = octave_value_list (nargout); + if (nargout < 2) // S = gsvd (A, B) + retval(0) = Matrix (0, 1); + else // [U, V, X, C, S, R] = gsvd (A, B) + { + retval(0) = identity_matrix (nc, nc); + retval(1) = identity_matrix (nc, nc); + if (nargout > 2) + retval(2) = identity_matrix (nr, nr); + if (nargout > 3) + retval(3) = Matrix (nr, nc); + if (nargout > 4) + retval(4) = identity_matrix (nr, nr); + if (nargout > 5) + retval(5) = identity_matrix (nr, nr); + } + } + else + { + if (nc != np) + print_usage (); + + if (argA.is_real_type () && argB.is_real_type ()) + { + Matrix tmpA = argA.matrix_value (); + Matrix tmpB = argB.matrix_value (); + + // FIXME: This code is still using error_state + if (! error_state) + { + if (tmpA.any_element_is_inf_or_nan ()) + error ("gsvd: B cannot have Inf or NaN values"); + if (tmpB.any_element_is_inf_or_nan ()) + error ("gsvd: B cannot have Inf or NaN values"); + + retval = function_gsvd (tmpA, tmpB, nargout); + } + } + else if (argA.is_complex_type () || argB.is_complex_type ()) + { + ComplexMatrix ctmpA = argA.complex_matrix_value (); + ComplexMatrix ctmpB = argB.complex_matrix_value (); + + if (! error_state) + { + if (ctmpA.any_element_is_inf_or_nan ()) + error ("gsvd: A cannot have Inf or NaN values"); + if (ctmpB.any_element_is_inf_or_nan ()) + error ("gsvd: B cannot have Inf or NaN values"); + + retval = function_gsvd (ctmpA, ctmpB, nargout); + } + } + else + { + // Actually, can't tell which arg is at fault + err_wrong_type_arg ("gsvd", argA); + //err_wrong_type_arg ("gsvd", argB); + } + } + + return retval; +} + +/* +## a few tests for gsvd.m +%!shared A, A0, B, B0, U, V, C, S, X, R, D1, D2 +%! A0 = randn (5, 3); +%! B0 = diag ([1 2 4]); +%! A = A0; +%! B = B0; + +## A (5x3) and B (3x3) are full rank +%!test +%! [U, V, X, C, S, R] = gsvd (A, B); +%! D1 = zeros (5, 3); D1(1:3, 1:3) = C; +%! D2 = S; +%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); +%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); +%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); + +## A: 5x3 full rank, B: 3x3 rank deficient +%!test +%! B(2, 2) = 0; +%! [U, V, X, C, S, R] = gsvd (A, B); +%! D1 = zeros (5, 3); D1(1, 1) = 1; D1(2:3, 2:3) = C; +%! D2 = [zeros(2, 1) S; zeros(1, 3)]; +%! assert (norm (diag (C).^2 + diag (S).^2 - ones (2, 1)) <= 1e-6); +%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); +%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); + +## A: 5x3 rank deficient, B: 3x3 full rank +%!test +%! B = B0; +%! A(:, 3) = 2*A(:, 1) - A(:, 2); +%! [U, V, X, C, S, R] = gsvd (A, B); +%! D1 = zeros(5, 3); D1(1:3, 1:3) = C; +%! D2 = S; +%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); +%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); +%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); + +## A and B are both rank deficient +%!test +%! B(:, 3) = 2*B(:, 1) - B(:, 2); +%! [U, V, X, C, S, R] = gsvd (A, B); +%! D1 = zeros(5, 2); D1(1:2, 1:2) = C; +%! D2 = [S; zeros(1, 2)]; +%! assert (norm (diag (C).^2 + diag (S).^2 - ones (2, 1)) <= 1e-6); +%! assert (norm ((U'*A*X) - D1*[zeros(2, 1) R]) <= 1e-6); +%! assert (norm ((V'*B*X) - D2*[zeros(2, 1) R]) <= 1e-6); + +## A (now 3x5) and B (now 5x5) are full rank +%!test +%! A = A0.'; +%! B0 = diag ([1 2 4 8 16]); +%! B = B0; +%! [U, V, X, C, S, R] = gsvd (A, B); +%! D1 = [C zeros(3,2)]; +%! D2 = [S zeros(3,2); zeros(2, 3) eye(2)]; +%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); +%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); +%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); + +## A: 3x5 full rank, B: 5x5 rank deficient +%!test +%! B(2, 2) = 0; +%! [U, V, X, C, S, R] = gsvd (A, B); +%! D1 = zeros(3, 5); D1(1, 1) = 1; D1(2:3, 2:3) = C; +%! D2 = zeros(5, 5); D2(1:2, 2:3) = S; D2(3:4, 4:5) = eye (2); +%! assert (norm (diag (C).^2 + diag (S).^2 - ones (2, 1)) <= 1e-6); +%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); +%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); + +## A: 3x5 rank deficient, B: 5x5 full rank +%!test +%! B = B0; +%! A(3, :) = 2*A(1, :) - A(2, :); +%! [U, V, X, C, S, R] = gsvd (A, B); +%! D1 = zeros (3, 5); D1(1:3, 1:3) = C; +%! D2 = zeros (5, 5); D2(1:3, 1:3) = S; D2(4:5, 4:5) = eye (2); +%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); +%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); +%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); + +## A and B are both rank deficient +%!test +%! A = A0.'; B = B0.'; +%! A(:, 3) = 2*A(:, 1) - A(:, 2); +%! B(:, 3) = 2*B(:, 1) - B(:, 2); +%! [U, V, X, C, S, R]=gsvd (A, B); +%! D1 = zeros(3, 4); D1(1:3, 1:3) = C; +%! D2 = eye (4); D2(1:3, 1:3) = S; D2(5,:) = 0; +%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); +%! assert (norm ((U'*A*X) - D1*[zeros(4, 1) R]) <= 1e-6); +%! assert (norm ((V'*B*X) - D2*[zeros(4, 1) R]) <= 1e-6); + +## A: 5x3 complex full rank, B: 3x3 complex full rank +%!test +%! A0 = A0 + j*randn (5, 3); +%! B0 = diag ([1 2 4]) + j*diag ([4 -2 -1]); +%! A = A0; +%! B = B0; +%! [U, V, X, C, S, R] = gsvd (A, B); +%! D1 = zeros(5, 3); D1(1:3, 1:3) = C; +%! D2 = S; +%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); +%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); +%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); + +## A: 5x3 complex full rank, B: 3x3 complex rank deficient +%!test +%! B(2, 2) = 0; +%! [U, V, X, C, S, R] = gsvd (A, B); +%! D1 = zeros(5, 3); D1(1, 1) = 1; D1(2:3, 2:3) = C; +%! D2 = [zeros(2, 1) S; zeros(1, 3)]; +%! assert (norm (diag (C).^2 + diag (S).^2 - ones (2, 1)) <= 1e-6); +%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); +%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); + +## A: 5x3 complex rank deficient, B: 3x3 complex full rank +%!test +%! B = B0; +%! A(:, 3) = 2*A(:, 1) - A(:, 2); +%! [U, V, X, C, S, R] = gsvd (A, B); +%! D1 = zeros(5, 3); D1(1:3, 1:3) = C; +%! D2 = S; +%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); +%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); +%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); + +## A (5x3) and B (3x3) are both complex rank deficient +%!test +%! B(:, 3) = 2*B(:, 1) - B(:, 2); +%! [U, V, X, C, S, R] = gsvd (A, B); +%! D1 = zeros(5, 2); D1(1:2, 1:2) = C; +%! D2 = [S; zeros(1, 2)]; +%! assert (norm (diag (C).^2 + diag (S).^2 - ones (2, 1)) <= 1e-6); +%! assert (norm ((U'*A*X) - D1*[zeros(2, 1) R]) <= 1e-6); +%! assert (norm ((V'*B*X) - D2*[zeros(2, 1) R]) <= 1e-6); + +## A (now 3x5) complex and B (now 5x5) complex are full rank +## now, A is 3x5 +%!test +%! A = A0.'; +%! B0 = diag ([1 2 4 8 16]) + j*diag ([-5 4 -3 2 -1]); +%! B = B0; +%! [U, V, X, C, S, R] = gsvd (A, B); +%! D1 = [C zeros(3,2)]; +%! D2 = [S zeros(3,2); zeros(2, 3) eye(2)]; +%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); +%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); +%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); + +## A: 3x5 complex full rank, B: 5x5 complex rank deficient +%!test +%! B(2, 2) = 0; +%! [U, V, X, C, S, R] = gsvd (A, B); +%! D1 = zeros(3, 5); D1(1, 1) = 1; D1(2:3, 2:3) = C; +%! D2 = zeros(5,5); D2(1:2, 2:3) = S; D2(3:4, 4:5) = eye (2); +%! assert (norm (diag (C).^2 + diag (S).^2 - ones (2, 1)) <= 1e-6); +%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); +%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); + +## A: 3x5 complex rank deficient, B: 5x5 complex full rank +%!test +%! B = B0; +%! A(3, :) = 2*A(1, :) - A(2, :); +%! [U, V, X, C, S, R] = gsvd (A, B); +%! D1 = zeros(3, 5); D1(1:3, 1:3) = C; +%! D2 = zeros(5,5); D2(1:3, 1:3) = S; D2(4:5, 4:5) = eye (2); +%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); +%! assert (norm ((U'*A*X) - D1*R) <= 1e-6); +%! assert (norm ((V'*B*X) - D2*R) <= 1e-6); + +## A and B are both complex rank deficient +%!test +%! A = A0.'; +%! B = B0.'; +%! A(:, 3) = 2*A(:, 1) - A(:, 2); +%! B(:, 3) = 2*B(:, 1) - B(:, 2); +%! [U, V, X, C, S, R] = gsvd (A, B); +%! D1 = zeros(3, 4); D1(1:3, 1:3) = C; +%! D2 = eye (4); D2(1:3, 1:3) = S; D2(5,:) = 0; +%! assert (norm (diag (C).^2 + diag (S).^2 - ones (3, 1)) <= 1e-6); +%! assert (norm ((U'*A*X) - D1*[zeros(4, 1) R]) <= 1e-6); +%! assert (norm ((V'*B*X) - D2*[zeros(4, 1) R]) <= 1e-6); +*/ +
--- a/libinterp/corefcn/module.mk Fri Sep 30 17:45:22 2016 -0700 +++ b/libinterp/corefcn/module.mk Sat Oct 01 20:35:36 2016 +0100 @@ -118,7 +118,6 @@ libinterp/corefcn/__contourc__.cc \ libinterp/corefcn/__dispatch__.cc \ libinterp/corefcn/__dsearchn__.cc \ - libinterp/corefcn/__gsvd__.cc \ libinterp/corefcn/__ichol__.cc \ libinterp/corefcn/__ilu__.cc \ libinterp/corefcn/__lin_interpn__.cc \ @@ -174,6 +173,7 @@ libinterp/corefcn/gl2ps-print.cc \ libinterp/corefcn/graphics.cc \ libinterp/corefcn/gripes.cc \ + libinterp/corefcn/gsvd.cc \ libinterp/corefcn/hash.cc \ libinterp/corefcn/help.cc \ libinterp/corefcn/hess.cc \
--- a/scripts/linear-algebra/gsvd.m Fri Sep 30 17:45:22 2016 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,100 +0,0 @@ -## Copyright (C) 2016 Rik Wehbring -## -## This file is part of Octave. -## -## Octave is free software; you can redistribute it and/or modify it -## under the terms of the GNU General Public License as published by -## the Free Software Foundation; either version 3 of the License, or (at -## your option) any later version. -## -## Octave is distributed in the hope that it will be useful, but -## WITHOUT ANY WARRANTY; without even the implied warranty of -## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -## General Public License for more details. -## -## You should have received a copy of the GNU General Public License -## along with Octave; see the file COPYING. If not, see -## <http://www.gnu.org/licenses/>. - -## -*- texinfo -*- -## @deftypefn {} {@var{S} =} gsvd (@var{A}, @var{B}) -## @deftypefnx {} {[@var{U}, @var{V}, @var{X}, @var{C}, @var{S}] =} gsvd (@var{A}, @var{B}) -## Compute the generalized singular value decomposition of (@var{A}, @var{B}): -## -## @tex -## $$ A = U C X^\dagger $$ -## $$ B = V S X^\dagger $$ -## $$ C^\dagger C + S^\dagger S = eye (columns (A)) $$ -## @end tex -## @ifnottex -## -## @example -## @group -## A = U*C*X' -## B = V*S*X' -## C'*C + S'*S = eye (columns (A)) -## @end group -## @end example -## -## @end ifnottex -## -## The function @code{gsvd} normally returns the vector of generalized singular -## values -## @tex -## $$ \sqrt{{{diag (C^\dagger C)} \over {diag (S^\dagger S)}}} $$ -## @end tex -## @ifnottex -## @code{sqrt (diag (C'*C) ./ diag (S'*S))}. -## @end ifnottex -## If asked for five return values, it also computes -## @tex -## $U$, $V$, and $X$. -## @end tex -## @ifnottex -## U, V, and X. -## @end ifnottex -## -## The code is a wrapper to the corresponding @sc{lapack} dggsvd and zggsvd -## routines. -## -## @seealso{svd} -## @end deftypefn - -## FIXME: This m-file is a wrapper around __gsvd__ in libinterp/corefcn. -## It was put in place strictly for the 4.2.0 release in order to achieve -## Matlab-compatible output for the gsvd function. Eventually the C++ code -## needs to be updated to reflect what is being done in this m-file and then -## this m-file should be deleted. - -function [U, V, X, C, S] = gsvd (A, B, econ = false) - - if (nargin < 2 || nargin > 3) - print_usage (); - endif - - if (nargin == 3) - warning ('gsvd: "economy" option is not yet implemented'); - endif - - if (nargout <= 1) - U = __gsvd__ (A, B); - else - [U, V, X, C, S, R] = __gsvd__ (A, B); - X = (R / X)'; - [m, n] = size (A); - if (m > n) - C = [C; zeros(m-n, n)]; - elseif (m < n) - C = [C, zeros(m, n-m)]; - S0 = S; - S = eye (n); - S(1:m, 1:m) = S0; - endif - endif - -endfunction - - -## FIXME: All BIST tests are in the C++ file __gsvd__.cc. They are currently -## not run because they have not been updated to reflect the actual expected -## output.
--- a/scripts/linear-algebra/module.mk Fri Sep 30 17:45:22 2016 -0700 +++ b/scripts/linear-algebra/module.mk Sat Oct 01 20:35:36 2016 +0100 @@ -9,7 +9,6 @@ scripts/linear-algebra/cross.m \ scripts/linear-algebra/duplication_matrix.m \ scripts/linear-algebra/expm.m \ - scripts/linear-algebra/gsvd.m \ scripts/linear-algebra/housh.m \ scripts/linear-algebra/isbanded.m \ scripts/linear-algebra/isdefinite.m \
--- a/scripts/plot/util/print.m Fri Sep 30 17:45:22 2016 -0700 +++ b/scripts/plot/util/print.m Sat Oct 01 20:35:36 2016 +0100 @@ -160,7 +160,9 @@ ## ## @item fig ## XFig. For the Gnuplot graphics toolkit, the additional options -## @option{-textspecial} or @option{-textnormal} can be used to control whether the special flag should be set for the text in the figure. (default is @option{-textnormal}) +## @option{-textspecial} or @option{-textnormal} can be used to control +## whether the special flag should be set for the text in the figure. +## (default is @option{-textnormal}) ## ## @item gif ## GIF image (only available for the Gnuplot graphics toolkit)
--- a/scripts/plot/util/private/__gnuplot_print__.m Fri Sep 30 17:45:22 2016 -0700 +++ b/scripts/plot/util/private/__gnuplot_print__.m Sat Oct 01 20:35:36 2016 +0100 @@ -115,7 +115,8 @@ local_drawnow ([opts.devopt " " gp_opts], opts.name, opts); case {"cairolatex", "epscairo", "epscairolatex", ... "epscairolatexstandalone", "pdfcairo", "pdfcairolatex", ... - "pdfcairolatexstandalone", "pngcairo"} + "pdfcairolatexstandalone", "pngcairo", ... + "pdflatexstandalone", "pdflatex"} term = opts.devopt; if (strfind (term, "standalone")) gp_opts = sprintf ("standalone %s", gp_opts); @@ -124,9 +125,10 @@ if (strfind (term, "epscairolatex")) gp_opts = sprintf ("eps %s", gp_opts); term = strrep (term, "epscairolatex", "cairolatex"); - elseif (strfind (term, "pdfcairolatex")) + elseif (strfind (term, "pdfcairolatex") || strfind (term, "pdflatex")) gp_opts = sprintf ("pdf %s", gp_opts); term = strrep (term, "pdfcairolatex", "cairolatex"); + term = strrep (term, "pdflatex", "cairolatex"); endif if (__gnuplot_has_terminal__ (term)) local_drawnow ([term " " gp_opts], opts.name, opts); @@ -273,7 +275,8 @@ endif case {"cairolatex", "epscairo", "epscairolatex", ... "epscairolatexstandalone", "pdfcairo", "pdfcairolatex", ... - "pdfcairolatexstandalone", "pngcairo"} + "pdfcairolatexstandalone", "pngcairo", ... + "pdflatexstandalone", "pdflatex"} if (! isempty (opts.font) && ! isempty (opts.fontsize)) f = sprintf ('font "%s,%d"', opts.font, opts.fontsize); elseif (! isempty (opts.font))
--- a/scripts/plot/util/private/__print_parse_opts__.m Fri Sep 30 17:45:22 2016 -0700 +++ b/scripts/plot/util/private/__print_parse_opts__.m Sat Oct 01 20:35:36 2016 +0100 @@ -228,7 +228,9 @@ "pstex", "tiff", "tiffn" "tikz", "pcxmono", ... "pcx24b", "pcx256", "pcx16", "pgm", "pgmraw", ... "ppm", "ppmraw", "pdflatex", "texdraw", ... - "pdfcairo", "pngcairo", "pstricks", ... + "epscairo", "pdfcairo", "pngcairo", "cairolatex", ... + "pdfcairolatex", "pdfcairolatexstandalone", ... + "epscairolatex", "epscairolatexstandalone", "pstricks", ... "epswrite", "eps2write", "pswrite", "ps2write", "pdfwrite"}; suffixes = {"ai", "cdr", "fig", "png", "jpg", ... @@ -240,7 +242,9 @@ "ps", "tiff", "tiff", "tikz", "pcx", ... "pcx", "pcx", "pcx", "pgm", "pgm", ... "ppm", "ppm", "tex", "tex", ... - "pdf", "png", "tex", ... + "eps", "pdf", "png", "tex", ... + "tex", "tex", ... + "tex", "tex", "tex", ... "eps", "eps", "ps", "ps", "pdf"}; if (isfigure (arg_st.figure))