# 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
{