Mercurial > hg > octave-lojdl
changeset 8185:69c5cce38c29
implement 64-bit arithmetics
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Mon, 06 Oct 2008 21:38:49 +0200 |
parents | bb3bdcdaa063 |
children | 23ff439ea0dd |
files | ChangeLog configure.in liboctave/ChangeLog liboctave/mx-ops liboctave/oct-inttypes.cc liboctave/oct-inttypes.h src/ChangeLog src/OPERATORS/op-i64-i64.cc src/OPERATORS/op-ui64-ui64.cc |
diffstat | 9 files changed, 705 insertions(+), 311 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2008-10-01 Jaroslav Hajek <highegg@gmail.com> + + * configure.in: Check for sizeof (long double) and randl. + 2008-09-30 Jaroslav Hajek <highegg@gmail.com> * aclocal.m4 (OCTAVE_FAST_INT_OPS): New macro.
--- a/configure.in +++ b/configure.in @@ -1378,6 +1378,10 @@ OCTAVE_FAST_INT_OPS +### Check for long double type (for 64-bit integers) + +AC_CHECK_SIZEOF(long double) + ### Checks for header files. AC_HEADER_STDC @@ -1452,7 +1456,7 @@ getppid getpwent getpwuid gettimeofday getuid getwd _kbhit kill \ lgamma lgammaf lgamma_r lgammaf_r link localtime_r log1p log1pf lstat \ memmove mkdir mkfifo mkstemp on_exit pipe poll putenv raise readlink \ - realpath rename resolvepath rindex rmdir round select setgrent setlocale \ + realpath rename resolvepath rindex rmdir round roundl select setgrent setlocale \ setpwent setvbuf sigaction siglongjmp sigpending sigprocmask sigsuspend \ snprintf stat strcasecmp strdup strerror stricmp strncasecmp \ strnicmp strptime strsignal symlink tempnam tgamma tgammaf trunc umask \ @@ -1967,6 +1971,13 @@ #define SIZEOF_OCTAVE_IDX_TYPE SIZEOF_INT #endif +// To be able to use long doubles for 64-bit mixed arithmetics, we need them at +// least 80 bits wide and we need roundl declared in math.h +// TODO: Maybe substitute this by a more precise check in the future. +#if (SIZEOF_LONG_DOUBLE >= 10) && defined (HAVE_ROUNDL) +#define OCTAVE_INT_USE_LONG_DOUBLE +#endif + #define OCTAVE_EMPTY_CPP_ARG #include "oct-dlldefs.h"
--- a/liboctave/ChangeLog +++ b/liboctave/ChangeLog @@ -1,3 +1,13 @@ +2008-10-01 Jaroslav Hajek <highegg@gmail.com> + + * oct-inttypes.h (octave_int<T>::one, octave_int<T>::zero): Declare + constants. + * oct-inttypes.cc: Define them. + * oct-inttypes.h: Define mixed operations via long double if possible. + * oct-inttypes.cc: Define alternative implementations for 64-bit + multiplication and mixed operations. + * mx-ops: Instantiate all 64-bit integer operations. + 2008-10-06 Jaroslav Hajek <highegg@gmail.com> * oct-lookup.h: Mark functions inline. Add missing std:: qualifiers.
--- a/liboctave/mx-ops +++ b/liboctave/mx-ops @@ -54,22 +54,22 @@ fm FloatMatrix M fMatrix.h YES static_cast<float>(0.0) fnda FloatNDArray ND fNDArray.h YES static_cast<float>(0.0) fs float S NONE NO static_cast<float>(0.0) -i8 octave_int8 S oct-inttypes.h YES octave_int8(0) int8_t -ui8 octave_uint8 S oct-inttypes.h YES octave_uint8(0) uint8_t -i16 octave_int16 S oct-inttypes.h YES octave_int16(0) int16_t -ui16 octave_uint16 S oct-inttypes.h YES octave_uint16(0) uint16_t -i32 octave_int32 S oct-inttypes.h YES octave_int32(0) int32_t -ui32 octave_uint32 S oct-inttypes.h YES octave_uint32(0) uint32_t -i64 octave_int64 S oct-inttypes.h YES octave_int64(0) int64_t -ui64 octave_uint64 S oct-inttypes.h YES octave_uint64(0) uint64_t -i8nda int8NDArray ND int8NDArray.h YES octave_int8(0) int8_t -ui8nda uint8NDArray ND uint8NDArray.h YES octave_uint8(0) uint8_t -i16nda int16NDArray ND int16NDArray.h YES octave_int16(0) int16_t -ui16nda uint16NDArray ND uint16NDArray.h YES octave_uint16(0) uint16_t -i32nda int32NDArray ND int32NDArray.h YES octave_int32(0) int32_t -ui32nda uint32NDArray ND uint32NDArray.h YES octave_uint32(0) uint32_t -i64nda int64NDArray ND int64NDArray.h YES octave_int64(0) int64_t -ui64nda uint64NDArray ND uint64NDArray.h YES octave_uint64(0) uint64_t +i8 octave_int8 S oct-inttypes.h YES octave_int8::zero int8_t +ui8 octave_uint8 S oct-inttypes.h YES octave_uint8::zero uint8_t +i16 octave_int16 S oct-inttypes.h YES octave_int16::zero int16_t +ui16 octave_uint16 S oct-inttypes.h YES octave_uint16::zero uint16_t +i32 octave_int32 S oct-inttypes.h YES octave_int32::zero int32_t +ui32 octave_uint32 S oct-inttypes.h YES octave_uint32::zero uint32_t +i64 octave_int64 S oct-inttypes.h YES octave_int64::zero int64_t +ui64 octave_uint64 S oct-inttypes.h YES octave_uint64::zero uint64_t +i8nda int8NDArray ND int8NDArray.h YES octave_int8::zero int8_t +ui8nda uint8NDArray ND uint8NDArray.h YES octave_uint8::zero uint8_t +i16nda int16NDArray ND int16NDArray.h YES octave_int16::zero int16_t +ui16nda uint16NDArray ND uint16NDArray.h YES octave_uint16::zero uint16_t +i32nda int32NDArray ND int32NDArray.h YES octave_int32::zero int32_t +ui32nda uint32NDArray ND uint32NDArray.h YES octave_uint32::zero uint32_t +i64nda int64NDArray ND int64NDArray.h YES octave_int64::zero int64_t +ui64nda uint64NDArray ND uint64NDArray.h YES octave_uint64::zero uint64_t # ops # result_t lhs_t rhs_t op-type lhs_conv rhs_conv headers ... # @@ -153,10 +153,10 @@ i32nda i32nda s BCL NONE NONE boolMatrix.h boolNDArray.h ui32nda s ui32nda BCL NONE NONE boolMatrix.h boolNDArray.h ui32nda ui32nda s BCL NONE NONE boolMatrix.h boolNDArray.h -i64nda s i64nda CL NONE NONE boolMatrix.h boolNDArray.h -i64nda i64nda s CL NONE NONE boolMatrix.h boolNDArray.h -ui64nda s ui64nda CL NONE NONE boolMatrix.h boolNDArray.h -ui64nda ui64nda s CL NONE NONE boolMatrix.h boolNDArray.h +i64nda s i64nda BCL NONE NONE boolMatrix.h boolNDArray.h +i64nda i64nda s BCL NONE NONE boolMatrix.h boolNDArray.h +ui64nda s ui64nda BCL NONE NONE boolMatrix.h boolNDArray.h +ui64nda ui64nda s BCL NONE NONE boolMatrix.h boolNDArray.h i8nda fs i8nda BCL NONE NONE boolMatrix.h boolNDArray.h i8nda i8nda fs BCL NONE NONE boolMatrix.h boolNDArray.h ui8nda fs ui8nda BCL NONE NONE boolMatrix.h boolNDArray.h @@ -169,10 +169,10 @@ i32nda i32nda fs BCL NONE NONE boolMatrix.h boolNDArray.h ui32nda fs ui32nda BCL NONE NONE boolMatrix.h boolNDArray.h ui32nda ui32nda fs BCL NONE NONE boolMatrix.h boolNDArray.h -i64nda fs i64nda CL NONE NONE boolMatrix.h boolNDArray.h -i64nda i64nda fs CL NONE NONE boolMatrix.h boolNDArray.h -ui64nda fs ui64nda CL NONE NONE boolMatrix.h boolNDArray.h -ui64nda ui64nda fs CL NONE NONE boolMatrix.h boolNDArray.h +i64nda fs i64nda BCL NONE NONE boolMatrix.h boolNDArray.h +i64nda i64nda fs BCL NONE NONE boolMatrix.h boolNDArray.h +ui64nda fs ui64nda BCL NONE NONE boolMatrix.h boolNDArray.h +ui64nda ui64nda fs BCL NONE NONE boolMatrix.h boolNDArray.h # i8nda nda i8 BCL NONE NONE boolMatrix.h boolNDArray.h i8nda i8 nda BCL NONE NONE boolMatrix.h boolNDArray.h @@ -186,10 +186,10 @@ i32nda i32 nda BCL NONE NONE boolMatrix.h boolNDArray.h ui32nda nda ui32 BCL NONE NONE boolMatrix.h boolNDArray.h ui32nda ui32 nda BCL NONE NONE boolMatrix.h boolNDArray.h -i64nda nda i64 CL NONE NONE boolMatrix.h boolNDArray.h -i64nda i64 nda CL NONE NONE boolMatrix.h boolNDArray.h -ui64nda nda ui64 CL NONE NONE boolMatrix.h boolNDArray.h -ui64nda ui64 nda CL NONE NONE boolMatrix.h boolNDArray.h +i64nda nda i64 BCL NONE NONE boolMatrix.h boolNDArray.h +i64nda i64 nda BCL NONE NONE boolMatrix.h boolNDArray.h +ui64nda nda ui64 BCL NONE NONE boolMatrix.h boolNDArray.h +ui64nda ui64 nda BCL NONE NONE boolMatrix.h boolNDArray.h i8nda fnda i8 BCL NONE NONE boolMatrix.h boolNDArray.h i8nda i8 fnda BCL NONE NONE boolMatrix.h boolNDArray.h ui8nda fnda ui8 BCL NONE NONE boolMatrix.h boolNDArray.h @@ -202,10 +202,10 @@ i32nda i32 fnda BCL NONE NONE boolMatrix.h boolNDArray.h ui32nda fnda ui32 BCL NONE NONE boolMatrix.h boolNDArray.h ui32nda ui32 fnda BCL NONE NONE boolMatrix.h boolNDArray.h -i64nda fnda i64 CL NONE NONE boolMatrix.h boolNDArray.h -i64nda i64 fnda CL NONE NONE boolMatrix.h boolNDArray.h -ui64nda fnda ui64 CL NONE NONE boolMatrix.h boolNDArray.h -ui64nda ui64 fnda CL NONE NONE boolMatrix.h boolNDArray.h +i64nda fnda i64 BCL NONE NONE boolMatrix.h boolNDArray.h +i64nda i64 fnda BCL NONE NONE boolMatrix.h boolNDArray.h +ui64nda fnda ui64 BCL NONE NONE boolMatrix.h boolNDArray.h +ui64nda ui64 fnda BCL NONE NONE boolMatrix.h boolNDArray.h # i8nda nda i8nda BCL NONE NONE boolMatrix.h boolNDArray.h i8nda i8nda nda BCL NONE NONE boolMatrix.h boolNDArray.h @@ -219,10 +219,10 @@ i32nda i32nda nda BCL NONE NONE boolMatrix.h boolNDArray.h ui32nda nda ui32nda BCL NONE NONE boolMatrix.h boolNDArray.h ui32nda ui32nda nda BCL NONE NONE boolMatrix.h boolNDArray.h -i64nda nda i64nda CL NONE NONE boolMatrix.h boolNDArray.h -i64nda i64nda nda CL NONE NONE boolMatrix.h boolNDArray.h -ui6nda nda ui64nda CL NONE NONE boolMatrix.h boolNDArray.h -ui64nda ui64nda nda CL NONE NONE boolMatrix.h boolNDArray.h +i64nda nda i64nda BCL NONE NONE boolMatrix.h boolNDArray.h +i64nda i64nda nda BCL NONE NONE boolMatrix.h boolNDArray.h +ui64nda nda ui64nda BCL NONE NONE boolMatrix.h boolNDArray.h +ui64nda ui64nda nda BCL NONE NONE boolMatrix.h boolNDArray.h i8nda fnda i8nda BCL NONE NONE boolMatrix.h boolNDArray.h i8nda i8nda fnda BCL NONE NONE boolMatrix.h boolNDArray.h ui8nda fnda ui8nda BCL NONE NONE boolMatrix.h boolNDArray.h @@ -235,10 +235,10 @@ i32nda i32nda fnda BCL NONE NONE boolMatrix.h boolNDArray.h ui32nda fnda ui32nda BCL NONE NONE boolMatrix.h boolNDArray.h ui32nda ui32nda fnda BCL NONE NONE boolMatrix.h boolNDArray.h -i64nda fnda i64nda CL NONE NONE boolMatrix.h boolNDArray.h -i64nda i64nda fnda CL NONE NONE boolMatrix.h boolNDArray.h -ui6nda fnda ui64nda CL NONE NONE boolMatrix.h boolNDArray.h -ui64nda ui64nda fnda CL NONE NONE boolMatrix.h boolNDArray.h +i64nda fnda i64nda BCL NONE NONE boolMatrix.h boolNDArray.h +i64nda i64nda fnda BCL NONE NONE boolMatrix.h boolNDArray.h +ui64nda fnda ui64nda BCL NONE NONE boolMatrix.h boolNDArray.h +ui64nda ui64nda fnda BCL NONE NONE boolMatrix.h boolNDArray.h # x i8nda ui8 CL NONE NONE boolMatrix.h boolNDArray.h x i8nda i16 CL NONE NONE boolMatrix.h boolNDArray.h
--- a/liboctave/oct-inttypes.cc +++ b/liboctave/oct-inttypes.cc @@ -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. @@ -28,6 +29,12 @@ #include "oct-inttypes.h" +template<class T> +const octave_int<T> octave_int<T>::zero (static_cast<T> (0)); + +template<class T> +const octave_int<T> octave_int<T>::one (static_cast<T> (1)); + // define type names. #define DECLARE_OCTAVE_INT_TYPENAME(TYPE, TYPENAME) \ template <> \ @@ -43,64 +50,472 @@ DECLARE_OCTAVE_INT_TYPENAME (uint32_t, "uint32") DECLARE_OCTAVE_INT_TYPENAME (uint64_t, "uint64") -static void -gripe_64bit_mul() +#ifndef OCTAVE_INT_USE_LONG_DOUBLE + +// Define comparison operators + +template <class xop> +OCTAVE_API bool +octave_int_cmp_op::mop (uint64_t x, double y) +{ + static const double xxup = std::numeric_limits<uint64_t>::max (); + // This converts to the nearest double. Unless there's an equality, the + // result is clear. + double xx = x; + if (xx != y) + return xop::op (xx, y); + else + { + // If equality occured we compare as integers. + if (xx == xxup) + return xop::gtval; + else + return xop::op (x, static_cast<uint64_t> (xx)); + } +} + +template <class xop> +OCTAVE_API bool +octave_int_cmp_op::mop (int64_t x, double y) { - (*current_liboctave_error_handler) - ("64-bit integer multiplication is not implemented"); + static const double xxup = std::numeric_limits<int64_t>::max (); + static const double xxlo = std::numeric_limits<int64_t>::min (); + // This converts to the nearest double. Unless there's an equality, the + // result is clear. + double xx = x; + if (xx != y) + return xop::op (xx, y); + else + { + // If equality occured we compare as integers. + if (xx == xxup) + return xop::gtval; + else if (xx == xxlo) + return xop::ltval; + else + return xop::op (x, static_cast<int64_t> (xx)); + } + } +// We define double-int operations by reverting the operator + +// A trait class reverting the operator +template <class xop> +class rev_op +{ +public: + typedef xop op; +}; + +#define DEFINE_REVERTED_OPERATOR(OP1,OP2) \ + template <> \ + class rev_op<octave_int_cmp_op::OP1> \ + { \ + public: \ + typedef octave_int_cmp_op::OP2 op; \ + } + +DEFINE_REVERTED_OPERATOR(lt,gt); +DEFINE_REVERTED_OPERATOR(gt,lt); +DEFINE_REVERTED_OPERATOR(le,ge); +DEFINE_REVERTED_OPERATOR(ge,le); + +template <class xop> +OCTAVE_API bool +octave_int_cmp_op::mop (double x, uint64_t y) +{ + typedef typename rev_op<xop>::op rop; + return mop<rop> (y, x); +} + +template <class xop> +OCTAVE_API bool +octave_int_cmp_op::mop (double x, int64_t y) +{ + typedef typename rev_op<xop>::op rop; + return mop<rop> (y, x); +} + + +// Define handlers for int64 multiplication + template <> uint64_t -octave_int_arith_base<uint64_t, false>::mul (uint64_t, uint64_t) +octave_int_arith_base<uint64_t, false>::mul (uint64_t x, uint64_t y) { - gripe_64bit_mul (); - return static_cast<uint64_t> (0); + // Get upper words + uint64_t ux = x >> 32, uy = y >> 32; + uint64_t res; + if (ux) + { + if (uy) + goto overflow; + else + { + uint64_t ly = static_cast<uint32_t> (y), uxly = ux*ly; + if (uxly >> 32) + goto overflow; + uxly <<= 32; // never overflows + uint64_t lx = static_cast<uint32_t> (x), lxly = lx*ly; + res = add (uxly, lxly); + } + } + else if (uy) + { + uint64_t lx = static_cast<uint32_t> (x), uylx = uy*lx; + if (uylx >> 32) + goto overflow; + uylx <<= 32; // never overflows + uint64_t ly = static_cast<uint32_t> (y), lylx = ly*lx; + res = add (uylx, lylx); + } + else + { + uint64_t lx = static_cast<uint32_t> (x); + uint64_t ly = static_cast<uint32_t> (y); + res = lx*ly; + } + + return res; + +overflow: + ftrunc = true; + return max_val (); } + template <> int64_t -octave_int_arith_base<int64_t, true>::mul (int64_t, int64_t) +octave_int_arith_base<int64_t, true>::mul (int64_t x, int64_t y) { - gripe_64bit_mul (); - return static_cast<int64_t> (0); + // The signed case is far worse. The problem is that + // even if neither integer fits into signed 32-bit range, the result may + // still be OK. Uh oh. + + // Essentially, what we do is compute sign, multiply absolute values + // (as above) and impose the sign. + // TODO: Can we do something faster if we HAVE_FAST_INT_OPS? + + uint64_t usx = std::abs (x), usy = std::abs (y); + bool positive = (x < 0) == (y < 0); + + // Get upper words + uint64_t ux = usx >> 32, uy = usy >> 32; + uint64_t res; + if (ux) + { + if (uy) + goto overflow; + else + { + uint64_t ly = static_cast<uint32_t> (usy), uxly = ux*ly; + if (uxly >> 32) + goto overflow; + uxly <<= 32; // never overflows + uint64_t lx = static_cast<uint32_t> (usx), lxly = lx*ly; + res = uxly + lxly; + if (res < uxly) + goto overflow; + } + } + else if (uy) + { + uint64_t lx = static_cast<uint32_t> (usx), uylx = uy*lx; + if (uylx >> 32) + goto overflow; + uylx <<= 32; // never overflows + uint64_t ly = static_cast<uint32_t> (usy), lylx = ly*lx; + res = uylx + lylx; + if (res < uylx) + goto overflow; + } + else + { + uint64_t lx = static_cast<uint32_t> (usx); + uint64_t ly = static_cast<uint32_t> (usy); + res = lx*ly; + } + + if (positive) + { + if (res > static_cast<uint64_t> (max_val ())) + { + ftrunc = true; + return max_val (); + } + else + return static_cast<int64_t> (res); + } + else + { + if (res > static_cast<uint64_t> (-min_val ())) + { + ftrunc = true; + return min_val (); + } + else + return -static_cast<int64_t> (res); + } + + +overflow: + ftrunc = true; + return positive ? max_val () : min_val (); + } -static void -gripe_64bit_mixed() +#define INT_DOUBLE_BINOP_DECL(OP,SUFFIX) \ + template <> \ + OCTAVE_API octave_ ## SUFFIX \ + operator OP (const octave_ ## SUFFIX & x, const double& y) + +#define DOUBLE_INT_BINOP_DECL(OP,SUFFIX) \ + template <> \ + OCTAVE_API octave_ ## SUFFIX \ + operator OP (const double& x, const octave_ ## SUFFIX & y) + +INT_DOUBLE_BINOP_DECL (+, uint64) +{ + return (y < 0) ? x - octave_uint64(-y) : x + octave_uint64(y); +} + +DOUBLE_INT_BINOP_DECL (+, uint64) +{ return y + x; } + +INT_DOUBLE_BINOP_DECL (+, int64) { - (*current_liboctave_error_handler) - ("mixed double - 64-bit integer operations are not implemented"); + if (fabs (y) < static_cast<double> (octave_int64::max ())) + return x + octave_int64 (y); + else + { + // If the number is within the int64 range (the most common case, + // probably), the above will work as expected. If not, it's more + // complicated - as long as y is within _twice_ the signed range, the + // result may still be an integer. An instance of such an operation is + // 3*2**62 + (1+intmin('int64')) that should yield int64(2**62) + 1. So + // what we do is to try to convert y/2 and add it twice. Note that if y/2 + // overflows, the result must overflow as well, and that y/2 cannot be a + // fractional number. + octave_int64 y2 (y / 2); + return (x + y2) + y2; + } +} + +DOUBLE_INT_BINOP_DECL (+, int64) +{ + return y + x; +} + +INT_DOUBLE_BINOP_DECL (-, uint64) +{ + return x + (-y); } -#define DEFINE_DOUBLE_INT64_OP0(OP,ARGT,RETT) \ - template <> \ - OCTAVE_API RETT \ - operator OP (const double&, const ARGT&) \ - { gripe_64bit_mixed (); return 0.0; } \ - template <> \ - OCTAVE_API RETT \ - operator OP (const ARGT&, const double&) \ - { gripe_64bit_mixed (); return 0.0; } \ +DOUBLE_INT_BINOP_DECL (-, uint64) +{ + if (x <= static_cast<double> (octave_uint64::max ())) + return octave_uint64(x) - y; + else + { + // Again a trick to get the corner cases right. Things like + // 3**2**63 - intmax('uint64') should produce the correct result, i.e. + // int64(2**63) + 1. + const double p2_64 = std::pow (2.0, 64); + if (y.bool_value ()) + { + const uint64_t p2_64my = (~y.value ()) + 1; // Equals 2**64 - y + return octave_uint64 (x - p2_64) + octave_uint64 (p2_64my); + } + else + return octave_uint64 (p2_64); + } +} + +INT_DOUBLE_BINOP_DECL (-, int64) +{ + return x + (-y); +} + +DOUBLE_INT_BINOP_DECL (-, int64) +{ + static const bool twosc = (std::numeric_limits<int64_t>::min () + < -std::numeric_limits<int64_t>::max ()); + // In case of symmetric integers (not two's complement), this will probably + // be eliminated at compile time. + if (twosc && y.value () == std::numeric_limits<int64_t>::min ()) + { + return octave_int64 (x + std::pow(2.0, 63)); + } + else + return x + (-y); +} -#define DEFINE_DOUBLE_INT64_BIN_OP(OP) \ - DEFINE_DOUBLE_INT64_OP0(OP,octave_int64,octave_int64) \ - DEFINE_DOUBLE_INT64_OP0(OP,octave_uint64,octave_uint64) +// NOTE: +// Emulated mixed multiplications are tricky due to possible precision loss. +// Here, after sorting out common cases for speed, we follow the strategy +// of converting the double number into the form sign * 64-bit integer* 2**exponent, +// multiply the 64-bit integers to get a 128-bit number, split that number into 32-bit words +// and form 4 double-valued summands (none of which loases precision), then convert these +// into integers and sum them. Though it is not immediately obvious, this should work +// even w.r.t. rounding (none of the summands lose precision). + +// Multiplies two unsigned 64-bit ints to get a 128-bit number represented +// as four 32-bit words. +static void +umul128 (uint64_t x, uint64_t y, uint32_t w[4]) +{ + uint64_t lx = static_cast<uint32_t> (x), ux = x >> 32; + uint64_t ly = static_cast<uint32_t> (y), uy = y >> 32; + uint64_t a = lx * ly; + w[0] = a; a >>= 32; + uint64_t uxly = ux*ly, uylx = uy*lx; + a += static_cast<uint32_t> (uxly); uxly >>= 32; + a += static_cast<uint32_t> (uylx); uylx >>= 32; + w[1] = a; a >>= 32; + uint64_t uxuy = ux * uy; + a += uxly; a += uylx; a += uxuy; + w[2] = a; a >>= 32; + w[3] = a; +} + +// Splits a double into bool sign, unsigned 64-bit mantissa and int exponent +static void +dblesplit (double x, bool& sign, uint64_t& mtis, int& exp) +{ + sign = x < 0; x = fabs (x); + x = frexp (x, &exp); + exp -= 52; + mtis = static_cast<uint64_t> (ldexp (x, 52)); +} + +// Gets a double number from a 32-bit unsigned integer mantissa, exponent and sign. +static double +dbleget (bool sign, uint32_t mtis, int exp) +{ + double x = ldexp (static_cast<double> (mtis), exp); + return sign ? -x : x; +} + -DEFINE_DOUBLE_INT64_BIN_OP(+) -DEFINE_DOUBLE_INT64_BIN_OP(-) -DEFINE_DOUBLE_INT64_BIN_OP(*) -DEFINE_DOUBLE_INT64_BIN_OP(/) +INT_DOUBLE_BINOP_DECL (*, uint64) +{ + if (y >= 0 && y < octave_uint64::max () && y == xround (y)) + { + return x * octave_uint64 (static_cast<uint64_t> (y)); + } + else if (y == 0.5) + { + return x / octave_uint64 (static_cast<uint64_t> (2)); + } + else if (y < 0 || lo_ieee_isnan (x) || lo_ieee_isinf (x)) + { + return octave_uint64 (x.value () * y); + } + else + { + bool sign; + uint64_t my; + int e; + dblesplit (y, sign, my, e); + uint32_t w[4]; + umul128 (x.value (), my, w); + octave_uint64 res = octave_uint64::zero; + for (short i = 0; i < 4; i++) + { + res += octave_uint64 (dbleget (sign, w[i], e)); + e += 32; + } + return res; + } +} + +DOUBLE_INT_BINOP_DECL (*, uint64) +{ return y * x; } -#define DEFINE_DOUBLE_INT64_CMP_OP(OP) \ - DEFINE_DOUBLE_INT64_OP0(OP,octave_int64,bool) \ - DEFINE_DOUBLE_INT64_OP0(OP,octave_uint64,bool) +INT_DOUBLE_BINOP_DECL (*, int64) +{ + if (fabs (y) < octave_int64::max () && y == xround (y)) + { + return x * octave_int64 (static_cast<int64_t> (y)); + } + else if (fabs (y) == 0.5) + { + return x / octave_int64 (static_cast<uint64_t> (4*y)); + } + else if (lo_ieee_isnan (x) || lo_ieee_isinf (x)) + { + return octave_int64 (x.value () * y); + } + else + { + bool sign; + uint64_t my; + int e; + dblesplit (y, sign, my, e); + uint32_t w[4]; + sign = (sign != (x.value () < 0)); + umul128 (std::abs (x.value ()), my, w); + octave_int64 res = octave_int64::zero; + for (short i = 0; i < 4; i++) + { + res += octave_int64 (dbleget (sign, w[i], e)); + e += 32; + } + return res; + } +} + +DOUBLE_INT_BINOP_DECL (*, int64) +{ return y * x; } + +DOUBLE_INT_BINOP_DECL (/, uint64) +{ + return octave_uint64 (x / static_cast<double> (y)); +} -DEFINE_DOUBLE_INT64_CMP_OP(<) -DEFINE_DOUBLE_INT64_CMP_OP(<=) -DEFINE_DOUBLE_INT64_CMP_OP(>) -DEFINE_DOUBLE_INT64_CMP_OP(>=) -DEFINE_DOUBLE_INT64_CMP_OP(==) -DEFINE_DOUBLE_INT64_CMP_OP(!=) +DOUBLE_INT_BINOP_DECL (/, int64) +{ + return octave_int64 (x / static_cast<double> (y)); +} + +INT_DOUBLE_BINOP_DECL (/, uint64) +{ + if (y >= 0 && y < octave_uint64::max () && y == xround (y)) + { + return x / octave_uint64 (y); + } + else + return x * (1.0/y); +} + +INT_DOUBLE_BINOP_DECL (/, int64) +{ + if (fabs (y) < octave_int64::max () && y == xround (y)) + { + return x / octave_int64 (y); + } + else + return x * (1.0/y); +} + +#define INSTANTIATE_INT64_DOUBLE_CMP_OP0(OP,T1,T2) \ + template OCTAVE_API bool \ + octave_int_cmp_op::mop<octave_int_cmp_op::OP> (T1 x, T2 y) + +#define INSTANTIATE_INT64_DOUBLE_CMP_OP(OP) \ + INSTANTIATE_INT64_DOUBLE_CMP_OP0(OP, double, int64_t); \ + INSTANTIATE_INT64_DOUBLE_CMP_OP0(OP, double, uint64_t); \ + INSTANTIATE_INT64_DOUBLE_CMP_OP0(OP, int64_t, double); \ + INSTANTIATE_INT64_DOUBLE_CMP_OP0(OP, uint64_t, double) + +INSTANTIATE_INT64_DOUBLE_CMP_OP(lt); +INSTANTIATE_INT64_DOUBLE_CMP_OP(le); +INSTANTIATE_INT64_DOUBLE_CMP_OP(gt); +INSTANTIATE_INT64_DOUBLE_CMP_OP(ge); +INSTANTIATE_INT64_DOUBLE_CMP_OP(eq); +INSTANTIATE_INT64_DOUBLE_CMP_OP(ne); + +#endif //template <class T> //bool @@ -178,8 +593,6 @@ template OCTAVE_API octave_int<T> pow (const octave_int<T>&, const double&); \ template OCTAVE_API octave_int<T> powf (const float&, const octave_int<T>&); \ template OCTAVE_API octave_int<T> powf (const octave_int<T>&, const float&); \ - template OCTAVE_API std::ostream& operator << (std::ostream&, const octave_int<T>&); \ - template OCTAVE_API std::istream& operator >> (std::istream&, octave_int<T>&); \ template OCTAVE_API octave_int<T> \ bitshift (const octave_int<T>&, int, const octave_int<T>&); \
--- a/liboctave/oct-inttypes.h +++ b/liboctave/oct-inttypes.h @@ -1,7 +1,7 @@ /* Copyright (C) 2004, 2005, 2006, 2007 John W. Eaton -Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com> +Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com> This file is part of Octave. @@ -30,10 +30,15 @@ #include <limits> #include <iostream> +#include "lo-math.h" #include "oct-types.h" #include "lo-ieee.h" #include "lo-mappers.h" +#ifdef OCTAVE_INT_USE_LONG_DOUBLE +inline long double xround (long double x) { return roundl (x); } +#endif + // Query for an integer type of certain sizeof, and signedness. template<int qsize, bool qsigned> struct query_integer_type @@ -166,6 +171,45 @@ return uiop<xop, sizeof (PT1)>::op (static_cast<PT1> (x), static_cast<PT2> (y)); } + +public: + + // Mixed comparisons + template <class xop, class T> + static bool + mop (T x, double y) + { return xop::op (static_cast<double> (x), y); } + + template <class xop, class T> + static bool + mop (double x, T y) + { return xop::op (x, static_cast<double> (y)); } + + // Typecasting to doubles won't work properly for 64-bit integers - they lose precision. + // If we have long doubles, use them... +#ifdef OCTAVE_INT_USE_LONG_DOUBLE +#define DEFINE_LONG_DOUBLE_CMP_OP(T1, T2) \ + template <class xop> \ + static bool \ + mop (T1 x, T2 y) \ + { \ + return xop::op (static_cast<long double> (x), \ + static_cast<long double> (y)); \ + } + DEFINE_LONG_DOUBLE_CMP_OP(double, uint64_t) + DEFINE_LONG_DOUBLE_CMP_OP(double, int64_t) + DEFINE_LONG_DOUBLE_CMP_OP(int64_t, double) + DEFINE_LONG_DOUBLE_CMP_OP(uint64_t, double) +#undef DEFINE_LONG_DOUBLE_CMP_OP + +#else + // ... otherwise, use external handlers + template <class xop> static OCTAVE_API bool mop (uint64_t, double); + template <class xop> static OCTAVE_API bool mop (int64_t, double); + template <class xop> static OCTAVE_API bool mop (double, uint64_t); + template <class xop> static OCTAVE_API bool mop (double, int64_t); +#endif + }; // Base integer class. No data, just conversion methods and exception flags. @@ -216,42 +260,40 @@ return static_cast<T> (value); } - // This does not check for NaN and non-int. It can be useful when using real - // types for integer arithmetics, e.g., 64-bit multiply via long double. +private: + + // Computes a real-valued threshold for a max/min check. template <class S> - static T - truncate_real (const S& value) - { - if (value < min_val ()) - { - ftrunc = true; - return min_val (); - } - else if (value > max_val ()) - { - ftrunc = true; - return max_val (); - } + static S + compute_threshold (S val, T orig_val) + { + if (static_cast <T> (val) != orig_val) + return val; else - return static_cast<T> (value); + // Next number away from zero. + return val * (static_cast<S> (1.0) + std::numeric_limits<S>::epsilon ()); } - + +public: // Convert a real number (check NaN and non-int). template <class S> static T convert_real (const S& value) { + // Compute proper thresholds. + static const S thmin = compute_threshold (static_cast<S> (min_val ()), min_val ()); + static const S thmax = compute_threshold (static_cast<S> (max_val ()), max_val ()); if (lo_ieee_isnan (value)) { fnan = true; return static_cast<T> (0); } - else if (value < min_val ()) + else if (value <= thmin) { octave_int_base<T>::ftrunc = true; return min_val (); } - else if (value > max_val ()) + else if (value >= thmax) { ftrunc = true; return max_val (); @@ -361,10 +403,8 @@ return u; } - // Multiplication is done using promotion to wider type. If there is no - // suitable promotion type, this operation *MUST* be specialized. But note - // that a real type can be used as the promotion type (e.g., long double for - // int64_t). + // 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) { @@ -393,10 +433,27 @@ } }; +#ifdef OCTAVE_INT_USE_LONG_DOUBLE +// Handle 64-bit multiply using long double +template <> +inline uint64_t +octave_int_arith_base<uint64_t, false>:: mul (uint64_t x, uint64_t y) +{ + long double p = static_cast<long double> (x) * static_cast<long double> (y); + if (p > static_cast<long double> (octave_int_base<uint64_t>::max_val ())) + { + octave_int_base<uint64_t>::ftrunc = true; + return octave_int_base<uint64_t>::max_val (); + } + else + return static_cast<uint64_t> (p); +} +#else // Special handler for 64-bit integer multiply. template <> OCTAVE_API uint64_t octave_int_arith_base<uint64_t, false>::mul (uint64_t, uint64_t); +#endif // Signed integer arithmetics. // Rationale: If HAVE_FAST_INT_OPS is defined, the following conditions @@ -599,10 +656,8 @@ #endif } - // Multiplication is done using promotion to wider type. If there is no - // suitable promotion type, this operation *MUST* be specialized. But note - // that a real type can be used as the promotion type (e.g., long double for - // int64_t). + // 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) { @@ -655,10 +710,35 @@ }; +#ifdef OCTAVE_INT_USE_LONG_DOUBLE +// Handle 64-bit multiply using long double +template <> +inline int64_t +octave_int_arith_base<int64_t, true>:: mul (int64_t x, int64_t y) +{ + long double p = static_cast<long double> (x) * static_cast<long double> (y); + // NOTE: We could maybe do it with a single branch if HAVE_FAST_INT_OPS, but it + // would require one more runtime conversion, so the question is whether it would + // really be faster. + if (p > static_cast<long double> (octave_int_base<int64_t>::max_val ())) + { + octave_int_base<int64_t>::ftrunc = true; + return octave_int_base<int64_t>::max_val (); + } + else if (p < static_cast<long double> (octave_int_base<int64_t>::min_val ())) + { + octave_int_base<int64_t>::ftrunc = true; + return octave_int_base<int64_t>::min_val (); + } + else + return static_cast<int64_t> (p); +} +#else // Special handler for 64-bit integer multiply. template <> OCTAVE_API int64_t octave_int_arith_base<int64_t, true>::mul (int64_t, int64_t); +#endif // This class simply selects the proper arithmetics. template<class T> @@ -681,6 +761,10 @@ octave_int (float d) : ival (octave_int_base<T>::convert_real (d)) { } +#ifdef OCTAVE_INT_USE_LONG_DOUBLE + octave_int (long double d) : ival (octave_int_base<T>::convert_real (d)) { } +#endif + octave_int (bool b) : ival (b) { } template <class U> @@ -735,7 +819,7 @@ OCTAVE_INT_UN_OP(abs, abs) OCTAVE_INT_UN_OP(signum, signum) -# undef OCTAVE_INT_UN_OP +#undef OCTAVE_INT_UN_OP // Homogeneous binary integer operations. #define OCTAVE_INT_BIN_OP(OP, NAME, ARGT) \ @@ -756,10 +840,10 @@ OCTAVE_INT_BIN_OP(<<, lshift, int) OCTAVE_INT_BIN_OP(>>, rshift, int) -# undef OCTAVE_INT_BIN_OP +#undef OCTAVE_INT_BIN_OP - octave_int<T> min (void) const { return std::numeric_limits<T>::min (); } - octave_int<T> max (void) const { return std::numeric_limits<T>::max (); } + static octave_int<T> min (void) { return std::numeric_limits<T>::min (); } + static octave_int<T> max (void) { return std::numeric_limits<T>::max (); } static int nbits (void) { return std::numeric_limits<T>::digits; } @@ -767,6 +851,9 @@ static const char *type_name (); + // The following are provided for convenience. + static const octave_int zero, one; + // 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); } @@ -821,7 +908,7 @@ OCTAVE_INT_CMP_OP (==, eq) OCTAVE_INT_CMP_OP (!=, ne) -# undef OCTAVE_INT_CMP_OP +#undef OCTAVE_INT_CMP_OP template <class T> inline std::ostream& @@ -853,7 +940,7 @@ OCTAVE_INT_BITCMP_OP (|) OCTAVE_INT_BITCMP_OP (^) -# undef OCTAVE_INT_BITCMP_OP +#undef OCTAVE_INT_BITCMP_OP // General bit shift. template <class T> @@ -879,67 +966,82 @@ typedef octave_int<uint32_t> octave_uint32; typedef octave_int<uint64_t> octave_uint64; -#define OCTAVE_INT_DOUBLE_BIN_OP(OP) \ +#define OCTAVE_INT_DOUBLE_BIN_OP0(OP) \ template <class 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 <class T> \ + inline octave_int<T> \ + operator OP (const double& x, const octave_int<T>& y) \ + { return octave_int<T> (x OP static_cast<double> (y)); } \ + +#ifdef OCTAVE_INT_USE_LONG_DOUBLE +// Handle mixed op using long double +#define OCTAVE_INT_DOUBLE_BIN_OP(OP) \ + 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_int64 (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_int64 (static_cast<long double> (x.value ()) OP y); } + +#else +// external handlers +#define OCTAVE_INT_DOUBLE_BIN_OP(OP) \ + 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&); \ - template <class T> \ - inline octave_int<T> \ - operator OP (const double& x, const octave_int<T>& y) \ - { return octave_int<T> (x OP static_cast<double> (y)); } \ - template <> \ - OCTAVE_API octave_int64 \ - operator OP (const double&, const octave_int64&); \ - template <> \ - OCTAVE_API octave_uint64 \ - operator OP (const double&, const octave_uint64&); + operator OP (const octave_uint64&, const double&); +#endif OCTAVE_INT_DOUBLE_BIN_OP (+) OCTAVE_INT_DOUBLE_BIN_OP (-) OCTAVE_INT_DOUBLE_BIN_OP (*) OCTAVE_INT_DOUBLE_BIN_OP (/) -# undef OCTAVE_INT_DOUBLE_BIN_OP +#undef OCTAVE_INT_DOUBLE_BIN_OP0 +#undef OCTAVE_INT_DOUBLE_BIN_OP -#define OCTAVE_INT_DOUBLE_CMP_OP(OP) \ +#define OCTAVE_INT_DOUBLE_CMP_OP(OP,NAME) \ template <class T> \ inline bool \ operator OP (const octave_int<T>& x, const double& y) \ - { return static_cast<double> (x.value ()) OP y; } \ - template <> \ - OCTAVE_API bool \ - operator OP (const octave_int64&, const double&); \ - template <> \ - OCTAVE_API bool \ - operator OP (const octave_uint64&, const double&); \ + { return octave_int_cmp_op::mop<octave_int_cmp_op::NAME> (x.value (), y); } \ template <class T> \ inline bool \ operator OP (const double& x, const octave_int<T>& y) \ - { return x OP static_cast<double> (y.value ()); } \ - template <> \ - OCTAVE_API bool \ - operator OP (const double&, const octave_int64&); \ - template <> \ - OCTAVE_API bool \ - operator OP (const double&, const octave_uint64&); - + { return octave_int_cmp_op::mop<octave_int_cmp_op::NAME> (x, y.value ()); } -OCTAVE_INT_DOUBLE_CMP_OP (<) -OCTAVE_INT_DOUBLE_CMP_OP (<=) -OCTAVE_INT_DOUBLE_CMP_OP (>=) -OCTAVE_INT_DOUBLE_CMP_OP (>) -OCTAVE_INT_DOUBLE_CMP_OP (==) -OCTAVE_INT_DOUBLE_CMP_OP (!=) +OCTAVE_INT_DOUBLE_CMP_OP (<, lt) +OCTAVE_INT_DOUBLE_CMP_OP (<=, le) +OCTAVE_INT_DOUBLE_CMP_OP (>=, ge) +OCTAVE_INT_DOUBLE_CMP_OP (>, gt) +OCTAVE_INT_DOUBLE_CMP_OP (==, eq) +OCTAVE_INT_DOUBLE_CMP_OP (!=, ne) -# undef OCTAVE_INT_DOUBLE_CMP_OP +#undef OCTAVE_INT_DOUBLE_CMP_OP // Floats are handled by simply converting to doubles. @@ -958,7 +1060,7 @@ OCTAVE_INT_FLOAT_BIN_OP (*) OCTAVE_INT_FLOAT_BIN_OP (/) -# undef OCTAVE_INT_FLOAT_BIN_OP +#undef OCTAVE_INT_FLOAT_BIN_OP #define OCTAVE_INT_FLOAT_CMP_OP(OP) \ template <class T> \ @@ -977,7 +1079,8 @@ OCTAVE_INT_FLOAT_CMP_OP (==) OCTAVE_INT_FLOAT_CMP_OP (!=) -# undef OCTAVE_INT_FLOAT_CMP_OP +#undef OCTAVE_INT_FLOAT_CMP_OP + #endif /*
--- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2008-10-01 Jaroslav Hajek <highegg@gmail.com> + + * OPERATORS/op-i64-i64.cc: Instantiate all 64-bit operations. + * OPERATORS/op-ui64-ui64.cc: Instantiate all unsigned 64-bit operations. + 2008-10-06 John W. Eaton <jwe@octave.org> * ov-type-conv.h (octave_type_conv_body): Avoid shadow warning
--- a/src/OPERATORS/op-i64-i64.cc +++ b/src/OPERATORS/op-i64-i64.cc @@ -84,41 +84,7 @@ #include "op-int.h" -OCTAVE_S_INT_UNOPS (int64) -OCTAVE_SS_INT_CMP_OPS (ss, int64_, int64_) -OCTAVE_SS_INT_CMP_OPS (sx, int64_, ) -OCTAVE_SS_INT_CMP_OPS (xs, , int64_) -OCTAVE_SS_INT_BOOL_OPS (ss, int64_, int64_, octave_int64 (0), octave_int64 (0)) -OCTAVE_SS_INT_BOOL_OPS (sx, int64_, , octave_int64 (0), 0) -OCTAVE_SS_INT_BOOL_OPS (xs, , int64_, 0, octave_int64 (0)) - -OCTAVE_SM_INT_CMP_OPS (sm, int64_, int64_) -OCTAVE_SM_INT_CMP_OPS (xm, , int64_) -OCTAVE_SM_INT_CMP_OPS (smx, int64_, ) -OCTAVE_SM_INT_BOOL_OPS (sm, int64_, int64_) -OCTAVE_SM_INT_BOOL_OPS (xm, , int64_) -OCTAVE_SM_INT_BOOL_OPS (smx, int64_, ) - -OCTAVE_MS_INT_CMP_OPS (ms, int64_, int64_) -OCTAVE_MS_INT_CMP_OPS (mx, int64_, ) -OCTAVE_MS_INT_CMP_OPS (mxs, , int64_) -OCTAVE_MS_INT_BOOL_OPS (ms, int64_, int64_) -OCTAVE_MS_INT_BOOL_OPS (mx, int64_, ) -OCTAVE_MS_INT_BOOL_OPS (mxs, , int64_) -OCTAVE_MS_INT_ASSIGN_OPS (ms, int64_, int64_, int64_) -OCTAVE_MS_INT_ASSIGN_OPS (mx, int64_, , ) -OCTAVE_MS_INT_ASSIGN_OPS (mc, int64_, complex_, ) - -OCTAVE_M_INT_UNOPS (int64) -OCTAVE_MM_INT_CMP_OPS (mm, int64_, int64_) -OCTAVE_MM_INT_CMP_OPS (mmx, int64_, ) -OCTAVE_MM_INT_CMP_OPS (mxm, , int64_) -OCTAVE_MM_INT_BOOL_OPS (mm, int64_, int64_) -OCTAVE_MM_INT_BOOL_OPS (mmx, int64_, ) -OCTAVE_MM_INT_BOOL_OPS (mxm, , int64_) -OCTAVE_MM_INT_ASSIGN_OPS (mm, int64_, int64_, int64_) -OCTAVE_MM_INT_ASSIGN_OPS (mmx, int64_, , ) -OCTAVE_MM_INT_ASSIGN_OPS (mmc, int64_, complex_, ) +OCTAVE_INT_OPS (int64) OCTAVE_MS_INT_ASSIGN_OPS (mi8, int64_, int8_, int8_) OCTAVE_MS_INT_ASSIGN_OPS (mui8, int64_, uint8_, uint8_) @@ -136,8 +102,6 @@ OCTAVE_MM_INT_ASSIGN_OPS (mmui32, int64_, uint32_, uint32_) OCTAVE_MM_INT_ASSIGN_OPS (mmui64, int64_, uint64_, uint64_) -OCTAVE_INT_NULL_ASSIGN_OPS (int64) - OCTAVE_MIXED_INT_CMP_OPS (int64, int8) OCTAVE_MIXED_INT_CMP_OPS (int64, uint8) OCTAVE_MIXED_INT_CMP_OPS (int64, int16) @@ -146,46 +110,10 @@ OCTAVE_MIXED_INT_CMP_OPS (int64, uint32) OCTAVE_MIXED_INT_CMP_OPS (int64, uint64) -OCTAVE_CONCAT_FN (int64); - void install_i64_i64_ops (void) { - OCTAVE_INSTALL_S_INT_UNOPS (int64); - OCTAVE_INSTALL_SS_INT_CMP_OPS (ss, int64_, int64_); - OCTAVE_INSTALL_SS_INT_CMP_OPS (sx, int64_, ); - OCTAVE_INSTALL_SS_INT_CMP_OPS (xs, , int64_); - OCTAVE_INSTALL_SS_INT_BOOL_OPS (ss, int64_, int64_); - OCTAVE_INSTALL_SS_INT_BOOL_OPS (sx, int64_, ); - OCTAVE_INSTALL_SS_INT_BOOL_OPS (xs, , int64_); - - OCTAVE_INSTALL_SM_INT_CMP_OPS (sm, int64_, int64_); - OCTAVE_INSTALL_SM_INT_CMP_OPS (xm, , int64_); - OCTAVE_INSTALL_SM_INT_CMP_OPS (smx, int64_, ); - OCTAVE_INSTALL_SM_INT_BOOL_OPS (sm, int64_, int64_); - OCTAVE_INSTALL_SM_INT_BOOL_OPS (xm, , int64_); - OCTAVE_INSTALL_SM_INT_BOOL_OPS (smx, int64_, ); - - OCTAVE_INSTALL_MS_INT_CMP_OPS (ms, int64_, int64_); - OCTAVE_INSTALL_MS_INT_CMP_OPS (mx, int64_, ); - OCTAVE_INSTALL_MS_INT_CMP_OPS (mxs, , int64_); - OCTAVE_INSTALL_MS_INT_BOOL_OPS (ms, int64_, int64_); - OCTAVE_INSTALL_MS_INT_BOOL_OPS (mx, int64_, ); - OCTAVE_INSTALL_MS_INT_BOOL_OPS (mxs, , int64_); - OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (ms, int64_, int64_); - OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mx, int64_, ); - OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mc, int64_, complex_); - - OCTAVE_INSTALL_M_INT_UNOPS (int64); - OCTAVE_INSTALL_MM_INT_CMP_OPS (mm, int64_, int64_); - OCTAVE_INSTALL_MM_INT_CMP_OPS (mmx, int64_, ); - OCTAVE_INSTALL_MM_INT_CMP_OPS (mxm, , int64_); - OCTAVE_INSTALL_MM_INT_BOOL_OPS (mm, int64_, int64_); - OCTAVE_INSTALL_MM_INT_BOOL_OPS (mmx, int64_, ); - OCTAVE_INSTALL_MM_INT_BOOL_OPS (mxm, , int64_); - OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mm, int64_, int64_); - OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmx, int64_, ); - OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmc, int64_, complex_); + OCTAVE_INSTALL_INT_OPS (int64); OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi8, int64_, int8_); OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui8, int64_, uint8_); @@ -203,8 +131,6 @@ OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui32, int64_, uint32_); OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui64, int64_, uint64_); - OCTAVE_INSTALL_INT_NULL_ASSIGN_OPS (int64) - OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int64, int8); OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int64, uint8); OCTAVE_INSTALL_SM_INT_ASSIGNCONV (int64, int16); @@ -220,8 +146,6 @@ OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int64, int32); OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int64, uint32); OCTAVE_INSTALL_MIXED_INT_CMP_OPS (int64, uint64); - - OCTAVE_INSTALL_CONCAT_FN (int64); } /*
--- a/src/OPERATORS/op-ui64-ui64.cc +++ b/src/OPERATORS/op-ui64-ui64.cc @@ -84,41 +84,7 @@ #include "op-int.h" -OCTAVE_S_INT_UNOPS (uint64) -OCTAVE_SS_INT_CMP_OPS (ss, uint64_, uint64_) -OCTAVE_SS_INT_CMP_OPS (sx, uint64_, ) -OCTAVE_SS_INT_CMP_OPS (xs, , uint64_) -OCTAVE_SS_INT_BOOL_OPS (ss, uint64_, uint64_, octave_uint64 (0), octave_uint64 (0)) -OCTAVE_SS_INT_BOOL_OPS (sx, uint64_, , octave_uint64 (0), 0) -OCTAVE_SS_INT_BOOL_OPS (xs, , uint64_, 0, octave_uint64 (0)) - -OCTAVE_SM_INT_CMP_OPS (sm, uint64_, uint64_) -OCTAVE_SM_INT_CMP_OPS (xm, , uint64_) -OCTAVE_SM_INT_CMP_OPS (smx, uint64_, ) -OCTAVE_SM_INT_BOOL_OPS (sm, uint64_, uint64_) -OCTAVE_SM_INT_BOOL_OPS (xm, , uint64_) -OCTAVE_SM_INT_BOOL_OPS (smx, uint64_, ) - -OCTAVE_MS_INT_CMP_OPS (ms, uint64_, uint64_) -OCTAVE_MS_INT_CMP_OPS (mx, uint64_, ) -OCTAVE_MS_INT_CMP_OPS (mxs, , uint64_) -OCTAVE_MS_INT_BOOL_OPS (ms, uint64_, uint64_) -OCTAVE_MS_INT_BOOL_OPS (mx, uint64_, ) -OCTAVE_MS_INT_BOOL_OPS (mxs, , uint64_) -OCTAVE_MS_INT_ASSIGN_OPS (ms, uint64_, uint64_, uint64_) -OCTAVE_MS_INT_ASSIGN_OPS (mx, uint64_, , ) -OCTAVE_MS_INT_ASSIGN_OPS (mc, uint64_, complex_, ) - -OCTAVE_M_INT_UNOPS (uint64) -OCTAVE_MM_INT_CMP_OPS (mm, uint64_, uint64_) -OCTAVE_MM_INT_CMP_OPS (mmx, uint64_, ) -OCTAVE_MM_INT_CMP_OPS (mxm, , uint64_) -OCTAVE_MM_INT_BOOL_OPS (mm, uint64_, uint64_) -OCTAVE_MM_INT_BOOL_OPS (mmx, uint64_, ) -OCTAVE_MM_INT_BOOL_OPS (mxm, , uint64_) -OCTAVE_MM_INT_ASSIGN_OPS (mm, uint64_, uint64_, uint64_) -OCTAVE_MM_INT_ASSIGN_OPS (mmx, uint64_, , ) -OCTAVE_MM_INT_ASSIGN_OPS (mmc, uint64_, complex_, ) +OCTAVE_INT_OPS (uint64) OCTAVE_MS_INT_ASSIGN_OPS (mi8, uint64_, int8_, int8_) OCTAVE_MS_INT_ASSIGN_OPS (mui8, uint64_, uint8_, uint8_) @@ -136,8 +102,6 @@ OCTAVE_MM_INT_ASSIGN_OPS (mmui32, uint64_, uint32_, uint32_) OCTAVE_MM_INT_ASSIGN_OPS (mmi64, uint64_, int64_, int64_) -OCTAVE_INT_NULL_ASSIGN_OPS (uint64) - OCTAVE_MIXED_INT_CMP_OPS (uint64, int8) OCTAVE_MIXED_INT_CMP_OPS (uint64, uint8) OCTAVE_MIXED_INT_CMP_OPS (uint64, int16) @@ -146,47 +110,11 @@ OCTAVE_MIXED_INT_CMP_OPS (uint64, uint32) OCTAVE_MIXED_INT_CMP_OPS (uint64, int64) -OCTAVE_CONCAT_FN (uint64) - void install_ui64_ui64_ops (void) { - OCTAVE_INSTALL_S_INT_UNOPS (uint64); - OCTAVE_INSTALL_SS_INT_CMP_OPS (ss, uint64_, uint64_); - OCTAVE_INSTALL_SS_INT_CMP_OPS (sx, uint64_, ); - OCTAVE_INSTALL_SS_INT_CMP_OPS (xs, , uint64_); - OCTAVE_INSTALL_SS_INT_BOOL_OPS (ss, uint64_, uint64_); - OCTAVE_INSTALL_SS_INT_BOOL_OPS (sx, uint64_, ); - OCTAVE_INSTALL_SS_INT_BOOL_OPS (xs, , uint64_); - - OCTAVE_INSTALL_SM_INT_CMP_OPS (sm, uint64_, uint64_); - OCTAVE_INSTALL_SM_INT_CMP_OPS (xm, , uint64_); - OCTAVE_INSTALL_SM_INT_CMP_OPS (smx, uint64_, ); - OCTAVE_INSTALL_SM_INT_BOOL_OPS (sm, uint64_, uint64_); - OCTAVE_INSTALL_SM_INT_BOOL_OPS (xm, , uint64_); - OCTAVE_INSTALL_SM_INT_BOOL_OPS (smx, uint64_, ); - - OCTAVE_INSTALL_MS_INT_CMP_OPS (ms, uint64_, uint64_); - OCTAVE_INSTALL_MS_INT_CMP_OPS (mx, uint64_, ); - OCTAVE_INSTALL_MS_INT_CMP_OPS (mxs, , uint64_); - OCTAVE_INSTALL_MS_INT_BOOL_OPS (ms, uint64_, uint64_); - OCTAVE_INSTALL_MS_INT_BOOL_OPS (mx, uint64_, ); - OCTAVE_INSTALL_MS_INT_BOOL_OPS (mxs, , uint64_); - OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (ms, uint64_, uint64_); - OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mx, uint64_, ); - OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mc, uint64_, complex_); - - OCTAVE_INSTALL_M_INT_UNOPS (uint64); - OCTAVE_INSTALL_MM_INT_CMP_OPS (mm, uint64_, uint64_); - OCTAVE_INSTALL_MM_INT_CMP_OPS (mmx, uint64_, ); - OCTAVE_INSTALL_MM_INT_CMP_OPS (mxm, , uint64_); - OCTAVE_INSTALL_MM_INT_BOOL_OPS (mm, uint64_, uint64_); - OCTAVE_INSTALL_MM_INT_BOOL_OPS (mmx, uint64_, ); - OCTAVE_INSTALL_MM_INT_BOOL_OPS (mxm, , uint64_); - OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mm, uint64_, uint64_); - OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmx, uint64_, ); - OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmc, uint64_, complex_); - + OCTAVE_INSTALL_INT_OPS (uint64); + OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi8, uint64_, int8_); OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mui8, uint64_, uint8_); OCTAVE_INSTALL_MS_INT_ASSIGN_OPS (mi16, uint64_, int16_); @@ -203,8 +131,6 @@ OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmui32, uint64_, uint32_); OCTAVE_INSTALL_MM_INT_ASSIGN_OPS (mmi64, uint64_, int64_); - OCTAVE_INSTALL_INT_NULL_ASSIGN_OPS (uint64) - OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint64, int8); OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint64, uint8); OCTAVE_INSTALL_SM_INT_ASSIGNCONV (uint64, int16); @@ -220,8 +146,6 @@ OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint64, int32); OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint64, uint32); OCTAVE_INSTALL_MIXED_INT_CMP_OPS (uint64, int64); - - OCTAVE_INSTALL_CONCAT_FN (uint64); } /*