# HG changeset patch # User Jaroslav Hajek # Date 1217424013 -7200 # Node ID 541db10d7cfcb8741c86495b9c4f43cfbbb897f7 # Parent 8ccd9b0bf6bcc747aa43ade83e2a863f562bef2c implement checked conversions between integers diff --git a/liboctave/ChangeLog b/liboctave/ChangeLog --- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,12 @@ +2008-07-30 Jaroslav Hajek + + * oct-inttypes.h (octave_int::trunc_flag): New member static field. + (octave_int::get_trunc_flag, octave_int::clear_trunc_flag): New + member functions. + (octave_int::octave_int (const octave_int&)): set trunc_flag on truncation. + (SPECIALIZE_WIDENING_CONVERSION): New macro. + (DECLARE_OCTAVE_INT_TYPENAME): New macro. + 2008-07-29 David Bateman * lo-ieee.h (LO_IEEE_NA_HW, LO_IEEE_NA_LW, LO_IEEE_NA_FLOAT): diff --git a/liboctave/oct-inttypes.h b/liboctave/oct-inttypes.h --- a/liboctave/oct-inttypes.h +++ b/liboctave/oct-inttypes.h @@ -1,6 +1,7 @@ /* Copyright (C) 2004, 2005, 2006, 2007 John W. Eaton +Copyright (C) 2008 Jaroslav Hajek This file is part of Octave. @@ -281,7 +282,10 @@ template octave_int (const octave_int& i) - : ival (OCTAVE_INT_FIT_TO_RANGE (i.value (), T)) { } + : ival (OCTAVE_INT_FIT_TO_RANGE (i.value (), T)) + { + trunc_flag = trunc_flag || (ival != i.value ()); + } octave_int (const octave_int& i) : ival (i.ival) { } @@ -398,14 +402,22 @@ 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 const char *type_name () { return "unknown type"; } + // Unsafe. This function exists to support the MEX interface. // You should not use it anywhere else. void *mex_get_data (void) const { return const_cast (&ival); } private: + static bool trunc_flag; T ival; }; + +template bool octave_int::trunc_flag = false; template bool @@ -488,6 +500,43 @@ ival = tmp; return is; } + +// specialize the widening conversions to make them faster +// gosh. the syntax is tricky! + +#define SPECIALIZE_WIDENING_CONVERSION(T1, T2) \ + template <> template <> \ + inline octave_int::octave_int (T1 i) : ival (i) {} \ + template <> template <> \ + inline octave_int::octave_int (const octave_int& i) : ival (i.value ()) {} + +SPECIALIZE_WIDENING_CONVERSION(int8_t, int16_t) +SPECIALIZE_WIDENING_CONVERSION(int8_t, int32_t) +SPECIALIZE_WIDENING_CONVERSION(int8_t, int64_t) +SPECIALIZE_WIDENING_CONVERSION(int16_t, int32_t) +SPECIALIZE_WIDENING_CONVERSION(int16_t, int64_t) +SPECIALIZE_WIDENING_CONVERSION(int32_t, int64_t) +SPECIALIZE_WIDENING_CONVERSION(uint8_t, uint16_t) +SPECIALIZE_WIDENING_CONVERSION(uint8_t, uint32_t) +SPECIALIZE_WIDENING_CONVERSION(uint8_t, uint64_t) +SPECIALIZE_WIDENING_CONVERSION(uint16_t, uint32_t) +SPECIALIZE_WIDENING_CONVERSION(uint16_t, uint64_t) +SPECIALIZE_WIDENING_CONVERSION(uint32_t, uint64_t) + +// declare type names +#define DECLARE_OCTAVE_INT_TYPENAME(TYPE, TYPENAME) \ + template<> \ + inline const char * \ + octave_int::type_name () { return TYPENAME; } + +DECLARE_OCTAVE_INT_TYPENAME(int8_t, "int8") +DECLARE_OCTAVE_INT_TYPENAME(int16_t, "int16") +DECLARE_OCTAVE_INT_TYPENAME(int32_t, "int32") +DECLARE_OCTAVE_INT_TYPENAME(int64_t, "int64") +DECLARE_OCTAVE_INT_TYPENAME(uint8_t, "uint8") +DECLARE_OCTAVE_INT_TYPENAME(uint16_t, "uint16") +DECLARE_OCTAVE_INT_TYPENAME(uint32_t, "uint32") +DECLARE_OCTAVE_INT_TYPENAME(uint64_t, "uint64") typedef octave_int octave_int8; typedef octave_int octave_int16; diff --git a/src/ChangeLog b/src/ChangeLog --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,18 @@ +2008-07-30 Jaroslav Hajek + + * gripes.cc (gripe_truncated_conversion): New function. + * gripes.h (gripe_truncated_conversion): Declare it. + * ops.h (DEFCONVFNX2): New macro. + (DEFCONVFN, DEFCONVFN2): Call DEFCONVFNX2 instead of DEFCONVFNX. + * ov-intx.h (OCTAVE_VALUE_INT_MATRIX_T::convert_gripe): New member function. + (OCTAVE_VALUE_INT_MATRIX_T::int*_array_value): Call convert_gripe. + (OCTAVE_VALUE_INT_SCALAR_T::convert_gripe): New member function. + (OCTAVE_VALUE_INT_SCALAR_T::int*_scalar_value): Call convert_gripe. + (OCTAVE_VALUE_INT_SCALAR_T::int*_array_value): Call int*_scalar_value. + * ov.cc (convert_to_int_array): New function. + (int_vector_value): Call convert_to_int_array. + + 2008-07-29 David Bateman * data.cc (FNA): Add tests for conversion of single to double NA diff --git a/src/gripes.cc b/src/gripes.cc --- a/src/gripes.cc +++ b/src/gripes.cc @@ -204,6 +204,14 @@ "value not equal to 1 or 0 converted to logical 1"); } +extern void +gripe_truncated_conversion (const char *srctype, const char *desttype) +{ + warning_with_id ("Octave:truncated_conversion", + "data truncated converting 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 @@ -108,6 +108,9 @@ const std::string& to); extern OCTINTERP_API void +gripe_truncated_conversion (const char *srctype, const char *desttype); + +extern OCTINTERP_API void gripe_divide_by_zero (void); extern OCTINTERP_API void diff --git a/src/ops.h b/src/ops.h --- a/src/ops.h +++ b/src/ops.h @@ -207,6 +207,14 @@ return new octave_ ## ovtto (tto ## NDArray (v.e ## array_value ())); \ } +#define DEFCONVFNX2(name, tfrom, ovtto, e) \ + CONVDECL (name) \ + { \ + CAST_CONV_ARG (const octave_ ## tfrom&); \ + \ + return new octave_ ## ovtto (v.e ## array_value ()); \ + } + #define DEFDBLCONVFN(name, ovtfrom, e) \ CONVDECL (name) \ { \ @@ -222,10 +230,10 @@ DEFCONVFNX(name, tfrom, matrix, , char_) #define DEFCONVFN(name, tfrom, tto) \ - DEFCONVFNX (name, tfrom, tto ## _matrix, tto, ) + DEFCONVFNX2 (name, tfrom, tto ## _matrix, tto ## _) #define DEFCONVFN2(name, tfrom, sm, tto) \ - DEFCONVFNX (name, tfrom ## _ ## sm, tto ## _matrix, tto, tfrom ## _) + DEFCONVFNX2 (name, tfrom ## _ ## sm, tto ## _matrix, tto ## _) #define UNOPDECL(name, a) \ static octave_value \ diff --git a/src/ov-intx.h b/src/ov-intx.h --- a/src/ov-intx.h +++ b/src/ov-intx.h @@ -67,29 +67,51 @@ bool is_integer_type (void) const { return true; } +private: + + template + _int_matrix convert_gripe () const + { + typedef typename _int_matrix::element_type dest_el_type; + typedef OCTAVE_INT_NDARRAY_T::element_type src_el_type; + dest_el_type::clear_trunc_flag (); + _int_matrix 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 (); + + } + + return retval; + } + +public: + int8NDArray - int8_array_value (void) const { return int8NDArray (matrix); } + int8_array_value (void) const { return convert_gripe (); } int16NDArray - int16_array_value (void) const { return int16NDArray (matrix); } + int16_array_value (void) const { return convert_gripe (); } int32NDArray - int32_array_value (void) const { return int32NDArray (matrix); } + int32_array_value (void) const { return convert_gripe (); } int64NDArray - int64_array_value (void) const { return int64NDArray (matrix); } + int64_array_value (void) const { return convert_gripe (); } uint8NDArray - uint8_array_value (void) const { return uint8NDArray (matrix); } + uint8_array_value (void) const { return convert_gripe (); } uint16NDArray - uint16_array_value (void) const { return uint16NDArray (matrix); } + uint16_array_value (void) const { return convert_gripe (); } uint32NDArray - uint32_array_value (void) const { return uint32NDArray (matrix); } + uint32_array_value (void) const { return convert_gripe (); } uint64NDArray - uint64_array_value (void) const { return uint64NDArray (matrix); } + uint64_array_value (void) const { return convert_gripe (); } double double_value (bool = false) const @@ -405,61 +427,83 @@ bool is_integer_type (void) const { return true; } +private: + + template + _int_scalar convert_gripe () const + { + typedef _int_scalar dest_el_type; + typedef OCTAVE_INT_T src_el_type; + dest_el_type::clear_trunc_flag (); + _int_scalar 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 (); + + } + + return retval; + } + +public: + octave_int8 - int8_scalar_value (void) const { return octave_int8 (scalar); } + int8_scalar_value (void) const { return convert_gripe (); } octave_int16 - int16_scalar_value (void) const { return octave_int16 (scalar); } + int16_scalar_value (void) const { return convert_gripe (); } octave_int32 - int32_scalar_value (void) const { return octave_int32 (scalar); } + int32_scalar_value (void) const { return convert_gripe (); } octave_int64 - int64_scalar_value (void) const { return octave_int64 (scalar); } + int64_scalar_value (void) const { return convert_gripe (); } octave_uint8 - uint8_scalar_value (void) const { return octave_uint8 (scalar); } + uint8_scalar_value (void) const { return convert_gripe (); } octave_uint16 - uint16_scalar_value (void) const { return octave_uint16 (scalar); } + uint16_scalar_value (void) const { return convert_gripe (); } octave_uint32 - uint32_scalar_value (void) const { return octave_uint32 (scalar); } + uint32_scalar_value (void) const { return convert_gripe (); } octave_uint64 - uint64_scalar_value (void) const { return octave_uint64 (scalar); } + uint64_scalar_value (void) const { return convert_gripe (); } int8NDArray int8_array_value (void) const - { return int8NDArray (dim_vector (1, 1), scalar); } + { return int8NDArray (dim_vector (1, 1), int8_scalar_value ()); } int16NDArray int16_array_value (void) const - { return int16NDArray (dim_vector (1, 1), scalar); } + { return int16NDArray (dim_vector (1, 1), int16_scalar_value ()); } int32NDArray int32_array_value (void) const - { return int32NDArray (dim_vector (1, 1), scalar); } + { return int32NDArray (dim_vector (1, 1), int32_scalar_value ()); } int64NDArray int64_array_value (void) const - { return int64NDArray (dim_vector (1, 1), scalar); } + { return int64NDArray (dim_vector (1, 1), int64_scalar_value ()); } uint8NDArray uint8_array_value (void) const - { return uint8NDArray (dim_vector (1, 1), scalar); } + { return uint8NDArray (dim_vector (1, 1), uint8_scalar_value ()); } uint16NDArray uint16_array_value (void) const - { return uint16NDArray (dim_vector (1, 1), scalar); } + { return uint16NDArray (dim_vector (1, 1), uint16_scalar_value ()); } uint32NDArray uint32_array_value (void) const - { return uint32NDArray (dim_vector (1, 1), scalar); } + { return uint32NDArray (dim_vector (1, 1), uint32_scalar_value ()); } uint64NDArray uint64_array_value (void) const - { return uint64NDArray (dim_vector (1, 1), scalar); } + { return uint64NDArray (dim_vector (1, 1), uint64_scalar_value ()); } octave_value resize (const dim_vector& dv, bool fill = false) const { diff --git a/src/ov.cc b/src/ov.cc --- a/src/ov.cc +++ b/src/ov.cc @@ -1346,6 +1346,25 @@ type_name (), "real vector")); } +template +static Array +convert_to_int_array (const Array >& A) +{ + Array O (A.dims ()); + octave_idx_type n = A.numel (); + + octave_int::clear_trunc_flag (); + for (octave_idx_type i = 0; i < n; i++) + O.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 (); + } + + return O; +} + Array octave_value::int_vector_value (bool force_string_conv, bool require_int, bool force_vector_conversion) const @@ -1354,14 +1373,24 @@ if (is_integer_type ()) { - // query for the first type that is wide enough -#if SIZEOF_INT == 2 - retval = int16_array_value (); -#elif SIZEOF_INT == 4 - retval = int32_array_value (); -#else - retval = int64_array_value (); -#endif + if (is_int32_type ()) + retval = convert_to_int_array (int32_array_value ()); + else if (is_int64_type ()) + retval = convert_to_int_array (int64_array_value ()); + else if (is_int16_type ()) + retval = convert_to_int_array (int16_array_value ()); + else if (is_int8_type ()) + retval = convert_to_int_array (int8_array_value ()); + else if (is_uint32_type ()) + retval = convert_to_int_array (uint32_array_value ()); + else if (is_uint64_type ()) + retval = convert_to_int_array (uint64_array_value ()); + else if (is_uint16_type ()) + retval = convert_to_int_array (uint16_array_value ()); + else if (is_uint8_type ()) + retval = convert_to_int_array (uint8_array_value ()); + else + retval = array_value (force_string_conv); } else {