Mercurial > hg > octave-lyh
changeset 7922:935be827eaf8
error for NaN values in & and | expressions
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 11 Jul 2008 14:56:30 -0400 |
parents | fcc70f30fe31 |
children | c3d21b9b94b6 |
files | liboctave/Array-util.cc liboctave/Array-util.h liboctave/CMatrix.cc liboctave/CMatrix.h liboctave/CNDArray.cc liboctave/CNDArray.h liboctave/CSparse.cc liboctave/CSparse.h liboctave/ChangeLog liboctave/dMatrix.cc liboctave/dMatrix.h liboctave/dNDArray.cc liboctave/dNDArray.h liboctave/dSparse.cc liboctave/dSparse.h liboctave/fCMatrix.cc liboctave/fCMatrix.h liboctave/fCNDArray.cc liboctave/fCNDArray.h liboctave/fMatrix.cc liboctave/fMatrix.h liboctave/fNDArray.cc liboctave/fNDArray.h liboctave/lo-mappers.h liboctave/mx-op-defs.h liboctave/oct-inttypes.h scripts/general/logical.m src/ChangeLog src/OPERATORS/op-fs-fs.cc src/OPERATORS/op-s-s.cc src/ops.h src/ov-float.h src/ov-flt-re-mat.cc src/ov-range.h src/ov-re-mat.cc src/ov-re-sparse.cc src/ov-scalar.h |
diffstat | 37 files changed, 322 insertions(+), 27 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/Array-util.cc +++ b/liboctave/Array-util.cc @@ -480,6 +480,11 @@ return pva->pidx > pvb->pidx; } +void +gripe_nan_to_logical_conversion (void) +{ + (*current_liboctave_error_handler) ("invalid conversion of NaN to logical"); +} void gripe_nonconformant (const char *op, int op1_len, int op2_len)
--- a/liboctave/Array-util.h +++ b/liboctave/Array-util.h @@ -89,6 +89,8 @@ extern int OCTAVE_API permute_vector_compare (const void *a, const void *b); +extern void OCTAVE_API gripe_nan_to_logical_conversion (void); + extern void OCTAVE_API gripe_nonconformant (const char *op, int op1_len, int op2_len); extern void OCTAVE_API gripe_nonconformant (const char *op, int op1_nr, int op1_nc,
--- a/liboctave/CMatrix.cc +++ b/liboctave/CMatrix.cc @@ -3302,6 +3302,23 @@ } bool +ComplexMatrix::any_element_is_nan (void) const +{ + octave_idx_type nr = rows (); + octave_idx_type nc = cols (); + + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + { + Complex val = elem (i, j); + if (xisnan (val)) + return true; + } + + return false; +} + +bool ComplexMatrix::any_element_is_inf_or_nan (void) const { octave_idx_type nr = rows ();
--- a/liboctave/CMatrix.h +++ b/liboctave/CMatrix.h @@ -327,6 +327,7 @@ ComplexMatrix map (cmapper fcn) const; boolMatrix map (bmapper fcn) const; + bool any_element_is_nan (void) const; bool any_element_is_inf_or_nan (void) const; bool all_elements_are_real (void) const; bool all_integers (double& max_val, double& min_val) const;
--- a/liboctave/CNDArray.cc +++ b/liboctave/CNDArray.cc @@ -497,6 +497,20 @@ // FIXME -- this is not quite the right thing. bool +ComplexNDArray::any_element_is_nan (void) const +{ + octave_idx_type nel = nelem (); + + for (octave_idx_type i = 0; i < nel; i++) + { + Complex val = elem (i); + if (xisnan (val)) + return true; + } + return false; +} + +bool ComplexNDArray::any_element_is_inf_or_nan (void) const { octave_idx_type nel = nelem ();
--- a/liboctave/CNDArray.h +++ b/liboctave/CNDArray.h @@ -64,6 +64,7 @@ // FIXME -- this is not quite the right thing. + bool any_element_is_nan (void) const; bool any_element_is_inf_or_nan (void) const; bool all_elements_are_real (void) const; bool all_integers (double& max_val, double& min_val) const;
--- a/liboctave/CSparse.cc +++ b/liboctave/CSparse.cc @@ -7179,6 +7179,21 @@ // other operations bool +SparseComplexMatrix::any_element_is_nan (void) const +{ + octave_idx_type nel = nnz (); + + for (octave_idx_type i = 0; i < nel; i++) + { + Complex val = data (i); + if (xisnan (val)) + return true; + } + + return false; +} + +bool SparseComplexMatrix::any_element_is_inf_or_nan (void) const { octave_idx_type nel = nnz ();
--- a/liboctave/CSparse.h +++ b/liboctave/CSparse.h @@ -402,6 +402,7 @@ SparseComplexMatrix ipermute (const Array<octave_idx_type>& vec) const; + bool any_element_is_nan (void) const; bool any_element_is_inf_or_nan (void) const; bool all_elements_are_real (void) const; bool all_integers (double& max_val, double& min_val) const;
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,19 @@ +2008-07-11 John W. Eaton <jwe@octave.org> + + * mx-op-defs.h (MS_BOOL_OP, SM_BOOL_OP, MM_BOOL_OP, NDS_BOOL_OP, + SND_BOOL_OP, NDND_BOOL_OP): Detect NaN values. + * Array-util.cc (gripe_nan_to_logical_conversion): New function. + * Array-util.h: Provide decl. + * oct-inttypes.h (xisnan (octave_int<T>)): New function. + * lo-mappers.h (xisnan (bool), xisnan (char)): New inline functions. + + * CMatrix.cc, CNDArray.cc, CSparse.cc, dMatrix.cc, dNDArray.cc, + dSparse.cc, fCMatrix.cc, fCNDArray.cc, fMatrix.cc, fNDArray.cc: + New member function, any_element_is_nan. + * CMatrix.h, CNDArray.h, CSparse.h, dMatrix.h, dNDArray.h, + dSparse.h, fCMatrix.h, fCNDArray.h, fMatrix.h, fNDArray.h: + Provide decl. + 2008-07-10 David Bateman <dbateman@free.fr> * dNDArray.cc (NDArray::NDArray (const Array<octave_idx_type>&,
--- a/liboctave/dMatrix.cc +++ b/liboctave/dMatrix.cc @@ -2849,6 +2849,20 @@ return false; } +bool +Matrix::any_element_is_nan (void) const +{ + octave_idx_type nel = nelem (); + + for (octave_idx_type i = 0; i < nel; i++) + { + double val = elem (i); + if (xisnan (val)) + return true; + } + + return false; +} bool Matrix::any_element_is_inf_or_nan (void) const
--- a/liboctave/dMatrix.h +++ b/liboctave/dMatrix.h @@ -282,6 +282,7 @@ boolMatrix map (bmapper fcn) const; bool any_element_is_negative (bool = false) const; + bool any_element_is_nan (void) const; bool any_element_is_inf_or_nan (void) const; bool any_element_not_one_or_zero (void) const; bool all_elements_are_int_or_inf_or_nan (void) const;
--- a/liboctave/dNDArray.cc +++ b/liboctave/dNDArray.cc @@ -556,6 +556,20 @@ return false; } +bool +NDArray::any_element_is_nan (void) const +{ + octave_idx_type nel = nelem (); + + for (octave_idx_type i = 0; i < nel; i++) + { + double val = elem (i); + if (xisnan (val)) + return true; + } + + return false; +} bool NDArray::any_element_is_inf_or_nan (void) const
--- a/liboctave/dNDArray.h +++ b/liboctave/dNDArray.h @@ -70,6 +70,7 @@ boolNDArray operator ! (void) const; bool any_element_is_negative (bool = false) const; + bool any_element_is_nan (void) const; bool any_element_is_inf_or_nan (void) const; bool any_element_not_one_or_zero (void) const; bool all_elements_are_zero (void) const;
--- a/liboctave/dSparse.cc +++ b/liboctave/dSparse.cc @@ -7237,6 +7237,21 @@ } bool +SparseMatrix::any_element_is_nan (void) const +{ + octave_idx_type nel = nnz (); + + for (octave_idx_type i = 0; i < nel; i++) + { + double val = data (i); + if (xisnan (val)) + return true; + } + + return false; +} + +bool SparseMatrix::any_element_is_inf_or_nan (void) const { octave_idx_type nel = nnz ();
--- a/liboctave/dSparse.h +++ b/liboctave/dSparse.h @@ -372,6 +372,7 @@ // other operations bool any_element_is_negative (bool = false) const; + bool any_element_is_nan (void) const; bool any_element_is_inf_or_nan (void) const; bool all_elements_are_zero (void) const; bool all_elements_are_int_or_inf_or_nan (void) const;
--- a/liboctave/fCMatrix.cc +++ b/liboctave/fCMatrix.cc @@ -3295,6 +3295,23 @@ } bool +FloatComplexMatrix::any_element_is_nan (void) const +{ + octave_idx_type nr = rows (); + octave_idx_type nc = cols (); + + for (octave_idx_type j = 0; j < nc; j++) + for (octave_idx_type i = 0; i < nr; i++) + { + FloatComplex val = elem (i, j); + if (xisnan (val)) + return true; + } + + return false; +} + +bool FloatComplexMatrix::any_element_is_inf_or_nan (void) const { octave_idx_type nr = rows ();
--- a/liboctave/fCMatrix.h +++ b/liboctave/fCMatrix.h @@ -327,6 +327,7 @@ FloatComplexMatrix map (cmapper fcn) const; boolMatrix map (bmapper fcn) const; + bool any_element_is_nan (void) const; bool any_element_is_inf_or_nan (void) const; bool all_elements_are_real (void) const; bool all_integers (float& max_val, float& min_val) const;
--- a/liboctave/fCNDArray.cc +++ b/liboctave/fCNDArray.cc @@ -492,6 +492,20 @@ // FIXME -- this is not quite the right thing. bool +FloatComplexNDArray::any_element_is_nan (void) const +{ + octave_idx_type nel = nelem (); + + for (octave_idx_type i = 0; i < nel; i++) + { + FloatComplex val = elem (i); + if (xisnan (val)) + return true; + } + return false; +} + +bool FloatComplexNDArray::any_element_is_inf_or_nan (void) const { octave_idx_type nel = nelem ();
--- a/liboctave/fCNDArray.h +++ b/liboctave/fCNDArray.h @@ -64,6 +64,7 @@ // FIXME -- this is not quite the right thing. + bool any_element_is_nan (void) const; bool any_element_is_inf_or_nan (void) const; bool all_elements_are_real (void) const; bool all_integers (float& max_val, float& min_val) const;
--- a/liboctave/fMatrix.cc +++ b/liboctave/fMatrix.cc @@ -2848,6 +2848,20 @@ return false; } +bool +FloatMatrix::any_element_is_nan (void) const +{ + octave_idx_type nel = nelem (); + + for (octave_idx_type i = 0; i < nel; i++) + { + float val = elem (i); + if (xisnan (val)) + return true; + } + + return false; +} bool FloatMatrix::any_element_is_inf_or_nan (void) const
--- a/liboctave/fMatrix.h +++ b/liboctave/fMatrix.h @@ -282,6 +282,7 @@ boolMatrix map (bmapper fcn) const; bool any_element_is_negative (bool = false) const; + bool any_element_is_nan (void) const; bool any_element_is_inf_or_nan (void) const; bool any_element_not_one_or_zero (void) const; bool all_elements_are_int_or_inf_or_nan (void) const;
--- a/liboctave/fNDArray.cc +++ b/liboctave/fNDArray.cc @@ -514,6 +514,20 @@ return false; } +bool +FloatNDArray::any_element_is_nan (void) const +{ + octave_idx_type nel = nelem (); + + for (octave_idx_type i = 0; i < nel; i++) + { + float val = elem (i); + if (xisnan (val)) + return true; + } + + return false; +} bool FloatNDArray::any_element_is_inf_or_nan (void) const
--- a/liboctave/fNDArray.h +++ b/liboctave/fNDArray.h @@ -67,6 +67,7 @@ boolNDArray operator ! (void) const; bool any_element_is_negative (bool = false) const; + bool any_element_is_nan (void) const; bool any_element_is_inf_or_nan (void) const; bool any_element_not_one_or_zero (void) const; bool all_elements_are_zero (void) const;
--- a/liboctave/lo-mappers.h +++ b/liboctave/lo-mappers.h @@ -42,6 +42,10 @@ extern OCTAVE_API Complex xlog2 (const Complex& x, int& exp); extern OCTAVE_API double xexp2 (double x); +// These are used by the BOOL_OP macros in mx-op-defs.h. +inline bool xisnan (bool) { return false; } +inline bool xisnan (char) { return false; } + extern OCTAVE_API bool xisnan (double x); extern OCTAVE_API bool xfinite (double x); extern OCTAVE_API bool xisinf (double x);
--- a/liboctave/mx-op-defs.h +++ b/liboctave/mx-op-defs.h @@ -228,9 +228,21 @@ { \ r.resize (nr, nc); \ \ - for (int j = 0; j < nc; j++) \ - for (int i = 0; i < nr; i++) \ - r.elem(i, j) = (m.elem(i, j) != LHS_ZERO) OP (s != RHS_ZERO); \ + if (xisnan (s)) \ + gripe_nan_to_logical_conversion (); \ + else \ + { \ + \ + for (int j = 0; j < nc; j++) \ + for (int i = 0; i < nr; i++) \ + if (xisnan (m.elem(i, j))) \ + { \ + gripe_nan_to_logical_conversion (); \ + return r; \ + } \ + else \ + r.elem(i, j) = (m.elem(i, j) != LHS_ZERO) OP (s != RHS_ZERO); \ + } \ } \ \ return r; \ @@ -331,9 +343,20 @@ { \ r.resize (nr, nc); \ \ - for (int j = 0; j < nc; j++) \ - for (int i = 0; i < nr; i++) \ - r.elem(i, j) = (s != LHS_ZERO) OP (m.elem(i, j) != RHS_ZERO); \ + if (xisnan (s)) \ + gripe_nan_to_logical_conversion (); \ + else \ + { \ + for (int j = 0; j < nc; j++) \ + for (int i = 0; i < nr; i++) \ + if (xisnan (m.elem(i, j))) \ + { \ + gripe_nan_to_logical_conversion (); \ + return r; \ + } \ + else \ + r.elem(i, j) = (s != LHS_ZERO) OP (m.elem(i, j) != RHS_ZERO); \ + } \ } \ \ return r; \ @@ -456,8 +479,14 @@ \ for (int j = 0; j < m1_nc; j++) \ for (int i = 0; i < m1_nr; i++) \ - r.elem(i, j) = (m1.elem(i, j) != LHS_ZERO) \ - OP (m2.elem(i, j) != RHS_ZERO); \ + if (xisnan (m1.elem(i, j)) || xisnan (m2.elem(i, j))) \ + { \ + gripe_nan_to_logical_conversion (); \ + return r; \ + } \ + else \ + r.elem(i, j) = (m1.elem(i, j) != LHS_ZERO) \ + OP (m2.elem(i, j) != RHS_ZERO); \ } \ } \ else \ @@ -605,8 +634,19 @@ { \ r.resize (m.dims ()); \ \ - for (int i = 0; i < len; i++) \ - r.elem(i) = (m.elem(i) != LHS_ZERO) OP (s != RHS_ZERO); \ + if (xisnan (s)) \ + gripe_nan_to_logical_conversion (); \ + else \ + { \ + for (int i = 0; i < len; i++) \ + if (xisnan (m.elem(i))) \ + { \ + gripe_nan_to_logical_conversion (); \ + return r; \ + } \ + else \ + r.elem(i) = (m.elem(i) != LHS_ZERO) OP (s != RHS_ZERO); \ + } \ } \ \ return r; \ @@ -748,8 +788,19 @@ { \ r.resize (m.dims ()); \ \ - for (int i = 0; i < len; i++) \ - r.elem(i) = (s != LHS_ZERO) OP (m.elem(i) != RHS_ZERO); \ + if (xisnan (s)) \ + gripe_nan_to_logical_conversion (); \ + else \ + { \ + for (int i = 0; i < len; i++) \ + if (xisnan (m.elem(i))) \ + { \ + gripe_nan_to_logical_conversion (); \ + return r; \ + } \ + else \ + r.elem(i) = (s != LHS_ZERO) OP (m.elem(i) != RHS_ZERO); \ + } \ } \ \ return r; \ @@ -863,7 +914,13 @@ r.resize (m1_dims); \ \ for (int i = 0; i < m1.length (); i++) \ - r.elem(i) = (m1.elem(i) != LHS_ZERO) OP (m2.elem(i) != RHS_ZERO); \ + if (xisnan (m1.elem(i)) || xisnan (m2.elem(i))) \ + { \ + gripe_nan_to_logical_conversion (); \ + return r; \ + } \ + else \ + r.elem(i) = (m1.elem(i) != LHS_ZERO) OP (m2.elem(i) != RHS_ZERO); \ } \ } \ else \
--- a/liboctave/oct-inttypes.h +++ b/liboctave/oct-inttypes.h @@ -408,6 +408,13 @@ }; template <class T> +bool +xisnan (const octave_int<T>&) +{ + return false; +} + +template <class T> octave_int<T> pow (const octave_int<T>& a, const octave_int<T>& b) {
--- a/scripts/general/logical.m +++ b/scripts/general/logical.m @@ -42,7 +42,11 @@ elseif (isempty (x)) y = zeros (size (x), "logical"); elseif (isnumeric (x)) - y = x != 0; + if (any (isnan (x(:)))) + error ("invalid conversion from NaN to logical"); + else + y = x != 0; + endif else error ("logical not defined for type `%s'", typeinfo (x)); endif @@ -59,4 +63,6 @@ %!assert (logical (-13), true); %!assert (logical (int8 (13)), true); %!assert (logical (int8 (-13)), true); -%!assert (logical ([-1, 0, 1, NaN, Inf]), [-1, 0, 1, NaN, Inf] != 0); +%!assert (logical ([-1, 0, 1, Inf]), [-1, 0, 1, Inf] != 0); +%!error (logical ([-1, 0, 1, NaN, Inf])) +%!error (logical (NaN))
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,13 @@ +2008-07-11 John W. Eaton <jwe@octave.org> + + * ov-float.h, ov-flt-re-mat.cc, ov-range.h, ov-re-mat.h, + ov-re-sparse.cc, ov-scalar.h: Check for NaN in bool_value and + bool_array_value member functions to bool. + + * ops.h (DEFSCALARBOOLOP_OP): New macro. + * OPERATORS/op-s-s.cc, OPERATORS/op-fs-fs.cc: Use it to define + el_and and el_or ops. + 2008-07-10 David Bateman <dbateman@free.fr> * DLD-FUNCTIONS/lookup.cc (assign): Delete.
--- a/src/OPERATORS/op-fs-fs.cc +++ b/src/OPERATORS/op-fs-fs.cc @@ -114,8 +114,8 @@ return octave_value (v2.float_value () / d); } -DEFBINOP_OP (el_and, float_scalar, float_scalar, &&) -DEFBINOP_OP (el_or, float_scalar, float_scalar, ||) +DEFSCALARBOOLOP_OP (el_and, float_scalar, float_scalar, &&) +DEFSCALARBOOLOP_OP (el_or, float_scalar, float_scalar, ||) DEFNDCATOP_FN (fs_fs, float_scalar, float_scalar, float_array, float_array, concat) DEFNDCATOP_FN (s_fs, scalar, float_scalar, float_array, float_array, concat)
--- a/src/OPERATORS/op-s-s.cc +++ b/src/OPERATORS/op-s-s.cc @@ -115,8 +115,8 @@ return octave_value (v2.double_value () / d); } -DEFBINOP_OP (el_and, scalar, scalar, &&) -DEFBINOP_OP (el_or, scalar, scalar, ||) +DEFSCALARBOOLOP_OP (el_and, scalar, scalar, &&) +DEFSCALARBOOLOP_OP (el_or, scalar, scalar, ||) DEFNDCATOP_FN (s_s, scalar, scalar, array, array, concat)
--- a/src/ops.h +++ b/src/ops.h @@ -293,6 +293,20 @@ (v1.t1 ## _value () op v2.t2 ## _value ()); \ } +#define DEFSCALARBOOLOP_OP(name, t1, t2, op) \ + BINOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ + if (xisnan (v1.t1 ## _value ()) || xisnan (v2.t2 ## _value ())) \ + { \ + error ("invalid conversion from NaN to logical"); \ + return octave_value (); \ + } \ + else \ + return octave_value \ + (v1.t1 ## _value () op v2.t2 ## _value ()); \ + } + #define DEFNDBINOP_OP(name, t1, t2, e1, e2, op) \ BINOPDECL (name, a1, a2) \ { \
--- a/src/ov-float.h +++ b/src/ov-float.h @@ -191,7 +191,9 @@ bool bool_value (bool warn = false) const { - if (warn && scalar != 0 && scalar != 1) + if (xisnan (scalar)) + error ("invalid conversion from NaN to logical"); + else if (warn && scalar != 0 && scalar != 1) gripe_logical_conversion (); return scalar; @@ -199,7 +201,9 @@ boolNDArray bool_array_value (bool warn = false) const { - if (warn && scalar != 0 && scalar != 1) + if (xisnan (scalar)) + error ("invalid conversion from NaN to logical"); + else if (warn && scalar != 0 && scalar != 1) gripe_logical_conversion (); return boolNDArray (dim_vector (1, 1), scalar);
--- a/src/ov-flt-re-mat.cc +++ b/src/ov-flt-re-mat.cc @@ -218,7 +218,9 @@ boolNDArray octave_float_matrix::bool_array_value (bool warn) const { - if (warn && matrix.any_element_not_one_or_zero ()) + if (matrix.any_element_is_nan ()) + error ("invalid conversion from NaN to logical"); + else if (warn && matrix.any_element_not_one_or_zero ()) gripe_logical_conversion (); return boolNDArray (matrix);
--- a/src/ov-range.h +++ b/src/ov-range.h @@ -227,7 +227,9 @@ { Matrix m = range.matrix_value (); - if (warn && m.any_element_not_one_or_zero ()) + if (m.any_element_is_nan ()) + error ("invalid conversion from NaN to logical"); + else if (warn && m.any_element_not_one_or_zero ()) gripe_logical_conversion (); return boolNDArray (m);
--- a/src/ov-re-mat.cc +++ b/src/ov-re-mat.cc @@ -224,7 +224,9 @@ boolNDArray octave_matrix::bool_array_value (bool warn) const { - if (warn && matrix.any_element_not_one_or_zero ()) + if (matrix.any_element_is_nan ()) + error ("invalid conversion from NaN to logical"); + else if (warn && matrix.any_element_not_one_or_zero ()) gripe_logical_conversion (); return boolNDArray (matrix);
--- a/src/ov-re-sparse.cc +++ b/src/ov-re-sparse.cc @@ -150,7 +150,9 @@ { NDArray m = matrix.matrix_value (); - if (warn && m.any_element_not_one_or_zero ()) + if (m.any_element_is_nan ()) + error ("invalid conversion from NaN to logical"); + else if (warn && m.any_element_not_one_or_zero ()) gripe_logical_conversion (); return boolNDArray (m);
--- a/src/ov-scalar.h +++ b/src/ov-scalar.h @@ -192,7 +192,9 @@ bool bool_value (bool warn = false) const { - if (warn && scalar != 0 && scalar != 1) + if (xisnan (scalar)) + error ("invalid conversion from NaN to logical"); + else if (warn && scalar != 0 && scalar != 1) gripe_logical_conversion (); return scalar; @@ -200,7 +202,9 @@ boolNDArray bool_array_value (bool warn = false) const { - if (warn && scalar != 0 && scalar != 1) + if (xisnan (scalar)) + error ("invalid conversion from NaN to logical"); + else if (warn && scalar != 0 && scalar != 1) gripe_logical_conversion (); return boolNDArray (dim_vector (1, 1), scalar);