# HG changeset patch # User David Bateman # Date 1219171595 14400 # Node ID cd90e28420808a8bd689670c17376f03c365a0f5 # Parent aa6484781a5be74f94b58ecb3087fcc13d663c51 Add additional integer math and conversion warnings, set their default state to be off and add the intwarning function diff --git a/doc/ChangeLog b/doc/ChangeLog --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,7 @@ +2008-08-19 David Bateman + + * interpreter/numbers.txi: Document intwarning. + 2008-08-06 Søren Hauberg * interpreter/basics.txi, interpreter/errors.txi, diff --git a/doc/interpreter/numbers.txi b/doc/interpreter/numbers.txi --- a/doc/interpreter/numbers.txi +++ b/doc/interpreter/numbers.txi @@ -492,6 +492,8 @@ @DOCSTRING(intmin) +@DOCSTRING(intwarning) + @menu * Integer Arithmetic:: @end menu diff --git a/liboctave/ChangeLog b/liboctave/ChangeLog --- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,35 @@ +2008-08-19 David Bateman + + * oct-inttypes.h (template inline T2 + octave_int_fit_to_range (const T1&, const T2&, const T2&), + template inline T octave_int_fit_to_range (const + double&, const T&, const T&), template <> inline T2 + octave_int_fit_to_range (const T1&, const T2&, const T2&), + OCTAVE_S_US_FTR): Check and flag integer trunctation. + (OCTAVE_INT_FIT_TO_RANGE, OCTAVE_INT_FIT_TO_RANGE2): Adapt for the + above change. + (OCTAVE_INT_CONV_FIT_TO_RANGE): New macro for conversion to + integer types. + (octave_int::conv_error_type): New enum to flag conversion and + math warnings. + (octave_int::octave_int (U i), octave_int::octave_int + (double i), octave_int<>::octave_int (const octave_int& i)): + Flag conversion and math errors other than integer truncation. + (octave_int octave_int::operator - (void)): Flag truncation + error. + (static bool get_trunc_flag (void), static bool clear_trunc_flag + (void, static bool trunc_flag)): Delete. + (static int get_conv_flag (void), static bool get_trunc_flag (void), + static bool get_nan_flag (void), static bool get_non_int_flag (void), + static bool get_math_trunc_flag (void), static void + clear_conv_flag (void)): New functions to query and reset + conversion and mathw arning state. + (static int cov_flag): New parameter holding current conversion + and math warning state. Set it to zero. + (template octave_int powf (float, const + octave_int&), template octave_int powf (const + octave_int&, float)): New functions. + 2008-08-12 Jaroslav Hajek * lo-ieee.cc (octave_ieee_init): Try to ensure that octave_NaN is diff --git a/liboctave/oct-inttypes.h b/liboctave/oct-inttypes.h --- a/liboctave/oct-inttypes.h +++ b/liboctave/oct-inttypes.h @@ -124,16 +124,26 @@ template inline T2 -octave_int_fit_to_range (const T1& x, const T2& mn, const T2& mx) +octave_int_fit_to_range (const T1& x, const T2& mn, const T2& mx, + int& conv_flag, int math_truncate) { - return (x > mx ? mx : (x < mn ? mn : T2 (x))); + bool out_of_range_max = x > mx; + bool out_of_range_min = x < mn; + conv_flag |= (out_of_range_max || out_of_range_min ? math_truncate : 0); + return (out_of_range_max ? mx : (out_of_range_min ? mn : T2 (x))); } template inline T -octave_int_fit_to_range (const double& x, const T& mn, const T& mx) +octave_int_fit_to_range (const double& x, const T& mn, const T& mx, + int& conv_flag, int math_truncate) { - return (__lo_ieee_isnan (x) ? 0 : (x > mx ? mx : (x < mn ? mn : static_cast (x)))); + bool out_of_range_max = x > mx; + bool out_of_range_min = x < mn; + conv_flag |= (out_of_range_max || out_of_range_min ? math_truncate : 0); + return (__lo_ieee_isnan (x) + ? 0 : (out_of_range_max + ? mx : (out_of_range_min ? mn : static_cast (x)))); } // If X is unsigned and the new type is signed, then we only have to @@ -145,9 +155,12 @@ #define OCTAVE_US_S_FTR(T1, T2, TC) \ template <> \ inline T2 \ - octave_int_fit_to_range (const T1& x, const T2&, const T2& mx) \ + octave_int_fit_to_range (const T1& x, const T2&, const T2& mx, \ + int& conv_flag, int math_truncate) \ { \ - return x > static_cast (mx) ? mx : x; \ + bool out_of_range = x > static_cast (mx); \ + conv_flag |= (out_of_range ? math_truncate : 0); \ + return out_of_range ? mx : x; \ } #define OCTAVE_US_S_FTR_FCNS(T) \ @@ -172,10 +185,13 @@ #define OCTAVE_S_US_FTR(T1, T2) \ template <> \ inline T2 \ - octave_int_fit_to_range (const T1& x, const T2&, const T2&) \ + octave_int_fit_to_range (const T1& x, const T2&, const T2&, \ + int& conv_flag, int math_truncate) \ { \ + bool out_of_range = x < 0; \ + conv_flag |= (out_of_range ? math_truncate : 0); \ return x <= 0 ? 0 : x; \ - } + } #define OCTAVE_S_US_FTR_FCNS(T) \ OCTAVE_S_US_FTR (T, unsigned char) \ @@ -191,10 +207,19 @@ OCTAVE_S_US_FTR_FCNS (long) OCTAVE_S_US_FTR_FCNS (long long) +#define OCTAVE_INT_CONV_FIT_TO_RANGE(r, T) \ + octave_int_fit_to_range (r, \ + std::numeric_limits::min (), \ + std::numeric_limits::max (), \ + octave_int::conv_flag, \ + octave_int::int_truncate) + #define OCTAVE_INT_FIT_TO_RANGE(r, T) \ octave_int_fit_to_range (r, \ std::numeric_limits::min (), \ - std::numeric_limits::max ()) + std::numeric_limits::max (), \ + octave_int::conv_flag, \ + octave_int::math_truncate) #define OCTAVE_INT_MIN_VAL2(T1, T2) \ std::numeric_limits::TR>::min () @@ -205,7 +230,9 @@ #define OCTAVE_INT_FIT_TO_RANGE2(r, T1, T2) \ octave_int_fit_to_range (r, \ OCTAVE_INT_MIN_VAL2 (T1, T2), \ - OCTAVE_INT_MAX_VAL2 (T1, T2)) + OCTAVE_INT_MAX_VAL2 (T1, T2), \ + octave_int::TR>::conv_flag, \ + octave_int::TR>::math_truncate) // We have all the machinery below (octave_int_helper) to avoid a few // warnings from GCC about comparisons always false due to limited @@ -268,24 +295,34 @@ octave_int { public: + enum conv_error_type + { + int_truncate = 1, + conv_nan = 2, + conv_non_int = 4, + math_truncate = 8 + }; typedef T val_type; octave_int (void) : ival () { } template - octave_int (U i) : ival (OCTAVE_INT_FIT_TO_RANGE (i, T)) { } + octave_int (U i) : ival (OCTAVE_INT_CONV_FIT_TO_RANGE (i, T)) { } - octave_int (double d) : ival (OCTAVE_INT_FIT_TO_RANGE (xround (d), T)) { } + octave_int (double d) : ival (OCTAVE_INT_CONV_FIT_TO_RANGE (xround (d), T)) + { + if (xisnan (d)) + conv_flag |= conv_nan; + else + conv_flag |= (d != xround (d) ? conv_non_int : 0); + } octave_int (bool b) : ival (b) { } template octave_int (const octave_int& i) - : ival (OCTAVE_INT_FIT_TO_RANGE (i.value (), T)) - { - trunc_flag = trunc_flag || (ival != i.value ()); - } + : ival (OCTAVE_INT_CONV_FIT_TO_RANGE (i.value (), T)) { } octave_int (const octave_int& i) : ival (i.ival) { } @@ -312,9 +349,13 @@ // symmetric, which causes things like -intmin("int32") to be the // same as intmin("int32") instead of intmax("int32") (which is // what we should get with saturation semantics). - - return std::numeric_limits::is_signed ? - OCTAVE_INT_FIT_TO_RANGE (- static_cast (ival), T) : 0; + if (std::numeric_limits::is_signed) + return OCTAVE_INT_FIT_TO_RANGE (- static_cast (ival), T); + else + { + conv_flag |= math_truncate; + return 0; + } } bool bool_value (void) const { return static_cast (value ()); } @@ -402,8 +443,12 @@ static int byte_size (void) { return sizeof(T); } - static bool get_trunc_flag () { return trunc_flag; } - static void clear_trunc_flag () { trunc_flag = false; } + static int get_conv_flag () { return conv_flag; } + static bool get_trunc_flag () { return (conv_flag & int_truncate); } + static bool get_nan_flag () { return (conv_flag & conv_nan); } + static bool get_non_int_flag () { return (conv_flag & conv_non_int); } + static bool get_math_trunc_flag () { return (conv_flag & math_truncate); } + static void clear_conv_flag () { conv_flag = 0; } static const char *type_name () { return "unknown type"; } @@ -411,13 +456,14 @@ // You should not use it anywhere else. void *mex_get_data (void) const { return const_cast (&ival); } + static int conv_flag; + private: - static bool trunc_flag; T ival; }; -template bool octave_int::trunc_flag = false; +template int octave_int::conv_flag = 0; template bool @@ -484,6 +530,26 @@ } template +octave_int +powf (float a, const octave_int& b) +{ + float tb = static_cast (b.value ()); + float r = powf (a, tb); + r = __lo_ieee_float_isnan (r) ? 0 : xround (r); + return OCTAVE_INT_FIT_TO_RANGE (r, T); +} + +template +octave_int +powf (const octave_int& a, float b) +{ + float ta = static_cast (a.value ()); + float r = pow (ta, b); + r = __lo_ieee_float_isnan (r) ? 0 : xround (r); + return OCTAVE_INT_FIT_TO_RANGE (r, T); +} + +template std::ostream& operator << (std::ostream& os, const octave_int& ival) { diff --git a/scripts/ChangeLog b/scripts/ChangeLog --- a/scripts/ChangeLog +++ b/scripts/ChangeLog @@ -4,7 +4,10 @@ 2008-08-19 David Bateman - statistics/base/ranks.m: Doc fix. + * miscellaneous/intwarning.m: New function. + * miscellaneous/Makefile.in (SOURCES): Add it here. + + * statistics/base/ranks.m: Doc fix. 2008-08-08 John W. Eaton diff --git a/scripts/miscellaneous/Makefile.in b/scripts/miscellaneous/Makefile.in --- a/scripts/miscellaneous/Makefile.in +++ b/scripts/miscellaneous/Makefile.in @@ -37,11 +37,11 @@ compare_versions.m computer.m copyfile.m debug.m \ delete.m dir.m doc.m dos.m dump_prefs.m edit.m \ fileattrib.m fileparts.m flops.m fullfile.m getfield.m gunzip.m gzip.m \ - info.m inputname.m ismac.m ispc.m isunix.m license.m list_primes.m ls.m \ - ls_command.m menu.m mex.m mexext.m mkoctfile.m movefile.m \ - namelengthmax.m news.m orderfields.m pack.m paren.m parseparams.m perl.m\ - run.m semicolon.m setfield.m substruct.m swapbytes.m symvar.m \ - tar.m tempdir.m tempname.m texas_lotto.m unix.m unpack.m untar.m \ + info.m inputname.m intwarning.m ismac.m ispc.m isunix.m license.m \ + list_primes.m ls.m ls_command.m menu.m mex.m mexext.m mkoctfile.m \ + movefile.m namelengthmax.m news.m orderfields.m pack.m paren.m \ + parseparams.m perl.m run.m semicolon.m setfield.m substruct.m swapbytes.m \ + symvar.m tar.m tempdir.m tempname.m texas_lotto.m unix.m unpack.m untar.m \ unzip.m ver.m version.m warning_ids.m what.m xor.m zip.m DISTFILES = $(addprefix $(srcdir)/, Makefile.in $(SOURCES)) diff --git a/scripts/miscellaneous/intwarning.m b/scripts/miscellaneous/intwarning.m new file mode 100644 --- /dev/null +++ b/scripts/miscellaneous/intwarning.m @@ -0,0 +1,125 @@ +## Copyright (C) 2008 David Bateman +## +## This file is part of Octave. +## +## Octave 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. +## +## Octave 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 Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} intwarning (@var{action}) +## @deftypefnx {Function File} {} intwarning (@var{s}) +## @deftypefnx {Function File} {@var{s} =} intwarning (@dots{}) +## Control the state of the warning for integer conversions and math +## operations. +## +## @table @asis +## @item "query" +## The state of the Octave integer conversion and math warnings is +## queried. If there is no output argument, then the state is printed. +## Otherwise it is returned in a structure with the fields "identifier" +## and "state". +## +## @example +## intwarning ("query") +## The state of warning "Octave:int-convert-nan" is "off" +## The state of warning "Octave:int-convert-non-int-val" is "off" +## The state of warning "Octave:int-convert-overflow" is "off" +## The state of warning "Octave:int-math-overflow" is "off" +## @end example +## +## @item "on" +## Turn integer conversion and math warnings "on". If there is no output +## argument, then nothing is printed. Otherwise the original state of +## the state of the integer conversion and math warnings is returned in +## a structure array. +## +## @item "off" +## Turn integer conversion and math warnings "on". If there is no output +## argument, then nothing is printed. Otherwise the original state of +## the state of the integer conversion and math warnings is returned in +## a structure array. +## @end table +## +## The original state of the integer warnings can be restored by passing +## the structure array returned by @code{intwarning} to a later call to +## @code{intwarning}. For example +## +## @example +## s = intwarning ("off"); +## @dots{} +## intwarning (s); +## @end example +## @seealso{warning} +## @end deftypefn + +## PKG_ADD: mark_as_command intwarning + +function y = intwarning (x) + + if (nargin != 1) + print_usage (); + else + if (nargout > 0) + y = warning("query", "Octave:int-convert-nan"); + y = [y; warning("query", "Octave:int-convert-non-int-val")]; + y = [y; warning("query", "Octave:int-convert-overflow")]; + y = [y; warning("query", "Octave:int-math-overflow")]; + endif + if (ischar (x)) + if (strcmpi (x, "query")) + if (nargout == 0) + __print_int_warn_state__ ("Octave:int-convert-nan"); + __print_int_warn_state__ ("Octave:int-convert-non-int-val"); + __print_int_warn_state__ ("Octave:int-convert-overflow"); + __print_int_warn_state__ ("Octave:int-math-overflow"); + printf("\n"); + endif + elseif (strcmpi (x, "on")) + warning ("on", "Octave:int-convert-nan"); + warning ("on", "Octave:int-convert-non-int-val"); + warning ("on", "Octave:int-convert-overflow"); + warning ("on", "Octave:int-math-overflow"); + elseif (strcmpi (x, "off")) + warning ("off", "Octave:int-convert-nan"); + warning ("off", "Octave:int-convert-non-int-val"); + warning ("off", "Octave:int-convert-overflow"); + warning ("off", "Octave:int-math-overflow"); + else + error ("intwarning: unrecognized argument"); + endif + elseif (isstruct(x)) + for fld = fieldnames (x) + if (strcmp ("Octave:int-convert-nan") || + strcmp ("Octave:int-convert-non-int-val") || + strcmp ("Octave:int-convert-overflow") || + strcmp ("Octave:int-cmath-overflow")) + s = getfield (x, fld); + if (! ischar (s) || !(strcmpi("s","on") || strcmpi("s","off"))) + error ("intwarning: unexpected warning state"); + endif + warning (s, fld); + else + error ("intwarning: unrecognized integer warning %s", fld); + endif + endfor + else + error ("intwarning: unexpected input"); + endif + endif +endfunction + +function __print_int_warn_state__ (s) + fprintf ("The state of warning \"%s\" is \"%s\"\n", + s, warning ("query", s).state); +endfunction diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -24,6 +24,39 @@ * parse.y (Feval): Return value produced by evaluating CATCH string. +2008-08-19 David Bateman + + * OPERATORS/op-int-conv.cc (DEFINTCONVFN): New macro that warn + for integer conversion issues. Use it to replace DEFCONVFN. + * OPERATORS/op-int.h (DEFINTBINOP_OP, DEFINTNDBINOP_OP, + DEFINTBINOP_FN, DEFINTNDBINOP_FN): New macros that warn for + integer truncation issues. Use them to replace the corresponding + macros in the integer arithmetic macros. Update other integer + arithmetic functions that don't use these macros individually. + * error.cc (initialize_default_warning_state (void)): Initialize + the default warning state for the integer warnings to be off. + * gripes.cc (void gripe_binop_integer_math_truncated (const char *, + const char *, const char *), void gripe_unop_integer_math_truncated + (const char *, const char *), void gripe_non_integer_conversion + (const char *, const char *), void gripe_nan_conversion (const char *, + const char *)): Warning functions for integer conversion and math + issues. + * gripes.h (void gripe_binop_integer_math_truncated (const char *, + const char *, const char *), void gripe_unop_integer_math_truncated + (const char *, const char *), void gripe_non_integer_conversion + (const char *, const char *), void gripe_nan_conversion (const char *, + const char *)): Declare them. + * ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::convert_gripe, + OCTAVE_VALUE_INT_SCALAR_T::convert_gripe): Adapt for new means of + flagging integer truncation. + (OCTAVE_VALUE_INT_MATRIX_T::decrement, + OCTAVE_VALUE_INT_MATRIX_T::increment, + OCTAVE_VALUE_INT_SCALAR_T::decrement, + OCTAVE_VALUE_INT_SCALAR_T::increment): Check for integer + truncation. + * ov.cc (convert_to_int_array): Adapt for new means of + flagging integer truncation. + 2008-08-12 John W. Eaton * pt-fcn-handle.cc (tree_anon_fcn_handle::rvalue): diff --git a/src/OPERATORS/op-int-conv.cc b/src/OPERATORS/op-int-conv.cc --- a/src/OPERATORS/op-int-conv.cc +++ b/src/OPERATORS/op-int-conv.cc @@ -46,47 +46,67 @@ #include "ov-typeinfo.h" #include "ops.h" +#define DEFINTCONVFN(name, tfrom, tto) \ + CONVDECL (name) \ + { \ + CAST_CONV_ARG (const octave_ ## tfrom&); \ + \ + octave_ ## tto ::clear_conv_flag (); \ + octave_ ## tto ## _matrix v2 = v.tto ## _array_value (); \ + if (octave_ ## tto ::get_trunc_flag ()) \ + gripe_truncated_conversion (v.type_name (). c_str (), \ + v2.type_name (). c_str ()); \ + if (octave_ ## tto ::get_nan_flag ()) \ + gripe_nan_conversion (v.type_name (). c_str (), \ + v2.type_name (). c_str ()); \ + if (octave_ ## tto ::get_non_int_flag ()) \ + gripe_non_integer_conversion (v.type_name (). c_str (), \ + v2.type_name (). c_str ()); \ + octave_ ## tto ::clear_conv_flag (); \ + return new octave_ ## tto ## _matrix (v2); \ + } + // conversion ops -DEFCONVFN (scalar_to_int8, scalar, int8) -DEFCONVFN (scalar_to_int16, scalar, int16) -DEFCONVFN (scalar_to_int32, scalar, int32) -DEFCONVFN (scalar_to_int64, scalar, int64) +DEFINTCONVFN (scalar_to_int8, scalar, int8) +DEFINTCONVFN (scalar_to_int16, scalar, int16) +DEFINTCONVFN (scalar_to_int32, scalar, int32) +DEFINTCONVFN (scalar_to_int64, scalar, int64) -DEFCONVFN (scalar_to_uint8, scalar, uint8) -DEFCONVFN (scalar_to_uint16, scalar, uint16) -DEFCONVFN (scalar_to_uint32, scalar, uint32) -DEFCONVFN (scalar_to_uint64, scalar, uint64) +DEFINTCONVFN (scalar_to_uint8, scalar, uint8) +DEFINTCONVFN (scalar_to_uint16, scalar, uint16) +DEFINTCONVFN (scalar_to_uint32, scalar, uint32) +DEFINTCONVFN (scalar_to_uint64, scalar, uint64) -DEFCONVFN (matrix_to_int8, matrix, int8) -DEFCONVFN (matrix_to_int16, matrix, int16) -DEFCONVFN (matrix_to_int32, matrix, int32) -DEFCONVFN (matrix_to_int64, matrix, int64) +DEFINTCONVFN (matrix_to_int8, matrix, int8) +DEFINTCONVFN (matrix_to_int16, matrix, int16) +DEFINTCONVFN (matrix_to_int32, matrix, int32) +DEFINTCONVFN (matrix_to_int64, matrix, int64) -DEFCONVFN (matrix_to_uint8, matrix, uint8) -DEFCONVFN (matrix_to_uint16, matrix, uint16) -DEFCONVFN (matrix_to_uint32, matrix, uint32) -DEFCONVFN (matrix_to_uint64, matrix, uint64) +DEFINTCONVFN (matrix_to_uint8, matrix, uint8) +DEFINTCONVFN (matrix_to_uint16, matrix, uint16) +DEFINTCONVFN (matrix_to_uint32, matrix, uint32) +DEFINTCONVFN (matrix_to_uint64, matrix, uint64) -DEFCONVFN (float_scalar_to_int8, float_scalar, int8) -DEFCONVFN (float_scalar_to_int16, float_scalar, int16) -DEFCONVFN (float_scalar_to_int32, float_scalar, int32) -DEFCONVFN (float_scalar_to_int64, float_scalar, int64) +DEFINTCONVFN (float_scalar_to_int8, float_scalar, int8) +DEFINTCONVFN (float_scalar_to_int16, float_scalar, int16) +DEFINTCONVFN (float_scalar_to_int32, float_scalar, int32) +DEFINTCONVFN (float_scalar_to_int64, float_scalar, int64) -DEFCONVFN (float_scalar_to_uint8, float_scalar, uint8) -DEFCONVFN (float_scalar_to_uint16, float_scalar, uint16) -DEFCONVFN (float_scalar_to_uint32, float_scalar, uint32) -DEFCONVFN (float_scalar_to_uint64, float_scalar, uint64) +DEFINTCONVFN (float_scalar_to_uint8, float_scalar, uint8) +DEFINTCONVFN (float_scalar_to_uint16, float_scalar, uint16) +DEFINTCONVFN (float_scalar_to_uint32, float_scalar, uint32) +DEFINTCONVFN (float_scalar_to_uint64, float_scalar, uint64) -DEFCONVFN (float_matrix_to_int8, float_matrix, int8) -DEFCONVFN (float_matrix_to_int16, float_matrix, int16) -DEFCONVFN (float_matrix_to_int32, float_matrix, int32) -DEFCONVFN (float_matrix_to_int64, float_matrix, int64) +DEFINTCONVFN (float_matrix_to_int8, float_matrix, int8) +DEFINTCONVFN (float_matrix_to_int16, float_matrix, int16) +DEFINTCONVFN (float_matrix_to_int32, float_matrix, int32) +DEFINTCONVFN (float_matrix_to_int64, float_matrix, int64) -DEFCONVFN (float_matrix_to_uint8, float_matrix, uint8) -DEFCONVFN (float_matrix_to_uint16, float_matrix, uint16) -DEFCONVFN (float_matrix_to_uint32, float_matrix, uint32) -DEFCONVFN (float_matrix_to_uint64, float_matrix, uint64) +DEFINTCONVFN (float_matrix_to_uint8, float_matrix, uint8) +DEFINTCONVFN (float_matrix_to_uint16, float_matrix, uint16) +DEFINTCONVFN (float_matrix_to_uint32, float_matrix, uint32) +DEFINTCONVFN (float_matrix_to_uint64, float_matrix, uint64) DEFCONVFN (bool_to_int8, bool, int8) DEFCONVFN (bool_to_int16, bool, int16) @@ -128,15 +148,15 @@ DEFSTRINTCONVFN (char_matrix_dq_str_to_uint32, uint32) DEFSTRINTCONVFN (char_matrix_dq_str_to_uint64, uint64) -DEFCONVFN (range_to_int8, range, int8) -DEFCONVFN (range_to_int16, range, int16) -DEFCONVFN (range_to_int32, range, int32) -DEFCONVFN (range_to_int64, range, int64) +DEFINTCONVFN (range_to_int8, range, int8) +DEFINTCONVFN (range_to_int16, range, int16) +DEFINTCONVFN (range_to_int32, range, int32) +DEFINTCONVFN (range_to_int64, range, int64) -DEFCONVFN (range_to_uint8, range, uint8) -DEFCONVFN (range_to_uint16, range, uint16) -DEFCONVFN (range_to_uint32, range, uint32) -DEFCONVFN (range_to_uint64, range, uint64) +DEFINTCONVFN (range_to_uint8, range, uint8) +DEFINTCONVFN (range_to_uint16, range, uint16) +DEFINTCONVFN (range_to_uint32, range, uint32) +DEFINTCONVFN (range_to_uint64, range, uint64) #define INT_CONV_FUNCTIONS(tfrom) \ DEFCONVFN2 (tfrom ## _scalar_to_int8, tfrom, scalar, int8) \ diff --git a/src/OPERATORS/op-int.h b/src/OPERATORS/op-int.h --- a/src/OPERATORS/op-int.h +++ b/src/OPERATORS/op-int.h @@ -22,6 +22,56 @@ #include "quit.h" +#define DEFINTBINOP_OP(name, t1, t2, op, t3) \ + BINOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ + octave_value retval = octave_value \ + (v1.t1 ## _value () op v2.t2 ## _value ()); \ + if (octave_ ## t3 ::get_math_trunc_flag ()) \ + gripe_binop_integer_math_truncated (#op, v1.type_name (). c_str (), \ + v2.type_name (). c_str ()); \ + octave_ ## t3 ::clear_conv_flag (); \ + return retval; \ + } + +#define DEFINTNDBINOP_OP(name, t1, t2, e1, e2, op, t3) \ + BINOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ + octave_value retval = octave_value \ + (v1.e1 ## _value () op v2.e2 ## _value ()); \ + if (octave_ ## t3 ::get_math_trunc_flag ()) \ + gripe_binop_integer_math_truncated (#op, v1.type_name (). c_str (), \ + v2.type_name (). c_str ()); \ + octave_ ## t3 ::clear_conv_flag (); \ + return retval; \ + } + +#define DEFINTBINOP_FN(name, t1, t2, f, t3, op) \ + BINOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ + octave_value retval = octave_value (f (v1.t1 ## _value (), v2.t2 ## _value ())); \ + if (octave_ ## t3 ::get_math_trunc_flag ()) \ + gripe_binop_integer_math_truncated (#op, v1.type_name (). c_str (), \ + v2.type_name (). c_str ()); \ + octave_ ## t3 ::clear_conv_flag (); \ + return retval; \ + } + +#define DEFINTNDBINOP_FN(name, t1, t2, e1, e2, f, t3, op) \ + BINOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ + octave_value retval = octave_value (f (v1.e1 ## _value (), v2.e2 ## _value ())); \ + if (octave_ ## t3 ::get_math_trunc_flag ()) \ + gripe_binop_integer_math_truncated (#op, v1.type_name (). c_str (), \ + v2.type_name (). c_str ()); \ + octave_ ## t3 ::clear_conv_flag (); \ + return retval; \ + } + #define OCTAVE_CONCAT_FN2(T1, T2) \ DEFNDCATOP_FN2 (T1 ## _ ## T2 ## _s_s, T1 ## _scalar, T2 ## _scalar, , T1 ## NDArray, T1 ## _array, T2 ## _array, concat) \ DEFNDCATOP_FN2 (T1 ## _ ## T2 ## _s_m, T1 ## _scalar, T2 ## _matrix, , T1 ## NDArray, T1 ## _array, T2 ## _array, concat) \ @@ -122,19 +172,27 @@ \ DEFUNOP_OP (s_not, TYPE ## _scalar, !) \ DEFUNOP_OP (s_uplus, TYPE ## _scalar, /* no-op */) \ - DEFUNOP_OP (s_uminus, TYPE ## _scalar, -) \ + DEFUNOP (s_uminus, TYPE ## _scalar) \ + { \ + CAST_UNOP_ARG (const octave_ ## TYPE ## _scalar &); \ + octave_value retval = octave_value (- v. TYPE ## _scalar_value ()); \ + if (octave_ ## TYPE ::get_math_trunc_flag ()) \ + gripe_unop_integer_math_truncated ("-", v.type_name (). c_str ()); \ + octave_ ## TYPE ::clear_conv_flag (); \ + return retval; \ + } \ DEFUNOP_OP (s_transpose, TYPE ## _scalar, /* no-op */) \ DEFUNOP_OP (s_hermitian, TYPE ## _scalar, /* no-op */) \ \ DEFNCUNOP_METHOD (s_incr, TYPE ## _scalar, increment) \ DEFNCUNOP_METHOD (s_decr, TYPE ## _scalar, decrement) -#define OCTAVE_SS_INT_ARITH_OPS(PFX, T1, T2) \ +#define OCTAVE_SS_INT_ARITH_OPS(PFX, T1, T2, T3) \ /* scalar by scalar ops. */ \ \ - DEFBINOP_OP (PFX ## _add, T1 ## scalar, T2 ## scalar, +) \ - DEFBINOP_OP (PFX ## _sub, T1 ## scalar, T2 ## scalar, -) \ - DEFBINOP_OP (PFX ## _mul, T1 ## scalar, T2 ## scalar, *) \ + DEFINTBINOP_OP (PFX ## _add, T1 ## scalar, T2 ## scalar, +, T3) \ + DEFINTBINOP_OP (PFX ## _sub, T1 ## scalar, T2 ## scalar, -, T3) \ + DEFINTBINOP_OP (PFX ## _mul, T1 ## scalar, T2 ## scalar, *, T3) \ \ DEFBINOP (PFX ## _div, T1 ## scalar, T2 ## scalar) \ { \ @@ -143,10 +201,15 @@ if (! v2.T2 ## scalar_value ()) \ gripe_divide_by_zero (); \ \ - return octave_value (v1.T1 ## scalar_value () / v2.T2 ## scalar_value ()); \ + octave_value retval = octave_value (v1.T1 ## scalar_value () / v2.T2 ## scalar_value ()); \ + if (octave_ ## T3 ::get_math_trunc_flag ()) \ + gripe_binop_integer_math_truncated ("/", v1.type_name (). c_str (), \ + v2.type_name (). c_str ()); \ + octave_ ## T3 ::clear_conv_flag (); \ + return retval; \ } \ \ - DEFBINOP_FN (PFX ## _pow, T1 ## scalar, T2 ## scalar, xpow) \ + DEFINTBINOP_FN (PFX ## _pow, T1 ## scalar, T2 ## scalar, xpow, T3, ^) \ \ DEFBINOP (PFX ## _ldiv, T1 ## scalar, T2 ## scalar) \ { \ @@ -155,10 +218,15 @@ if (! v1.T1 ## scalar_value ()) \ gripe_divide_by_zero (); \ \ - return octave_value (v2.T2 ## scalar_value () / v1.T1 ## scalar_value ()); \ + octave_value retval = octave_value (v2.T2 ## scalar_value () / v1.T1 ## scalar_value ()); \ + if (octave_ ## T3 ::get_math_trunc_flag ()) \ + gripe_binop_integer_math_truncated ("\\", v1.type_name (). c_str (), \ + v2.type_name (). c_str ()); \ + octave_ ## T3 ::clear_conv_flag (); \ + return retval; \ } \ \ - DEFBINOP_OP (PFX ## _el_mul, T1 ## scalar, T2 ## scalar, *) \ + DEFINTBINOP_OP (PFX ## _el_mul, T1 ## scalar, T2 ## scalar, *, T3) \ \ DEFBINOP (PFX ## _el_div, T1 ## scalar, T2 ## scalar) \ { \ @@ -167,10 +235,15 @@ if (! v2.T2 ## scalar_value ()) \ gripe_divide_by_zero (); \ \ - return octave_value (v1.T1 ## scalar_value () / v2.T2 ## scalar_value ()); \ + octave_value retval = octave_value (v1.T1 ## scalar_value () / v2.T2 ## scalar_value ()); \ + if (octave_ ## T3 ::get_math_trunc_flag ()) \ + gripe_binop_integer_math_truncated (".\\", v1.type_name (). c_str (), \ + v2.type_name (). c_str ()); \ + octave_ ## T3 ::clear_conv_flag (); \ + return retval; \ } \ \ - DEFBINOP_FN (PFX ## _el_pow, T1 ## scalar, T2 ## scalar, xpow) \ + DEFINTBINOP_FN (PFX ## _el_pow, T1 ## scalar, T2 ## scalar, xpow, T3, .^) \ \ DEFBINOP (PFX ## _el_ldiv, T1 ## scalar, T2 ## scalar) \ { \ @@ -179,7 +252,12 @@ if (! v1.T1 ## scalar_value ()) \ gripe_divide_by_zero (); \ \ - return octave_value (v2.T2 ## scalar_value () / v1.T1 ## scalar_value ()); \ + octave_value retval = octave_value (v2.T2 ## scalar_value () / v1.T1 ## scalar_value ()); \ + if (octave_ ## T3 ::get_math_trunc_flag ()) \ + gripe_binop_integer_math_truncated (".\\", v1.type_name (). c_str (), \ + v2.type_name (). c_str ()); \ + octave_ ## T3 ::clear_conv_flag (); \ + return retval; \ } \ #define OCTAVE_SS_INT_BOOL_OPS(PFX, T1, T2, Z1, Z2) \ @@ -239,11 +317,11 @@ #define OCTAVE_SS_INT_OPS(TYPE) \ OCTAVE_S_INT_UNOPS (TYPE) \ OCTAVE_SS_POW_OPS (TYPE, TYPE) \ - OCTAVE_SS_INT_ARITH_OPS (ss, TYPE ## _, TYPE ## _) \ - OCTAVE_SS_INT_ARITH_OPS (ssx, TYPE ## _, ) \ - OCTAVE_SS_INT_ARITH_OPS (sxs, , TYPE ## _) \ - OCTAVE_SS_INT_ARITH_OPS (ssfx, TYPE ## _, float_) \ - OCTAVE_SS_INT_ARITH_OPS (sfxs, float_, TYPE ## _) \ + OCTAVE_SS_INT_ARITH_OPS (ss, TYPE ## _, TYPE ## _, TYPE) \ + OCTAVE_SS_INT_ARITH_OPS (ssx, TYPE ## _, , TYPE) \ + OCTAVE_SS_INT_ARITH_OPS (sxs, , TYPE ## _, TYPE) \ + OCTAVE_SS_INT_ARITH_OPS (ssfx, TYPE ## _, float_, TYPE) \ + OCTAVE_SS_INT_ARITH_OPS (sfxs, float_, TYPE ## _, TYPE) \ OCTAVE_SS_INT_CMP_OPS (ss, TYPE ## _, TYPE ## _) \ OCTAVE_SS_INT_CMP_OPS (sx, TYPE ## _, ) \ OCTAVE_SS_INT_CMP_OPS (xs, , TYPE ## _) \ @@ -255,12 +333,12 @@ OCTAVE_SS_INT_BOOL_OPS (sfx, TYPE ## _, float_, octave_ ## TYPE (0), 0) \ OCTAVE_SS_INT_BOOL_OPS (fxs, float_, TYPE ## _, 0, octave_ ## TYPE (0)) -#define OCTAVE_SM_INT_ARITH_OPS(PFX, TS, TM) \ +#define OCTAVE_SM_INT_ARITH_OPS(PFX, TS, TM, TI) \ /* scalar by matrix ops. */ \ \ - DEFNDBINOP_OP (PFX ## _add, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, +) \ - DEFNDBINOP_OP (PFX ## _sub, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, -) \ - DEFNDBINOP_OP (PFX ## _mul, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, *) \ + DEFINTNDBINOP_OP (PFX ## _add, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, +, TI) \ + DEFINTNDBINOP_OP (PFX ## _sub, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, -, TI) \ + DEFINTNDBINOP_OP (PFX ## _mul, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, *, TI) \ \ /* DEFBINOP (PFX ## _div, TS ## scalar, TM ## matrix) */ \ /* { */ \ @@ -281,18 +359,28 @@ if (! v1.TS ## scalar_value ()) \ gripe_divide_by_zero (); \ \ - return octave_value (v2.TS ## scalar_value () / v1.TS ## scalar_value ()); \ + octave_value retval = octave_value (v2.TS ## scalar_value () / v1.TS ## scalar_value ()); \ + if (octave_ ## TI ::get_math_trunc_flag ()) \ + gripe_binop_integer_math_truncated ("\\", v1.type_name (). c_str (), \ + v2.type_name (). c_str ()); \ + octave_ ## TI ::clear_conv_flag (); \ + return retval; \ } \ \ - DEFNDBINOP_OP (PFX ## _el_mul, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, *) \ + DEFINTNDBINOP_OP (PFX ## _el_mul, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, *, TI) \ DEFBINOP (PFX ## _el_div, TS ## scalar, TM ## matrix) \ { \ CAST_BINOP_ARGS (const octave_ ## TS ## scalar&, const octave_ ## TM ## matrix&); \ \ - return octave_value (v1.TS ## scalar_value () / v2.TM ## array_value ()); \ + octave_value retval = octave_value (v1.TS ## scalar_value () / v2.TM ## array_value ()); \ + if (octave_ ## TI ::get_math_trunc_flag ()) \ + gripe_binop_integer_math_truncated (".\\", v1.type_name (). c_str (), \ + v2.type_name (). c_str ()); \ + octave_ ## TI ::clear_conv_flag (); \ + return retval; \ } \ \ - DEFNDBINOP_FN (PFX ## _el_pow, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, elem_xpow) \ + DEFINTNDBINOP_FN (PFX ## _el_pow, TS ## scalar, TM ## matrix, TS ## scalar, TM ## array, elem_xpow, TI, .^) \ \ DEFBINOP (PFX ## _el_ldiv, TS ## scalar, TM ## matrix) \ { \ @@ -301,7 +389,12 @@ if (! v1.TS ## scalar_value ()) \ gripe_divide_by_zero (); \ \ - return octave_value (v2.TM ## array_value () / v1.TS ## scalar_value ()); \ + octave_value retval = octave_value (v2.TM ## array_value () / v1.TS ## scalar_value ()); \ + if (octave_ ## TI ::get_math_trunc_flag ()) \ + gripe_binop_integer_math_truncated (".\\", v1.type_name (). c_str (), \ + v2.type_name (). c_str ()); \ + octave_ ## TI ::clear_conv_flag (); \ + return retval; \ } #define OCTAVE_SM_INT_CMP_OPS(PFX, TS, TM) \ @@ -388,11 +481,11 @@ #define OCTAVE_SM_INT_OPS(TYPE) \ OCTAVE_SM_POW_OPS (TYPE, TYPE) \ - OCTAVE_SM_INT_ARITH_OPS (sm, TYPE ## _, TYPE ## _) \ - OCTAVE_SM_INT_ARITH_OPS (smx, TYPE ## _, ) \ - OCTAVE_SM_INT_ARITH_OPS (sxm, , TYPE ## _) \ - OCTAVE_SM_INT_ARITH_OPS (smfx, TYPE ## _, float_) \ - OCTAVE_SM_INT_ARITH_OPS (sfxm, float_, TYPE ## _) \ + OCTAVE_SM_INT_ARITH_OPS (sm, TYPE ## _, TYPE ## _, TYPE) \ + OCTAVE_SM_INT_ARITH_OPS (smx, TYPE ## _, , TYPE) \ + OCTAVE_SM_INT_ARITH_OPS (sxm, , TYPE ## _, TYPE) \ + OCTAVE_SM_INT_ARITH_OPS (smfx, TYPE ## _, float_, TYPE) \ + OCTAVE_SM_INT_ARITH_OPS (sfxm, float_, TYPE ## _, TYPE) \ OCTAVE_SM_INT_CMP_OPS (sm, TYPE ## _, TYPE ## _) \ OCTAVE_SM_INT_CMP_OPS (xm, , TYPE ## _) \ OCTAVE_SM_INT_CMP_OPS (smx, TYPE ## _, ) \ @@ -407,12 +500,12 @@ OCTAVE_SM_CONV (TYPE ## _, complex_) \ OCTAVE_SM_CONV (TYPE ## _, float_complex_) -#define OCTAVE_MS_INT_ARITH_OPS(PFX, TM, TS) \ +#define OCTAVE_MS_INT_ARITH_OPS(PFX, TM, TS, TI) \ /* matrix by scalar ops. */ \ \ - DEFNDBINOP_OP (PFX ## _add, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, +) \ - DEFNDBINOP_OP (PFX ## _sub, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, -) \ - DEFNDBINOP_OP (PFX ## _mul, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, *) \ + DEFINTNDBINOP_OP (PFX ## _add, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, +, TI) \ + DEFINTNDBINOP_OP (PFX ## _sub, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, -, TI) \ + DEFINTNDBINOP_OP (PFX ## _mul, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, *, TI) \ \ DEFBINOP (PFX ## _div, TM ## matrix, TS ## scalar) \ { \ @@ -421,7 +514,12 @@ if (! v2.TS ## scalar_value ()) \ gripe_divide_by_zero (); \ \ - return octave_value (v1.TM ## array_value () / v2.TS ## scalar_value ()); \ + octave_value retval = octave_value (v1.TM ## array_value () / v2.TS ## scalar_value ()); \ + if (octave_ ## TI ::get_math_trunc_flag ()) \ + gripe_binop_integer_math_truncated ("/", v1.type_name (). c_str (), \ + v2.type_name (). c_str ()); \ + octave_ ## TI ::clear_conv_flag (); \ + return retval; \ } \ \ /* DEFBINOP_FN (PFX ## _pow, TM ## matrix, TS ## scalar, xpow) */ \ @@ -436,7 +534,7 @@ /* return octave_value (xleftdiv (m1, m2)); */ \ /* } */ \ \ - DEFNDBINOP_OP (PFX ## _el_mul, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, *) \ + DEFINTNDBINOP_OP (PFX ## _el_mul, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, *, TI) \ \ DEFBINOP (PFX ## _el_div, TM ## matrix, TS ## scalar) \ { \ @@ -445,16 +543,26 @@ if (! v2.TS ## scalar_value ()) \ gripe_divide_by_zero (); \ \ - return octave_value (v1.TM ## array_value () / v2.TS ## scalar_value ()); \ + octave_value retval = octave_value (v1.TM ## array_value () / v2.TS ## scalar_value ()); \ + if (octave_ ## TI ::get_math_trunc_flag ()) \ + gripe_binop_integer_math_truncated ("./", v1.type_name (). c_str (), \ + v2.type_name (). c_str ()); \ + octave_ ## TI ::clear_conv_flag (); \ + return retval; \ } \ \ - DEFNDBINOP_FN (PFX ## _el_pow, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, elem_xpow) \ + DEFINTNDBINOP_FN (PFX ## _el_pow, TM ## matrix, TS ## scalar, TM ## array, TS ## scalar, elem_xpow, TI, .^) \ \ DEFBINOP (PFX ## _el_ldiv, TM ## matrix, TS ## scalar) \ { \ CAST_BINOP_ARGS (const octave_ ## TM ## matrix&, const octave_ ## TS ## scalar&); \ \ - return v2.TS ## scalar_value () / v1.TM ## array_value (); \ + octave_value retval = v2.TS ## scalar_value () / v1.TM ## array_value (); \ + if (octave_ ## TI ::get_math_trunc_flag ()) \ + gripe_binop_integer_math_truncated (".^", v1.type_name (). c_str (), \ + v2.type_name (). c_str ()); \ + octave_ ## TI ::clear_conv_flag (); \ + return retval; \ } #define OCTAVE_MS_INT_CMP_OPS(PFX, TM, TS) \ @@ -531,11 +639,11 @@ #define OCTAVE_MS_INT_OPS(TYPE) \ OCTAVE_MS_POW_OPS (TYPE, TYPE) \ - OCTAVE_MS_INT_ARITH_OPS (ms, TYPE ## _, TYPE ## _) \ - OCTAVE_MS_INT_ARITH_OPS (msx, TYPE ## _, ) \ - OCTAVE_MS_INT_ARITH_OPS (mxs, , TYPE ## _) \ - OCTAVE_MS_INT_ARITH_OPS (msfx, TYPE ## _, float_) \ - OCTAVE_MS_INT_ARITH_OPS (mfxs, float_, TYPE ## _) \ + OCTAVE_MS_INT_ARITH_OPS (ms, TYPE ## _, TYPE ## _, TYPE) \ + OCTAVE_MS_INT_ARITH_OPS (msx, TYPE ## _, , TYPE) \ + OCTAVE_MS_INT_ARITH_OPS (mxs, , TYPE ## _, TYPE) \ + OCTAVE_MS_INT_ARITH_OPS (msfx, TYPE ## _, float_, TYPE) \ + OCTAVE_MS_INT_ARITH_OPS (mfxs, float_, TYPE ## _, TYPE) \ OCTAVE_MS_INT_CMP_OPS (ms, TYPE ## _, TYPE ## _) \ OCTAVE_MS_INT_CMP_OPS (mx, TYPE ## _, ) \ OCTAVE_MS_INT_CMP_OPS (mxs, , TYPE ## _) \ @@ -555,7 +663,15 @@ \ DEFNDUNOP_OP (m_not, TYPE ## _matrix, TYPE ## _array, !) \ DEFNDUNOP_OP (m_uplus, TYPE ## _matrix, TYPE ## _array, /* no-op */) \ - DEFNDUNOP_OP (m_uminus, TYPE ## _matrix, TYPE ## _array, -) \ + DEFUNOP (m_uminus, TYPE ## _matrix) \ + { \ + CAST_UNOP_ARG (const octave_ ## TYPE ## _matrix &); \ + octave_value retval = octave_value (- v. TYPE ## _array_value ()); \ + if (octave_ ## TYPE ::get_math_trunc_flag ()) \ + gripe_unop_integer_math_truncated ("-", v.type_name (). c_str ()); \ + octave_ ## TYPE ::clear_conv_flag (); \ + return retval; \ + } \ \ DEFUNOP (m_transpose, TYPE ## _matrix) \ { \ @@ -573,11 +689,11 @@ DEFNCUNOP_METHOD (m_incr, TYPE ## _matrix, increment) \ DEFNCUNOP_METHOD (m_decr, TYPE ## _matrix, decrement) -#define OCTAVE_MM_INT_ARITH_OPS(PFX, T1, T2) \ +#define OCTAVE_MM_INT_ARITH_OPS(PFX, T1, T2, T3) \ /* matrix by matrix ops. */ \ \ - DEFNDBINOP_OP (PFX ## _add, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, +) \ - DEFNDBINOP_OP (PFX ## _sub, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, -) \ + DEFINTNDBINOP_OP (PFX ## _add, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, +, T3) \ + DEFINTNDBINOP_OP (PFX ## _sub, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, -, T3) \ \ /* DEFBINOP_OP (PFX ## _mul, T1 ## matrix, T2 ## matrix, *) */ \ /* DEFBINOP_FN (PFX ## _div, T1 ## matrix, T2 ## matrix, xdiv) */ \ @@ -590,17 +706,22 @@ \ /* DEFBINOP_FN (PFX ## _ldiv, T1 ## matrix, T2 ## matrix, xleftdiv) */ \ \ - DEFNDBINOP_FN (PFX ## _el_mul, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, product) \ + DEFINTNDBINOP_FN (PFX ## _el_mul, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, product, T3, .*) \ \ - DEFNDBINOP_FN (PFX ## _el_div, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, quotient) \ + DEFINTNDBINOP_FN (PFX ## _el_div, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, quotient, T3, ./) \ \ - DEFNDBINOP_FN (PFX ## _el_pow, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, elem_xpow) \ + DEFINTNDBINOP_FN (PFX ## _el_pow, T1 ## matrix, T2 ## matrix, T1 ## array, T2 ## array, elem_xpow, T3, .^) \ \ DEFBINOP (PFX ## _el_ldiv, T1 ## matrix, T2 ## matrix) \ { \ CAST_BINOP_ARGS (const octave_ ## T1 ## matrix&, const octave_ ## T2 ## matrix&); \ \ - return octave_value (quotient (v2.T2 ## array_value (), v1.T1 ## array_value ())); \ + octave_value retval = octave_value (quotient (v2.T2 ## array_value (), v1.T1 ## array_value ())); \ + if (octave_ ## T3 ::get_math_trunc_flag ()) \ + gripe_binop_integer_math_truncated (".\\", v1.type_name (). c_str (), \ + v2.type_name (). c_str ()); \ + octave_ ## T3 ::clear_conv_flag (); \ + return retval; \ } #define OCTAVE_MM_INT_CMP_OPS(PFX, T1, T2) \ @@ -726,11 +847,11 @@ #define OCTAVE_MM_INT_OPS(TYPE) \ OCTAVE_M_INT_UNOPS (TYPE) \ OCTAVE_MM_POW_OPS (TYPE, TYPE) \ - OCTAVE_MM_INT_ARITH_OPS (mm, TYPE ## _, TYPE ## _) \ - OCTAVE_MM_INT_ARITH_OPS (mmx, TYPE ## _, ) \ - OCTAVE_MM_INT_ARITH_OPS (mxm, , TYPE ## _) \ - OCTAVE_MM_INT_ARITH_OPS (mmfx, TYPE ## _, float_) \ - OCTAVE_MM_INT_ARITH_OPS (mfxm, float_, TYPE ## _) \ + OCTAVE_MM_INT_ARITH_OPS (mm, TYPE ## _, TYPE ## _, TYPE) \ + OCTAVE_MM_INT_ARITH_OPS (mmx, TYPE ## _, , TYPE) \ + OCTAVE_MM_INT_ARITH_OPS (mxm, , TYPE ## _, TYPE) \ + OCTAVE_MM_INT_ARITH_OPS (mmfx, TYPE ## _, float_, TYPE) \ + OCTAVE_MM_INT_ARITH_OPS (mfxm, float_, TYPE ## _, TYPE) \ OCTAVE_MM_INT_CMP_OPS (mm, TYPE ## _, TYPE ## _) \ OCTAVE_MM_INT_CMP_OPS (mmx, TYPE ## _, ) \ OCTAVE_MM_INT_CMP_OPS (mfxm, float_, TYPE ## _) \ diff --git a/src/error.cc b/src/error.cc --- a/src/error.cc +++ b/src/error.cc @@ -1396,6 +1396,10 @@ disable_warning ("Octave:str-to-num"); disable_warning ("Octave:string-concat"); disable_warning ("Octave:variable-switch-label"); + disable_warning ("Octave:int-convert-nan"); + disable_warning ("Octave:int-convert-non-int-val"); + disable_warning ("Octave:int-convert-overflow"); + disable_warning ("Octave:int-math-overflow"); } DEFUN (lasterror, args, , diff --git a/src/gripes.cc b/src/gripes.cc --- a/src/gripes.cc +++ b/src/gripes.cc @@ -213,6 +213,21 @@ } void +gripe_binop_integer_math_truncated (const char *op, const char *type1, const char *type2) +{ + warning_with_id ("Octave:int-math-overflow", + "data truncated for %s by %s binary operator %s", + type1, type2, op); +} + +void +gripe_unop_integer_math_truncated (const char* op, const char *type) +{ + warning_with_id ("Octave:int-math-overflow", + "data truncated for the %s unary operator %s", type, op); +} + +void gripe_library_execution_error (void) { octave_exception_state = octave_no_exception; @@ -221,6 +236,21 @@ error ("caught execution error in library function"); } +void +gripe_non_integer_conversion (const char *srctype, const char *desttype) +{ + warning_with_id ("Octave:int-convert-non-int-val", + "Conversion of non-integer value from %s to %s", + srctype, desttype); +} +void +gripe_nan_conversion (const char *srctype, const char *desttype) +{ + warning_with_id ("Octave:int-convert-nan", + "Conversion of NaN from %s to %s", + srctype, desttype); +} + /* ;;; Local Variables: *** ;;; mode: C++ *** diff --git a/src/gripes.h b/src/gripes.h --- a/src/gripes.h +++ b/src/gripes.h @@ -111,6 +111,18 @@ gripe_truncated_conversion (const char *srctype, const char *desttype); extern OCTINTERP_API void +gripe_binop_integer_math_truncated (const char *op, const char *type1, const char *type2); + +extern OCTINTERP_API void +gripe_unop_integer_math_truncated (const char *op, const char *type); + +extern OCTINTERP_API void +gripe_non_integer_conversion (const char *srctype, const char *desttype); + +extern OCTINTERP_API void +gripe_nan_conversion (const char *srctype, const char *desttype); + +extern OCTINTERP_API void gripe_divide_by_zero (void); extern OCTINTERP_API void diff --git a/src/ov-intx.h b/src/ov-intx.h --- a/src/ov-intx.h +++ b/src/ov-intx.h @@ -74,15 +74,12 @@ { typedef typename IM::element_type dest_el_type; typedef OCTAVE_INT_NDARRAY_T::element_type src_el_type; - dest_el_type::clear_trunc_flag (); + dest_el_type::clear_conv_flag (); IM retval (matrix); if (dest_el_type::get_trunc_flag ()) - { - gripe_truncated_conversion (src_el_type::type_name (), - dest_el_type::type_name ()); - dest_el_type::clear_trunc_flag (); - } - + gripe_truncated_conversion (src_el_type::type_name (), + dest_el_type::type_name ()); + dest_el_type::clear_conv_flag (); return retval; } @@ -301,9 +298,22 @@ return retval; } - void increment (void) { matrix += 1; } + void increment (void) + { + matrix += 1; + if (OCTAVE_INT_T::get_math_trunc_flag ()) + gripe_unop_integer_math_truncated ("++", type_name (). c_str ()); - void decrement (void) { matrix -= 1; } + OCTAVE_INT_T::clear_conv_flag (); + } + + void decrement (void) + { + matrix -= 1; + if (OCTAVE_INT_T::get_math_trunc_flag ()) + gripe_unop_integer_math_truncated ("--", type_name (). c_str ()); + OCTAVE_INT_T::clear_conv_flag (); + } idx_vector index_vector (void) const { return idx_vector (matrix); } @@ -433,16 +443,13 @@ { typedef IS dest_el_type; typedef OCTAVE_INT_T src_el_type; - dest_el_type::clear_trunc_flag (); + dest_el_type::clear_conv_flag (); IS retval (scalar); + if (dest_el_type::get_trunc_flag ()) - { - gripe_truncated_conversion (src_el_type::type_name (), - dest_el_type::type_name ()); - dest_el_type::clear_trunc_flag (); - - } - + gripe_truncated_conversion (src_el_type::type_name (), + dest_el_type::type_name ()); + dest_el_type::clear_conv_flag (); return retval; } @@ -615,9 +622,21 @@ return retval; } - void increment (void) { scalar += 1; } + void increment (void) + { + scalar += 1; + if (OCTAVE_INT_T::get_math_trunc_flag ()) + gripe_unop_integer_math_truncated ("++", type_name (). c_str ()); + OCTAVE_INT_T::clear_conv_flag (); + } - void decrement (void) { scalar -= 1; } + void decrement (void) + { + scalar -= 1; + if (OCTAVE_INT_T::get_math_trunc_flag ()) + gripe_unop_integer_math_truncated ("--", type_name (). c_str ()); + OCTAVE_INT_T::clear_conv_flag (); + } idx_vector index_vector (void) const { return idx_vector (scalar); } diff --git a/src/ov.cc b/src/ov.cc --- a/src/ov.cc +++ b/src/ov.cc @@ -1368,14 +1368,14 @@ Array retval (A.dims ()); octave_idx_type n = A.numel (); - octave_int::clear_trunc_flag (); + octave_int::clear_conv_flag (); for (octave_idx_type i = 0; i < n; i++) retval.xelem (i) = octave_int (A.xelem (i)); + if (octave_int::get_trunc_flag ()) - { - gripe_truncated_conversion (octave_int::type_name (), "int"); - octave_int::clear_trunc_flag (); - } + gripe_truncated_conversion (octave_int::type_name (), "int"); + + octave_int::clear_conv_flag (); return retval; }