Mercurial > octave
changeset 22595:acfb81e6992a
maint: merge stable to default
author | Carlo de Falco <carlo.defalco@polimi.it> |
---|---|
date | Thu, 06 Oct 2016 07:36:59 +0200 |
parents | 354b7a6e642c (diff) b8d525710075 (current diff) |
children | f812283c4367 |
files | scripts/ode/private/integrate_const.m scripts/ode/private/integrate_n_steps.m scripts/ode/private/ode_struct_value_check.m |
diffstat | 13 files changed, 1061 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Thu Oct 06 07:13:24 2016 +0200 +++ b/NEWS Thu Oct 06 07:36:59 2016 +0200 @@ -1,3 +1,11 @@ +Summary of important user-visible changes for version 4.4: +--------------------------------------------------------- + + ** Other new functions added in 4.4: + + gsvd + + Summary of important user-visible changes for version 4.2: ---------------------------------------------------------
--- a/configure.ac Thu Oct 06 07:13:24 2016 +0200 +++ b/configure.ac Thu Oct 06 07:36:59 2016 +0200 @@ -19,14 +19,14 @@ ### <http://www.gnu.org/licenses/>. AC_PREREQ([2.63]) -AC_INIT([GNU Octave], [4.2.0-rc2], [http://octave.org/bugs.html], [octave]) +AC_INIT([GNU Octave], [4.3.0+], [http://octave.org/bugs.html], [octave]) dnl Note that the version number is duplicated here and in AC_INIT dnl because AC_INIT requires it to be static, not computed from dnl shell variables. OCTAVE_MAJOR_VERSION=4 -OCTAVE_MINOR_VERSION=2 -OCTAVE_PATCH_VERSION=0-rc2 +OCTAVE_MINOR_VERSION=3 +OCTAVE_PATCH_VERSION=0+ dnl PACKAGE_VERSION is set by the AC_INIT VERSION arg OCTAVE_VERSION="$PACKAGE_VERSION"
--- a/doc/interpreter/linalg.txi Thu Oct 06 07:13:24 2016 +0200 +++ b/doc/interpreter/linalg.txi Thu Oct 06 07:36:59 2016 +0200 @@ -108,6 +108,8 @@ @DOCSTRING(givens) +@DOCSTRING(gsvd) + @DOCSTRING(planerot) @DOCSTRING(inv)
--- a/libinterp/corefcn/data.cc Thu Oct 06 07:13:24 2016 +0200 +++ b/libinterp/corefcn/data.cc Thu Oct 06 07:36:59 2016 +0200 @@ -3549,6 +3549,49 @@ return retval; } +/* +%!error <undefined> 1+Infj +%!error <undefined> 1+Infi + +%!test <31974> +%! assert (Inf + Inf*i, complex (Inf, Inf)) +%! +%! assert (1 + Inf*i, complex (1, Inf)) +%! assert (1 + Inf*j, complex (1, Inf)) +%! +%! ## whitespace should not affect parsing +%! assert (1+Inf*i, complex (1, Inf)) +%! assert (1+Inf*j, complex (1, Inf)) +%! +%! assert (NaN*j, complex (0, NaN)) +%! +%! assert (Inf * 4j, complex (0, Inf)) + +%!test <31974> +%! x = Inf; +%! assert (x * j, complex (0, Inf)) +%! j = complex (0, 1); +%! assert (Inf * j, complex (0, Inf)) + +%!test <31974> +%! exp = complex (zeros (2, 2), Inf (2, 2)); +%! assert (Inf (2, 2) * j, exp) +%! assert (Inf (2, 2) .* j, exp) +%! assert (Inf * (ones (2, 2) * j), exp) +%! assert (Inf (2, 2) .* (ones (2, 2) * j), exp) + +%!test <31974> +%! assert ([Inf; 0] * [i, 0], complex ([NaN NaN; 0 0], [Inf NaN; 0 0])) +%! assert ([Inf, 0] * [i; 0], complex (NaN, Inf)) +%! assert ([Inf, 0] .* [i, 0], complex ([0 0], [Inf 0])) + +%!test <31974> +%! m = @(x, y) x * y; +%! d = @(x, y) x / y; +%! assert (m (Inf, i), complex (0, +Inf)) +%! assert (d (Inf, i), complex (0, -Inf)) +*/ + DEFUN (isreal, args, , doc: /* -*- texinfo -*- @deftypefn {} {} isreal (@var{x})
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/corefcn/gsvd.cc Thu Oct 06 07:36:59 2016 +0200 @@ -0,0 +1,402 @@ +// 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}] =} gsvd (@var{A}, @var{B}) +@deftypefnx {} {[@var{U}, @var{V}, @var{X}, @var{C}, @var{S}] =} gsvd (@var{A}, @var{B}, 0) +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 just 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$, $X$, and $C$. +@end tex +@ifnottex +U, V, X, and C. +@end ifnottex + +If the optional third input is present, @code{gsvd} constructs the +"economy-sized" decomposition where the number of columns of @var{U}, @var{V} +and the number of rows of @var{C}, @var{S} is less than or equal to the number +of columns of @var{A}. This option is not yet implemented. + +Programming Note: the code is a wrapper to the corresponding @sc{lapack} dggsvd +and zggsvd routines. + +@seealso{svd} +@end deftypefn */) +{ + int nargin = args.length (); + + if (nargin < 2 || nargin > 3) + print_usage (); + else if (nargin == 3) + warning ("gsvd: economy-sized decomposition is not yet implemented, returning full decomposition"); + + 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 (); + + // FIXME: 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 (); + + // FIXME: Remove when interface to gsvd single class has been written + if (argA.is_single_type () && argB.is_single_type ()) + warning ("gsvd: no implementation for single matrices, converting to double"); + + if (argA.is_real_type () && argB.is_real_type ()) + { + Matrix tmpA = argA.xmatrix_value ("gsvd: A must be a real or complex matrix"); + Matrix tmpB = argB.xmatrix_value ("gsvd: B must be a real or complex matrix"); + + if (tmpA.any_element_is_inf_or_nan ()) + error ("gsvd: A 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.xcomplex_matrix_value ("gsvd: A must be a real or complex matrix"); + ComplexMatrix ctmpB = argB.xcomplex_matrix_value ("gsvd: B must be a real or complex matrix"); + + 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; +} + +/* + +## Basic test of decomposition +%!test <48807> +%! A = reshape (1:15,5,3); +%! B = magic (3); +%! [U,V,X,C,S] = gsvd (A,B); +%! assert (U*C*X', A, 50*eps); +%! assert (V*S*X', B, 50*eps); +%! S0 = gsvd (A, B); +%! S1 = svd (A / B); +%! assert (S0, S1, 10*eps); + +## 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 <48807> +%! [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 <48807> +%! 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 <48807> +%! 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 <48807> +%! 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 <48807> +%! 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 <48807> +%! 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 <48807> +%! 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 <48807> +%! 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 <48807> +%! 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 <48807> +%! 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 <48807> +%! 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 <48807> +%! 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 <48807> +%! 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 <48807> +%! 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 <48807> +%! 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 <48807> +%! 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 Thu Oct 06 07:13:24 2016 +0200 +++ b/libinterp/corefcn/module.mk Thu Oct 06 07:36:59 2016 +0200 @@ -173,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 \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liboctave/numeric/gsvd.cc Thu Oct 06 07:36:59 2016 +0200 @@ -0,0 +1,371 @@ +// Copyright (C) 2016 Barbara Lócsi +// Copyright (C) 2006 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 <vector> + +#include "gsvd.h" + +#include "lo-error.h" +#include "lo-lapack-proto.h" +#include "dMatrix.h" +#include "fMatrix.h" +#include "CMatrix.h" +#include "fCMatrix.h" +#include "dDiagMatrix.h" +#include "fDiagMatrix.h" + +namespace octave +{ + namespace math + { + template <> + void + gsvd<Matrix>::ggsvd (char& jobu, char& jobv, char& jobq, + octave_idx_type m, octave_idx_type n, + octave_idx_type p, + octave_idx_type& k, octave_idx_type& l, + double *tmp_dataA, octave_idx_type m1, + double *tmp_dataB, octave_idx_type p1, Matrix& alpha, + Matrix& beta, double *u, octave_idx_type nrow_u, + double *v, octave_idx_type nrow_v, double *q, + octave_idx_type nrow_q, + Matrix& work, octave_idx_type* iwork, + octave_idx_type& info) + { + F77_XFCN (dggsvd, DGGSVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + F77_CONST_CHAR_ARG2 (&jobq, 1), + m, n, p, k, l, tmp_dataA, m1, + tmp_dataB, p1, alpha.fortran_vec (), + beta.fortran_vec (), u, nrow_u, + v, nrow_v, q, nrow_q, work.fortran_vec (), + iwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); + } + + template <> + void + gsvd<FloatMatrix>::ggsvd (char& jobu, char& jobv, char& jobq, + octave_idx_type m, octave_idx_type n, + octave_idx_type p, + octave_idx_type& k, octave_idx_type& l, + float *tmp_dataA, octave_idx_type m1, + float *tmp_dataB, octave_idx_type p1, + FloatMatrix& alpha, FloatMatrix& beta, float *u, + octave_idx_type nrow_u, float *v, + octave_idx_type nrow_v, float *q, + octave_idx_type nrow_q, FloatMatrix& work, + octave_idx_type* iwork, octave_idx_type& info) + { + F77_XFCN (sggsvd, SGGSVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + F77_CONST_CHAR_ARG2 (&jobq, 1), + m, n, p, k, l, tmp_dataA, m1, + tmp_dataB, p1, alpha.fortran_vec (), + beta.fortran_vec (), u, nrow_u, + v, nrow_v, q, nrow_q, work.fortran_vec (), + iwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); + } + + template <> + void + gsvd<ComplexMatrix>::ggsvd (char& jobu, char& jobv, char& jobq, + octave_idx_type m, octave_idx_type n, + octave_idx_type p, octave_idx_type& k, + octave_idx_type& l, Complex *tmp_dataA, + octave_idx_type m1, Complex *tmp_dataB, + octave_idx_type p1, Matrix& alpha, + Matrix& beta, Complex *u, + octave_idx_type nrow_u, + Complex *v, octave_idx_type nrow_v, Complex *q, + octave_idx_type nrow_q, ComplexMatrix& work, + octave_idx_type* iwork, octave_idx_type& info) + { + Matrix rwork(2*n, 1); + F77_XFCN (zggsvd, ZGGSVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + F77_CONST_CHAR_ARG2 (&jobq, 1), + m, n, p, k, l, F77_DBLE_CMPLX_ARG (tmp_dataA), + m1, F77_DBLE_CMPLX_ARG (tmp_dataB), p1, + alpha.fortran_vec (), beta.fortran_vec (), + F77_DBLE_CMPLX_ARG (u), nrow_u, + F77_DBLE_CMPLX_ARG (v), nrow_v, + F77_DBLE_CMPLX_ARG (q), nrow_q, + F77_DBLE_CMPLX_ARG (work.fortran_vec ()), + rwork.fortran_vec (), iwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); + } + + template <> + void + gsvd<FloatComplexMatrix>::ggsvd (char& jobu, char& jobv, char& jobq, + octave_idx_type m, octave_idx_type n, + octave_idx_type p, octave_idx_type& k, + octave_idx_type& l, + FloatComplex *tmp_dataA, + octave_idx_type m1, + FloatComplex *tmp_dataB, + octave_idx_type p1, FloatMatrix& alpha, + FloatMatrix& beta, FloatComplex *u, + octave_idx_type nrow_u, FloatComplex *v, + octave_idx_type nrow_v, FloatComplex *q, + octave_idx_type nrow_q, + FloatComplexMatrix& work, + octave_idx_type* iwork, + octave_idx_type& info) + { + FloatMatrix rwork(2*n, 1); + F77_XFCN (cggsvd, CGGSVD, (F77_CONST_CHAR_ARG2 (&jobu, 1), + F77_CONST_CHAR_ARG2 (&jobv, 1), + F77_CONST_CHAR_ARG2 (&jobq, 1), + m, n, p, k, l, F77_CMPLX_ARG (tmp_dataA), m1, + F77_CMPLX_ARG (tmp_dataB), p1, + alpha.fortran_vec (), beta.fortran_vec (), + F77_CMPLX_ARG (u), nrow_u, + F77_CMPLX_ARG (v), nrow_v, + F77_CMPLX_ARG (q), nrow_q, + F77_CMPLX_ARG (work.fortran_vec ()), + rwork.fortran_vec (), iwork, info + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1) + F77_CHAR_ARG_LEN (1))); + } + + template <typename T> + T + gsvd<T>::left_singular_matrix_A (void) const + { + if (type == gsvd::Type::sigma_only) + { + (*current_liboctave_error_handler) + ("gsvd: U not computed because type == gsvd::sigma_only"); + return T (); + } + else + return left_smA; + } + + template <typename T> + T + gsvd<T>::left_singular_matrix_B (void) const + { + if (type == gsvd::Type::sigma_only) + { + (*current_liboctave_error_handler) + ("gsvd: V not computed because type == gsvd::sigma_only"); + return T (); + } + else + return left_smB; + } + + template <typename T> + T + gsvd<T>::right_singular_matrix (void) const + { + if (type == gsvd::Type::sigma_only) + { + (*current_liboctave_error_handler) + ("gsvd: X not computed because type == gsvd::sigma_only"); + return T (); + } + else + return right_sm; + } + + template <typename T> + T + gsvd<T>::R_matrix (void) const + { + if (type != gsvd::Type::std) + { + (*current_liboctave_error_handler) + ("gsvd: R not computed because type != gsvd::std"); + return T (); + } + else + return R; + } + + template <typename T> + gsvd<T>::gsvd (const T& a, const T& b, gsvd::Type gsvd_type) + { + octave_idx_type info; + + octave_idx_type m = a.rows (); + octave_idx_type n = a.cols (); + octave_idx_type p = b.rows (); + + T atmp = a; + P *tmp_dataA = atmp.fortran_vec (); + + T btmp = b; + P *tmp_dataB = btmp.fortran_vec (); + + char jobu = 'U'; + char jobv = 'V'; + char jobq = 'Q'; + + octave_idx_type nrow_u = m; + octave_idx_type nrow_v = p; + octave_idx_type nrow_q = n; + + octave_idx_type k, l; + + switch (gsvd_type) + { + case gsvd<T>::Type::sigma_only: + + // Note: for this case, both jobu and jobv should be 'N', but + // there seems to be a bug in dgesvd from Lapack V2.0. To + // demonstrate the bug, set both jobu and jobv to 'N' and find + // the singular values of [eye(3), eye(3)]. The result is + // [-sqrt(2), -sqrt(2), -sqrt(2)]. + // + // For Lapack 3.0, this problem seems to be fixed. + + jobu = 'N'; + jobv = 'N'; + jobq = 'N'; + nrow_u = nrow_v = nrow_q = 1; + break; + + default: + break; + } + + type = gsvd_type; + + if (! (jobu == 'N' || jobu == 'O')) + left_smA.resize (nrow_u, m); + + P *u = left_smA.fortran_vec (); + + if (! (jobv == 'N' || jobv == 'O')) + left_smB.resize (nrow_v, p); + + P *v = left_smB.fortran_vec (); + + if (! (jobq == 'N' || jobq == 'O')) + right_sm.resize (nrow_q, n); + + P *q = right_sm.fortran_vec (); + + octave_idx_type lwork = 3*n; + lwork = lwork > m ? lwork : m; + lwork = (lwork > p ? lwork : p) + n; + + T work (lwork, 1); + real_matrix alpha (n, 1); + real_matrix beta (n, 1); + + std::vector<octave_idx_type> iwork (n); + + gsvd<T>::ggsvd (jobu, jobv, jobq, m, n, p, k, l, + tmp_dataA, m, tmp_dataB, p, alpha, beta, u, + nrow_u, v, nrow_v, q, nrow_q, work, iwork.data (), info); + + if (f77_exception_encountered) + (*current_liboctave_error_handler) ("unrecoverable error in *ggsvd"); + + if (info < 0) + (*current_liboctave_error_handler) ("*ggsvd.f: argument %d illegal", + -info); + else + { + if (info > 0) + (*current_liboctave_error_handler) + ("*ggsvd.f: Jacobi-type procedure failed to converge."); + else + { + octave_idx_type i, j; + + if (gsvd<T>::Type::std == gsvd_type) + { + R.resize(k+l, k+l); + int astart = n-k-l; + if (m - k - l >= 0) + { + astart = n-k-l; + // R is stored in A(1:K+L,N-K-L+1:N) + for (i = 0; i < k+l; i++) + for (j = 0; j < k+l; j++) + R.xelem (i, j) = atmp.xelem (i, astart + j); + } + else + { + // (R11 R12 R13 ) is stored in A(1:M, N-K-L+1:N), + // ( 0 R22 R23 ) + + for (i = 0; i < m; i++) + for (j = 0; j < k+l; j++) + R.xelem (i, j) = atmp.xelem (i, astart + j); + // and R33 is stored in B(M-K+1:L,N+M-K-L+1:N) + for (i = k+l-1; i >=m; i--) + { + for (j = 0; j < m; j++) + R.xelem(i, j) = 0.0; + for (j = m; j < k+l; j++) + R.xelem (i, j) = btmp.xelem (i - k, astart + j); + } + } + } + + if (m-k-l >= 0) + { + // Fills in C and S + sigmaA.resize (l, l); + sigmaB.resize (l, l); + for (i = 0; i < l; i++) + { + sigmaA.dgxelem(i) = alpha.elem(k+i); + sigmaB.dgxelem(i) = beta.elem(k+i); + } + } + else + { + // Fills in C and S + sigmaA.resize (m-k, m-k); + sigmaB.resize (m-k, m-k); + for (i = 0; i < m-k; i++) + { + sigmaA.dgxelem(i) = alpha.elem(k+i); + sigmaB.dgxelem(i) = beta.elem(k+i); + } + } + } + } + } + + // Instantiations we need. + template class gsvd<Matrix>; + template class gsvd<FloatMatrix>; + template class gsvd<ComplexMatrix>; + template class gsvd<FloatComplexMatrix>; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liboctave/numeric/gsvd.h Thu Oct 06 07:36:59 2016 +0200 @@ -0,0 +1,102 @@ +// Copyright (C) 2016 Barbara Lócsi +// Copyright (C) 2006 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/>. + +#if !defined (octave_gsvd_h) +#define octave_gsvd_h 1 + +#include "octave-config.h" + +namespace octave +{ + namespace math + { + template <typename T> + class + gsvd + { + public: + + enum class Type + { + std, + economy, + sigma_only + }; + + gsvd (void) : sigmaA (), sigmaB (), left_smA (), left_smB (), right_sm () + { } + + gsvd (const T& a, const T& b, + gsvd::Type gsvd_type = gsvd<T>::Type::economy); + + gsvd (const gsvd& a) + : type (a.type), + sigmaA (a.sigmaA), sigmaB (a.sigmaB), + left_smA (a.left_smA), left_smB (a.left_smB), right_sm (a.right_sm), + R(a.R) { } + + gsvd& operator = (const gsvd& a) + { + if (this != &a) + { + type = a.type; + sigmaA = a.sigmaA; + sigmaB = a.sigmaB; + left_smA = a.left_smA; + left_smB = a.left_smB; + right_sm = a.right_sm; + R = a.R; + } + + return *this; + } + + ~gsvd (void) { } + + typename T::real_diag_matrix_type + singular_values_A (void) const { return sigmaA; } + + typename T::real_diag_matrix_type + singular_values_B (void) const { return sigmaB; } + + T left_singular_matrix_A (void) const; + T left_singular_matrix_B (void) const; + + T right_singular_matrix (void) const; + T R_matrix (void) const; + + private: + typedef typename T::value_type P; + typedef typename T::real_matrix_type real_matrix; + + gsvd::Type type; + typename T::real_diag_matrix_type sigmaA, sigmaB; + T left_smA, left_smB; + T right_sm, R; + + void ggsvd (char& jobu, char& jobv, char& jobq, octave_idx_type m, + octave_idx_type n, octave_idx_type p, octave_idx_type& k, + octave_idx_type& l, P *tmp_dataA, octave_idx_type m1, + P *tmp_dataB, octave_idx_type p1, real_matrix& alpha, + real_matrix& beta, P *u, octave_idx_type nrow_u, P *v, + octave_idx_type nrow_v, P *q, octave_idx_type nrow_q, T& work, + octave_idx_type* iwork, octave_idx_type& info); + }; + } +} + +#endif
--- a/liboctave/numeric/lo-lapack-proto.h Thu Oct 06 07:13:24 2016 +0200 +++ b/liboctave/numeric/lo-lapack-proto.h Thu Oct 06 07:36:59 2016 +0200 @@ -807,6 +807,126 @@ F77_CHAR_ARG_LEN_DECL F77_CHAR_ARG_LEN_DECL); + // GGSVD + + F77_RET_T + F77_FUNC (dggsvd, DGGSVD) + (F77_CONST_CHAR_ARG_DECL, // JOBU + F77_CONST_CHAR_ARG_DECL, // JOBV + F77_CONST_CHAR_ARG_DECL, // JOBQ + const F77_INT&, // M + const F77_INT&, // N + const F77_INT&, // P + F77_INT &, // K + F77_INT &, // L + F77_DBLE*, // A(LDA,N) + const F77_INT&, // LDA + F77_DBLE*, // B(LDB,N) + const F77_INT&, // LDB + F77_DBLE*, // ALPHA(N) + F77_DBLE*, // BETA(N) + F77_DBLE*, // U(LDU,M) + const F77_INT&, // LDU + F77_DBLE*, // V(LDV,P) + const F77_INT&, // LDV + F77_DBLE*, // Q(LDQ,N) + const F77_INT&, // LDQ + F77_DBLE*, // WORK + F77_INT*, // IWORK(N) + F77_INT& // INFO + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (sggsvd, SGGSVD) + (F77_CONST_CHAR_ARG_DECL, // JOBU + F77_CONST_CHAR_ARG_DECL, // JOBV + F77_CONST_CHAR_ARG_DECL, // JOBQ + const F77_INT&, // M + const F77_INT&, // N + const F77_INT&, // P + F77_INT &, // K + F77_INT &, // L + F77_REAL*, // A + const F77_INT&, // LDA + F77_REAL*, // B + const F77_INT&, // LDB + F77_REAL*, // ALPHA + F77_REAL*, // BETA + F77_REAL*, // U + const F77_INT&, // LDU + F77_REAL*, // V + const F77_INT&, // LDV + F77_REAL*, // Q + const F77_INT&, // LDQ + F77_REAL*, // WORK + F77_INT*, // IWORK + F77_INT& // INFO + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (zggsvd, ZGGSVD) + (F77_CONST_CHAR_ARG_DECL, // JOBU + F77_CONST_CHAR_ARG_DECL, // JOBV + F77_CONST_CHAR_ARG_DECL, // JOBQ + const F77_INT&, // M + const F77_INT&, // N + const F77_INT&, // P + F77_INT &, // K + F77_INT &, // L + F77_DBLE_CMPLX*, // A(LDA,N) + const F77_INT&, // LDA + F77_DBLE_CMPLX*, // B(LDB,N) + const F77_INT&, // LDB + F77_DBLE*, // ALPHA(N) + F77_DBLE*, // BETA(N) + F77_DBLE_CMPLX*, // U(LDU,M) + const F77_INT&, // LDU + F77_DBLE_CMPLX*, // V(LDV,P) + const F77_INT&, // LDV + F77_DBLE_CMPLX*, // Q(LDQ,N) + const F77_INT&, // LDQ + F77_DBLE_CMPLX*, // WORK + F77_DBLE*, // RWORK + F77_INT*, // IWORK(N) + F77_INT& // INFO + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL); + + F77_RET_T + F77_FUNC (cggsvd, CGGSVD) + (F77_CONST_CHAR_ARG_DECL, // JOBU + F77_CONST_CHAR_ARG_DECL, // JOBV + F77_CONST_CHAR_ARG_DECL, // JOBQ + const F77_INT&, // M + const F77_INT&, // N + const F77_INT&, // P + F77_INT &, // K + F77_INT &, // L + F77_CMPLX*, // A + const F77_INT&, // LDA + F77_CMPLX*, // B + const F77_INT&, // LDB + F77_REAL*, // ALPHA + F77_REAL*, // BETA + F77_CMPLX*, // U + const F77_INT&, // LDU + F77_CMPLX*, // V + const F77_INT&, // LDV + F77_CMPLX*, // Q + const F77_INT&, // LDQ + F77_CMPLX*, // WORK + F77_REAL*, // RWORK + F77_INT*, // IWORK + F77_INT& // INFO + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL + F77_CHAR_ARG_LEN_DECL); + // GTSV F77_RET_T
--- a/liboctave/numeric/module.mk Thu Oct 06 07:13:24 2016 +0200 +++ b/liboctave/numeric/module.mk Thu Oct 06 07:36:59 2016 +0200 @@ -18,6 +18,7 @@ liboctave/numeric/DASSL.h \ liboctave/numeric/DET.h \ liboctave/numeric/EIG.h \ + liboctave/numeric/gsvd.h \ liboctave/numeric/LSODE.h \ liboctave/numeric/ODE.h \ liboctave/numeric/ODEFunc.h \ @@ -69,6 +70,7 @@ liboctave/numeric/DASRT.cc \ liboctave/numeric/DASSL.cc \ liboctave/numeric/EIG.cc \ + liboctave/numeric/gsvd.cc \ liboctave/numeric/LSODE.cc \ liboctave/numeric/ODES.cc \ liboctave/numeric/Quad.cc \
--- a/liboctave/operators/mx-defs.h Thu Oct 06 07:13:24 2016 +0200 +++ b/liboctave/operators/mx-defs.h Thu Oct 06 07:36:59 2016 +0200 @@ -66,6 +66,8 @@ class EIG; +template <typename T> class gsvd; + template <typename T> class hess; template <typename T> class schur;
--- a/liboctave/operators/mx-ext.h Thu Oct 06 07:13:24 2016 +0200 +++ b/liboctave/operators/mx-ext.h Thu Oct 06 07:36:59 2016 +0200 @@ -57,6 +57,11 @@ #include "EIG.h" +// Result of a Generalized Singular Value Decomposition. + +#include "gsvd.h" + + // Result of an LU decomposition. #include "lu.h"
--- a/scripts/help/__unimplemented__.m Thu Oct 06 07:13:24 2016 +0200 +++ b/scripts/help/__unimplemented__.m Thu Oct 06 07:36:59 2016 +0200 @@ -49,11 +49,6 @@ txt = ["exifread is deprecated. " ... "The functionality is available in the imfinfo function."]; - case "gsvd" - txt = ["gsvd is not currently part of core Octave. ", ... - "See the linear-algebra package at ", ... - "@url{http://octave.sourceforge.net/linear-algebra/}."]; - case "funm" txt = ["funm is not currently part of core Octave. ", ... "See the linear-algebra package at ", ... @@ -657,7 +652,6 @@ "graph", "graymon", "griddedInterpolant", - "gsvd", "guide", "h5create", "h5disp",