oct-inttypes.h

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 2004-2012 John W. Eaton
00004 Copyright (C) 2008-2009 Jaroslav Hajek
00005 
00006 This file is part of Octave.
00007 
00008 Octave is free software; you can redistribute it and/or modify it
00009 under the terms of the GNU General Public License as published by the
00010 Free Software Foundation; either version 3 of the License, or (at your
00011 option) any later version.
00012 
00013 Octave is distributed in the hope that it will be useful, but WITHOUT
00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016 for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Octave; see the file COPYING.  If not, see
00020 <http://www.gnu.org/licenses/>.
00021 
00022 */
00023 
00024 #if !defined (octave_inttypes_h)
00025 #define octave_inttypes_h 1
00026 
00027 #include <climits>
00028 #include <cstdlib>
00029 
00030 #include <limits>
00031 #include <iosfwd>
00032 
00033 #include "lo-traits.h"
00034 #include "lo-math.h"
00035 #include "lo-mappers.h"
00036 
00037 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
00038 inline long double xround (long double x) { return roundl (x); }
00039 inline long double xisnan (long double x) { return xisnan (static_cast<double> (x)); }
00040 #endif
00041 
00042 // FIXME -- we define this by our own because some compilers, such as
00043 // MSVC, do not provide std::abs (int64_t) and std::abs (uint64_t).  In
00044 // the future, it should go away in favor of std::abs.
00045 template <class T>
00046 inline T octave_int_abs (T x) { return x >= 0 ? x : -x; }
00047 
00048 // Query for an integer type of certain sizeof, and signedness.
00049 template<int qsize, bool qsigned>
00050 struct query_integer_type
00051 {
00052 public:
00053   static const bool registered = false;
00054   typedef void type; // Void shall result in a compile-time error if we
00055                      // attempt to use it in computations.
00056 };
00057 
00058 #define REGISTER_INT_TYPE(TYPE) \
00059 template <> \
00060 class query_integer_type<sizeof (TYPE), std::numeric_limits<TYPE>::is_signed> \
00061 { \
00062 public: \
00063   static const bool registered = true; \
00064   typedef TYPE type; \
00065 }
00066 
00067 // No two registered integers can share sizeof and signedness.
00068 REGISTER_INT_TYPE (int8_t);
00069 REGISTER_INT_TYPE (uint8_t);
00070 REGISTER_INT_TYPE (int16_t);
00071 REGISTER_INT_TYPE (uint16_t);
00072 REGISTER_INT_TYPE (int32_t);
00073 REGISTER_INT_TYPE (uint32_t);
00074 REGISTER_INT_TYPE (int64_t);
00075 REGISTER_INT_TYPE (uint64_t);
00076 
00077 // Rationale: Comparators have a single static method, rel(), that returns the
00078 // result of the binary relation. They also have two static boolean fields:
00079 // ltval, gtval determine the value of x OP y if x < y, x > y, respectively.
00080 #define REGISTER_OCTAVE_CMP_OP(NM,OP) \
00081   class NM \
00082     { \
00083     public: \
00084       static const bool ltval = (0 OP 1), gtval = (1 OP 0); \
00085       template <class T> \
00086       static bool op (T x, T y) { return x OP y; } \
00087     }
00088 
00089 // We also provide two special relations: ct, yielding always true, and cf,
00090 // yielding always false.
00091 #define REGISTER_OCTAVE_CONST_OP(NM,value) \
00092   class NM \
00093     { \
00094     public: \
00095       static const bool ltval = value, gtval = value; \
00096       template <class T> \
00097       static bool op (T, T) { return value; } \
00098     }
00099 
00100 // Handles non-homogeneous integer comparisons. Avoids doing useless tests.
00101 class octave_int_cmp_op
00102 {
00103   // This determines a suitable promotion type for T1 when meeting T2 in a
00104   // binary relation. If promotion to int or T2 is safe, it is used. Otherwise,
00105   // the signedness of T1 is preserved and it is widened if T2 is wider.
00106   // Notice that if this is applied to both types, they must end up with equal
00107   // size.
00108   template <class T1, class T2>
00109   class prom
00110     {
00111       // Promote to int?
00112       static const bool pint = (sizeof (T1) < sizeof (int)
00113                                 && sizeof (T2) < sizeof (int));
00114       static const bool t1sig = std::numeric_limits<T1>::is_signed;
00115       static const bool t2sig = std::numeric_limits<T2>::is_signed;
00116       static const bool psig =
00117         (pint || (sizeof (T2) > sizeof (T1) && t2sig) || t1sig);
00118       static const int psize =
00119         (pint ? sizeof (int) : (sizeof (T2) > sizeof (T1)
00120                                 ? sizeof (T2) : sizeof (T1)));
00121     public:
00122       typedef typename query_integer_type<psize, psig>::type type;
00123     };
00124 
00125   // Implements comparisons between two types of equal size but
00126   // possibly different signedness.
00127   template<class xop, int size>
00128   class uiop
00129     {
00130       typedef typename query_integer_type<size, false>::type utype;
00131       typedef typename query_integer_type<size, true>::type stype;
00132     public:
00133       static bool op (utype x, utype y)
00134         { return xop::op (x, y); }
00135       static bool op (stype x, stype y)
00136         { return xop::op (x, y); }
00137       static bool op (stype x, utype y)
00138         { return (x < 0) ? xop::ltval : xop::op (static_cast<utype> (x), y); }
00139       static bool op (utype x, stype y)
00140         { return (y < 0) ? xop::gtval : xop::op (x, static_cast<utype> (y)); }
00141     };
00142 
00143 public:
00144   REGISTER_OCTAVE_CMP_OP (lt, <);
00145   REGISTER_OCTAVE_CMP_OP (le, <=);
00146   REGISTER_OCTAVE_CMP_OP (gt, >);
00147   REGISTER_OCTAVE_CMP_OP (ge, >=);
00148   REGISTER_OCTAVE_CMP_OP (eq, ==);
00149   REGISTER_OCTAVE_CMP_OP (ne, !=);
00150   REGISTER_OCTAVE_CONST_OP (ct, true);
00151   REGISTER_OCTAVE_CONST_OP (cf, false);
00152 
00153   // Universal comparison operation.
00154   template<class xop, class T1, class T2>
00155   static bool
00156   op (T1 x, T2 y)
00157     {
00158       typedef typename prom<T1, T2>::type PT1;
00159       typedef typename prom<T2, T1>::type PT2;
00160       return uiop<xop, sizeof (PT1)>::op (static_cast<PT1> (x),
00161                                           static_cast<PT2> (y));
00162     }
00163 
00164 public:
00165 
00166   // Mixed comparisons
00167   template <class xop, class T>
00168   static bool
00169   mop (T x, double y)
00170     { return xop::op (static_cast<double> (x), y); }
00171 
00172   template <class xop, class T>
00173   static bool
00174   mop (double x, T y)
00175     { return xop::op (x, static_cast<double> (y)); }
00176 
00177   // Typecasting to doubles won't work properly for 64-bit integers - they lose precision.
00178   // If we have long doubles, use them...
00179 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
00180 #define DEFINE_LONG_DOUBLE_CMP_OP(T1, T2) \
00181   template <class xop> \
00182   static bool \
00183   mop (T1 x, T2 y) \
00184     { \
00185       return xop::op (static_cast<long double> (x), \
00186                       static_cast<long double> (y)); \
00187     }
00188 #else
00189   // ... otherwise, use external handlers
00190 
00191   // FIXME: We could declare directly the mop methods as external,
00192   // but we can't do this because bugs in gcc (<= 4.3) prevent
00193   // explicit instantiations later in that case.
00194 #define DEFINE_LONG_DOUBLE_CMP_OP(T1, T2) \
00195   template <class xop> static OCTAVE_API bool \
00196   emulate_mop (T1, T2); \
00197   template <class xop> \
00198   static bool \
00199   mop (T1 x, T2 y) \
00200     { \
00201       return emulate_mop<xop> (x, y); \
00202     }
00203 #endif
00204 
00205   DEFINE_LONG_DOUBLE_CMP_OP(double, uint64_t)
00206   DEFINE_LONG_DOUBLE_CMP_OP(double, int64_t)
00207   DEFINE_LONG_DOUBLE_CMP_OP(int64_t, double)
00208   DEFINE_LONG_DOUBLE_CMP_OP(uint64_t, double)
00209 
00210 #undef DEFINE_LONG_DOUBLE_CMP_OP
00211 };
00212 
00213 // Base integer class. No data, just conversion methods and exception flags.
00214 template <class T>
00215 class octave_int_base
00216 {
00217 protected:
00218 
00219   static T min_val () { return std::numeric_limits<T>:: min (); }
00220   static T max_val () { return std::numeric_limits<T>:: max (); }
00221 
00222 public:
00223 
00224   // Convert integer value.
00225   template <class S>
00226   static T
00227   truncate_int (const S& value)
00228     {
00229       // An exhaustive test whether the max and/or min check can be omitted.
00230       static const bool t_is_signed = std::numeric_limits<T>::is_signed;
00231       static const bool s_is_signed = std::numeric_limits<S>::is_signed;
00232       static const int t_size = sizeof (T), s_size = sizeof (S);
00233       static const bool omit_chk_min =
00234         (! s_is_signed || (t_is_signed && t_size >= s_size));
00235       static const bool omit_chk_max =
00236         (t_size > s_size || (t_size == s_size
00237          && (! t_is_signed || s_is_signed)));
00238       // If the check can be omitted, substitute constant false relation.
00239       typedef octave_int_cmp_op::cf cf;
00240       typedef octave_int_cmp_op::lt lt;
00241       typedef octave_int_cmp_op::gt gt;
00242       typedef typename if_then_else<omit_chk_min, cf, lt>::result chk_min;
00243       typedef typename if_then_else<omit_chk_max, cf, gt>::result chk_max;
00244 
00245       // Efficiency of the following depends on inlining and dead code
00246       // elimination, but that should be a piece of cake for most compilers.
00247       if (chk_min::op (value, static_cast<S> (min_val ())))
00248         {
00249           return min_val ();
00250         }
00251       else if (chk_max::op (value, static_cast<S> (max_val ())))
00252         {
00253           return max_val ();
00254         }
00255       else
00256         return static_cast<T> (value);
00257     }
00258 
00259 private:
00260 
00261   // Computes a real-valued threshold for a max/min check.
00262   template <class S>
00263   static S
00264   compute_threshold (S val, T orig_val)
00265     {
00266       val = xround (val); // Fool optimizations (maybe redundant)
00267       // If val is even, but orig_val is odd, we're one unit off.
00268       if (orig_val % 2 && val / 2 == xround (val / 2))
00269         // FIXME -- is this always correct?
00270         val *= (static_cast<S>(1) - (std::numeric_limits<S>::epsilon () / 2));
00271       return val;
00272     }
00273 
00274 public:
00275   // Convert a real number (check NaN and non-int).
00276   template <class S>
00277   static T
00278   convert_real (const S& value)
00279     {
00280       // Compute proper thresholds.
00281       static const S thmin = compute_threshold (static_cast<S> (min_val ()), min_val ());
00282       static const S thmax = compute_threshold (static_cast<S> (max_val ()), max_val ());
00283       if (xisnan (value))
00284         {
00285           return static_cast<T> (0);
00286         }
00287       else if (value < thmin)
00288         {
00289           return min_val ();
00290         }
00291       else if (value > thmax)
00292         {
00293           return max_val ();
00294         }
00295       else
00296         {
00297           S rvalue = xround (value);
00298           return static_cast<T> (rvalue);
00299         }
00300     }
00301 };
00302 
00303 // Saturated (homogeneous) integer arithmetics. The signed and unsigned
00304 // implementations are significantly different, so we implement another layer
00305 // and completely specialize. Arithmetics inherits from octave_int_base so that
00306 // it can use its exceptions and truncation functions.
00307 
00308 template <class T, bool is_signed>
00309 class octave_int_arith_base
00310 { };
00311 
00312 // Unsigned arithmetics. C++ standard requires it to be modular, so the
00313 // overflows can be handled efficiently and reliably.
00314 template <class T>
00315 class octave_int_arith_base<T, false> : octave_int_base<T>
00316 {
00317 public:
00318 
00319   static T
00320   abs (T x) { return x; }
00321 
00322   static T
00323   signum (T x) { return x ? static_cast<T> (1) : static_cast<T> (0); }
00324 
00325   // Shifts do not overflow.
00326   static T
00327   rshift (T x, int n) { return x >> n; }
00328 
00329   static T
00330   lshift (T x, int n) { return x << n; }
00331 
00332   static T
00333   minus (T)
00334     {
00335       return static_cast<T> (0);
00336     }
00337 
00338   // the overflow behaviour for unsigned integers is guaranteed by C/C++,
00339   // so the following should always work.
00340   static T
00341   add (T x, T y)
00342     {
00343       T u = x + y;
00344       if (u < x)
00345         {
00346           u = octave_int_base<T>::max_val ();
00347         }
00348       return u;
00349     }
00350 
00351   static T
00352   sub (T x, T y)
00353     {
00354       T u = x - y;
00355       if (u > x)
00356         {
00357           u = 0;
00358         }
00359       return u;
00360     }
00361 
00362   // Multiplication is done using promotion to wider integer type. If there is
00363   // no suitable promotion type, this operation *MUST* be specialized.
00364   static T
00365   mul (T x, T y)
00366     {
00367       // Promotion type for multiplication (if exists).
00368       typedef typename query_integer_type<2*sizeof (T), false>::type mptype;
00369       return octave_int_base<T>::truncate_int (static_cast<mptype> (x)
00370                                                * static_cast<mptype> (y));
00371     }
00372 
00373   // Division with rounding to nearest. Note that / and % are probably
00374   // computed by a single instruction.
00375   static T
00376   div (T x, T y)
00377     {
00378       if (y != 0)
00379         {
00380           T z = x / y, w = x % y;
00381           if (w >= y-w) z += 1;
00382           return z;
00383         }
00384       else
00385         {
00386           return x ? octave_int_base<T>::max_val () : 0;
00387         }
00388     }
00389 
00390   // Remainder.
00391   static T
00392   rem (T x, T y)
00393     {
00394       return y != 0 ? x % y : 0;
00395     }
00396 
00397   // Modulus. Note the weird y = 0 case for Matlab compatibility.
00398   static T
00399   mod (T x, T y)
00400     {
00401       return y != 0 ? x % y : x;
00402     }
00403 };
00404 
00405 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
00406 // Handle 64-bit multiply using long double
00407 template <>
00408 inline uint64_t
00409 octave_int_arith_base<uint64_t, false>:: mul (uint64_t x, uint64_t y)
00410 {
00411   long double p = static_cast<long double> (x) * static_cast<long double> (y);
00412   if (p > static_cast<long double> (octave_int_base<uint64_t>::max_val ()))
00413     {
00414       return octave_int_base<uint64_t>::max_val ();
00415     }
00416   else
00417     return static_cast<uint64_t> (p);
00418 }
00419 #else
00420 // Special handler for 64-bit integer multiply.
00421 template <>
00422 OCTAVE_API uint64_t
00423 octave_int_arith_base<uint64_t, false>::mul (uint64_t, uint64_t);
00424 #endif
00425 
00426 // Signed integer arithmetics.
00427 // Rationale: If HAVE_FAST_INT_OPS is defined, the following conditions
00428 // should hold:
00429 // 1. Signed numbers are represented by twos complement
00430 //    (see <http://en.wikipedia.org/wiki/Two%27s_complement>)
00431 // 2. static_cast to unsigned int counterpart works like interpreting
00432 //    the signed bit pattern as unsigned (and is thus zero-cost).
00433 // 3. Signed addition and subtraction yield the same bit results as unsigned.
00434 //    (We use casts to prevent optimization interference, so there is no
00435 //     need for things like -ftrapv).
00436 // 4. Bit operations on signed integers work like on unsigned integers,
00437 //    except for the shifts. Shifts are arithmetic.
00438 //
00439 // The above conditions are satisfied by most modern platforms. If
00440 // HAVE_FAST_INT_OPS is defined, bit tricks and wraparound arithmetics are used
00441 // to avoid conditional jumps as much as possible, thus being friendly to modern
00442 // pipeline processor architectures.
00443 // Otherwise, we fall back to a bullet-proof code that only uses assumptions
00444 // guaranteed by the standard.
00445 
00446 template <class T>
00447 class octave_int_arith_base<T, true> : octave_int_base<T>
00448 {
00449   // The corresponding unsigned type.
00450   typedef typename query_integer_type<sizeof (T), false>::type UT;
00451 public:
00452 
00453   // Returns 1 for negative number, 0 otherwise.
00454   static T
00455   __signbit (T x)
00456     {
00457 #ifdef HAVE_FAST_INT_OPS
00458       return static_cast<UT> (x) >> std::numeric_limits<T>::digits;
00459 #else
00460       return (x < 0) ? 1 : 0;
00461 #endif
00462     }
00463 
00464   static T
00465   abs (T x)
00466     {
00467 #ifdef HAVE_FAST_INT_OPS
00468       // This is close to how GCC does std::abs, but we can't just use std::abs,
00469       // because its behaviour for INT_MIN is undefined and the compiler could
00470       // discard the following test.
00471       T m = x >> std::numeric_limits<T>::digits;
00472       T y = (x ^ m) - m;
00473       if (y < 0)
00474         {
00475           y = octave_int_base<T>::max_val ();
00476         }
00477       return y;
00478 #else
00479       // -INT_MAX is safe because C++ actually allows only three implementations
00480       // of integers: sign & magnitude, ones complement and twos complement.
00481       // The first test will, with modest optimizations, evaluate at compile
00482       // time, and maybe eliminate the branch completely.
00483       T y;
00484       if (octave_int_base<T>::min_val () < -octave_int_base<T>::max_val ()
00485           && x == octave_int_base<T>::min_val ())
00486         {
00487           y = octave_int_base<T>::max_val ();
00488         }
00489       else
00490         y = (x < 0) ? -x : x;
00491       return y;
00492 #endif
00493     }
00494 
00495   static T
00496   signum (T x)
00497     {
00498       // With modest optimizations, this will compile without a jump.
00499       return ((x > 0) ? 1 : 0) - __signbit (x);
00500     }
00501 
00502   // FIXME -- we do not have an authority what signed shifts should
00503   // exactly do, so we define them the easy way. Note that Matlab does
00504   // not define signed shifts.
00505 
00506   static T
00507   rshift (T x, int n) { return x >> n; }
00508 
00509   static T
00510   lshift (T x, int n) { return x << n; }
00511 
00512   // Minus has problems similar to abs.
00513   static T
00514   minus (T x)
00515     {
00516 #ifdef HAVE_FAST_INT_OPS
00517       T y = -x;
00518       if (y == octave_int_base<T>::min_val ())
00519         {
00520           --y;
00521         }
00522       return y;
00523 #else
00524       T y;
00525       if (octave_int_base<T>::min_val () < -octave_int_base<T>::max_val ()
00526           && x == octave_int_base<T>::min_val ())
00527         {
00528           y = octave_int_base<T>::max_val ();
00529         }
00530       else
00531         y = -x;
00532       return y;
00533 #endif
00534     }
00535 
00536   static T
00537   add (T x, T y)
00538     {
00539 #ifdef HAVE_FAST_INT_OPS
00540     // The typecasts do nothing, but they are here to prevent an optimizing
00541     // compiler from interfering. Also, the signed operations on small types
00542     // actually return int.
00543       T u = static_cast<UT> (x) + static_cast<UT> (y);
00544       T ux = u ^ x, uy = u ^ y;
00545       if ((ux & uy) < 0)
00546         {
00547           u = octave_int_base<T>::max_val () + __signbit (~u);
00548         }
00549       return u;
00550 #else
00551       // We shall carefully avoid anything that may overflow.
00552       T u;
00553       if (y < 0)
00554         {
00555           if (x < octave_int_base<T>::min_val () - y)
00556             {
00557               u = octave_int_base<T>::min_val ();
00558             }
00559           else
00560             u = x + y;
00561         }
00562       else
00563         {
00564           if (x > octave_int_base<T>::max_val () - y)
00565             {
00566               u = octave_int_base<T>::max_val ();
00567             }
00568           else
00569             u = x + y;
00570         }
00571 
00572       return u;
00573 #endif
00574     }
00575 
00576   // This is very similar to addition.
00577   static T
00578   sub (T x, T y)
00579     {
00580 #ifdef HAVE_FAST_INT_OPS
00581     // The typecasts do nothing, but they are here to prevent an optimizing
00582     // compiler from interfering. Also, the signed operations on small types
00583     // actually return int.
00584       T u = static_cast<UT> (x) - static_cast<UT> (y);
00585       T ux = u ^ x, uy = u ^ ~y;
00586       if ((ux & uy) < 0)
00587         {
00588           u = octave_int_base<T>::max_val () + __signbit (~u);
00589         }
00590       return u;
00591 #else
00592       // We shall carefully avoid anything that may overflow.
00593       T u;
00594       if (y < 0)
00595         {
00596           if (x > octave_int_base<T>::max_val () + y)
00597             {
00598               u = octave_int_base<T>::max_val ();
00599             }
00600           else
00601             u = x - y;
00602         }
00603       else
00604         {
00605           if (x < octave_int_base<T>::min_val () + y)
00606             {
00607               u = octave_int_base<T>::min_val ();
00608             }
00609           else
00610             u = x - y;
00611         }
00612 
00613       return u;
00614 #endif
00615     }
00616 
00617   // Multiplication is done using promotion to wider integer type. If there is
00618   // no suitable promotion type, this operation *MUST* be specialized.
00619   static T
00620   mul (T x, T y)
00621     {
00622       // Promotion type for multiplication (if exists).
00623       typedef typename query_integer_type<2*sizeof (T), true>::type mptype;
00624       return octave_int_base<T>::truncate_int (static_cast<mptype> (x)
00625                                                * static_cast<mptype> (y));
00626     }
00627 
00628   // Division.
00629   static T
00630   div (T x, T y)
00631     {
00632       T z;
00633       if (y == 0)
00634         {
00635           if (x < 0)
00636             z = octave_int_base<T>::min_val ();
00637           else if (x != 0)
00638             z = octave_int_base<T>::max_val ();
00639           else
00640             z = 0;
00641         }
00642       else if (y < 0)
00643         {
00644           // This is a special case that overflows as well.
00645           if (y == -1 && x == octave_int_base<T>::min_val ())
00646             {
00647               z = octave_int_base<T>::max_val ();
00648             }
00649           else
00650             {
00651               z = x / y;
00652               T w = -octave_int_abs (x % y); // Can't overflow, but std::abs (x) can!
00653               if (w <= y - w)
00654                 z -= 1 - (__signbit (x) << 1);
00655             }
00656         }
00657       else
00658         {
00659           z = x / y;
00660           // FIXME -- this is a workaround due to MSVC's absence of
00661           // std::abs (int64_t).  The call to octave_int_abs can't
00662           // overflow, but std::abs (x) can!
00663           T w = octave_int_abs (x % y);
00664 
00665           if (w >= y - w)
00666             z += 1 - (__signbit (x) << 1);
00667         }
00668       return z;
00669     }
00670 
00671   // Remainder.
00672   static T
00673   rem (T x, T y)
00674     {
00675       return y != 0 ? x % y : 0;
00676     }
00677 
00678   // Modulus. Note the weird y = 0 case for Matlab compatibility.
00679   static T
00680   mod (T x, T y)
00681     {
00682       if (y != 0)
00683         {
00684           T r = x % y;
00685           return ((r < 0) != (y < 0)) ? r + y : r;
00686         }
00687       else
00688         return x;
00689     }
00690 };
00691 
00692 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
00693 // Handle 64-bit multiply using long double
00694 template <>
00695 inline int64_t
00696 octave_int_arith_base<int64_t, true>:: mul (int64_t x, int64_t y)
00697 {
00698   long double p = static_cast<long double> (x) * static_cast<long double> (y);
00699   // NOTE: We could maybe do it with a single branch if HAVE_FAST_INT_OPS, but it
00700   // would require one more runtime conversion, so the question is whether it would
00701   // really be faster.
00702   if (p > static_cast<long double> (octave_int_base<int64_t>::max_val ()))
00703     {
00704       return octave_int_base<int64_t>::max_val ();
00705     }
00706   else if (p < static_cast<long double> (octave_int_base<int64_t>::min_val ()))
00707     {
00708       return octave_int_base<int64_t>::min_val ();
00709     }
00710   else
00711     return static_cast<int64_t> (p);
00712 }
00713 #else
00714 // Special handler for 64-bit integer multiply.
00715 template <>
00716 OCTAVE_API int64_t
00717 octave_int_arith_base<int64_t, true>::mul (int64_t, int64_t);
00718 #endif
00719 
00720 // This class simply selects the proper arithmetics.
00721 template<class T>
00722 class octave_int_arith
00723  : public octave_int_arith_base<T, std::numeric_limits<T>::is_signed>
00724 {};
00725 
00726 template <class T>
00727 class
00728 octave_int : public octave_int_base<T>
00729 {
00730 public:
00731   typedef T val_type;
00732 
00733   octave_int (void) : ival () { }
00734 
00735   octave_int (T i) : ival (i) { }
00736 
00737   octave_int (double d) : ival (octave_int_base<T>::convert_real (d)) { }
00738 
00739   octave_int (float d) : ival (octave_int_base<T>::convert_real (d)) { }
00740 
00741 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
00742   octave_int (long double d) : ival (octave_int_base<T>::convert_real (d)) { }
00743 #endif
00744 
00745   octave_int (bool b) : ival (b) { }
00746 
00747   template <class U>
00748   octave_int (const U& i) : ival(octave_int_base<T>::truncate_int (i)) { }
00749 
00750   template <class U>
00751   octave_int (const octave_int<U>& i)
00752     : ival (octave_int_base<T>::truncate_int (i.value ())) { }
00753 
00754   octave_int (const octave_int<T>& i) : ival (i.ival) { }
00755 
00756   octave_int& operator = (const octave_int<T>& i)
00757   {
00758     ival = i.ival;
00759     return *this;
00760   }
00761 
00762   T value (void) const { return ival; }
00763 
00764   const unsigned char * iptr (void) const
00765   { return reinterpret_cast<const unsigned char *> (& ival); }
00766 
00767   bool operator ! (void) const { return ! ival; }
00768 
00769   bool bool_value (void) const { return static_cast<bool> (value ()); }
00770 
00771   char char_value (void) const { return static_cast<char> (value ()); }
00772 
00773   double double_value (void) const { return static_cast<double> (value ()); }
00774 
00775   float float_value (void) const { return static_cast<float> (value ()); }
00776 
00777   operator T (void) const { return value (); }
00778 
00779   // char and bool operators intentionally omitted.
00780 
00781   operator double (void) const { return double_value (); }
00782 
00783   operator float (void) const { return float_value (); }
00784 
00785   octave_int<T>
00786   operator + () const
00787     { return *this; }
00788 
00789   // unary operators & mappers
00790 #define OCTAVE_INT_UN_OP(OPNAME,NAME) \
00791   inline octave_int<T> \
00792   OPNAME () const \
00793   { return octave_int_arith<T>::NAME (ival); }
00794 
00795   OCTAVE_INT_UN_OP(operator -, minus)
00796   OCTAVE_INT_UN_OP(abs, abs)
00797   OCTAVE_INT_UN_OP(signum, signum)
00798 
00799 #undef OCTAVE_INT_UN_OP
00800 
00801 // Homogeneous binary integer operations.
00802 #define OCTAVE_INT_BIN_OP(OP, NAME, ARGT) \
00803   inline octave_int<T> \
00804   operator OP (const ARGT& y) const \
00805   { return octave_int_arith<T>::NAME (ival, y); } \
00806   inline octave_int<T>& \
00807   operator OP##= (const ARGT& y) \
00808   { \
00809     ival = octave_int_arith<T>::NAME (ival, y); \
00810     return *this; \
00811   }
00812 
00813   OCTAVE_INT_BIN_OP(+, add, octave_int<T>)
00814   OCTAVE_INT_BIN_OP(-, sub, octave_int<T>)
00815   OCTAVE_INT_BIN_OP(*, mul, octave_int<T>)
00816   OCTAVE_INT_BIN_OP(/, div, octave_int<T>)
00817   OCTAVE_INT_BIN_OP(%, rem, octave_int<T>)
00818   OCTAVE_INT_BIN_OP(<<, lshift, int)
00819   OCTAVE_INT_BIN_OP(>>, rshift, int)
00820 
00821 #undef OCTAVE_INT_BIN_OP
00822 
00823   static octave_int<T> min (void) { return std::numeric_limits<T>::min (); }
00824   static octave_int<T> max (void) { return std::numeric_limits<T>::max (); }
00825 
00826   static int nbits (void) { return std::numeric_limits<T>::digits; }
00827 
00828   static int byte_size (void) { return sizeof(T); }
00829 
00830   static const char *type_name ();
00831 
00832   // The following are provided for convenience.
00833   static const octave_int zero, one;
00834 
00835   // Unsafe.  This function exists to support the MEX interface.
00836   // You should not use it anywhere else.
00837   void *mex_get_data (void) const { return const_cast<T *> (&ival); }
00838 
00839 private:
00840 
00841   T ival;
00842 };
00843 
00844 template <class T>
00845 inline octave_int<T>
00846 rem (const octave_int<T>& x, const octave_int<T>& y)
00847 { return octave_int_arith<T>::rem (x.value (), y.value ()); }
00848 
00849 template <class T>
00850 inline octave_int<T>
00851 mod (const octave_int<T>& x, const octave_int<T>& y)
00852 { return octave_int_arith<T>::mod (x.value (), y.value ()); }
00853 
00854 // No mixed integer binary operations!
00855 
00856 template <class T>
00857 inline bool
00858 xisnan (const octave_int<T>&)
00859 { return false; }
00860 
00861 // FIXME -- can/should any of these be inline?
00862 
00863 template <class T>
00864 extern OCTAVE_API octave_int<T>
00865 pow (const octave_int<T>&, const octave_int<T>&);
00866 
00867 template <class T>
00868 extern OCTAVE_API octave_int<T>
00869 pow (const double& a, const octave_int<T>& b);
00870 
00871 template <class T>
00872 extern OCTAVE_API octave_int<T>
00873 pow (const octave_int<T>& a, const double& b);
00874 
00875 template <class T>
00876 extern OCTAVE_API octave_int<T>
00877 pow (const float& a, const octave_int<T>& b);
00878 
00879 template <class T>
00880 extern OCTAVE_API octave_int<T>
00881 pow (const octave_int<T>& a, const float& b);
00882 
00883 // FIXME: Do we really need a differently named single-precision
00884 //        function integer power function here instead of an overloaded
00885 //        one?
00886 template <class T>
00887 extern OCTAVE_API octave_int<T>
00888 powf (const float& a, const octave_int<T>& b);
00889 
00890 template <class T>
00891 extern OCTAVE_API octave_int<T>
00892 powf (const octave_int<T>& a, const float& b);
00893 
00894 // Binary relations
00895 
00896 #define OCTAVE_INT_CMP_OP(OP, NAME) \
00897   template<class T1, class T2> \
00898   inline bool \
00899   operator OP (const octave_int<T1>& x, const octave_int<T2>& y) \
00900   { return octave_int_cmp_op::op<octave_int_cmp_op::NAME, T1, T2> \
00901     (x.value (), y.value ()); }
00902 
00903 OCTAVE_INT_CMP_OP (<, lt)
00904 OCTAVE_INT_CMP_OP (<=, le)
00905 OCTAVE_INT_CMP_OP (>, gt)
00906 OCTAVE_INT_CMP_OP (>=, ge)
00907 OCTAVE_INT_CMP_OP (==, eq)
00908 OCTAVE_INT_CMP_OP (!=, ne)
00909 
00910 #undef OCTAVE_INT_CMP_OP
00911 
00912 template <class T>
00913 inline std::ostream&
00914 operator << (std::ostream& os, const octave_int<T>& ival)
00915 {
00916   os << ival.value ();
00917   return os;
00918 }
00919 
00920 template <class T>
00921 inline std::istream&
00922 operator >> (std::istream& is, octave_int<T>& ival)
00923 {
00924   T tmp = 0;
00925   is >> tmp;
00926   ival = tmp;
00927   return is;
00928 }
00929 
00930 // Bitwise operations
00931 
00932 #define OCTAVE_INT_BITCMP_OP(OP) \
00933   template <class T> \
00934   octave_int<T> \
00935   operator OP (const octave_int<T>& x, const octave_int<T>& y) \
00936   { return x.value () OP y.value (); }
00937 
00938 OCTAVE_INT_BITCMP_OP (&)
00939 OCTAVE_INT_BITCMP_OP (|)
00940 OCTAVE_INT_BITCMP_OP (^)
00941 
00942 #undef OCTAVE_INT_BITCMP_OP
00943 
00944 // General bit shift.
00945 template <class T>
00946 octave_int<T>
00947 bitshift (const octave_int<T>& a, int n,
00948           const octave_int<T>& mask = std::numeric_limits<T>::max ())
00949 {
00950   if (n > 0)
00951     return (a << n) & mask;
00952   else if (n < 0)
00953     return (a >> -n) & mask;
00954   else
00955     return a & mask;
00956 }
00957 
00958 typedef octave_int<int8_t> octave_int8;
00959 typedef octave_int<int16_t> octave_int16;
00960 typedef octave_int<int32_t> octave_int32;
00961 typedef octave_int<int64_t> octave_int64;
00962 
00963 typedef octave_int<uint8_t> octave_uint8;
00964 typedef octave_int<uint16_t> octave_uint16;
00965 typedef octave_int<uint32_t> octave_uint32;
00966 typedef octave_int<uint64_t> octave_uint64;
00967 
00968 #define OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
00969   template <class T> \
00970   inline octave_int<T> \
00971   operator OP (const octave_int<T>& x, const double& y) \
00972   { return octave_int<T> (static_cast<double> (x) OP y); } \
00973   template <class T> \
00974   inline octave_int<T> \
00975   operator OP (const double& x, const octave_int<T>& y) \
00976   { return octave_int<T> (x OP static_cast<double> (y)); } \
00977 
00978 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
00979 // Handle mixed op using long double
00980 #define OCTAVE_INT_DOUBLE_BIN_OP(OP) \
00981   OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
00982   template <> \
00983   inline octave_int64 \
00984   operator OP (const double& x, const octave_int64& y) \
00985   { return octave_int64 (x OP static_cast<long double> (y.value ())); } \
00986   template <> \
00987   inline octave_uint64 \
00988   operator OP (const double& x, const octave_uint64& y) \
00989   { return octave_uint64 (x OP static_cast<long double> (y.value ())); } \
00990   template <> \
00991   inline octave_int64 \
00992   operator OP (const octave_int64& x, const double& y) \
00993   { return octave_int64 (static_cast<long double> (x.value ()) OP y); } \
00994   template <> \
00995   inline octave_uint64 \
00996   operator OP (const octave_uint64& x, const double& y) \
00997   { return octave_uint64 (static_cast<long double> (x.value ()) OP y); }
00998 
00999 #else
01000 // external handlers
01001 #define OCTAVE_INT_DOUBLE_BIN_OP(OP) \
01002   OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
01003   template <> \
01004   OCTAVE_API octave_int64 \
01005   operator OP (const double&, const octave_int64&); \
01006   template <> \
01007   OCTAVE_API octave_uint64 \
01008   operator OP (const double&, const octave_uint64&); \
01009   template <> \
01010   OCTAVE_API octave_int64 \
01011   operator OP (const octave_int64&, const double&); \
01012   template <> \
01013   OCTAVE_API octave_uint64 \
01014   operator OP (const octave_uint64&, const double&);
01015 
01016 #endif
01017 
01018 OCTAVE_INT_DOUBLE_BIN_OP (+)
01019 OCTAVE_INT_DOUBLE_BIN_OP (-)
01020 OCTAVE_INT_DOUBLE_BIN_OP (*)
01021 OCTAVE_INT_DOUBLE_BIN_OP (/)
01022 
01023 #undef OCTAVE_INT_DOUBLE_BIN_OP0
01024 #undef OCTAVE_INT_DOUBLE_BIN_OP
01025 
01026 #define OCTAVE_INT_DOUBLE_CMP_OP(OP,NAME) \
01027   template <class T> \
01028   inline bool \
01029   operator OP (const octave_int<T>& x, const double& y) \
01030   { return octave_int_cmp_op::mop<octave_int_cmp_op::NAME> (x.value (), y); } \
01031   template <class T> \
01032   inline bool \
01033   operator OP (const double& x, const octave_int<T>& y) \
01034   { return octave_int_cmp_op::mop<octave_int_cmp_op::NAME> (x, y.value ()); }
01035 
01036 OCTAVE_INT_DOUBLE_CMP_OP (<, lt)
01037 OCTAVE_INT_DOUBLE_CMP_OP (<=, le)
01038 OCTAVE_INT_DOUBLE_CMP_OP (>=, ge)
01039 OCTAVE_INT_DOUBLE_CMP_OP (>, gt)
01040 OCTAVE_INT_DOUBLE_CMP_OP (==, eq)
01041 OCTAVE_INT_DOUBLE_CMP_OP (!=, ne)
01042 
01043 #undef OCTAVE_INT_DOUBLE_CMP_OP
01044 
01045 // Floats are handled by simply converting to doubles.
01046 
01047 #define OCTAVE_INT_FLOAT_BIN_OP(OP) \
01048   template <class T> \
01049   inline octave_int<T> \
01050   operator OP (const octave_int<T>& x, float y) \
01051   { return x OP static_cast<double> (y); } \
01052   template <class T> \
01053   inline octave_int<T> \
01054   operator OP (float x, const octave_int<T>& y) \
01055   { return static_cast<double> (x) OP y; }
01056 
01057 OCTAVE_INT_FLOAT_BIN_OP (+)
01058 OCTAVE_INT_FLOAT_BIN_OP (-)
01059 OCTAVE_INT_FLOAT_BIN_OP (*)
01060 OCTAVE_INT_FLOAT_BIN_OP (/)
01061 
01062 #undef OCTAVE_INT_FLOAT_BIN_OP
01063 
01064 #define OCTAVE_INT_FLOAT_CMP_OP(OP) \
01065   template <class T> \
01066   inline bool \
01067   operator OP (const octave_int<T>& x, const float& y) \
01068   { return x OP static_cast<double> (y); } \
01069   template <class T> \
01070   bool \
01071   operator OP (const float& x, const octave_int<T>& y) \
01072   { return static_cast<double> (x) OP y; }
01073 
01074 OCTAVE_INT_FLOAT_CMP_OP (<)
01075 OCTAVE_INT_FLOAT_CMP_OP (<=)
01076 OCTAVE_INT_FLOAT_CMP_OP (>=)
01077 OCTAVE_INT_FLOAT_CMP_OP (>)
01078 OCTAVE_INT_FLOAT_CMP_OP (==)
01079 OCTAVE_INT_FLOAT_CMP_OP (!=)
01080 
01081 #undef OCTAVE_INT_FLOAT_CMP_OP
01082 
01083 template <class T>
01084 octave_int<T>
01085 xmax (const octave_int<T>& x, const octave_int<T>& y)
01086 {
01087   const T xv = x.value (), yv = y.value ();
01088   return octave_int<T> (xv >= yv ? xv : yv);
01089 }
01090 
01091 template <class T>
01092 octave_int<T>
01093 xmin (const octave_int<T>& x, const octave_int<T>& y)
01094 {
01095   const T xv = x.value (), yv = y.value ();
01096   return octave_int<T> (xv <= yv ? xv : yv);
01097 }
01098 
01099 #endif
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines