Mercurial > hg > octave-lojdl
changeset 7997:2b8952e133c9
implement checked conversions between integers
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Wed, 30 Jul 2008 15:20:13 +0200 |
parents | 6a7db240b3a3 |
children | a4acda9fc3e7 |
files | liboctave/ChangeLog liboctave/oct-inttypes.h src/ChangeLog src/gripes.cc src/gripes.h src/ops.h src/ov-intx.h src/ov.cc |
diffstat | 8 files changed, 200 insertions(+), 35 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,12 @@ +2008-07-30 Jaroslav Hajek <highegg@gmail.com> + + * oct-inttypes.h (octave_int<T>::trunc_flag): New member static field. + (octave_int<T>::get_trunc_flag, octave_int<T>::clear_trunc_flag): New + member functions. + (octave_int<T>::octave_int (const octave_int<U>&)): set trunc_flag on truncation. + (SPECIALIZE_WIDENING_CONVERSION): New macro. + (DECLARE_OCTAVE_INT_TYPENAME): New macro. + 2008-07-29 David Bateman <dbateman@free.fr> * lo-ieee.h (LO_IEEE_NA_HW, LO_IEEE_NA_LW, LO_IEEE_NA_FLOAT):
--- 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 <highegg@gmail.com> This file is part of Octave. @@ -281,7 +282,10 @@ template <class U> octave_int (const octave_int<U>& 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<T>& i) : ival (i.ival) { } @@ -398,15 +402,23 @@ 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<T *> (&ival); } private: + static bool trunc_flag; T ival; }; +template<class T> bool octave_int<T>::trunc_flag = false; + template <class T> bool xisnan (const octave_int<T>&) @@ -489,6 +501,43 @@ 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<T2>::octave_int (T1 i) : ival (i) {} \ + template <> template <> \ + inline octave_int<T2>::octave_int (const octave_int<T1>& 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>::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<int8_t> octave_int8; typedef octave_int<int16_t> octave_int16; typedef octave_int<int32_t> octave_int32;
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,18 @@ +2008-07-30 Jaroslav Hajek <highegg@gmail.com> + + * 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-30 John W. Eaton <jwe@octave.org> * defun-dld.h (DEFUNX_DLD): Eliminate fsname arg.
--- 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++ ***
--- 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
--- 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 \
--- a/src/ov-intx.h +++ b/src/ov-intx.h @@ -67,29 +67,51 @@ bool is_integer_type (void) const { return true; } +private: + + template <class _int_matrix> + _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<int8NDArray> (); } int16NDArray - int16_array_value (void) const { return int16NDArray (matrix); } + int16_array_value (void) const { return convert_gripe<int16NDArray> (); } int32NDArray - int32_array_value (void) const { return int32NDArray (matrix); } + int32_array_value (void) const { return convert_gripe<int32NDArray> (); } int64NDArray - int64_array_value (void) const { return int64NDArray (matrix); } + int64_array_value (void) const { return convert_gripe<int64NDArray> (); } uint8NDArray - uint8_array_value (void) const { return uint8NDArray (matrix); } + uint8_array_value (void) const { return convert_gripe<uint8NDArray> (); } uint16NDArray - uint16_array_value (void) const { return uint16NDArray (matrix); } + uint16_array_value (void) const { return convert_gripe<uint16NDArray> (); } uint32NDArray - uint32_array_value (void) const { return uint32NDArray (matrix); } + uint32_array_value (void) const { return convert_gripe<uint32NDArray> (); } uint64NDArray - uint64_array_value (void) const { return uint64NDArray (matrix); } + uint64_array_value (void) const { return convert_gripe<uint64NDArray> (); } double double_value (bool = false) const @@ -405,61 +427,83 @@ bool is_integer_type (void) const { return true; } +private: + + template <class _int_scalar> + _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_int8> (); } octave_int16 - int16_scalar_value (void) const { return octave_int16 (scalar); } + int16_scalar_value (void) const { return convert_gripe<octave_int16> (); } octave_int32 - int32_scalar_value (void) const { return octave_int32 (scalar); } + int32_scalar_value (void) const { return convert_gripe<octave_int32> (); } octave_int64 - int64_scalar_value (void) const { return octave_int64 (scalar); } + int64_scalar_value (void) const { return convert_gripe<octave_int64> (); } octave_uint8 - uint8_scalar_value (void) const { return octave_uint8 (scalar); } + uint8_scalar_value (void) const { return convert_gripe<octave_uint8> (); } octave_uint16 - uint16_scalar_value (void) const { return octave_uint16 (scalar); } + uint16_scalar_value (void) const { return convert_gripe<octave_uint16> (); } octave_uint32 - uint32_scalar_value (void) const { return octave_uint32 (scalar); } + uint32_scalar_value (void) const { return convert_gripe<octave_uint32> (); } octave_uint64 - uint64_scalar_value (void) const { return octave_uint64 (scalar); } + uint64_scalar_value (void) const { return convert_gripe<octave_uint64> (); } 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 {
--- a/src/ov.cc +++ b/src/ov.cc @@ -1346,6 +1346,25 @@ type_name (), "real vector")); } +template <class T> +static Array<int> +convert_to_int_array (const Array<octave_int<T> >& A) +{ + Array<int> O (A.dims ()); + octave_idx_type n = A.numel (); + + octave_int<int>::clear_trunc_flag (); + for (octave_idx_type i = 0; i < n; i++) + O.xelem (i) = octave_int<int> (A.xelem (i)); + if (octave_int<int>::get_trunc_flag ()) + { + gripe_truncated_conversion (octave_int<T>::type_name (), "int"); + octave_int<int>::clear_trunc_flag (); + } + + return O; +} + Array<int> 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 {