Skip to content

Commit f98d6c6

Browse files
author
Rik
committed
Check input matrices for Inf or NaN before calling ARPACK (bug #57475)
* __eigs__.cc (F__eigs__): For Matrix A or B inputs, use any_element_is_inf_or_nan() to check for non-finite values. Stop reading Matrix B from varargin twice.
1 parent c1ff212 commit f98d6c6

File tree

1 file changed

+51
-39
lines changed

1 file changed

+51
-39
lines changed

libinterp/corefcn/__eigs__.cc

Lines changed: 51 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -230,77 +230,74 @@ Undocumented internal function.
230230
if (args(0).is_function_handle () || args(0).is_inline_function ()
231231
|| args(0).is_string ())
232232
{
233+
have_a_fcn = true;
233234
callback.m_eigs_fcn = get_function_handle (interp, args(0), "x");
234235

235236
if (callback.m_eigs_fcn.is_undefined ())
236237
error ("eigs: unknown function");
237-
238238
if (nargin < 2)
239239
error ("eigs: incorrect number of arguments");
240240

241241
n = args(1).strict_int_value ();
242242
arg_offset = 1;
243-
have_a_fcn = true;
244243
}
245244
else
246245
{
246+
// Matrix A
247247
if (args(0).iscomplex ())
248248
{
249+
a_is_complex = true;
249250
if (args(0).issparse ())
250251
{
251-
ascm = (args(0).sparse_complex_matrix_value ());
252252
a_is_sparse = true;
253+
ascm = args(0).sparse_complex_matrix_value ();
254+
// Validation is 17x faster in C++ than in m-file.
255+
if (ascm.any_element_is_inf_or_nan ())
256+
error ("eigs: matrix A contains Inf or NaN values");
253257
}
254258
else
255-
acm = (args(0).complex_matrix_value ());
256-
a_is_complex = true;
259+
{
260+
acm = args(0).complex_matrix_value ();
261+
if (acm.any_element_is_inf_or_nan ())
262+
error ("eigs: matrix A contains Inf or NaN values");
263+
}
257264
}
258265
else
259266
{
260267
if (args(0).issparse ())
261268
{
262-
asmm = (args(0).sparse_matrix_value ());
263269
a_is_sparse = true;
270+
asmm = args(0).sparse_matrix_value ();
271+
if (asmm.any_element_is_inf_or_nan ())
272+
error ("eigs: matrix A contains Inf or NaN values");
264273
}
265274
else
266275
{
267-
amm = (args(0).matrix_value ());
276+
amm = args(0).matrix_value ();
277+
if (amm.any_element_is_inf_or_nan ())
278+
error ("eigs: matrix A contains Inf or NaN values");
268279
}
269280
}
270281
}
271282

272-
// Note hold off reading B until later to avoid issues of double
283+
// Note: hold off converting B until later to avoid issues of double
273284
// copies of the matrix if B is full/real while A is complex.
274-
if (nargin > 1 + arg_offset
275-
&& ! (args(1 + arg_offset).is_real_scalar ()))
285+
if (nargin > (1+arg_offset) && ! args(1+arg_offset).is_real_scalar ())
276286
{
277-
if (args(1+arg_offset).iscomplex ())
287+
have_b = true;
288+
b_arg = 1 + arg_offset;
289+
if (args(b_arg).iscomplex ())
278290
{
279-
b_arg = 1+arg_offset;
280-
if (args(b_arg).issparse ())
281-
{
282-
bscm = (args(b_arg).sparse_complex_matrix_value ());
283-
b_is_sparse = true;
284-
}
285-
else
286-
bcm = (args(b_arg).complex_matrix_value ());
287-
have_b = true;
288291
b_is_complex = true;
289-
arg_offset++;
292+
if (args(b_arg).issparse ())
293+
b_is_sparse = true;
290294
}
291295
else
292296
{
293-
b_arg = 1+arg_offset;
294297
if (args(b_arg).issparse ())
295-
{
296-
bsmm = (args(b_arg).sparse_matrix_value ());
297-
b_is_sparse = true;
298-
}
299-
else
300-
bmm = (args(b_arg).matrix_value ());
301-
have_b = true;
302-
arg_offset++;
298+
b_is_sparse = true;
303299
}
300+
arg_offset++;
304301
}
305302

306303
if (nargin > (1+arg_offset))
@@ -311,17 +308,15 @@ Undocumented internal function.
311308
if (args(2+arg_offset).is_string ())
312309
{
313310
typ = args(2+arg_offset).string_value ();
314-
315311
// Use STL function to convert to upper case
316312
transform (typ.begin (), typ.end (), typ.begin (), toupper);
317313

318314
sigma = 0.0;
319315
}
320316
else
321317
{
322-
sigma = args(2+arg_offset).xcomplex_value ("eigs: SIGMA must be a scalar or a string");
323-
324318
have_sigma = true;
319+
sigma = args(2+arg_offset).xcomplex_value ("eigs: SIGMA must be a scalar or a string");
325320
}
326321
}
327322

@@ -333,8 +328,7 @@ Undocumented internal function.
333328
if (! args(3+arg_offset).isstruct ())
334329
error ("eigs: OPTS argument must be a structure");
335330

336-
octave_scalar_map map = args(3
337-
+arg_offset).xscalar_map_value ("eigs: OPTS argument must be a scalar structure");
331+
octave_scalar_map map = args(3+arg_offset).xscalar_map_value ("eigs: OPTS argument must be a scalar structure");
338332

339333
octave_value tmp;
340334

@@ -423,21 +417,39 @@ Undocumented internal function.
423417
}
424418
}
425419

420+
// Matrix B
426421
if (have_b)
427422
{
428423
if (a_is_complex || b_is_complex)
429424
{
430425
if (b_is_sparse)
431-
bscm = args(b_arg).sparse_complex_matrix_value ();
426+
{
427+
bscm = args(b_arg).sparse_complex_matrix_value ();
428+
// Validation is 17x faster in C++ than in m-file.
429+
if (bscm.any_element_is_inf_or_nan ())
430+
error ("eigs: matrix A contains Inf or NaN values");
431+
}
432432
else
433-
bcm = args(b_arg).complex_matrix_value ();
433+
{
434+
bcm = args(b_arg).complex_matrix_value ();
435+
if (bcm.any_element_is_inf_or_nan ())
436+
error ("eigs: matrix B contains Inf or NaN values");
437+
}
434438
}
435439
else
436440
{
437441
if (b_is_sparse)
438-
bsmm = args(b_arg).sparse_matrix_value ();
442+
{
443+
bsmm = args(b_arg).sparse_matrix_value ();
444+
if (bsmm.any_element_is_inf_or_nan ())
445+
error ("eigs: matrix B contains Inf or NaN values");
446+
}
439447
else
440-
bmm = args(b_arg).matrix_value ();
448+
{
449+
bmm = args(b_arg).matrix_value ();
450+
if (bmm.any_element_is_inf_or_nan ())
451+
error ("eigs: matrix B contains Inf or NaN values");
452+
}
441453
}
442454
}
443455

0 commit comments

Comments
 (0)