Mercurial > octave
changeset 25847:c756e9a1e776
style fixes for oct-inttypes.h
* oct-inttypes.h: Style fixes. Undefine all macros after they are
used. None are needed outside of the header file. Use "OCTAVE_"
prefix for all macros.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 30 Aug 2018 15:19:21 -0400 |
parents | e88d3e648e1c |
children | 4c25d8d3a0ae |
files | liboctave/util/oct-inttypes.h |
diffstat | 1 files changed, 382 insertions(+), 268 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/util/oct-inttypes.h Thu Aug 30 11:14:43 2018 -0700 +++ b/liboctave/util/oct-inttypes.h Thu Aug 30 15:19:21 2018 -0400 @@ -53,9 +53,15 @@ { namespace math { - inline long double round (long double x) { return std::roundl (x); } + inline long double round (long double x) + { + return std::roundl (x); + } - inline long double isnan (long double x) { return isnan (static_cast<double> (x)); } + inline long double isnan (long double x) + { + return isnan (static_cast<double> (x)); + } } } @@ -64,244 +70,317 @@ // FIXME: we define this by our own because some compilers, such as // MSVC, do not provide std::abs (int64_t) and std::abs (uint64_t). In // the future, it should go away in favor of std::abs. + template <typename T> -inline T octave_int_abs (T x) { return (x >= 0 ? x : -x); } +inline T +octave_int_abs (T x) +{ + return (x >= 0 ? x : -x); +} // Query for an integer type of certain sizeof, and signedness. + template <int qsize, bool qsigned> struct query_integer_type { public: + static const bool registered = false; - typedef void type; // Void shall result in a compile-time error if we - // attempt to use it in computations. + + // Void shall result in a compile-time error if we attempt to use it + // in computations. + + typedef void type; }; -#define REGISTER_INT_TYPE(TYPE) \ +#define OCTAVE_REGISTER_INT_TYPE(TYPE) \ template <> \ - class query_integer_type<sizeof (TYPE), std::numeric_limits<TYPE>::is_signed> \ + class query_integer_type<sizeof (TYPE), \ + std::numeric_limits<TYPE>::is_signed> \ { \ public: \ + \ static const bool registered = true; \ + \ typedef TYPE type; \ } // No two registered integers can share sizeof and signedness. -REGISTER_INT_TYPE (int8_t); -REGISTER_INT_TYPE (uint8_t); -REGISTER_INT_TYPE (int16_t); -REGISTER_INT_TYPE (uint16_t); -REGISTER_INT_TYPE (int32_t); -REGISTER_INT_TYPE (uint32_t); -REGISTER_INT_TYPE (int64_t); -REGISTER_INT_TYPE (uint64_t); +OCTAVE_REGISTER_INT_TYPE (int8_t); +OCTAVE_REGISTER_INT_TYPE (uint8_t); +OCTAVE_REGISTER_INT_TYPE (int16_t); +OCTAVE_REGISTER_INT_TYPE (uint16_t); +OCTAVE_REGISTER_INT_TYPE (int32_t); +OCTAVE_REGISTER_INT_TYPE (uint32_t); +OCTAVE_REGISTER_INT_TYPE (int64_t); +OCTAVE_REGISTER_INT_TYPE (uint64_t); -// Rationale: Comparators have a single static method, rel(), that returns the -// result of the binary relation. They also have two static boolean fields: -// ltval, gtval determine the value of x OP y if x < y, x > y, respectively. -#define REGISTER_OCTAVE_CMP_OP(NM,OP) \ - class NM \ - { \ - public: \ - static const bool ltval = (0 OP 1); \ - static const bool gtval = (1 OP 0); \ - template <typename T> \ - static bool op (T x, T y) { return x OP y; } \ - } +#undef OCTAVE_REGISTER_INT_TYPE -// We also provide two special relations: ct, yielding always true, and cf, -// yielding always false. -#define REGISTER_OCTAVE_CONST_OP(NM,value) \ - class NM \ - { \ - public: \ - static const bool ltval = value; \ - static const bool gtval = value; \ - template <typename T> \ - static bool op (T, T) { return value; } \ - } +// Handles non-homogeneous integer comparisons. Avoids doing useless +// tests. -// Handles non-homogeneous integer comparisons. Avoids doing useless tests. class octave_int_cmp_op { - // This determines a suitable promotion type for T1 when meeting T2 in a - // binary relation. If promotion to int or T2 is safe, it is used. - // Otherwise, the signedness of T1 is preserved and it is widened if T2 is - // wider. - // Notice that if this is applied to both types, they must end up with equal - // size. + // This determines a suitable promotion type for T1 when meeting T2 + // in a binary relation. If promotion to int or T2 is safe, it is + // used. Otherwise, the signedness of T1 is preserved and it is + // widened if T2 is wider. Notice that if this is applied to both + // types, they must end up with equal size. + template <typename T1, typename T2> class prom { // Promote to int? static const bool pint = (sizeof (T1) < sizeof (int) && sizeof (T2) < sizeof (int)); + static const bool t1sig = std::numeric_limits<T1>::is_signed; static const bool t2sig = std::numeric_limits<T2>::is_signed; + static const bool psig = (pint || (sizeof (T2) > sizeof (T1) && t2sig) || t1sig); + static const int psize = (pint ? sizeof (int) : (sizeof (T2) > sizeof (T1) ? sizeof (T2) : sizeof (T1))); public: + typedef typename query_integer_type<psize, psig>::type type; }; // Implements comparisons between two types of equal size but // possibly different signedness. + template <typename xop, int size> class uiop { typedef typename query_integer_type<size, false>::type utype; typedef typename query_integer_type<size, true>::type stype; + public: + static bool op (utype x, utype y) - { return xop::op (x, y); } + { + return xop::op (x, y); + } + static bool op (stype x, stype y) - { return xop::op (x, y); } + { + return xop::op (x, y); + } + static bool op (stype x, utype y) - { return (x < 0) ? xop::ltval : xop::op (static_cast<utype> (x), y); } + { + return (x < 0) ? xop::ltval : xop::op (static_cast<utype> (x), y); + } + static bool op (utype x, stype y) - { return (y < 0) ? xop::gtval : xop::op (x, static_cast<utype> (y)); } + { + return (y < 0) ? xop::gtval : xop::op (x, static_cast<utype> (y)); + } }; public: - REGISTER_OCTAVE_CMP_OP (lt, <); - REGISTER_OCTAVE_CMP_OP (le, <=); - REGISTER_OCTAVE_CMP_OP (gt, >); - REGISTER_OCTAVE_CMP_OP (ge, >=); - REGISTER_OCTAVE_CMP_OP (eq, ==); - REGISTER_OCTAVE_CMP_OP (ne, !=); - REGISTER_OCTAVE_CONST_OP (ct, true); - REGISTER_OCTAVE_CONST_OP (cf, false); + + // Rationale: Comparators have a single static method, rel(), that + // returns the result of the binary relation. They also have two + // static boolean fields: ltval, gtval determine the value of x OP y + // if x < y, x > y, respectively. + +#define OCTAVE_REGISTER_INT_CMP_OP(NM, OP) \ + class NM \ + { \ + public: \ + \ + static const bool ltval = (0 OP 1); \ + static const bool gtval = (1 OP 0); \ + \ + template <typename T> \ + static bool op (T x, T y) { return x OP y; } \ + } + + OCTAVE_REGISTER_INT_CMP_OP (lt, <); + OCTAVE_REGISTER_INT_CMP_OP (le, <=); + OCTAVE_REGISTER_INT_CMP_OP (gt, >); + OCTAVE_REGISTER_INT_CMP_OP (ge, >=); + OCTAVE_REGISTER_INT_CMP_OP (eq, ==); + OCTAVE_REGISTER_INT_CMP_OP (ne, !=); + +#undef OCTAVE_REGISTER_INT_CMP_OP + + // We also provide two special relations: ct, yielding always true, + // and cf, yielding always false. + +#define OCTAVE_REGISTER_INT_CONST_OP(NM, VALUE) \ + class NM \ + { \ + public: \ + \ + static const bool ltval = VALUE; \ + static const bool gtval = VALUE; \ + \ + template <typename T> \ + static bool op (T, T) { return VALUE; } \ + } + + OCTAVE_REGISTER_INT_CONST_OP (ct, true); + OCTAVE_REGISTER_INT_CONST_OP (cf, false); + +#undef OCTAVE_REGISTER_INT_CONST_OP // Universal comparison operation. + template <typename xop, typename T1, typename T2> static bool op (T1 x, T2 y) { typedef typename prom<T1, T2>::type PT1; typedef typename prom<T2, T1>::type PT2; + return uiop<xop, sizeof (PT1)>::op (static_cast<PT1> (x), static_cast<PT2> (y)); } public: - // Mixed comparisons + // Mixed comparisons. + template <typename xop, typename T> - static bool - mop (T x, double y) - { return xop::op (static_cast<double> (x), y); } + static bool mop (T x, double y) + { + return xop::op (static_cast<double> (x), y); + } template <typename xop, typename T> - static bool - mop (double x, T y) - { return xop::op (x, static_cast<double> (y)); } + static bool mop (double x, T y) + { + return xop::op (x, static_cast<double> (y)); + } #if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED) -# define DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS(T) \ - template <typename xop> static OCTAVE_API bool \ - external_mop (double, T); \ - template <typename xop> static OCTAVE_API bool \ - external_mop (T, double) - DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS (int64_t); - DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS (uint64_t); +# define OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_CMP_OPS(T) \ + template <typename xop> \ + static OCTAVE_API bool external_mop (double, T); \ + \ + template <typename xop> \ + static OCTAVE_API bool external_mop (T, double) + + OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_CMP_OPS (int64_t); + OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_CMP_OPS (uint64_t); + #endif // Typecasting to doubles won't work properly for 64-bit integers -- - // they lose precision. - // If we have long doubles, use them... + // they lose precision. If we have long doubles, use them... + #if defined (OCTAVE_INT_USE_LONG_DOUBLE) + # if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED) -# define DEFINE_LONG_DOUBLE_CMP_OP(T) \ - template <typename xop> \ - static bool \ - mop (double x, T y) \ - { \ - return external_mop<xop> (x, y); \ - } \ - template <typename xop> \ - static bool \ - mop (T x, double y) \ - { \ - return external_mop<xop> (x, y); \ + +# define OCTAVE_DEFINE_LONG_DOUBLE_INT_CMP_OP(T) \ + template <typename xop> \ + static bool mop (double x, T y) \ + { \ + return external_mop<xop> (x, y); \ + } \ + \ + template <typename xop> \ + static bool mop (T x, double y) \ + { \ + return external_mop<xop> (x, y); \ } + # else -# define DEFINE_LONG_DOUBLE_CMP_OP(T) \ + +# define OCTAVE_DEFINE_LONG_DOUBLE_INT_CMP_OP(T) \ template <typename xop> \ - static bool \ - mop (double x, T y) \ + static bool mop (double x, T y) \ { \ return xop::op (static_cast<long double> (x), \ static_cast<long double> (y)); \ } \ + \ template <typename xop> \ - static bool \ - mop (T x, double y) \ + static bool mop (T x, double y) \ { \ return xop::op (static_cast<long double> (x), \ static_cast<long double> (y)); \ } + # endif + #else + // ... otherwise, use external handlers - // FIXME: We could declare directly the mop methods as external, - // but we can't do this because bugs in gcc (<= 4.3) prevent - // explicit instantiations later in that case. -# define DEFINE_LONG_DOUBLE_CMP_OP(T) \ - template <typename xop> static OCTAVE_API bool \ - emulate_mop (double, T); \ + // FIXME: We could declare directly the mop methods as external, but + // we can't do this because bugs in gcc (<= 4.3) prevent explicit + // instantiations later in that case. + +# define OCTAVE_DEFINE_LONG_DOUBLE_INT_CMP_OP(T) \ template <typename xop> \ - static bool \ - mop (double x, T y) \ + static OCTAVE_API bool emulate_mop (double, T); \ + \ + template <typename xop> \ + static bool mop (double x, T y) \ { \ return emulate_mop<xop> (x, y); \ } \ - template <typename xop> static OCTAVE_API bool \ - emulate_mop (T, double); \ + \ template <typename xop> \ - static bool \ - mop (T x, double y) \ + static OCTAVE_API bool emulate_mop (T, double); \ + \ + template <typename xop> \ + static bool mop (T x, double y) \ { \ return emulate_mop<xop> (x, y); \ } + #endif - DEFINE_LONG_DOUBLE_CMP_OP(int64_t) - DEFINE_LONG_DOUBLE_CMP_OP(uint64_t) + OCTAVE_DEFINE_LONG_DOUBLE_INT_CMP_OP (int64_t) + OCTAVE_DEFINE_LONG_DOUBLE_INT_CMP_OP (uint64_t) -#undef DEFINE_LONG_DOUBLE_CMP_OP +#undef OCTAVE_DEFINE_LONG_DOUBLE_INT_CMP_OP }; -// Base integer class. No data, just conversion methods and exception flags. +// Base integer class. No data, just conversion methods and exception +// flags. + template <typename T> class octave_int_base { public: - static T min_val () { return std::numeric_limits<T>::min (); } - static T max_val () { return std::numeric_limits<T>::max (); } + static T min_val (void) { return std::numeric_limits<T>::min (); } + static T max_val (void) { return std::numeric_limits<T>::max (); } // Convert integer value. + template <typename S> - static T - truncate_int (const S& value) + static T truncate_int (const S& value) { - // An exhaustive test whether the max and/or min check can be omitted. + // An exhaustive test whether the max and/or min check can be + // omitted. + static const bool t_is_signed = std::numeric_limits<T>::is_signed; static const bool s_is_signed = std::numeric_limits<S>::is_signed; + static const int t_size = sizeof (T); static const int s_size = sizeof (S); static const bool omit_chk_min = (! s_is_signed || (t_is_signed && t_size >= s_size)); + static const bool omit_chk_max = (t_size > s_size || (t_size == s_size && (! t_is_signed || s_is_signed))); - // If the check can be omitted, substitute constant false relation. + + // If the check can be omitted, substitute constant false + // relation. + typedef octave_int_cmp_op::cf cf; typedef octave_int_cmp_op::lt lt; typedef octave_int_cmp_op::gt gt; @@ -309,157 +388,152 @@ typedef typename if_then_else<omit_chk_max, cf, gt>::result chk_max; // Efficiency of the following depends on inlining and dead code - // elimination, but that should be a piece of cake for most compilers. + // elimination, but that should be a piece of cake for most + // compilers. + if (chk_min::op (value, static_cast<S> (min_val ()))) - { - return min_val (); - } + return min_val (); else if (chk_max::op (value, static_cast<S> (max_val ()))) - { - return max_val (); - } + return max_val (); else return static_cast<T> (value); } private: - // Computes a real-valued threshold for a max/min check. + // Compute a real-valued threshold for a max/min check. + template <typename S> - static S - compute_threshold (S val, T orig_val) + static S compute_threshold (S val, T orig_val) { - val = octave::math::round (val); // Fool optimizations (maybe redundant) + // Fool optimizations (maybe redundant). + + val = octave::math::round (val); + // If val is even, but orig_val is odd, we're one unit off. + if (orig_val % 2 && val / 2 == octave::math::round (val / 2)) // FIXME: is this always correct? val *= (static_cast<S> (1) - (std::numeric_limits<S>::epsilon () / 2)); + return val; } public: // Convert a real number (check NaN and non-int). + template <typename S> - static T - convert_real (const S& value); + static T convert_real (const S& value); }; -// Saturated (homogeneous) integer arithmetics. The signed and unsigned -// implementations are significantly different, so we implement another layer -// and completely specialize. Arithmetics inherits from octave_int_base so -// that it can use its exceptions and truncation functions. +// Saturated (homogeneous) integer arithmetics. The signed and +// unsigned implementations are significantly different, so we +// implement another layer and completely specialize. Arithmetics +// inherits from octave_int_base so that it can use its exceptions and +// truncation functions. template <typename T, bool is_signed> class octave_int_arith_base { }; -// Unsigned arithmetics. C++ standard requires it to be modular, so the -// overflows can be handled efficiently and reliably. +// Unsigned arithmetics. C++ standard requires it to be modular, so +// the overflows can be handled efficiently and reliably. + template <typename T> class octave_int_arith_base<T, false> : octave_int_base<T> { public: - static T - abs (T x) { return x; } + static T abs (T x) { return x; } - static T - signum (T x) { return x ? static_cast<T> (1) : static_cast<T> (0); } + static T signum (T x) { return x ? static_cast<T> (1) : static_cast<T> (0); } // Shifts do not overflow. - static T - rshift (T x, int n) { return x >> n; } - static T - lshift (T x, int n) { return x << n; } + static T rshift (T x, int n) { return x >> n; } + + static T lshift (T x, int n) { return x << n; } - static T - minus (T) - { - return static_cast<T> (0); - } + static T minus (T) { return static_cast<T> (0); } - // the overflow behavior for unsigned integers is guaranteed by C/C++, - // so the following should always work. - static T - add (T x, T y) + // The overflow behavior for unsigned integers is guaranteed by + // C and C++, so the following should always work. + + static T add (T x, T y) { T u = x + y; + if (u < x) - { - u = octave_int_base<T>::max_val (); - } + u = octave_int_base<T>::max_val (); + return u; } - static T - sub (T x, T y) + static T sub (T x, T y) { T u = x - y; + if (u > x) - { - u = 0; - } + u = 0; + return u; } - // Multiplication is done using promotion to wider integer type. If there is - // no suitable promotion type, this operation *MUST* be specialized. + // Multiplication is done using promotion to wider integer type. If + // there is no suitable promotion type, this operation *MUST* be + // specialized. + static T mul (T x, T y) { return mul_internal (x, y); } - static T - mul_internal (T x, T y) + static T mul_internal (T x, T y) { // Promotion type for multiplication (if exists). + typedef typename query_integer_type<2*sizeof (T), false>::type mptype; + return octave_int_base<T>::truncate_int (static_cast<mptype> (x) - * static_cast<mptype> (y)); + * static_cast<mptype> (y)); } - // Division with rounding to nearest. Note that / and % are probably - // computed by a single instruction. - static T - div (T x, T y) + // Division with rounding to nearest. Note that / and % are + // probably computed by a single instruction. + + static T div (T x, T y) { if (y != 0) { T z = x / y; T w = x % y; - if (w >= y-w) z += 1; + + if (w >= y-w) + z += 1; + return z; } else - { - return x ? octave_int_base<T>::max_val () : 0; - } + return x ? octave_int_base<T>::max_val () : 0; } // Remainder. - static T - rem (T x, T y) - { - return y != 0 ? x % y : 0; - } + + static T rem (T x, T y) { return y != 0 ? x % y : 0; } // Modulus. Note the weird y = 0 case for Matlab compatibility. - static T - mod (T x, T y) - { - return y != 0 ? x % y : x; - } + + static T mod (T x, T y) { return y != 0 ? x % y : x; } }; #if defined (OCTAVE_INT_USE_LONG_DOUBLE) -// Handle 64-bit multiply using long double +// Handle 64-bit multiply using long double. -#if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED) +# if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED) extern OCTAVE_API uint64_t octave_external_uint64_uint64_mul (uint64_t, uint64_t); -#endif +# endif template <> inline uint64_t @@ -481,16 +555,17 @@ inline uint64_t octave_int_arith_base<uint64_t, false>::mul (uint64_t x, uint64_t y) { -#if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED) +# if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED) return octave_external_uint64_uint64_mul (x, y); -#else +# else return mul_internal (x, y); -#endif +# endif } #else // Special handler for 64-bit integer multiply. + template <> OCTAVE_API uint64_t octave_int_arith_base<uint64_t, false>::mul_internal (uint64_t, uint64_t); @@ -502,17 +577,14 @@ { // The corresponding unsigned type. typedef typename query_integer_type<sizeof (T), false>::type UT; + public: // Returns 1 for negative number, 0 otherwise. - static T - __signbit (T x) - { - return (x < 0) ? 1 : 0; - } - static T - abs (T x) + static T __signbit (T x) { return (x < 0) ? 1 : 0; } + + static T abs (T x) { // -INT_MAX is safe because C++ actually allows only three // implementations of integers: sign & magnitude, ones complement @@ -526,27 +598,24 @@ : ((x < 0) ? -x : x)); } - static T - signum (T x) + static T signum (T x) { // With modest optimizations, this will compile without a jump. + return ((x > 0) ? 1 : 0) - __signbit (x); } // FIXME: we do not have an authority what signed shifts should - // exactly do, so we define them the easy way. Note that Matlab does - // not define signed shifts. + // exactly do, so we define them the easy way. Note that Matlab + // does not define signed shifts. - static T - rshift (T x, int n) { return x >> n; } + static T rshift (T x, int n) { return x >> n; } - static T - lshift (T x, int n) { return x << n; } + static T lshift (T x, int n) { return x << n; } // Minus has problems similar to abs. - static T - minus (T x) + static T minus (T x) { return ((octave_int_base<T>::min_val () < -octave_int_base<T>::max_val () && x == octave_int_base<T>::min_val ()) @@ -554,8 +623,7 @@ : -x); } - static T - add (T x, T y) + static T add (T x, T y) { // Avoid anything that may overflow. @@ -568,8 +636,7 @@ : x + y)); } - static T - sub (T x, T y) + static T sub (T x, T y) { // Avoid anything that may overflow. @@ -582,24 +649,28 @@ : x - y)); } - // Multiplication is done using promotion to wider integer type. If there is - // no suitable promotion type, this operation *MUST* be specialized. + // Multiplication is done using promotion to wider integer type. If + // there is no suitable promotion type, this operation *MUST* be + // specialized. + static T mul (T x, T y) { return mul_internal (x, y); } - static T - mul_internal (T x, T y) + static T mul_internal (T x, T y) { // Promotion type for multiplication (if exists). + typedef typename query_integer_type<2*sizeof (T), true>::type mptype; + return octave_int_base<T>::truncate_int (static_cast<mptype> (x) * static_cast<mptype> (y)); } // Division. - static T - div (T x, T y) + + static T div (T x, T y) { T z; + if (y == 0) { if (x < 0) @@ -613,9 +684,7 @@ { // This is a special case that overflows as well. if (y == -1 && x == octave_int_base<T>::min_val ()) - { - z = octave_int_base<T>::max_val (); - } + z = octave_int_base<T>::max_val (); else { z = x / y; @@ -628,6 +697,7 @@ else { z = x / y; + // FIXME: this is a workaround due to MSVC's absence of // std::abs (int64_t). The call to octave_int_abs can't // overflow, but std::abs (x) can! @@ -640,15 +710,15 @@ } // Remainder. - static T - rem (T x, T y) + + static T rem (T x, T y) { return y != 0 ? x % y : 0; } // Modulus. Note the weird y = 0 case for Matlab compatibility. - static T - mod (T x, T y) + + static T mod (T x, T y) { if (y != 0) { @@ -664,12 +734,12 @@ // Handle 64-bit multiply using long double -#if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED) +# if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED) extern OCTAVE_API int64_t octave_external_int64_int64_mul (int64_t, int64_t); -#endif +# endif template <> inline int64_t @@ -693,16 +763,17 @@ inline int64_t octave_int_arith_base<int64_t, true>::mul (int64_t x, int64_t y) { -#if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED) +# if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED) return octave_external_int64_int64_mul (x, y); -#else +# else return mul_internal (x, y); -#endif +# endif } #else // Special handler for 64-bit integer multiply. + template <> OCTAVE_API int64_t octave_int_arith_base<int64_t, true>::mul_internal (int64_t, int64_t); @@ -720,6 +791,7 @@ octave_int : public octave_int_base<T> { public: + typedef T val_type; octave_int (void) : ival () { } @@ -727,24 +799,32 @@ octave_int (T i) : ival (i) { } #if defined (OCTAVE_HAVE_OVERLOAD_CHAR_INT8_TYPES) + // Always treat characters as unsigned. octave_int (char c) : ival (octave_int_base<T>::truncate_int (static_cast<unsigned char> (c))) { } + #endif - octave_int (double d) : ival (octave_int_base<T>::convert_real (d)) { } + octave_int (double d) + : ival (octave_int_base<T>::convert_real (d)) { } - octave_int (float d) : ival (octave_int_base<T>::convert_real (d)) { } + octave_int (float d) + : ival (octave_int_base<T>::convert_real (d)) { } #if defined (OCTAVE_INT_USE_LONG_DOUBLE) - octave_int (long double d) : ival (octave_int_base<T>::convert_real (d)) { } + + octave_int (long double d) + : ival (octave_int_base<T>::convert_real (d)) { } + #endif octave_int (bool b) : ival (b) { } template <typename U> - octave_int (const U& i) : ival(octave_int_base<T>::truncate_int (i)) { } + octave_int (const U& i) + : ival(octave_int_base<T>::truncate_int (i)) { } template <typename U> octave_int (const octave_int<U>& i) @@ -761,7 +841,9 @@ T value (void) const { return ival; } const unsigned char * iptr (void) const - { return reinterpret_cast<const unsigned char *> (& ival); } + { + return reinterpret_cast<const unsigned char *> (& ival); + } bool operator ! (void) const { return ! ival; } @@ -775,21 +857,19 @@ operator T (void) const { return value (); } - octave_int<T> - operator + () const - { return *this; } + octave_int<T> operator + () const { return *this; } // unary operators & mappers -#define OCTAVE_INT_UN_OP(OPNAME,NAME) \ +#define OCTAVE_INT_UN_OP(OPNAME, NAME) \ inline octave_int<T> \ OPNAME () const \ { \ return octave_int_arith<T>::NAME (ival); \ } - OCTAVE_INT_UN_OP(operator -, minus) - OCTAVE_INT_UN_OP(abs, abs) - OCTAVE_INT_UN_OP(signum, signum) + OCTAVE_INT_UN_OP (operator -, minus) + OCTAVE_INT_UN_OP (abs, abs) + OCTAVE_INT_UN_OP (signum, signum) #undef OCTAVE_INT_UN_OP @@ -800,6 +880,7 @@ { \ return octave_int_arith<T>::NAME (ival, y); \ } \ + \ inline octave_int<T>& \ operator OP##= (const ARGT& y) \ { \ @@ -807,13 +888,13 @@ return *this; \ } - OCTAVE_INT_BIN_OP(+, add, octave_int<T>) - OCTAVE_INT_BIN_OP(-, sub, octave_int<T>) - OCTAVE_INT_BIN_OP(*, mul, octave_int<T>) - OCTAVE_INT_BIN_OP(/, div, octave_int<T>) - OCTAVE_INT_BIN_OP(%, rem, octave_int<T>) - OCTAVE_INT_BIN_OP(<<, lshift, int) - OCTAVE_INT_BIN_OP(>>, rshift, int) + OCTAVE_INT_BIN_OP (+, add, octave_int<T>) + OCTAVE_INT_BIN_OP (-, sub, octave_int<T>) + OCTAVE_INT_BIN_OP (*, mul, octave_int<T>) + OCTAVE_INT_BIN_OP (/, div, octave_int<T>) + OCTAVE_INT_BIN_OP (%, rem, octave_int<T>) + OCTAVE_INT_BIN_OP (<<, lshift, int) + OCTAVE_INT_BIN_OP (>>, rshift, int) #undef OCTAVE_INT_BIN_OP @@ -892,6 +973,7 @@ // FIXME: Do we really need a differently named single-precision // function integer power function here instead of an overloaded // one? + template <typename T> extern OCTAVE_API octave_int<T> powf (const float& a, const octave_int<T>& b); @@ -948,6 +1030,7 @@ operator << (std::ostream& os, const octave_int<int8_t>& ival) { os << static_cast<int> (ival.value ()); + return os; } @@ -956,6 +1039,7 @@ operator << (std::ostream& os, const octave_int<uint8_t>& ival) { os << static_cast<unsigned int> (ival.value ()); + return os; } @@ -966,6 +1050,7 @@ int tmp = 0; is >> tmp; ival = static_cast<int8_t> (tmp); + return is; } @@ -976,6 +1061,7 @@ unsigned int tmp = 0; is >> tmp; ival = static_cast<uint8_t> (tmp); + return is; } @@ -1011,30 +1097,32 @@ #if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED) -#define DECLARE_EXTERNAL_LONG_DOUBLE_OP(T, OP) \ - extern OCTAVE_API T \ - external_double_ ## T ## _ ## OP (double x, T y); \ - extern OCTAVE_API T \ +# define OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OP(T, OP) \ + extern OCTAVE_API T \ + external_double_ ## T ## _ ## OP (double x, T y); \ + \ + extern OCTAVE_API T \ external_ ## T ## _double_ ## OP (T x, double y) -#define DECLARE_EXTERNAL_LONG_DOUBLE_OPS(T) \ - DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, add); \ - DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, sub); \ - DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, mul); \ - DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, div) +# define OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OPS(T) \ + OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OP (T, add); \ + OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OP (T, sub); \ + OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OP (T, mul); \ + OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OP (T, div) -DECLARE_EXTERNAL_LONG_DOUBLE_OPS (octave_int64); -DECLARE_EXTERNAL_LONG_DOUBLE_OPS (octave_uint64); + OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OPS (octave_int64); + OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OPS (octave_uint64); #endif -#define OCTAVE_INT_DOUBLE_BIN_OP0(OP) \ - template <typename T> \ - inline octave_int<T> \ +#define OCTAVE_INT_DOUBLE_BIN_OP0(OP) \ + template <typename T> \ + inline octave_int<T> \ operator OP (const octave_int<T>& x, const double& y) \ { \ return octave_int<T> (static_cast<double> (x) OP y); \ } \ + \ template <typename T> \ inline octave_int<T> \ operator OP (const double& x, const octave_int<T>& y) \ @@ -1043,75 +1131,96 @@ } #if defined (OCTAVE_INT_USE_LONG_DOUBLE) -// Handle mixed op using long double -#if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED) -# define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \ + +// Handle mixed op using long double. + +# if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED) + +# define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \ OCTAVE_INT_DOUBLE_BIN_OP0(OP) \ + \ template <> \ inline octave_int64 \ operator OP (const double& x, const octave_int64& y) \ { \ return external_double_octave_int64_ ## NAME (x, y); \ } \ + \ template <> \ inline octave_uint64 \ operator OP (const double& x, const octave_uint64& y) \ { \ return external_double_octave_uint64_ ## NAME (x, y); \ } \ + \ template <> \ inline octave_int64 \ operator OP (const octave_int64& x, const double& y) \ { \ return external_octave_int64_double_ ## NAME (x, y); \ } \ + \ template <> \ inline octave_uint64 \ operator OP (const octave_uint64& x, const double& y) \ { \ return external_octave_uint64_double_ ## NAME (x, y); \ } -#else -# define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \ + +# else + +# define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \ OCTAVE_INT_DOUBLE_BIN_OP0(OP) \ + \ template <> \ inline octave_int64 \ operator OP (const double& x, const octave_int64& y) \ { \ return octave_int64 (x OP static_cast<long double> (y.value ())); \ } \ + \ template <> \ inline octave_uint64 \ operator OP (const double& x, const octave_uint64& y) \ { \ return octave_uint64 (x OP static_cast<long double> (y.value ())); \ } \ + \ template <> \ inline octave_int64 \ operator OP (const octave_int64& x, const double& y) \ { \ return octave_int64 (static_cast<long double> (x.value ()) OP y); \ } \ + \ template <> \ inline octave_uint64 \ operator OP (const octave_uint64& x, const double& y) \ { \ return octave_uint64 (static_cast<long double> (x.value ()) OP y); \ } -#endif + +# endif + #else -// external handlers -#define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \ + +// External handlers. + +# define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \ OCTAVE_INT_DOUBLE_BIN_OP0(OP) \ + \ template <> \ OCTAVE_API octave_int64 \ operator OP (const double&, const octave_int64&); \ + \ template <> \ OCTAVE_API octave_uint64 \ operator OP (const double&, const octave_uint64&); \ + \ template <> \ OCTAVE_API octave_int64 \ operator OP (const octave_int64&, const double&); \ + \ template <> \ OCTAVE_API octave_uint64 \ operator OP (const octave_uint64&, const double&); @@ -1125,16 +1234,17 @@ #undef OCTAVE_INT_DOUBLE_BIN_OP0 #undef OCTAVE_INT_DOUBLE_BIN_OP -#undef DECLARE_EXTERNAL_LONG_DOUBLE_OP -#undef DECLARE_EXTERNAL_LONG_DOUBLE_OPS +#undef OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OP +#undef OCTAVE_DECLARE_EXTERNAL_LONG_DOUBLE_INT_OPS -#define OCTAVE_INT_DOUBLE_CMP_OP(OP,NAME) \ +#define OCTAVE_INT_DOUBLE_CMP_OP(OP, NAME) \ template <typename T> \ inline bool \ operator OP (const octave_int<T>& x, const double& y) \ { \ return octave_int_cmp_op::mop<octave_int_cmp_op::NAME> (x.value (), y); \ } \ + \ template <typename T> \ inline bool \ operator OP (const double& x, const octave_int<T>& y) \ @@ -1160,6 +1270,7 @@ { \ return x OP static_cast<double> (y); \ } \ + \ template <typename T> \ inline octave_int<T> \ operator OP (float x, const octave_int<T>& y) \ @@ -1181,6 +1292,7 @@ { \ return x OP static_cast<double> (y); \ } \ + \ template <typename T> \ bool \ operator OP (const float& x, const octave_int<T>& y) \ @@ -1203,6 +1315,7 @@ { const T xv = x.value (); const T yv = y.value (); + return octave_int<T> (xv >= yv ? xv : yv); } @@ -1212,6 +1325,7 @@ { const T xv = x.value (); const T yv = y.value (); + return octave_int<T> (xv <= yv ? xv : yv); }