00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00043
00044
00045 template <class T>
00046 inline T octave_int_abs (T x) { return x >= 0 ? x : -x; }
00047
00048
00049 template<int qsize, bool qsigned>
00050 struct query_integer_type
00051 {
00052 public:
00053 static const bool registered = false;
00054 typedef void type;
00055
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
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
00078
00079
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
00090
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
00101 class octave_int_cmp_op
00102 {
00103
00104
00105
00106
00107
00108 template <class T1, class T2>
00109 class prom
00110 {
00111
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
00126
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
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
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
00178
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
00190
00191
00192
00193
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
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
00225 template <class S>
00226 static T
00227 truncate_int (const S& value)
00228 {
00229
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
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
00246
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
00262 template <class S>
00263 static S
00264 compute_threshold (S val, T orig_val)
00265 {
00266 val = xround (val);
00267
00268 if (orig_val % 2 && val / 2 == xround (val / 2))
00269
00270 val *= (static_cast<S>(1) - (std::numeric_limits<S>::epsilon () / 2));
00271 return val;
00272 }
00273
00274 public:
00275
00276 template <class S>
00277 static T
00278 convert_real (const S& value)
00279 {
00280
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
00304
00305
00306
00307
00308 template <class T, bool is_signed>
00309 class octave_int_arith_base
00310 { };
00311
00312
00313
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
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
00339
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
00363
00364 static T
00365 mul (T x, T y)
00366 {
00367
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
00374
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
00391 static T
00392 rem (T x, T y)
00393 {
00394 return y != 0 ? x % y : 0;
00395 }
00396
00397
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
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
00421 template <>
00422 OCTAVE_API uint64_t
00423 octave_int_arith_base<uint64_t, false>::mul (uint64_t, uint64_t);
00424 #endif
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446 template <class T>
00447 class octave_int_arith_base<T, true> : octave_int_base<T>
00448 {
00449
00450 typedef typename query_integer_type<sizeof (T), false>::type UT;
00451 public:
00452
00453
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
00469
00470
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
00480
00481
00482
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
00499 return ((x > 0) ? 1 : 0) - __signbit (x);
00500 }
00501
00502
00503
00504
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
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
00541
00542
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
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
00577 static T
00578 sub (T x, T y)
00579 {
00580 #ifdef HAVE_FAST_INT_OPS
00581
00582
00583
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
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
00618
00619 static T
00620 mul (T x, T y)
00621 {
00622
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
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
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);
00653 if (w <= y - w)
00654 z -= 1 - (__signbit (x) << 1);
00655 }
00656 }
00657 else
00658 {
00659 z = x / y;
00660
00661
00662
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
00672 static T
00673 rem (T x, T y)
00674 {
00675 return y != 0 ? x % y : 0;
00676 }
00677
00678
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
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
00700
00701
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
00715 template <>
00716 OCTAVE_API int64_t
00717 octave_int_arith_base<int64_t, true>::mul (int64_t, int64_t);
00718 #endif
00719
00720
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
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
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
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
00833 static const octave_int zero, one;
00834
00835
00836
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
00855
00856 template <class T>
00857 inline bool
00858 xisnan (const octave_int<T>&)
00859 { return false; }
00860
00861
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
00884
00885
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
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
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
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
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
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
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