Commit 24305294 authored by Tim Mitchell's avatar Tim Mitchell
Browse files

Version 2.1

parent 5fba3651
Version: 2.1
Description: added support up through R2018a
Details:
- Note that in R2017b, a new Krylov Schur algorithm replaces ARPACK
Version: 2.0
Description: initial public release
Details: n/a
......@@ -26,7 +26,7 @@ function cleanEigsPlus(varargin)
% For comments/bug reports, please visit the eigsPlus GitLab webpage:
% https://gitlab.com/timmitchell/eigsPlus
%
% eigsPlus Version 2.0, 2016, see AGPL license info below.
% eigsPlus Version 2.1, 2016-2018, see AGPL license info below.
% cleanEigsPlus.m introduced in eigsPlus Version 2.0.
%
% =========================================================================
......
--- /Users/tim/research/releases/eigsPlus/sources/matlab/R2017a/eigs.m 2018-03-20 15:17:56.000000000 +0100
+++ /Users/tim/research/releases/eigsPlus/sources/modified/eigsPlus_R2017a.m 2018-03-28 10:49:12.000000000 +0200
@@ -1,4 +1,22 @@
-function [V, D, flag] = eigs(varargin)
+function [V, D, flag] = eigsPlus_R2017a(varargin)
+%
+% eigsPlus autogenerated code
+%
+% eigsPlus modified version of eigs.m (R2017a) makes the following changes:
+%
+% 1) The optional third output argument now returns the number of ARPACK
+% iterations. 0 is returned if a full eig call is done. Flag is no
+% longer returned as the user may check for the presence of NaNs is the
+% eigenvalue output to determine if not all k requested eigenvalues
+% converged to tolerance.
+%
+% 2) opts.isreal may be set to false to force the complex solver if A is
+% real and opts.v0 is real or if A is real and opts.v0 is complex.
+%
+% The default eigs in R2017a now adopts the convention that only a warning
+% is thrown when no eigenvalues converge so this particular eigsPlus
+% modification is no longer necessary.
+%
%EIGS Find a few eigenvalues and eigenvectors of a matrix
% D = EIGS(A) returns a vector of A's 6 largest magnitude eigenvalues.
% A must be square and should be large and sparse.
@@ -311,7 +329,11 @@
error(message('MATLAB:eigs:InvalidOptsIssym'));
end
end
- if isfield(opts,'isreal') && ~Amatrix
+ % EIGSPLUS modification block START
+ % allow forcing complex solver, with (real A and real v0) or
+ % (real A and complex v0)
+ if isfield(opts,'isreal') % && ~Amatrix
+ % EIGSPLUS modification block END
if ~isscalar(opts.isreal) || (opts.isreal ~= true && opts.isreal ~= false)
error(message('MATLAB:eigs:InvalidOptsIsreal'));
end
@@ -1051,7 +1073,12 @@
end
end
-flag = processEUPDinfo(nOutputs<3);
+% EIGSPLUS modification block START
+% replace third argument flag to instead be the number of ARPACK iters
+% flag = processEUPDinfo(nOutputs<3);
+processEUPDinfo(nOutputs<3);
+flag = double(ipntr(15));
+% EIGSPLUS modification block END
% Nested functions in CallARPACK
function cols = checkIpntr
--- /Users/tim/research/releases/eigsPlus/sources/matlab/R2017b/eigs.m 2018-03-20 15:14:16.000000000 +0100
+++ /Users/tim/research/releases/eigsPlus/sources/modified/eigsPlus_R2017b.m 2018-03-28 12:23:49.000000000 +0200
@@ -1,4 +1,20 @@
-function [V, D, flag] = eigs(varargin)
+function [V, D, flag] = eigsPlus_R2017b(varargin)
+%
+% eigsPlus autogenerated code
+%
+% eigsPlus modified version of eigs.m (R2017b) makes the following change:
+%
+% 1) The optional third output argument now returns the number of
+% iterations of the new Krylov Schur algorithm, introduced in R2017b and
+% which replaces ARPACK used in previous versions of MATLAB. 0 is
+% returned if a full eig call is done. Flag is no longer returned as
+% the user may check for the presence of NaNs is the eigenvalue output
+% to determine if not all k requested eigenvalues converged to
+% tolerance.
+%
+% Note that opts.isreal, which used to be to select which variant of the
+% ARPACK routines is called, is no longer a relevant feature for eigsPlus.
+%
% EIGS Find a few eigenvalues and eigenvectors of a matrix
% D = EIGS(A) returns a vector of A's 6 largest magnitude eigenvalues.
% A must be square and should be large and sparse.
@@ -109,11 +125,16 @@
V = fullEig(A, B, n, k, cholB, permB, scaleB, eigsSigma);
else
[V, D] = fullEig(A, B, n, k, cholB, permB, scaleB, eigsSigma);
- if strcmp(innerOpts.fail,'keep')
- flag = false(k,1);
- else
- flag = 0;
- end
+ % EIGSPLUS modification block START
+ % flag is only used to return the number of iterations.
+ % In the dense case, this is zero.
+ % if strcmp(innerOpts.fail,'keep')
+ % flag = false(k,1);
+ % else
+ % flag = 0;
+ % end
+ flag = 0;
+ % EIGSPLUS modification block END
end
return
end
@@ -123,8 +144,11 @@
Amatrix, innerOpts);
% Send variables to KS and run algorithm
-[V, d, isNotConverged, spdBout, VV] = KrylovSchur(applyOP, applyM, innerOpts, n, k,...
+% EIGSPLUS modification block START
+% added returning the number of KrylovSchur iterations
+[V, d, isNotConverged, spdBout, VV, iters] = KrylovSchur(applyOP, applyM, innerOpts, n, k,...
shiftAndInvert, randStr, spdB);
+% EIGSPLUS modification block END
% Do some post processing of the output for generalized problem
[V, d, isNotConverged] = postProcessing(V, d, isNotConverged, eigsSigma, B, scaleB, ...
@@ -153,18 +177,22 @@
end
% Give correct output based on Failure Treatment option (replacenan is default)
+% EIGSPLUS modification block START
+% flag is only used to return the number of iterations.
if strcmpi(innerOpts.fail,'keep')
- flag = isNotConverged;
+ % flag = isNotConverged;
elseif strcmpi(innerOpts.fail,'drop')
d = d(~isNotConverged);
if nargout > 1
V = V(:,~isNotConverged);
end
- flag = double(any(isNotConverged));
+ % flag = double(any(isNotConverged));
else
d(isNotConverged) = NaN;
- flag = double(any(isNotConverged));
+ % flag = double(any(isNotConverged));
end
+flag = iters;
+% EIGSPLUS modification block END
% If flag is not returned, give warning about convergence failure
if nargout < 3 && any(isNotConverged)
@@ -1254,8 +1282,11 @@
end
end
-function [V, d, isNotConverged, spdB, VV] = KrylovSchur(applyOP, applyM, ...
+% EIGSPLUS modification block START
+% added returning the number of KrylovSchur iterations
+function [V, d, isNotConverged, spdB, VV, iters] = KrylovSchur(applyOP, applyM, ...
innerOpts, n, k, shiftAndInvert, randStr, spdB)
+% EIGSPLUS modification block END
if innerOpts.disp
disp(['--- ' getString(message('MATLAB:eigs:StartKrylovSchur')) ' ---']);
@@ -1277,14 +1308,18 @@
innerOpts.v0 = v;
+% EIGSPLUS modification block START
+% added returning the number of KrylovSchur iterations
if innerOpts.ishermprob
- [V, d, isNotConverged, stopAlgorithm] = KSherm(applyOP, applyM, n, k, ...
+ [V, d, isNotConverged, stopAlgorithm, iters] = KSherm(applyOP, applyM, n, k, ...
innerOpts, randStr, shiftAndInvert);
VV = V; % V already orthogonal
else
- [V, d, isNotConverged, stopAlgorithm, VV] = KSnonherm(applyOP, applyM, n, k, ...
+ [V, d, isNotConverged, stopAlgorithm, VV, iters] = KSnonherm(applyOP, applyM, n, k, ...
innerOpts, randStr, shiftAndInvert);
end
+iters_prev = iters;
+% EIGSPLUS modification block END
if stopAlgorithm
if spdB && shiftAndInvert
@@ -1301,8 +1336,12 @@
innerOpts.v0 = v;
applyOP = @(x) applyOP(applyM(x));
applyM = @(x) x;
- [V, d, isNotConverged, stopAlgorithm, VV] = KSnonherm(applyOP, applyM, n, k, ...
+ % EIGSPLUS modification block START
+ % added returning the number of KrylovSchur iterations
+ [V, d, isNotConverged, stopAlgorithm, VV, iters] = KSnonherm(applyOP, applyM, n, k, ...
innerOpts, randStr, shiftAndInvert);
+ iters = iters + iters_prev;
+ % EIGSPLUS modification block END
end
if stopAlgorithm
@@ -1317,8 +1356,11 @@
end
-function [U, d, isNotConverged, stopAlgorithm] = KSherm(applyOP, applyM, n, k, ...
+% EIGSPLUS modification block START
+% added returning the number of KrylovSchur iterations
+function [U, d, isNotConverged, stopAlgorithm, mm] = KSherm(applyOP, applyM, n, k, ...
innerOpts, randStr, shiftAndInvert)
+% EIGSPLUS modification block END
% Applies Krylov Schur algorithm for Hermitian matrices (reference 1)
% Get previously set algorithm options
@@ -1462,8 +1504,11 @@
end
-function [U, d, isNotConverged, stopAlgorithm, V] = KSnonherm(applyOP, applyM, n, k, ...
+% EIGSPLUS modification block START
+% added returning the number of KrylovSchur iterations
+function [U, d, isNotConverged, stopAlgorithm, V, mm] = KSnonherm(applyOP, applyM, n, k, ...
innerOpts, randStr, shiftAndInvert)
+% EIGSPLUS modification block END
% Applies Krylov Schur algorithm for non-Hermitian matrices (reference 1)
% Get previously set algorithm options
--- /Users/tim/research/releases/eigsPlus/sources/matlab/R2018a/eigs.m 2018-03-21 10:30:20.000000000 +0100
+++ /Users/tim/research/releases/eigsPlus/sources/modified/eigsPlus_R2018a.m 2018-03-28 12:34:08.000000000 +0200
@@ -1,4 +1,20 @@
-function [V, D, flag] = eigs(varargin)
+function [V, D, flag] = eigsPlus_R2018a(varargin)
+%
+% eigsPlus autogenerated code
+%
+% eigsPlus modified version of eigs.m (R2018a) makes the following change:
+%
+% 1) The optional third output argument now returns the number of
+% iterations of the new Krylov Schur algorithm, introduced in R2017b and
+% which replaces ARPACK used in previous versions of MATLAB. 0 is
+% returned if a full eig call is done. Flag is no longer returned as
+% the user may check for the presence of NaNs is the eigenvalue output
+% to determine if not all k requested eigenvalues converged to
+% tolerance.
+%
+% Note that opts.isreal, which used to be to select which variant of the
+% ARPACK routines is called, is no longer a relevant feature for eigsPlus.
+%
% EIGS Find a few eigenvalues and eigenvectors of a matrix
% D = EIGS(A) returns a vector of A's 6 largest magnitude eigenvalues.
% A must be square and should be large and sparse.
@@ -109,11 +125,16 @@
V = fullEig(A, B, n, k, cholB, permB, scaleB, eigsSigma);
else
[V, D] = fullEig(A, B, n, k, cholB, permB, scaleB, eigsSigma);
- if strcmp(innerOpts.fail,'keep')
- flag = false(k,1);
- else
- flag = 0;
- end
+ % EIGSPLUS modification block START
+ % flag is only used to return the number of iterations.
+ % In the dense case, this is zero.
+ % if strcmp(innerOpts.fail,'keep')
+ % flag = false(k,1);
+ % else
+ % flag = 0;
+ % end
+ flag = 0;
+ % EIGSPLUS modification block END
end
return
end
@@ -123,8 +144,11 @@
Amatrix, innerOpts);
% Send variables to KS and run algorithm
-[V, d, isNotConverged, spdBout, VV] = KrylovSchur(applyOP, applyM, innerOpts, n, k,...
+% EIGSPLUS modification block START
+% added returning the number of KrylovSchur iterations
+[V, d, isNotConverged, spdBout, VV, iters] = KrylovSchur(applyOP, applyM, innerOpts, n, k,...
shiftAndInvert, randStr, spdB);
+% EIGSPLUS modification block END
% Do some post processing of the output for generalized problem
[V, d, isNotConverged] = postProcessing(V, d, isNotConverged, eigsSigma, B, scaleB, ...
@@ -153,18 +177,22 @@
end
% Give correct output based on Failure Treatment option (replacenan is default)
+% EIGSPLUS modification block START
+% flag is only used to return the number of iterations.
if strcmpi(innerOpts.fail,'keep')
- flag = isNotConverged;
+ % flag = isNotConverged;
elseif strcmpi(innerOpts.fail,'drop')
d = d(~isNotConverged);
if nargout > 1
V = V(:,~isNotConverged);
end
- flag = double(any(isNotConverged));
+ % flag = double(any(isNotConverged));
else
d(isNotConverged) = NaN;
- flag = double(any(isNotConverged));
+ % flag = double(any(isNotConverged));
end
+flag = iters;
+% EIGSPLUS modification block END
% If flag is not returned, give warning about convergence failure
if nargout < 3 && any(isNotConverged)
@@ -1254,8 +1282,11 @@
end
end
-function [V, d, isNotConverged, spdB, VV] = KrylovSchur(applyOP, applyM, ...
+% EIGSPLUS modification block START
+% added returning the number of KrylovSchur iterations
+function [V, d, isNotConverged, spdB, VV, iters] = KrylovSchur(applyOP, applyM, ...
innerOpts, n, k, shiftAndInvert, randStr, spdB)
+% EIGSPLUS modification block END
if innerOpts.disp
disp(['--- ' getString(message('MATLAB:eigs:StartKrylovSchur')) ' ---']);
@@ -1277,14 +1308,18 @@
innerOpts.v0 = v;
+% EIGSPLUS modification block START
+% added returning the number of KrylovSchur iterations
if innerOpts.ishermprob
- [V, d, isNotConverged, stopAlgorithm] = KSherm(applyOP, applyM, n, k, ...
+ [V, d, isNotConverged, stopAlgorithm, iters] = KSherm(applyOP, applyM, n, k, ...
innerOpts, randStr, shiftAndInvert);
VV = V; % V already orthogonal
else
- [V, d, isNotConverged, stopAlgorithm, VV] = KSnonherm(applyOP, applyM, n, k, ...
+ [V, d, isNotConverged, stopAlgorithm, VV, iters] = KSnonherm(applyOP, applyM, n, k, ...
innerOpts, randStr, shiftAndInvert);
end
+iters_prev = iters;
+% EIGSPLUS modification block END
if stopAlgorithm
if spdB && shiftAndInvert
@@ -1301,8 +1336,12 @@
innerOpts.v0 = v;
applyOP = @(x) applyOP(applyM(x));
applyM = @(x) x;
- [V, d, isNotConverged, stopAlgorithm, VV] = KSnonherm(applyOP, applyM, n, k, ...
+ % EIGSPLUS modification block START
+ % added returning the number of KrylovSchur iterations
+ [V, d, isNotConverged, stopAlgorithm, VV, iters] = KSnonherm(applyOP, applyM, n, k, ...
innerOpts, randStr, shiftAndInvert);
+ iters = iters + iters_prev;
+ % EIGSPLUS modification block END
end
if stopAlgorithm
@@ -1317,8 +1356,11 @@
end
-function [U, d, isNotConverged, stopAlgorithm] = KSherm(applyOP, applyM, n, k, ...
+% EIGSPLUS modification block START
+% added returning the number of KrylovSchur iterations
+function [U, d, isNotConverged, stopAlgorithm, mm] = KSherm(applyOP, applyM, n, k, ...
innerOpts, randStr, shiftAndInvert)
+% EIGSPLUS modification block END
% Applies Krylov Schur algorithm for Hermitian matrices (reference 1)
% Get previously set algorithm options
@@ -1464,8 +1506,11 @@
end
-function [U, d, isNotConverged, stopAlgorithm, V] = KSnonherm(applyOP, applyM, n, k, ...
+% EIGSPLUS modification block START
+% added returning the number of KrylovSchur iterations
+function [U, d, isNotConverged, stopAlgorithm, V, mm] = KSnonherm(applyOP, applyM, n, k, ...
innerOpts, randStr, shiftAndInvert)
+% EIGSPLUS modification block END
% Applies Krylov Schur algorithm for non-Hermitian matrices (reference 1)
% Get previously set algorithm options
......@@ -7,29 +7,40 @@ function varargout = eigsPlus(varargin)
% are returned, so the user no longer needs to worry about
% accidentally using the placeholder zeros (R2013a and earlier)
% or NaNs for unconverged Ritz values in a subsequent
% computation.
% computation. If none converge, empty arrays are returned.
%
% 2) The eigenvalues are always returned in a column vector, and
% never a diagonal matrix, unlike Matlab's eigs routine which
% will return the eigenvalues as a diagonal matrix when
% eigenvectors are always requested.
%
% 3) If no eigenvalues are resolved, a warning is issued instead of
% throwing an error. In this case, the returned eigenvalues and
% eigenvectors will respectively be an empty vector and an empty
% matrix.
% 3) If no eigenvalues are resolved, R2016b and earlier would throw
% an error. On these versions, eigsPlus will instead throw a
% warning. On R2017a, eigs also adopted the same convention of
% throwing a warning instead of an error. However, on R2017b,
% eigs no longer throws a warning or an error. To maintain
% consistency, as of R2017b, eigsPlus also no longer throws a
% warning. Recall in the case that no Ritz value converges, the
% returned eigenvalues and eigenvectors will respectively be an
% empty vector and an empty matrix.
%
% 4) The number of ARPACK iterations incurred is returned via the
% third output argument. Flag is no longer returned as the user
% can always equivalently check if the number of eigenvalues
% returned is less than what the user requested.
%
% 5) The user may set opts.isreal to false to force the complex
% ARPACK routines to be used even if matrix A is real and opts.v0
% is either real or complex (whereas Matlabs's eigs would throw
% an error in these cases). eigsPlus will throw an error in
% either of these cases if opts.isreal is either not provided or
% if it is set to true.
% 4) The number of iterations incurred is returned via the third
% output argument. Flag is no longer returned as the user can
% always equivalently check if the number of eigenvalues returned
% is less than what the user requested. For R2017a and earlier,
% this is the number of ARPACK iterations. On newer releases,
% this is the number of Krylov Schur iterations but note that for
% problems with symmetric positive definite B matrices using
% shift-invert, the Krylov Schur method may be restarted once, if
% the first fails; in this case, the number of iterations is the
% sum of two attempts.
%
% 5) R2017a and earlier only: The user may set opts.isreal to false
% to force the complex ARPACK routines to be used even if matrix
% A is real and opts.v0 is either real or complex (whereas
% Matlabs's eigs would throw an error in these cases). eigsPlus
% will throw an error in either of these cases if opts.isreal is
% either not provided or if it is set to true.
%
% NOTE: On Octave, only features (1) and (2) are enabled.
%
......@@ -88,7 +99,7 @@ function varargout = eigsPlus(varargin)
% For comments/bug reports, please visit the eigsPlus GitLab webpage:
% https://gitlab.com/timmitchell/eigsPlus
%
% eigsPlus Version 2.0, 2016, see AGPL license info below.
% eigsPlus Version 2.1, 2016-2018, see AGPL license info below.
% eigsPlus.m introduced in eigsPlus Version 2.0.
%
% =========================================================================
......
......@@ -21,7 +21,7 @@ function makeEigsPlus()
% For comments/bug reports, please visit the eigsPlus GitLab webpage:
% https://gitlab.com/timmitchell/eigsPlus
%
% eigsPlus Version 2.0, 2016, see AGPL license info below.
% eigsPlus Version 2.1, 2016-2018, see AGPL license info below.
% makeEigsPlus.m introduced in eigsPlus Version 2.0.
%
% =========================================================================
......
......@@ -65,6 +65,12 @@ function [eigsPlus_suffix,rel_name,newer_matlab] = getEigsPlusSuffix()
eigsPlus_suffix = 'R2015a_R2016a';
case {'2016b'}
eigsPlus_suffix = 'R2016b';
case {'2017a'}
eigsPlus_suffix = 'R2017a';
case {'2017b'}
eigsPlus_suffix = 'R2017b';
case {'2018a'}
eigsPlus_suffix = 'R2018a';
otherwise
if ~atLeastVersion('2012b')
error( 'eigsPlus:unsupportedMatlab', ...
......@@ -72,6 +78,6 @@ function [eigsPlus_suffix,rel_name,newer_matlab] = getEigsPlusSuffix()
else
newer_matlab = true;
end
eigsPlus_suffix = 'R2016b';
eigsPlus_suffix = 'R2018a';
end
end
\ No newline at end of file
......@@ -15,6 +15,9 @@ function makeEigsPlusDiffs()
% the eigsPlus modifications. A version-specific diff patch will be
% created for each pair of the original source and its corresponding
% eigsPlus-modified source file.
%
% NOTE: getEigsPlusSuffix.m must also be updated when adding support
% for new releases of MATLAB.
%
% REQUIREMENTS:
%
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment