int_u6 = int_u8 + int_u8
est safe au niveau de l'opération arithmétique, seul l'affectation à
besoin d'être checkée.
int_u6 = int_u32 + int_u8
n'est pas safe au niveau arithmétique, ie. il ne suffit pas de faire
l'opération puis de vérifier l'affectation. (int + int => int en C/C++).
Ce patch permet de déterminer avec plus de précision les cas où un
check dynamique est requis.
Index: integre/ChangeLog
from Nicolas Burrus <burrus_n(a)lrde.epita.fr>
* tests/types/tests/int_u8: New test.
* tests/types/runtests: Rename KEEP_RUN as KEEP_RUNS.
+2003-11-27 Nicolas Burrus <burrus_n(a)lrde.epita.fr>
+
+ * ntg/real/behavior.hh: Check arithmetic operators, not arithmetic
+ assignment operators.
+ (force): New behavior.
+ (ret_behavior_if): New helper struct.
+
+ * ntg/core/value.hh: Define unsafe_type.
+ * ntg/core/macros.hh (ntg_unsafe_type): New macro.
+ * ntg/utils/cast.hh: Use ntg_unsafe_type.
+
+ * ntg/real/typetraits_builtin_int.hh: Define abstract_behavior_type.
+ * ntg/real/builtin_float.hh: Likewise.
+ * ntg/real/range.hh: Likewise.
+ * ntg/real/cycle.hh: Likewise.
+
+ * ntg/real/int_s.hh: Remove useless arithmetic operations
+ checks. Define need_check for operation traits.
+ * ntg/real/int_u.hh: Likewise.
+
+ * ntg/real/optraits_real_defs.hh: Derive arithmetic assignment
+ operators from arithmetic operators. Use the behavior given by the
+ operator traits instead of the behavior of the return type.
+ * ntg/real/optraits_real.hh: Adjust consequently.
+
+2003-11-27 Nicolas Burrus <burrus_n(a)lrde.epita.fr>
+
Make typetraits and optraits reproduce more accurately the value
hierarchy.
Index: integre/ntg/real/behavior.hh
--- integre/ntg/real/behavior.hh Wed, 26 Nov 2003 16:45:27 +0100 burrus_n
(oln/g/31_behaviour. 1.13.1.16 640)
+++ integre/ntg/real/behavior.hh Thu, 27 Nov 2003 11:26:27 +0100 burrus_n
(oln/g/31_behaviour. 1.13.1.15.1.1 640)
@@ -29,7 +29,7 @@
# define NTG_REAL_BEHAVIOUR_HH
/*
- Behaviors for data_types int_u, int_s, etc ...
+ Behaviors for real datatypes int_u, int_s, etc ...
<WARNING> Don't forget that behaviors are checked on assignements
and contruction of types, and use comparison, so create only vars
@@ -53,10 +53,10 @@
# include <string>
# include <sstream>
-
// FIXME: there is maybe simpler a way to write that, but we want it
// to be compatible with icc, so the behaviors must stay classes, not
// meta classes.
+// FIXME: are these considerations still accurate?
namespace ntg
{
@@ -86,28 +86,28 @@
template <class T1, class T2>
static T
- check_plus_equal (T1 lhs, T2 rhs)
+ check_plus (T1 lhs, T2 rhs)
{ return lhs + rhs; }
template <class T1, class T2>
static T
- check_minus_equal (T1 lhs, T2 rhs)
+ check_minus (T1 lhs, T2 rhs)
{ return lhs - rhs; }
template <class T1, class T2>
static T
- check_times_equal (T1 lhs, T2 rhs)
+ check_times (T1 lhs, T2 rhs)
{ return lhs * rhs; }
template <class T1, class T2>
static T
- check_div_equal (T1 lhs, T2 rhs)
+ check_div (T1 lhs, T2 rhs)
{ return lhs / rhs; }
template <class P>
static storage_type
check (const P& p)
- { return static_cast<storage_type>(p); }
+ { return p; }
};
static std::string
@@ -115,6 +115,63 @@
{ return "unsafe"; }
};
+ /*------.
+ | force |
+ `------*/
+ //! Force the value to be assigned without checks.
+ /*!
+ Quite similar to unsafe, but even if the destination type has a
+ strict behavior, by using cast::force we ensure that no check will
+ be performed.
+
+ Example:
+
+ int_u<8, strict> a;
+ a = force::get<int_u<8, strict> >::check_plus(5, 6);
+
+ => no check
+
+ This construction is useful when we want to use code from a
+ particular behavior to a type defined with another behavior.
+ */
+ struct force
+ {
+ template <class T>
+ struct get
+ {
+ typedef ntgi_storage_type(T) storage_type;
+
+ template <class T1, class T2>
+ static T
+ check_plus (T1 lhs, T2 rhs)
+ { return cast::force<T>(lhs + rhs); }
+
+ template <class T1, class T2>
+ static T
+ check_minus (T1 lhs, T2 rhs)
+ { return cast::force<T>(lhs - rhs); }
+
+ template <class T1, class T2>
+ static T
+ check_times (T1 lhs, T2 rhs)
+ { return cast::force<T>(lhs * rhs); }
+
+ template <class T1, class T2>
+ static T
+ check_div (T1 lhs, T2 rhs)
+ { return cast::force<T>(lhs / rhs); }
+
+ template <class P>
+ static storage_type
+ check (const P& p)
+ { return cast::force<T>(p); }
+ };
+
+ static std::string
+ name()
+ { return "force"; }
+ };
+
/*-------.
| strict |
`-------*/
@@ -136,7 +193,7 @@
template <class T1, class T2>
static T
- check_plus_equal (T1 lhs, T2 rhs)
+ check_plus (T1 lhs, T2 rhs)
{
T ret = lhs + rhs;
if (rhs > 0)
@@ -148,7 +205,7 @@
template <class T1, class T2>
static T
- check_minus_equal (T1 lhs, T2 rhs)
+ check_minus (T1 lhs, T2 rhs)
{
T ret = lhs - rhs;
if (rhs > 0)
@@ -161,7 +218,7 @@
// FIXME: this check is very slow! Find another solution.
template <class T1, class T2>
static T
- check_times_equal (T1 lhs, T2 rhs)
+ check_times (T1 lhs, T2 rhs)
{
T ret = lhs * rhs;
if (rhs != 0)
@@ -171,7 +228,7 @@
template <class T1, class T2>
static T
- check_div_equal (T1 lhs, T2 rhs)
+ check_div (T1 lhs, T2 rhs)
{ return lhs / rhs; }
template <class P>
@@ -203,7 +260,7 @@
template <class T1, class T2>
static T
- check_plus_equal (T1 lhs, T2 rhs)
+ check_plus (T1 lhs, T2 rhs)
{
T ret = lhs + rhs;
if (rhs > 0)
@@ -218,7 +275,7 @@
template <class T1, class T2>
static T
- check_minus_equal (T1 lhs, T2 rhs)
+ check_minus (T1 lhs, T2 rhs)
{
T ret = lhs - rhs;
if (rhs > 0)
@@ -234,7 +291,7 @@
// FIXME: this check is very slow ! find another solution ...
template <class T1, class T2>
static T
- check_times_equal (T1 lhs, T2 rhs)
+ check_times (T1 lhs, T2 rhs)
{
T ret = lhs * rhs;
if ((ret / rhs) != lhs)
@@ -250,7 +307,7 @@
template <class T1, class T2>
static T
- check_div_equal (T1 lhs, T2 rhs)
+ check_div (T1 lhs, T2 rhs)
{ return lhs / rhs; }
template <class P>
@@ -292,19 +349,19 @@
// FIXME: calculate real values!
template <class T1, class T2>
- static T check_plus_equal (T1 lhs, T2 rhs)
+ static T check_plus (T1 lhs, T2 rhs)
{ return lhs + rhs; }
template <class T1, class T2>
- static T check_minus_equal (T1 lhs, T2 rhs)
+ static T check_minus (T1 lhs, T2 rhs)
{ return lhs - rhs; }
template <class T1, class T2>
- static T check_times_equal (T1 lhs, T2 rhs)
+ static T check_times (T1 lhs, T2 rhs)
{ return lhs * rhs; }
template <class T1, class T2>
- static T check_div_equal (T1 lhs, T2 rhs)
+ static T check_div (T1 lhs, T2 rhs)
{ return lhs / rhs; }
// float modulus
@@ -372,6 +429,32 @@
struct deduce_op_behavior<B, B>
{ typedef B ret; };
+ /*----------------.
+ | ret_behavior_if |
+ `----------------*/
+
+ //! Determine the behavior to use depending on check requirements.
+ /*!
+ If need_check is true, the returned behavior will be the same as
+ the previously determined return type (generally safe).
+
+ In some cases, no check is required, thus type used to perform
+ the calculus does not need to be safe. The force behavior is
+ returned in such cases.
+ */
+
+ template <bool need_check, class Ret>
+ struct ret_behavior_if
+ {
+ typedef typename typetraits<Ret>::abstract_behavior_type ret;
+ };
+
+ template <class Ret>
+ struct ret_behavior_if<false, Ret>
+ {
+ typedef ntg::force ret;
+ };
+
} // end of internal.
} // end of ntg.
Index: integre/ntg/utils/cast.hh
--- integre/ntg/utils/cast.hh Fri, 07 Nov 2003 17:26:19 +0100 burrus_n (oln/i/26_cast.hh
1.3.1.10 640)
+++ integre/ntg/utils/cast.hh Thu, 27 Nov 2003 11:26:27 +0100 burrus_n (oln/i/26_cast.hh
1.3.1.11 640)
@@ -74,7 +74,7 @@
const Tdest
force(const Tsrc& val)
{
- Tdest tmp(static_cast<ntg_storage_type(Tdest)>(val));
+ ntg_unsafe_type(Tdest) tmp (val);
return tmp;
}
Index: integre/ntg/real/int_s.hh
--- integre/ntg/real/int_s.hh Thu, 27 Nov 2003 11:17:00 +0100 burrus_n (oln/g/24_int_s.hh
1.16.1.18 640)
+++ integre/ntg/real/int_s.hh Thu, 27 Nov 2003 11:26:27 +0100 burrus_n (oln/g/24_int_s.hh
1.16.1.16.1.1 640)
@@ -46,17 +46,41 @@
// FIXME: add bits number comparison to avoid useless checks.
-# define INT_S_CTOR_FROM_BUILTIN(Builtin) \
+# define INT_S_CTOR_FROM_UNSIGNED_BUILTIN(Builtin) \
int_s (const Builtin rhs) \
{ \
+ if ((unsigned) internal::typetraits<ntg_type(Builtin)>::size < nbits) \
+ this->val_ = rhs; \
+ else \
this->val_ = optraits_type::check(rhs); \
} \
self& operator=(const Builtin rhs) \
{ \
+ if ((unsigned) internal::typetraits<ntg_type(Builtin)>::size < nbits) \
+ this->val_ = rhs; \
+ else \
this->val_ = optraits_type::check(rhs); \
return *this; \
}
+# define INT_S_CTOR_FROM_SIGNED_BUILTIN(Builtin) \
+int_s (const Builtin rhs) \
+{ \
+ if ((unsigned)internal::typetraits<ntg_type(Builtin)>::size <= nbits) \
+ this->val_ = rhs; \
+ else \
+ this->val_ = optraits_type::check(rhs); \
+} \
+self& operator=(const Builtin rhs) \
+{ \
+ if ((unsigned)internal::typetraits<ntg_type(Builtin)>::size <= nbits) \
+ this->val_ = rhs; \
+ else \
+ this->val_ = optraits_type::check(rhs); \
+ return *this; \
+}
+
+
namespace ntg {
namespace internal {
@@ -76,6 +100,7 @@
ntg_build_value_type(sint_value<E>);
typedef optraits<self> optraits_type;
+ typedef behavior abstract_behavior_type;
typedef typename behavior::template get<self> behavior_type;
typedef self base_type;
@@ -90,6 +115,9 @@
typedef int_u<32, behavior> unsigned_largest_type;
typedef int_u<32, behavior> unsigned_cumul_type;
typedef signed int integer_type;
+
+ // Particular properties
+ enum { size = nbits };
};
} // end of internal.
@@ -112,18 +140,18 @@
// We define ctor for each builtin to avoid implicit builtin
// promotion.
- INT_S_CTOR_FROM_BUILTIN(unsigned long);
- INT_S_CTOR_FROM_BUILTIN(signed long);
+ INT_S_CTOR_FROM_UNSIGNED_BUILTIN(unsigned long);
+ INT_S_CTOR_FROM_SIGNED_BUILTIN(signed long);
- INT_S_CTOR_FROM_BUILTIN(unsigned int);
- INT_S_CTOR_FROM_BUILTIN(signed int);
+ INT_S_CTOR_FROM_UNSIGNED_BUILTIN(unsigned int);
+ INT_S_CTOR_FROM_SIGNED_BUILTIN(signed int);
- INT_S_CTOR_FROM_BUILTIN(unsigned short);
- INT_S_CTOR_FROM_BUILTIN(signed short);
+ INT_S_CTOR_FROM_UNSIGNED_BUILTIN(unsigned short);
+ INT_S_CTOR_FROM_SIGNED_BUILTIN(signed short);
- INT_S_CTOR_FROM_BUILTIN(unsigned char);
- INT_S_CTOR_FROM_BUILTIN(signed char);
- INT_S_CTOR_FROM_BUILTIN(char);
+ INT_S_CTOR_FROM_UNSIGNED_BUILTIN(unsigned char);
+ INT_S_CTOR_FROM_SIGNED_BUILTIN(signed char);
+ INT_S_CTOR_FROM_SIGNED_BUILTIN(char);
template <unsigned mbits, class B2>
int_s (const int_s<mbits, B2>& rhs)
@@ -306,7 +334,8 @@
// debug
static std::string name() {
std::ostringstream out;
- out << "int_s<" << int(nbits) << ", " <<
behavior::name() << ">"<< std::ends;
+ out << "int_s<" << int(nbits) << ", " <<
behavior::name() << ">"
+ << std::ends;
return out.str();
}
};
@@ -325,10 +354,12 @@
template<unsigned nbits, class B1, unsigned mbits, class B2>
struct operator_traits<operator_plus, int_s<nbits, B1>, int_s<mbits,
B2> >
{
- enum { commutative = true };
+ enum { commutative = true,
+ need_check = ((unsigned) mlc::max<nbits, mbits>::ret >= 32) };
typedef int_s<(unsigned)mlc::maxN<nbits + 1,mbits + 1, 32>::ret,
typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_s<nbits, B1> impl;
+ typedef int_s<nbits,
+ typename ret_behavior_if<need_check, ret>::ret> impl;
};
@@ -337,10 +368,12 @@
template <unsigned nbits, class B1, unsigned mbits, class B2>
struct operator_traits<operator_plus, int_s<nbits, B1>, int_u<mbits,
B2> >
{
- enum { commutative = true };
+ enum { commutative = true,
+ need_check = ((mbits >= 31) || (nbits >= 32)) };
typedef int_s<(unsigned)mlc::maxN<nbits + 1,mbits + 2, 32>::ret,
typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_s<nbits, B1> impl;
+ typedef int_s<nbits,
+ typename ret_behavior_if<need_check, ret>::ret> impl;
};
@@ -353,10 +386,12 @@
template<unsigned nbits, class B1, unsigned mbits, class B2>
struct operator_traits<operator_minus, int_s<nbits, B1>, int_s<mbits,
B2> >
{
- enum { commutative = true };
+ enum { commutative = true,
+ need_check = ((mbits >= 31) || (nbits >= 31)) };
typedef int_s<(unsigned)mlc::maxN<nbits + 1, mbits + 1, 32>::ret,
typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_s<nbits, B1> impl;
+ typedef int_s<nbits,
+ typename ret_behavior_if<need_check, ret>::ret> impl;
};
// int_s - int_u ; int_u - int_s
@@ -364,10 +399,12 @@
template <unsigned nbits, class B1, unsigned mbits, class B2>
struct operator_traits<operator_minus, int_s<nbits, B1>, int_u<mbits,
B2> >
{
- enum { commutative = true };
+ enum { commutative = true,
+ need_check = ((mbits >= 31) || (nbits >= 32)) };
typedef int_s<(unsigned)mlc::maxN<nbits + 1, mbits + 2, 32>::ret,
typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_s<nbits, B1> impl;
+ typedef int_s<nbits,
+ typename ret_behavior_if<need_check, ret>::ret> impl;
};
@@ -380,10 +417,12 @@
template<unsigned nbits, class B1, unsigned mbits, class B2>
struct operator_traits<operator_times, int_s<nbits, B1>, int_s<mbits,
B2> >
{
- enum { commutative = true };
+ enum { commutative = true,
+ need_check = (mbits + nbits > 32) };
typedef int_s<(unsigned)mlc::saturateN<nbits + mbits, 32>::ret,
typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_s<nbits, B1> impl;
+ typedef int_s<nbits,
+ typename ret_behavior_if<need_check, ret>::ret> impl;
};
@@ -392,10 +431,12 @@
template <unsigned nbits, class B1, unsigned mbits, class B2>
struct operator_traits<operator_times, int_s<nbits, B1>, int_u<mbits,
B2> >
{
- enum { commutative = true };
+ enum { commutative = true,
+ need_check = (nbits + mbits + 1 > 32)};
typedef int_s<(unsigned)mlc::saturateN<nbits + mbits+1, 32>::ret,
typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_s<nbits, B1> impl;
+ typedef int_s<nbits,
+ typename ret_behavior_if<need_check, ret>::ret> impl;
};
//
@@ -409,7 +450,7 @@
{
enum { commutative = true };
typedef int_s<nbits, typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_s<nbits, B1> impl;
+ typedef int_s<nbits, force> impl;
};
// int_s / int_u ; int_u / int_s
@@ -417,18 +458,22 @@
template <unsigned nbits, class B1, unsigned mbits, class B2>
struct operator_traits<operator_div, int_s<nbits, B1>, int_u<mbits,
B2> >
{
- enum { commutative = false };
+ enum { commutative = false,
+ need_check = (mbits >= 32) };
typedef int_s<nbits, typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_s<nbits, B1> impl;
+ typedef int_s<nbits,
+ typename ret_behavior_if<need_check, ret>::ret> impl;
};
template <unsigned nbits, class B1, unsigned mbits, class B2>
struct operator_traits<operator_div, int_u<mbits, B2>, int_s<nbits,
B1> >
{
- enum { commutative = false };
+ enum { commutative = false,
+ need_check = (mbits >= 32) };
typedef int_s<mlc::saturateN<mbits + 1, 32>::ret,
typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_s<nbits, B1> impl;
+ typedef int_s<nbits,
+ typename ret_behavior_if<need_check, ret>::ret> impl;
};
//
@@ -442,7 +487,7 @@
{
enum { commutative = false };
typedef int_s<mbits, typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_s<nbits, B1> impl;
+ typedef int_s<nbits, force> impl;
};
// int_s % int_u ; int_u % int_s
@@ -450,12 +495,19 @@
template <unsigned nbits, class B1, unsigned mbits, class B2>
struct operator_traits<operator_mod, int_s<nbits, B1>, int_u<mbits,
B2> >
{
- enum { commutative = false };
+ enum { commutative = false,
+ need_check = (mbits >= 32) };
typedef int_s<(unsigned)mlc::saturateN<mbits + 1, 32>::ret,
typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_s<nbits, B1> impl;
+ typedef int_s<nbits,
+ typename ret_behavior_if<need_check, ret>::ret> impl;
};
+ // FIXME: don't know what to do with this operator, so the
+ // implementation is disabled. In classical C++, (a % b) with b < 0
+ // returns a whatever b is.
+
+#if 0
template <unsigned nbits, class B1, unsigned mbits, class B2>
struct operator_traits<operator_mod, int_u<nbits, B1>, int_s<mbits,
B2> >
{
@@ -463,7 +515,7 @@
typedef int_u<mbits, typename deduce_op_behavior<B1, B2>::ret> ret;
typedef int_s<nbits, B1> impl;
};
-
+#endif
//
// Min
@@ -477,7 +529,7 @@
enum { commutative = true };
typedef int_s<(unsigned) mlc::min<nbits, mbits>::ret,
typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_s<nbits, B1> impl;
+ typedef int_s<nbits, force> impl;
};
//
@@ -492,7 +544,7 @@
enum { commutative = true };
typedef int_s<(unsigned) mlc::max<nbits, mbits>::ret,
typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_s<nbits, B1> impl;
+ typedef int_s<nbits, force> impl;
};
//
@@ -506,7 +558,7 @@
{
enum { commutative = true };
typedef int_s<(unsigned)mlc::maxN<nbits,mbits,32>::ret, unsafe> ret;
- typedef int_s<nbits, B1> impl;
+ typedef int_s<nbits, force> impl;
};
@@ -517,7 +569,7 @@
{
enum { commutative = true };
typedef int_s<(unsigned)mlc::maxN<nbits,mbits+1, 32>::ret, unsafe>
ret;
- typedef int_s<nbits, B1> impl;
+ typedef int_s<nbits, force> impl;
};
} // end of internal.
Index: integre/ntg/real/int_u.hh
--- integre/ntg/real/int_u.hh Thu, 27 Nov 2003 11:17:00 +0100 burrus_n (oln/g/23_int_u.hh
1.19.1.18 640)
+++ integre/ntg/real/int_u.hh Thu, 27 Nov 2003 11:26:27 +0100 burrus_n (oln/g/23_int_u.hh
1.19.1.16.1.1 640)
@@ -42,6 +42,23 @@
| macros |
`-------*/
+# define INT_U_CTOR_FROM_UNSIGNED_BUILTIN_INT(Builtin) \
+int_u (const Builtin rhs) \
+{ \
+ if ((unsigned) internal::typetraits<ntg_type(Builtin)>::size <= nbits) \
+ this->val_ = rhs; \
+ else \
+ this->val_ = optraits_type::check(rhs); \
+} \
+self& operator=(const Builtin rhs) \
+{ \
+ if ((unsigned) internal::typetraits<ntg_type(Builtin)>::size <= nbits) \
+ this->val_ = rhs; \
+ else \
+ this->val_ = optraits_type::check(rhs); \
+ return *this; \
+}
+
# define INT_U_CTOR_FROM_BUILTIN_INT(Builtin) \
int_u (const Builtin rhs) \
{ \
@@ -53,6 +70,7 @@
return *this; \
}
+
namespace ntg {
namespace internal {
@@ -72,9 +90,9 @@
ntg_build_value_type(uint_value<E>);
typedef optraits<self> optraits_type;
+ typedef behavior abstract_behavior_type;
typedef typename behavior::template get<self> behavior_type;
-
typedef self base_type;
typedef typename C_for_int_u<nbits>::type storage_type;
typedef int_s<mlc::saturateN<nbits+1, 32>::ret,
@@ -88,6 +106,10 @@
typedef int_u<32, behavior> unsigned_largest_type;
typedef int_u<32, behavior> unsigned_cumul_type;
typedef unsigned int integer_type;
+ typedef int_u<nbits, unsafe> unsafe_type;
+
+ // Particular properties
+ enum { size = nbits };
};
} // end of internal.
@@ -111,16 +133,18 @@
// We define ctor for each builtin to avoid implicit builtin
// promotion.
- INT_U_CTOR_FROM_BUILTIN_INT(unsigned long);
+ // FIXME: dynamic checks are not necessary for all builtin types!
+
+ INT_U_CTOR_FROM_UNSIGNED_BUILTIN_INT(unsigned long);
INT_U_CTOR_FROM_BUILTIN_INT(signed long);
- INT_U_CTOR_FROM_BUILTIN_INT(unsigned int);
+ INT_U_CTOR_FROM_UNSIGNED_BUILTIN_INT(unsigned int);
INT_U_CTOR_FROM_BUILTIN_INT(signed int);
- INT_U_CTOR_FROM_BUILTIN_INT(unsigned short);
+ INT_U_CTOR_FROM_UNSIGNED_BUILTIN_INT(unsigned short);
INT_U_CTOR_FROM_BUILTIN_INT(signed short);
- INT_U_CTOR_FROM_BUILTIN_INT(unsigned char);
+ INT_U_CTOR_FROM_UNSIGNED_BUILTIN_INT(unsigned char);
INT_U_CTOR_FROM_BUILTIN_INT(signed char);
INT_U_CTOR_FROM_BUILTIN_INT(char);
@@ -252,10 +276,12 @@
template<unsigned nbits, class B1, unsigned mbits, class B2>
struct operator_traits<operator_plus, int_u<nbits, B1>, int_u<mbits,
B2> >
{
- enum { commutative = true };
+ enum { commutative = true,
+ need_check = ((unsigned) mlc::max<nbits, mbits>::ret >= 32) };
typedef int_u<(unsigned) mlc::maxN<nbits + 1, mbits + 1, 32>::ret,
typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_u<nbits, B1> impl;
+ typedef int_u<nbits,
+ typename ret_behavior_if<need_check, ret>::ret> impl;
};
//
@@ -267,10 +293,12 @@
template<unsigned nbits, class B1, unsigned mbits, class B2>
struct operator_traits<operator_minus, int_u<nbits, B1>, int_u<mbits,
B2> >
{
- enum { commutative = true };
+ enum { commutative = true,
+ need_check = ((unsigned) mlc::max<nbits, mbits>::ret >= 32) };
typedef int_s<(unsigned) mlc::maxN<nbits+1, mbits+1, 32>::ret,
typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_u<nbits, B1> impl;
+ typedef int_u<nbits,
+ typename ret_behavior_if<need_check, ret>::ret> impl;
};
// int_u32 - int_u : we do not convert result to int_s because we
@@ -281,7 +309,7 @@
{
enum { commutative = true };
typedef int_u<32, typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_u<32, B1> impl;
+ typedef int_u<32, force> impl;
};
//
@@ -293,10 +321,11 @@
template<unsigned nbits, class B1, unsigned mbits, class B2>
struct operator_traits<operator_times, int_u<nbits, B1>, int_u<mbits,
B2> >
{
- enum { commutative = true };
+ enum { commutative = true, need_check = (nbits + mbits > 32) };
typedef int_u<(unsigned) mlc::saturateN<nbits + mbits, 32>::ret,
typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_u<nbits, B1> impl;
+ typedef int_u<nbits,
+ typename ret_behavior_if<need_check, ret>::ret> impl;
};
//
@@ -310,7 +339,7 @@
{
enum { commutative = true };
typedef int_u<nbits, typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_u<nbits, B1> impl;
+ typedef int_u<nbits, force> impl;
};
//
@@ -324,7 +353,7 @@
{
enum { commutative = false };
typedef int_u<mbits, typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_u<nbits, B1> impl;
+ typedef int_u<nbits, force> impl;
};
//
@@ -339,7 +368,7 @@
enum { commutative = true };
typedef int_u<(unsigned) mlc::min<nbits, mbits>::ret,
typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_u<nbits, B1> impl;
+ typedef int_u<nbits, force> impl;
};
@@ -355,7 +384,7 @@
enum { commutative = true };
typedef int_u<(unsigned) mlc::max<nbits, mbits>::ret,
typename deduce_op_behavior<B1, B2>::ret> ret;
- typedef int_u<nbits, B1> impl;
+ typedef int_u<nbits, force> impl;
};
@@ -369,8 +398,9 @@
struct operator_traits<operator_cmp, int_u<nbits, B1>, int_u<mbits,
B2> >
{
enum { commutative = true };
+ // FIXME: why unsafe? I think there is a reason.
typedef int_u<(unsigned) mlc::maxN<nbits, mbits, 32>::ret, unsafe>
ret;
- typedef int_u<nbits, B1> impl;
+ typedef int_u<nbits, force> impl;
};
} // end of internal.
Index: integre/ntg/real/optraits_real_defs.hh
--- integre/ntg/real/optraits_real_defs.hh Wed, 26 Nov 2003 16:45:27 +0100 burrus_n
(oln/g/11_optraits_s 1.15 640)
+++ integre/ntg/real/optraits_real_defs.hh Thu, 27 Nov 2003 11:26:27 +0100 burrus_n
(oln/g/11_optraits_s 1.14.1.1 640)
@@ -29,23 +29,23 @@
# define NTG_OPTRAITS_REAL_DEFS_HH
//
-// macros used in optraits_scalar definition
+// macros used in optraits_real definition
//
/////////////////////////////////////////////
-# define ASSIGN_SCALAR_OPERATOR(Name, Op) \
+# define ASSIGN_SCALAR_OPERATOR(Name) \
template <class T1, class T2> inline \
- static T1& Name(T1& lhs, const T2& rhs) \
+ static T1& Name##_equal(T1& lhs, const T2& rhs) \
{ \
ntg_is_a(T1, ntg::real)::ensure(); \
ntg_is_a(T2, ntg::real)::ensure(); \
\
- return Name##_impl<T1,T2>(lhs, rhs); \
+ return Name##_equal_impl<T1,T2>(lhs, rhs); \
} \
\
template <class T1, class T2> inline \
static T1& \
- Name##_impl(ntg::real_value<T1>& lhs, \
+ Name##_equal_impl(ntg::real_value<T1>& lhs, \
const ntg::real_value<T2>& rhs) \
{ \
typedef typename typetraits<T1>::behavior_type behavior_type; \
@@ -56,7 +56,7 @@
\
template <class T1, class T2> inline \
static T1& \
- Name##_impl(ntg::real_value<T1>& lhs, \
+ Name##_equal_impl(ntg::real_value<T1>& lhs, \
const ntg::any_const_class<T2> rhs) \
{ \
typedef typename typetraits<T1>::behavior_type behavior_type; \
@@ -67,7 +67,7 @@
\
template <class T1, class T2> inline \
static T1& \
- Name##_impl(ntg::any_class<T1> lhs, \
+ Name##_equal_impl(ntg::any_class<T1> lhs, \
const ntg::real_value<T2>& rhs) \
{ \
typedef typename typetraits<T1>::behavior_type behavior_type; \
@@ -76,7 +76,7 @@
return lhs.exact(); \
}
-# define ARITH_SCALAR_OPERATOR(Name, Op) \
+# define ARITH_SCALAR_OPERATOR(Name) \
template <class T1, class T2> inline \
static ntg_return_type(Name, T1, T2) \
Name(const T1& lhs, const T2& rhs) \
@@ -84,13 +84,54 @@
ntg_is_a(T1, ntg::real)::ensure(); \
ntg_is_a(T2, ntg::real)::ensure(); \
\
+ return Name##_impl<T1,T2>(lhs, rhs); \
+ } \
+ \
+ template <class T1, class T2> inline \
+ static ntg_return_type(Name, T1, T2) \
+ Name##_impl(const ntg::real_value<T1>& lhs, \
+ const ntg::real_value<T2>& rhs) \
+ { \
typedef ntg_return_type(Name, T1, T2) return_type; \
- return_type result(lhs); \
- result Op rhs; \
- return result; \
+ typedef typename \
+ typetraits<E>::abstract_behavior_type::get<return_type> \
+ behavior_type; \
+ return_type tmp; \
+ tmp = behavior_type::check_##Name(lhs.exact().val(), \
+ rhs.exact().val()); \
+ return tmp; \
+ } \
+ \
+ template <class T1, class T2> inline \
+ static ntg_return_type(Name, T1, T2) \
+ Name##_impl(const ntg::real_value<T1>& lhs, \
+ const ntg::any_const_class<T2>& rhs) \
+ { \
+ typedef ntg_return_type(Name, T1, T2) return_type; \
+ typedef typename \
+ typetraits<E>::abstract_behavior_type::get<return_type> \
+ behavior_type; \
+ return_type tmp; \
+ tmp = behavior_type::check_##Name(lhs.exact().val(), \
+ rhs.exact()); \
+ return tmp; \
+ } \
+ \
+ template <class T1, class T2> inline \
+ static ntg_return_type(Name, T1, T2) \
+ Name##_impl(const ntg::any_const_class<T1>& lhs, \
+ const ntg::real_value<T2>& rhs) \
+ { \
+ typedef ntg_return_type(Name, T1, T2) return_type; \
+ typedef typename \
+ typetraits<E>::abstract_behavior_type::get<return_type> \
+ behavior_type; \
+ return_type tmp; \
+ tmp = behavior_type::check_##Name(lhs.exact(), \
+ rhs.exact().val()); \
+ return tmp; \
}
-
# define CMP_SCALAR_OPERATOR(Name, Op) \
template <class T1, class T2> inline \
static bool Name (const T1& lhs, const T2& rhs) \
@@ -105,7 +146,8 @@
} \
\
template <class T> inline \
- static bool Name##_impl(const ntg::real_value<T>& lhs, \
+ static bool \
+ Name##_impl(const ntg::real_value<T>& lhs, \
const ntg::real_value<T>& rhs) \
{ return lhs.exact().val() Op rhs.exact().val(); } \
\
@@ -121,7 +163,6 @@
//
////////////////////////////
-
# define ASSIGN_INT_OPERATOR(Name, Op) \
template <class T1, class T2> inline \
static T1& Name(T1& lhs, const T2& rhs) \
Index: integre/ntg/real/optraits_real.hh
--- integre/ntg/real/optraits_real.hh Thu, 27 Nov 2003 11:17:00 +0100 burrus_n
(oln/g/12_optraits_s 1.11.1.10 640)
+++ integre/ntg/real/optraits_real.hh Thu, 27 Nov 2003 11:26:27 +0100 burrus_n
(oln/g/12_optraits_s 1.11.1.8.1.1 640)
@@ -65,27 +65,26 @@
static storage_type_ default_val() { return zero(); }
//
- // dev note : the goal in those default operators is to check the kind
+ // dev note : the aim of these default operators is to check the kind
// of operands (value or not), and then call the good function.
//
// ASSIGN_SCALAR_OPERATOR includes default check_xxx_equal functions
//
- ASSIGN_SCALAR_OPERATOR(plus_equal, +)
- ASSIGN_SCALAR_OPERATOR(minus_equal, -)
- ASSIGN_SCALAR_OPERATOR(times_equal, *)
- ASSIGN_SCALAR_OPERATOR(div_equal, /)
-
- ARITH_SCALAR_OPERATOR(plus, +=)
- ARITH_SCALAR_OPERATOR(minus, -=)
- ARITH_SCALAR_OPERATOR(times, *=)
- ARITH_SCALAR_OPERATOR(div, /=)
+ ASSIGN_SCALAR_OPERATOR(plus)
+ ASSIGN_SCALAR_OPERATOR(minus)
+ ASSIGN_SCALAR_OPERATOR(times)
+ ASSIGN_SCALAR_OPERATOR(div)
+
+ ARITH_SCALAR_OPERATOR(plus)
+ ARITH_SCALAR_OPERATOR(minus)
+ ARITH_SCALAR_OPERATOR(times)
+ ARITH_SCALAR_OPERATOR(div)
CMP_SCALAR_OPERATOR(cmp_eq, ==)
CMP_SCALAR_OPERATOR(cmp_lt, <)
};
-
/*----------------------.
| optraits<float_value> |
`----------------------*/
Index: integre/ntg/core/value.hh
--- integre/ntg/core/value.hh Thu, 27 Nov 2003 11:17:00 +0100 burrus_n (oln/g/8_rec_value.
1.8.1.9 640)
+++ integre/ntg/core/value.hh Thu, 27 Nov 2003 11:26:27 +0100 burrus_n (oln/g/8_rec_value.
1.8.1.8.1.1 640)
@@ -107,7 +107,9 @@
template <class E>
struct typetraits<value<E> >
- {};
+ {
+ typedef E unsafe_type;
+ };
template <class E>
struct optraits<value<E> >
Index: integre/ntg/real/typetraits_builtin_int.hh
--- integre/ntg/real/typetraits_builtin_int.hh Thu, 27 Nov 2003 11:17:00 +0100 burrus_n
(oln/g/3_typetraits 1.7.1.13 640)
+++ integre/ntg/real/typetraits_builtin_int.hh Thu, 27 Nov 2003 11:26:27 +0100 burrus_n
(oln/g/3_typetraits 1.7.1.11.1.1 640)
@@ -51,6 +51,7 @@
\
typedef optraits<self> optraits; \
typedef unsafe::get<self> behavior_type; \
+ typedef unsafe abstract_behavior_type; \
\
typedef self base_type; \
typedef self storage_type; \
Index: integre/tests/types/runtests
--- integre/tests/types/runtests Fri, 01 Aug 2003 11:42:33 +0200 burrus_n
(oln/h/3_runtests 1.14.1.6 750)
+++ integre/tests/types/runtests Thu, 27 Nov 2003 11:26:27 +0100 burrus_n
(oln/h/3_runtests 1.14.1.7 750)
@@ -93,7 +93,7 @@
msg="";
case $expected:$estatus in
ok:0 | compfail:50 | abort:134)
- if test ! x"$KEEP_RUN" = x"1"; then
+ if test ! x"$KEEP_RUNS" = x"1"; then
rm -rf "$dir";
fi
msg="(ok)" ;;
Index: integre/ntg/core/macros.hh
--- integre/ntg/core/macros.hh Sun, 27 Jul 2003 19:14:42 +0200 burrus_n
(oln/s/19_macros.hh 1.7 640)
+++ integre/ntg/core/macros.hh Thu, 27 Nov 2003 11:26:27 +0100 burrus_n
(oln/s/19_macros.hh 1.8 640)
@@ -92,6 +92,9 @@
# define ntg_comp_type_(T) \
ntg::type_traits<T>::comp_type
+# define ntg_unsafe_type(T) typename ntg::type_traits<T>::unsafe_type
+# define ntg_unsafe_type_(T) ntg::type_traits<T>::unsafe_type
+
/*-----------------.
| values accessors |
`-----------------*/
Index: integre/ntg/real/builtin_float.hh
--- integre/ntg/real/builtin_float.hh Thu, 27 Nov 2003 11:17:00 +0100 burrus_n
(oln/s/47_builtin_fl 1.4 640)
+++ integre/ntg/real/builtin_float.hh Thu, 27 Nov 2003 11:26:27 +0100 burrus_n
(oln/s/47_builtin_fl 1.2.1.1 640)
@@ -57,6 +57,7 @@
typedef optraits<self> optraits_type;
typedef unsafe::get<self> behavior_type;
+ typedef unsafe abstract_behavior_type;
typedef self base_type;
typedef self storage_type;
@@ -86,6 +87,7 @@
typedef optraits<self> optraits_type;
typedef unsafe::get<self> behavior_type;
+ typedef unsafe abstract_behavior_type;
typedef self base_type;
typedef self storage_type;
Index: integre/ntg/real/range.hh
--- integre/ntg/real/range.hh Thu, 27 Nov 2003 11:17:00 +0100 burrus_n (oln/t/16_range.hh
1.5 640)
+++ integre/ntg/real/range.hh Thu, 27 Nov 2003 11:26:27 +0100 burrus_n (oln/t/16_range.hh
1.3.1.1 640)
@@ -53,6 +53,7 @@
typedef self ntg_type;
typedef optraits<self> optraits_type;
typedef typename behavior::template get<self> behavior_type;
+ typedef behavior abstract_behavior_type;
typedef ntgi_base_type(T) base_type;
typedef T storage_type;
Index: integre/ntg/real/cycle.hh
--- integre/ntg/real/cycle.hh Thu, 27 Nov 2003 11:17:00 +0100 burrus_n (oln/t/17_cycle.hh
1.3 640)
+++ integre/ntg/real/cycle.hh Thu, 27 Nov 2003 11:26:27 +0100 burrus_n (oln/t/17_cycle.hh
1.2.1.1 640)
@@ -53,6 +53,7 @@
typedef self ntg_type;
typedef optraits<self> optraits_type;
typedef cycle_behavior::get<self> behavior_type;
+ typedef cycle_behavior abstract_behavior_type;
typedef typename typetraits<T>::base_type base_type;
typedef T storage_type;
Index: integre/tests/types/tests/int_u8
--- integre/tests/types/tests/int_u8 Thu, 27 Nov 2003 11:45:11 +0100 burrus_n ()
+++ integre/tests/types/tests/int_u8 Thu, 27 Nov 2003 11:26:27 +0100 burrus_n
(oln/w/6_int_u8 1.1 640)
@@ -0,0 +1,9 @@
+int_u8 u1 = (unsigned char) 56;
+int_u8 u2 = (unsigned char) 153;
+int_u32 u = 0U;
+
+for (unsigned i = 0; i < 5000000; ++i)
+ for (unsigned j = 0; j < 10; ++j)
+ u = u1 * u2 + int_u8u(i % 50);
+
+return u != 8617;