time | Calls | line |
---|
| | 189 | function [A, n, B, k, Amatrix, eigsSigma, shiftAndInvert, cholB, permB, scaleB, spdB, ...
|
| | 190 | innerOpts, randStr, useEig, originalB] = checkInputs(varargin)
|
| | 191 | % Process the inputs and get some information from them
|
| | 192 |
|
| | 193 | % Set the rand stream to make algorithm reproducible
|
0.036 | 1 | 194 | randStr = RandStream('dsfmt19937','Seed',0);
|
| | 195 |
|
< 0.001 | 1 | 196 | isrealprob = true;
|
< 0.001 | 1 | 197 | ishermprob = false;
|
| | 198 |
|
< 0.001 | 1 | 199 | if isa(varargin{1},'double')
|
< 0.001 | 1 | 200 | A = varargin{1};
|
< 0.001 | 1 | 201 | Amatrix = true;
|
< 0.001 | 1 | 202 | isrealprob = isreal(A);
|
< 0.001 | 1 | 203 | ishermprob = ishermitian(A);
|
< 0.001 | 1 | 204 | [m, n] = size(A);
|
< 0.001 | 1 | 205 | if m ~= n
|
| | 206 | error(message('MATLAB:eigs:NonSquareMatrixOrFunction'));
|
| | 207 | end
|
| | 208 | else
|
| | 209 | % By checking the function A with fcnchk, we can now use direct
|
| | 210 | % function evaluation on the result, without resorting to feval
|
| | 211 | [A, notFunc] = fcnchk(varargin{1});
|
| | 212 | Amatrix = false;
|
| | 213 | if ~isempty(notFunc)
|
| | 214 | error(message('MATLAB:eigs:NonDoubleOrFunction'));
|
| | 215 | end
|
| | 216 | if nargin < 2
|
| | 217 | error(message('MATLAB:eigs:MustHaveSecondInput'));
|
| | 218 | end
|
| | 219 | n = varargin{2};
|
| | 220 | if ~isscalar(n) || ~isreal(n) || n<0 || ~isfinite(n) || round(n) ~= n
|
| | 221 | error(message('MATLAB:eigs:NonPosIntSize'));
|
| | 222 | end
|
| | 223 | n = full(n);
|
< 0.001 | 1 | 224 | end
|
| | 225 |
|
| | 226 | % Process the input B. Is B present in the eigs call or not?
|
< 0.001 | 1 | 227 | if nargin < 3-Amatrix
|
| | 228 | Bpresent = false;
|
| | 229 | B = [];
|
< 0.001 | 1 | 230 | else
|
| | 231 | % Is the next input B or K?
|
< 0.001 | 1 | 232 | Bpresent = isBpresent(varargin{3-Amatrix}, nargin, Amatrix, n);
|
< 0.001 | 1 | 233 | if Bpresent
|
| | 234 | B = varargin{3-Amatrix};
|
| | 235 | isrealprob = isrealprob && isreal(B);
|
< 0.001 | 1 | 236 | else
|
< 0.001 | 1 | 237 | B = [];
|
< 0.001 | 1 | 238 | end
|
< 0.001 | 1 | 239 | end
|
| | 240 |
|
| | 241 | % Store the original B before any scaling
|
< 0.001 | 1 | 242 | originalB = B;
|
| | 243 |
|
| | 244 | % argOffset tells us where to get the eigs inputs K, SIGMA and OPTS.
|
| | 245 | % If A is really the function afun, then it also helps us find the
|
| | 246 | % trailing parameters in eigs(afun,n,[B],k,sigma,opts,P1,P2,...)
|
| | 247 | % Values of argOffset:
|
| | 248 | % 0: Amatrix is false and Bpresent is true:
|
| | 249 | % eigs(afun,n,B,k,sigma,opts,P1,P2,...)
|
| | 250 | % 1: Amatrix and Bpresent are both true, or both false
|
| | 251 | % eigs(A,B,k,sigma,opts)
|
| | 252 | % eigs(afun,n,k,sigma,opts,P1,P2,...)
|
| | 253 | % 2: Amatrix is true and Bpresent is false:
|
| | 254 | % eigs(A,k,sigma,opts)
|
< 0.001 | 1 | 255 | argOffset = Amatrix + ~Bpresent;
|
| | 256 |
|
| | 257 | % Process the input K
|
< 0.001 | 1 | 258 | if nargin < 4-argOffset
|
| | 259 | k = min(n,6);
|
< 0.001 | 1 | 260 | else
|
< 0.001 | 1 | 261 | k = varargin{4-argOffset};
|
< 0.001 | 1 | 262 | if ~isnumeric(k) || ~isscalar(k) || ~isreal(k) || k>n || ...
|
| 1 | 263 | k<0 || ~isfinite(k) || round(k) ~= k
|
| | 264 | if isnumeric(k) && isscalar(k)
|
| | 265 | error(message('MATLAB:eigs:NonIntegerEigQtyDetail', n, num2str(k)));
|
| | 266 | elseif ischar(k)
|
| | 267 | error(message('MATLAB:eigs:NonIntegerEigQtyDetail', n, ['''' k '''']));
|
| | 268 | elseif isstruct(k)
|
| | 269 | error(message('MATLAB:eigs:NonIntegerEigQtyStruct', n));
|
| | 270 | else
|
| | 271 | error(message('MATLAB:eigs:NonIntegerEigQty', n));
|
| | 272 | end
|
| | 273 | end
|
< 0.001 | 1 | 274 | k = double(full(k));
|
< 0.001 | 1 | 275 | end
|
| | 276 |
|
| | 277 | % Process the input SIGMA:
|
| | 278 | % eigsSigma = 'SM' or 0 : sigma = 0, method = 'LM' , shiftAndInvert = true
|
| | 279 | % eigsSigma is scalar : sigma = eigsSigma, method = 'LM' , shiftAndInvert = true
|
| | 280 | % otherwise: sigma = 0, method = eigsSigma, shiftAndInvert = false
|
< 0.001 | 1 | 281 | if nargin < 5-argOffset
|
| | 282 | % set default
|
| | 283 | eigsSigma = 'largestabs';
|
| | 284 | method = 'largestabs';
|
| | 285 | sigma = 0;
|
| | 286 | shiftAndInvert = false;
|
< 0.001 | 1 | 287 | else
|
< 0.001 | 1 | 288 | eigsSigma = varargin{5-argOffset};
|
< 0.001 | 1 | 289 | if (ischar(eigsSigma) && isrow(eigsSigma)) || (isstring(eigsSigma) && isscalar(eigsSigma))
|
| | 290 | validSigmasOld = {'LM','SM','LA','LR','SA','SR','BE','LI','SI'};
|
| | 291 | validSigmasNew = {'largestabs','smallestabs','largestreal','smallestreal',...
|
| | 292 | 'bothendsreal','largestimag','smallestimag','bothendsimag'};
|
| | 293 | if length(eigsSigma) == 2
|
| | 294 | match = startsWith(validSigmasOld, eigsSigma, 'IgnoreCase', true);
|
| | 295 | if nnz(match) ~= 1 || strlength(eigsSigma) == 0
|
| | 296 | error(message('MATLAB:eigs:InvalidSigma'));
|
| | 297 | else
|
| | 298 | eigsSigma = validSigmasOld{match};
|
| | 299 | end
|
| | 300 | else
|
| | 301 | match = startsWith(validSigmasNew, eigsSigma, 'IgnoreCase', true);
|
| | 302 | if nnz(match) ~= 1 || strlength(eigsSigma) == 0
|
| | 303 | error(message('MATLAB:eigs:InvalidSigma'));
|
| | 304 | else
|
| | 305 | eigsSigma = validSigmasNew{match};
|
| | 306 | end
|
| | 307 | end
|
| | 308 |
|
| | 309 | if ismember(eigsSigma,{'SM','smallestabs'})
|
| | 310 | eigsSigma = 'smallestabs';
|
| | 311 | method = 'largestabs';
|
| | 312 | shiftAndInvert = true;
|
| | 313 | else
|
| | 314 | % Allow old sigma values to flow through. Will convert 'LI' and
|
| | 315 | % 'SI' in extraChecks once we have the required info
|
| | 316 | if strcmp(eigsSigma,'LM')
|
| | 317 | eigsSigma = 'largestabs';
|
| | 318 | elseif ismember(eigsSigma,{'LA','LR'})
|
| | 319 | eigsSigma = 'largestreal';
|
| | 320 | elseif ismember(eigsSigma,{'SA','SR'})
|
| | 321 | eigsSigma = 'smallestreal';
|
| | 322 | elseif strcmp(eigsSigma,'BE')
|
| | 323 | eigsSigma = 'bothendsreal';
|
| | 324 | end
|
| | 325 |
|
| | 326 | method = eigsSigma;
|
| | 327 | shiftAndInvert = false;
|
| | 328 | end
|
| | 329 | sigma = 0;
|
< 0.001 | 1 | 330 | elseif isfloat(eigsSigma) && isscalar(eigsSigma)
|
| | 331 | % SIGMA is a scalar
|
< 0.001 | 1 | 332 | eigsSigma = double(full(eigsSigma));
|
< 0.001 | 1 | 333 | sigma = eigsSigma;
|
< 0.001 | 1 | 334 | isrealprob = isrealprob && isreal(sigma);
|
< 0.001 | 1 | 335 | method = 'largestabs';
|
< 0.001 | 1 | 336 | shiftAndInvert = true;
|
| | 337 | else
|
| | 338 | error(message('MATLAB:eigs:InvalidSigma'));
|
< 0.001 | 1 | 339 | end
|
< 0.001 | 1 | 340 | end
|
| | 341 |
|
| | 342 | % Set defaults for input options
|
< 0.001 | 1 | 343 | tol = 1e-14;
|
< 0.001 | 1 | 344 | maxit = 300;
|
< 0.001 | 1 | 345 | p = min(max(2*k,20),n);
|
< 0.001 | 1 | 346 | userp = false; % logical -- did the user set option p?
|
0.002 | 1 | 347 | v0 = randn(randStr, n,1);
|
< 0.001 | 1 | 348 | fail = 'replacenan';
|
< 0.001 | 1 | 349 | disp = 0;
|
< 0.001 | 1 | 350 | cholB = false;
|
< 0.001 | 1 | 351 | permB = [];
|
< 0.001 | 1 | 352 | spdB = [];
|
| | 353 |
|
| | 354 | % Process the input options struct
|
< 0.001 | 1 | 355 | NameValueFlag = false;
|
< 0.001 | 1 | 356 | optsStart = 6-argOffset;
|
< 0.001 | 1 | 357 | if nargin >= optsStart
|
| | 358 | if isstruct(varargin{optsStart})
|
| | 359 | opts = varargin{optsStart};
|
| | 360 | if nargin > optsStart
|
| | 361 | if Amatrix
|
| | 362 | error(message('MATLAB:eigs:TooManyInputs'));
|
| | 363 | else
|
| | 364 | % Add trailing parameters into function handle A
|
| | 365 | args = varargin(7-argOffset:nargin);
|
| | 366 | A = createAfun(A, args{:});
|
| | 367 | end
|
| | 368 | end
|
| | 369 | else
|
| | 370 | % Convert name-value pairs to struct for ease of error checking
|
| | 371 | NameValueFlag = true;
|
| | 372 | for j = optsStart:2:length(varargin)
|
| | 373 | name = varargin{j};
|
| | 374 | if (~(ischar(name) && isrow(name)) && ~(isstring(name) && isscalar(name))) ...
|
| | 375 | || (isstring(name) && strlength(name) == 0)
|
| | 376 | error(message('MATLAB:eigs:ParseFlags'));
|
| | 377 | end
|
| | 378 | nvNames = ["IsFunctionSymmetric", "Tolerance", "MaxIterations", ...
|
| | 379 | "SubspaceDimension", "StartVector", "IsSymmetricDefinite", ...
|
| | 380 | "IsCholesky", "CholeskyPermutation", "FailureTreatment", ...
|
| | 381 | "Display"];
|
| | 382 | structNames = {'issym','tol','maxit','p','v0','spdB','cholB','permB','fail','disp'};
|
| | 383 | ind = startsWith(nvNames, name, 'IgnoreCase', true);
|
| | 384 | if nnz(ind) ~= 1
|
| | 385 | error(message('MATLAB:eigs:ParseFlags'));
|
| | 386 | end
|
| | 387 | if j+1 > length(varargin)
|
| | 388 | error(message('MATLAB:eigs:KeyWithoutValue'));
|
| | 389 | end
|
| | 390 |
|
| | 391 | opts.(structNames{ind}) = varargin{j+1};
|
| | 392 | end
|
| | 393 | end
|
| | 394 |
|
| | 395 | % Check option for AFUN: issym and isreal
|
| | 396 | if isfield(opts,'issym')
|
| | 397 | ishermprob = checkIsSym(opts.issym, ishermprob, Amatrix, NameValueFlag);
|
| | 398 | end
|
| | 399 | if isfield(opts,'isreal') && ~Amatrix
|
| | 400 | % opts.isreal is an old option that is now only used with inputs
|
| | 401 | % 'si' or 'li', to determine to which new sigma value they
|
| | 402 | % translate.
|
| | 403 | if ~isscalar(opts.isreal) || (opts.isreal ~= true && opts.isreal ~= false)
|
| | 404 | error(message('MATLAB:eigs:InvalidOptsIsreal'));
|
| | 405 | end
|
| | 406 | isrealprob = isrealprob && opts.isreal;
|
| | 407 | end
|
| | 408 |
|
| | 409 | % Check options for algorithm: tol, p, maxit, v0, and fail
|
| | 410 | if isfield(opts,'tol')
|
| | 411 | tol = checkTol(opts.tol, NameValueFlag);
|
| | 412 | end
|
| | 413 | if isfield(opts,'p')
|
| | 414 | p = checkP(opts.p, n, k, NameValueFlag);
|
| | 415 | userp = true;
|
| | 416 | end
|
| | 417 | if isfield(opts,'maxit')
|
| | 418 | maxit = checkMaxit(opts.maxit, NameValueFlag);
|
| | 419 | end
|
| | 420 | if isfield(opts,'v0')
|
| | 421 | v0 = checkV0(opts.v0, n, NameValueFlag);
|
| | 422 | isrealprob = isrealprob && isreal(v0);
|
| | 423 | end
|
| | 424 | if isfield(opts, 'fail')
|
| | 425 | fail = checkFail(opts.fail, NameValueFlag);
|
| | 426 | end
|
| | 427 | if isfield(opts, 'disp')
|
| | 428 | disp = checkDisp(opts.disp, NameValueFlag);
|
| | 429 | end
|
| | 430 |
|
| | 431 | % Check options for B: cholB, permB and spdB
|
| | 432 | if ~isempty(B) && isfield(opts,'cholB')
|
| | 433 | cholB = checkCholB(opts.cholB, B, NameValueFlag);
|
| | 434 | if isfield(opts,'permB')
|
| | 435 | % Note, permB is silently ignored if user does not give cholB
|
| | 436 | permB = checkPermB(opts.permB, cholB, issparse(B), n, NameValueFlag);
|
| | 437 | end
|
| | 438 | end
|
| | 439 |
|
| | 440 | if ~isempty(B) && isfield(opts, 'spdB')
|
| | 441 | spdB = checkSPDB(opts.spdB, B, cholB, NameValueFlag);
|
| | 442 | end
|
| | 443 |
|
| | 444 | end
|
| | 445 |
|
< 0.001 | 1 | 446 | if p >= n || k == 0
|
| | 447 | % Since we are going to build the whole subspace anyway, just use
|
| | 448 | % full eig. Ignore starting vector and InnerOpts.
|
| | 449 | useEig = true;
|
< 0.001 | 1 | 450 | else
|
< 0.001 | 1 | 451 | useEig = false;
|
< 0.001 | 1 | 452 | end
|
| | 453 |
|
| | 454 | % Scale the matrix B, if needed
|
< 0.001 | 1 | 455 | if ~isempty(B)
|
| | 456 | scaleB = norm(B,'fro')./sqrt(n);
|
| | 457 | scaleB = 2.^floor(log2(scaleB+1));
|
| | 458 | B = B./scaleB;
|
| | 459 | if cholB
|
| | 460 | scaleB = scaleB.^2;
|
| | 461 | end
|
| | 462 | if isscalar(eigsSigma)
|
| | 463 | sigma = scaleB.*eigsSigma;
|
| | 464 | end
|
< 0.001 | 1 | 465 | else
|
< 0.001 | 1 | 466 | scaleB = [];
|
< 0.001 | 1 | 467 | end
|
| | 468 |
|
| | 469 | % Create an inner options struct to carry around values
|
< 0.001 | 1 | 470 | innerOpts = struct('tol', tol, 'maxit', maxit, 'p', p, 'v0', v0, 'method',...
|
| 1 | 471 | method, 'sigma', sigma, 'ishermprob', ishermprob, 'isrealprob', isrealprob, ...
|
| 1 | 472 | 'fail', fail, 'disp', disp, 'userp', userp);
|
| | 473 |
|
< 0.001 | 1 | 474 | end
|
Other subfunctions in this file are not included in this listing.