GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
oct-inttypes.h
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2004-2013 John W. Eaton
4 Copyright (C) 2008-2009 Jaroslav Hajek
5 
6 This file is part of Octave.
7 
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if !defined (octave_oct_inttypes_h)
25 #define octave_oct_inttypes_h 1
26 
27 #include <cstdlib>
28 
29 #include <limits>
30 #include <iosfwd>
31 
32 #include "lo-traits.h"
33 #include "lo-math.h"
34 #include "lo-mappers.h"
35 
36 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
37 inline long double xround (long double x) { return roundl (x); }
38 inline long double xisnan (long double x)
39 { return xisnan (static_cast<double> (x)); }
40 #endif
41 
42 // FIXME: we define this by our own because some compilers, such as
43 // MSVC, do not provide std::abs (int64_t) and std::abs (uint64_t). In
44 // the future, it should go away in favor of std::abs.
45 template <class T>
46 inline T octave_int_abs (T x) { return x >= 0 ? x : -x; }
47 
48 // Query for an integer type of certain sizeof, and signedness.
49 template<int qsize, bool qsigned>
51 {
52 public:
53  static const bool registered = false;
54  typedef void type; // Void shall result in a compile-time error if we
55  // attempt to use it in computations.
56 };
57 
58 #define REGISTER_INT_TYPE(TYPE) \
59 template <> \
60 class query_integer_type<sizeof (TYPE), std::numeric_limits<TYPE>::is_signed> \
61 { \
62 public: \
63  static const bool registered = true; \
64  typedef TYPE type; \
65 }
66 
67 // No two registered integers can share sizeof and signedness.
71 REGISTER_INT_TYPE (uint16_t);
73 REGISTER_INT_TYPE (uint32_t);
75 REGISTER_INT_TYPE (uint64_t);
76 
77 // Rationale: Comparators have a single static method, rel(), that returns the
78 // result of the binary relation. They also have two static boolean fields:
79 // ltval, gtval determine the value of x OP y if x < y, x > y, respectively.
80 #define REGISTER_OCTAVE_CMP_OP(NM,OP) \
81  class NM \
82  { \
83  public: \
84  static const bool ltval = (0 OP 1), gtval = (1 OP 0); \
85  template <class T> \
86  static bool op (T x, T y) { return x OP y; } \
87  }
88 
89 // We also provide two special relations: ct, yielding always true, and cf,
90 // yielding always false.
91 #define REGISTER_OCTAVE_CONST_OP(NM,value) \
92  class NM \
93  { \
94  public: \
95  static const bool ltval = value, gtval = value; \
96  template <class T> \
97  static bool op (T, T) { return value; } \
98  }
99 
100 // Handles non-homogeneous integer comparisons. Avoids doing useless tests.
102 {
103  // This determines a suitable promotion type for T1 when meeting T2 in a
104  // binary relation. If promotion to int or T2 is safe, it is used. Otherwise,
105  // the signedness of T1 is preserved and it is widened if T2 is wider.
106  // Notice that if this is applied to both types, they must end up with equal
107  // size.
108  template <class T1, class T2>
109  class prom
110  {
111  // Promote to int?
112  static const bool pint = (sizeof (T1) < sizeof (int)
113  && sizeof (T2) < sizeof (int));
114  static const bool t1sig = std::numeric_limits<T1>::is_signed;
115  static const bool t2sig = std::numeric_limits<T2>::is_signed;
116  static const bool psig =
117  (pint || (sizeof (T2) > sizeof (T1) && t2sig) || t1sig);
118  static const int psize =
119  (pint ? sizeof (int) : (sizeof (T2) > sizeof (T1)
120  ? sizeof (T2) : sizeof (T1)));
121  public:
123  };
124 
125  // Implements comparisons between two types of equal size but
126  // possibly different signedness.
127  template<class xop, int size>
128  class uiop
129  {
132  public:
133  static bool op (utype x, utype y)
134  { return xop::op (x, y); }
135  static bool op (stype x, stype y)
136  { return xop::op (x, y); }
137  static bool op (stype x, utype y)
138  { return (x < 0) ? xop::ltval : xop::op (static_cast<utype> (x), y); }
139  static bool op (utype x, stype y)
140  { return (y < 0) ? xop::gtval : xop::op (x, static_cast<utype> (y)); }
141  };
142 
143 public:
152 
153  // Universal comparison operation.
154  template<class xop, class T1, class T2>
155  static bool
156  op (T1 x, T2 y)
157  {
158  typedef typename prom<T1, T2>::type PT1;
159  typedef typename prom<T2, T1>::type PT2;
160  return uiop<xop, sizeof (PT1)>::op (static_cast<PT1> (x),
161  static_cast<PT2> (y));
162  }
163 
164 public:
165 
166  // Mixed comparisons
167  template <class xop, class T>
168  static bool
169  mop (T x, double y)
170  { return xop::op (static_cast<double> (x), y); }
171 
172  template <class xop, class T>
173  static bool
174  mop (double x, T y)
175  { return xop::op (x, static_cast<double> (y)); }
176 
177 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
178 #define DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS(T) \
179  template <class xop> static OCTAVE_API bool \
180  external_mop (double, T); \
181  template <class xop> static OCTAVE_API bool \
182  external_mop (T, double)
183 
184  DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS (int64_t);
185  DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS (uint64_t);
186 #endif
187 
188  // Typecasting to doubles won't work properly for 64-bit integers --
189  // they lose precision.
190  // If we have long doubles, use them...
191 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
192 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
193 #define DEFINE_LONG_DOUBLE_CMP_OP(T) \
194  template <class xop> \
195  static bool \
196  mop (double x, T y) \
197  { \
198  return external_mop<xop> (x, y); \
199  } \
200  template <class xop> \
201  static bool \
202  mop (T x, double y) \
203  { \
204  return external_mop<xop> (x, y); \
205  }
206 #else
207 #define DEFINE_LONG_DOUBLE_CMP_OP(T) \
208  template <class xop> \
209  static bool \
210  mop (double x, T y) \
211  { \
212  return xop::op (static_cast<long double> (x), \
213  static_cast<long double> (y)); \
214  } \
215  template <class xop> \
216  static bool \
217  mop (T x, double y) \
218  { \
219  return xop::op (static_cast<long double> (x), \
220  static_cast<long double> (y)); \
221  }
222 #endif
223 #else
224  // ... otherwise, use external handlers
225 
226  // FIXME: We could declare directly the mop methods as external,
227  // but we can't do this because bugs in gcc (<= 4.3) prevent
228  // explicit instantiations later in that case.
229 #define DEFINE_LONG_DOUBLE_CMP_OP(T) \
230  template <class xop> static OCTAVE_API bool \
231  emulate_mop (double, T); \
232  template <class xop> \
233  static bool \
234  mop (double x, T y) \
235  { \
236  return emulate_mop<xop> (x, y); \
237  } \
238  template <class xop> static OCTAVE_API bool \
239  emulate_mop (T, double); \
240  template <class xop> \
241  static bool \
242  mop (T x, double y) \
243  { \
244  return emulate_mop<xop> (x, y); \
245  }
246 #endif
247 
250 
251 #undef DEFINE_LONG_DOUBLE_CMP_OP
252 };
253 
254 // Base integer class. No data, just conversion methods and exception flags.
255 template <class T>
257 {
258 public:
259 
260  static T min_val () { return std::numeric_limits<T>:: min (); }
261  static T max_val () { return std::numeric_limits<T>:: max (); }
262 
263  // Convert integer value.
264  template <class S>
265  static T
266  truncate_int (const S& value)
267  {
268  // An exhaustive test whether the max and/or min check can be omitted.
269  static const bool t_is_signed = std::numeric_limits<T>::is_signed;
270  static const bool s_is_signed = std::numeric_limits<S>::is_signed;
271  static const int t_size = sizeof (T), s_size = sizeof (S);
272  static const bool omit_chk_min =
273  (! s_is_signed || (t_is_signed && t_size >= s_size));
274  static const bool omit_chk_max =
275  (t_size > s_size || (t_size == s_size
276  && (! t_is_signed || s_is_signed)));
277  // If the check can be omitted, substitute constant false relation.
278  typedef octave_int_cmp_op::cf cf;
279  typedef octave_int_cmp_op::lt lt;
280  typedef octave_int_cmp_op::gt gt;
281  typedef typename if_then_else<omit_chk_min, cf, lt>::result chk_min;
282  typedef typename if_then_else<omit_chk_max, cf, gt>::result chk_max;
283 
284  // Efficiency of the following depends on inlining and dead code
285  // elimination, but that should be a piece of cake for most compilers.
286  if (chk_min::op (value, static_cast<S> (min_val ())))
287  {
288  return min_val ();
289  }
290  else if (chk_max::op (value, static_cast<S> (max_val ())))
291  {
292  return max_val ();
293  }
294  else
295  return static_cast<T> (value);
296  }
297 
298 private:
299 
300  // Computes a real-valued threshold for a max/min check.
301  template <class S>
302  static S
303  compute_threshold (S val, T orig_val)
304  {
305  val = xround (val); // Fool optimizations (maybe redundant)
306  // If val is even, but orig_val is odd, we're one unit off.
307  if (orig_val % 2 && val / 2 == xround (val / 2))
308  // FIXME: is this always correct?
309  val *= (static_cast<S>(1) - (std::numeric_limits<S>::epsilon () / 2));
310  return val;
311  }
312 
313 public:
314  // Convert a real number (check NaN and non-int).
315  template <class S>
316  static T
317  convert_real (const S& value)
318  {
319  // Compute proper thresholds.
320  static const S thmin = compute_threshold (static_cast<S> (min_val ()),
321  min_val ());
322  static const S thmax = compute_threshold (static_cast<S> (max_val ()),
323  max_val ());
324  if (xisnan (value))
325  {
326  return static_cast<T> (0);
327  }
328  else if (value < thmin)
329  {
330  return min_val ();
331  }
332  else if (value > thmax)
333  {
334  return max_val ();
335  }
336  else
337  {
338  S rvalue = xround (value);
339  return static_cast<T> (rvalue);
340  }
341  }
342 };
343 
344 // Saturated (homogeneous) integer arithmetics. The signed and unsigned
345 // implementations are significantly different, so we implement another layer
346 // and completely specialize. Arithmetics inherits from octave_int_base so that
347 // it can use its exceptions and truncation functions.
348 
349 template <class T, bool is_signed>
351 { };
352 
353 // Unsigned arithmetics. C++ standard requires it to be modular, so the
354 // overflows can be handled efficiently and reliably.
355 template <class T>
357 {
358 public:
359 
360  static T
361  abs (T x) { return x; }
362 
363  static T
364  signum (T x) { return x ? static_cast<T> (1) : static_cast<T> (0); }
365 
366  // Shifts do not overflow.
367  static T
368  rshift (T x, int n) { return x >> n; }
369 
370  static T
371  lshift (T x, int n) { return x << n; }
372 
373  static T
374  minus (T)
375  {
376  return static_cast<T> (0);
377  }
378 
379  // the overflow behaviour for unsigned integers is guaranteed by C/C++,
380  // so the following should always work.
381  static T
382  add (T x, T y)
383  {
384  T u = x + y;
385  if (u < x)
386  {
388  }
389  return u;
390  }
391 
392  static T
393  sub (T x, T y)
394  {
395  T u = x - y;
396  if (u > x)
397  {
398  u = 0;
399  }
400  return u;
401  }
402 
403  // Multiplication is done using promotion to wider integer type. If there is
404  // no suitable promotion type, this operation *MUST* be specialized.
405  static T mul (T x, T y) { return mul_internal (x, y); }
406 
407  static T
408  mul_internal (T x, T y)
409  {
410  // Promotion type for multiplication (if exists).
411  typedef typename query_integer_type<2*sizeof (T), false>::type mptype;
412  return octave_int_base<T>::truncate_int (static_cast<mptype> (x)
413  * static_cast<mptype> (y));
414  }
415 
416  // Division with rounding to nearest. Note that / and % are probably
417  // computed by a single instruction.
418  static T
419  div (T x, T y)
420  {
421  if (y != 0)
422  {
423  T z = x / y, w = x % y;
424  if (w >= y-w) z += 1;
425  return z;
426  }
427  else
428  {
429  return x ? octave_int_base<T>::max_val () : 0;
430  }
431  }
432 
433  // Remainder.
434  static T
435  rem (T x, T y)
436  {
437  return y != 0 ? x % y : 0;
438  }
439 
440  // Modulus. Note the weird y = 0 case for Matlab compatibility.
441  static T
442  mod (T x, T y)
443  {
444  return y != 0 ? x % y : x;
445  }
446 };
447 
448 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
449 
450 // Handle 64-bit multiply using long double
451 
452 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
453 
454 extern OCTAVE_API uint64_t
455 octave_external_uint64_uint64_mul (uint64_t, uint64_t);
456 
457 #endif
458 
459 template <>
460 inline uint64_t
462 {
463  uint64_t retval;
464 
465  long double p = static_cast<long double> (x) * static_cast<long double> (y);
466 
467  if (p > static_cast<long double> (octave_int_base<uint64_t>::max_val ()))
469  else
470  retval = static_cast<uint64_t> (p);
471 
472  return retval;
473 }
474 
475 template <>
476 inline uint64_t
477 octave_int_arith_base<uint64_t, false>::mul (uint64_t x, uint64_t y)
478 {
479 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
480  return octave_external_uint64_uint64_mul (x, y);
481 #else
482  return mul_internal (x, y);
483 #endif
484 }
485 
486 #else
487 
488 // Special handler for 64-bit integer multiply.
489 template <>
490 OCTAVE_API uint64_t
492 
493 #endif
494 
495 // Signed integer arithmetics.
496 // Rationale: If HAVE_FAST_INT_OPS is defined, the following conditions
497 // should hold:
498 // 1. Signed numbers are represented by twos complement
499 // (see <http://en.wikipedia.org/wiki/Two%27s_complement>)
500 // 2. static_cast to unsigned int counterpart works like interpreting
501 // the signed bit pattern as unsigned (and is thus zero-cost).
502 // 3. Signed addition and subtraction yield the same bit results as unsigned.
503 // (We use casts to prevent optimization interference, so there is no
504 // need for things like -ftrapv).
505 // 4. Bit operations on signed integers work like on unsigned integers,
506 // except for the shifts. Shifts are arithmetic.
507 //
508 // The above conditions are satisfied by most modern platforms. If
509 // HAVE_FAST_INT_OPS is defined, bit tricks and wraparound arithmetics are used
510 // to avoid conditional jumps as much as possible, thus being friendly to
511 // modern pipeline processor architectures.
512 // Otherwise, we fall back to a bullet-proof code that only uses assumptions
513 // guaranteed by the standard.
514 
515 template <class T>
517 {
518  // The corresponding unsigned type.
520 public:
521 
522  // Returns 1 for negative number, 0 otherwise.
523  static T
524  __signbit (T x)
525  {
526 #ifdef HAVE_FAST_INT_OPS
527  return static_cast<UT> (x) >> std::numeric_limits<T>::digits;
528 #else
529  return (x < 0) ? 1 : 0;
530 #endif
531  }
532 
533  static T
534  abs (T x)
535  {
536 #ifdef HAVE_FAST_INT_OPS
537  // This is close to how GCC does std::abs, but we can't just use std::abs,
538  // because its behaviour for INT_MIN is undefined and the compiler could
539  // discard the following test.
540  T m = x >> std::numeric_limits<T>::digits;
541  T y = (x ^ m) - m;
542  if (y < 0)
543  {
545  }
546  return y;
547 #else
548  // -INT_MAX is safe because C++ actually allows only three implementations
549  // of integers: sign & magnitude, ones complement and twos complement.
550  // The first test will, with modest optimizations, evaluate at compile
551  // time, and maybe eliminate the branch completely.
552  T y;
554  && x == octave_int_base<T>::min_val ())
555  {
557  }
558  else
559  y = (x < 0) ? -x : x;
560  return y;
561 #endif
562  }
563 
564  static T
565  signum (T x)
566  {
567  // With modest optimizations, this will compile without a jump.
568  return ((x > 0) ? 1 : 0) - __signbit (x);
569  }
570 
571  // FIXME: we do not have an authority what signed shifts should
572  // exactly do, so we define them the easy way. Note that Matlab does
573  // not define signed shifts.
574 
575  static T
576  rshift (T x, int n) { return x >> n; }
577 
578  static T
579  lshift (T x, int n) { return x << n; }
580 
581  // Minus has problems similar to abs.
582  static T
583  minus (T x)
584  {
585 #ifdef HAVE_FAST_INT_OPS
586  T y = -x;
587  if (y == octave_int_base<T>::min_val ())
588  {
589  --y;
590  }
591  return y;
592 #else
593  T y;
595  && x == octave_int_base<T>::min_val ())
596  {
598  }
599  else
600  y = -x;
601  return y;
602 #endif
603  }
604 
605  static T
606  add (T x, T y)
607  {
608 #ifdef HAVE_FAST_INT_OPS
609  // The typecasts do nothing, but they are here to prevent an optimizing
610  // compiler from interfering. Also, the signed operations on small types
611  // actually return int.
612  T u = static_cast<UT> (x) + static_cast<UT> (y);
613  T ux = u ^ x, uy = u ^ y;
614  if ((ux & uy) < 0)
615  {
616  u = octave_int_base<T>::max_val () + __signbit (~u);
617  }
618  return u;
619 #else
620  // We shall carefully avoid anything that may overflow.
621  T u;
622  if (y < 0)
623  {
624  if (x < octave_int_base<T>::min_val () - y)
625  {
627  }
628  else
629  u = x + y;
630  }
631  else
632  {
633  if (x > octave_int_base<T>::max_val () - y)
634  {
636  }
637  else
638  u = x + y;
639  }
640 
641  return u;
642 #endif
643  }
644 
645  // This is very similar to addition.
646  static T
647  sub (T x, T y)
648  {
649 #ifdef HAVE_FAST_INT_OPS
650  // The typecasts do nothing, but they are here to prevent an optimizing
651  // compiler from interfering. Also, the signed operations on small types
652  // actually return int.
653  T u = static_cast<UT> (x) - static_cast<UT> (y);
654  T ux = u ^ x, uy = u ^ ~y;
655  if ((ux & uy) < 0)
656  {
657  u = octave_int_base<T>::max_val () + __signbit (~u);
658  }
659  return u;
660 #else
661  // We shall carefully avoid anything that may overflow.
662  T u;
663  if (y < 0)
664  {
665  if (x > octave_int_base<T>::max_val () + y)
666  {
668  }
669  else
670  u = x - y;
671  }
672  else
673  {
674  if (x < octave_int_base<T>::min_val () + y)
675  {
677  }
678  else
679  u = x - y;
680  }
681 
682  return u;
683 #endif
684  }
685 
686  // Multiplication is done using promotion to wider integer type. If there is
687  // no suitable promotion type, this operation *MUST* be specialized.
688  static T mul (T x, T y) { return mul_internal (x, y); }
689 
690  static T
691  mul_internal (T x, T y)
692  {
693  // Promotion type for multiplication (if exists).
694  typedef typename query_integer_type<2*sizeof (T), true>::type mptype;
695  return octave_int_base<T>::truncate_int (static_cast<mptype> (x)
696  * static_cast<mptype> (y));
697  }
698 
699  // Division.
700  static T
701  div (T x, T y)
702  {
703  T z;
704  if (y == 0)
705  {
706  if (x < 0)
708  else if (x != 0)
710  else
711  z = 0;
712  }
713  else if (y < 0)
714  {
715  // This is a special case that overflows as well.
716  if (y == -1 && x == octave_int_base<T>::min_val ())
717  {
719  }
720  else
721  {
722  z = x / y;
723  // Can't overflow, but std::abs (x) can!
724  T w = -octave_int_abs (x % y);
725  if (w <= y - w)
726  z -= 1 - (__signbit (x) << 1);
727  }
728  }
729  else
730  {
731  z = x / y;
732  // FIXME: this is a workaround due to MSVC's absence of
733  // std::abs (int64_t). The call to octave_int_abs can't
734  // overflow, but std::abs (x) can!
735  T w = octave_int_abs (x % y);
736 
737  if (w >= y - w)
738  z += 1 - (__signbit (x) << 1);
739  }
740  return z;
741  }
742 
743  // Remainder.
744  static T
745  rem (T x, T y)
746  {
747  return y != 0 ? x % y : 0;
748  }
749 
750  // Modulus. Note the weird y = 0 case for Matlab compatibility.
751  static T
752  mod (T x, T y)
753  {
754  if (y != 0)
755  {
756  T r = x % y;
757  return ((r < 0) != (y < 0)) ? r + y : r;
758  }
759  else
760  return x;
761  }
762 };
763 
764 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
765 
766 // Handle 64-bit multiply using long double
767 
768 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
769 
770 extern OCTAVE_API int64_t
771 octave_external_int64_int64_mul (int64_t, int64_t);
772 
773 #endif
774 
775 template <>
776 inline int64_t
778 {
779  int64_t retval;
780 
781  long double p = static_cast<long double> (x) * static_cast<long double> (y);
782 
783  // NOTE: We could maybe do it with a single branch if HAVE_FAST_INT_OPS,
784  // but it would require one more runtime conversion, so the question is
785  // whether it would really be faster.
786  if (p > static_cast<long double> (octave_int_base<int64_t>::max_val ()))
788  else if (p < static_cast<long double> (octave_int_base<int64_t>::min_val ()))
790  else
791  retval = static_cast<int64_t> (p);
792 
793  return retval;
794 }
795 
796 template <>
797 inline int64_t
798 octave_int_arith_base<int64_t, true>::mul (int64_t x, int64_t y)
799 {
800 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
801  return octave_external_int64_int64_mul (x, y);
802 #else
803  return mul_internal (x, y);
804 #endif
805 }
806 
807 #else
808 
809 // Special handler for 64-bit integer multiply.
810 template <>
811 OCTAVE_API int64_t
813 
814 #endif
815 
816 // This class simply selects the proper arithmetics.
817 template<class T>
819  : public octave_int_arith_base<T, std::numeric_limits<T>::is_signed>
820 { };
821 
822 template <class T>
823 class
825 {
826 public:
827  typedef T val_type;
828 
829  octave_int (void) : ival () { }
830 
831  octave_int (T i) : ival (i) { }
832 
833  octave_int (double d) : ival (octave_int_base<T>::convert_real (d)) { }
834 
835  octave_int (float d) : ival (octave_int_base<T>::convert_real (d)) { }
836 
837 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
838  octave_int (long double d) : ival (octave_int_base<T>::convert_real (d)) { }
839 #endif
840 
841  octave_int (bool b) : ival (b) { }
842 
843  template <class U>
844  octave_int (const U& i) : ival(octave_int_base<T>::truncate_int (i)) { }
845 
846  template <class U>
848  : ival (octave_int_base<T>::truncate_int (i.value ())) { }
849 
850  octave_int (const octave_int<T>& i) : ival (i.ival) { }
851 
852  octave_int& operator = (const octave_int<T>& i)
853  {
854  ival = i.ival;
855  return *this;
856  }
857 
858  T value (void) const { return ival; }
859 
860  const unsigned char * iptr (void) const
861  { return reinterpret_cast<const unsigned char *> (& ival); }
862 
863  bool operator ! (void) const { return ! ival; }
864 
865  bool bool_value (void) const { return static_cast<bool> (value ()); }
866 
867  char char_value (void) const { return static_cast<char> (value ()); }
868 
869  double double_value (void) const { return static_cast<double> (value ()); }
870 
871  float float_value (void) const { return static_cast<float> (value ()); }
872 
873  operator T (void) const { return value (); }
874 
875  // char and bool operators intentionally omitted.
876 
877  operator double (void) const { return double_value (); }
878 
879  operator float (void) const { return float_value (); }
880 
882  operator + () const
883  { return *this; }
884 
885  // unary operators & mappers
886 #define OCTAVE_INT_UN_OP(OPNAME,NAME) \
887  inline octave_int<T> \
888  OPNAME () const \
889  { return octave_int_arith<T>::NAME (ival); }
890 
891  OCTAVE_INT_UN_OP(operator -, minus)
894 
895 #undef OCTAVE_INT_UN_OP
896 
897 // Homogeneous binary integer operations.
898 #define OCTAVE_INT_BIN_OP(OP, NAME, ARGT) \
899  inline octave_int<T> \
900  operator OP (const ARGT& y) const \
901  { return octave_int_arith<T>::NAME (ival, y); } \
902  inline octave_int<T>& \
903  operator OP##= (const ARGT& y) \
904  { \
905  ival = octave_int_arith<T>::NAME (ival, y); \
906  return *this; \
907  }
908 
914  OCTAVE_INT_BIN_OP(<<, lshift, int)
915  OCTAVE_INT_BIN_OP(>>, rshift, int)
916 
917 #undef OCTAVE_INT_BIN_OP
918 
919  static octave_int<T> min (void) { return std::numeric_limits<T>::min (); }
920  static octave_int<T> max (void) { return std::numeric_limits<T>::max (); }
921 
922  static int nbits (void) { return std::numeric_limits<T>::digits; }
923 
924  static int byte_size (void) { return sizeof (T); }
925 
926  static const char *type_name ();
927 
928  // The following are provided for convenience.
929  static const octave_int zero, one;
930 
931  // Unsafe. This function exists to support the MEX interface.
932  // You should not use it anywhere else.
933  void *mex_get_data (void) const { return const_cast<T *> (&ival); }
934 
935 private:
936 
937  T ival;
938 };
939 
940 template <class T>
941 inline octave_int<T>
942 rem (const octave_int<T>& x, const octave_int<T>& y)
943 { return octave_int_arith<T>::rem (x.value (), y.value ()); }
944 
945 template <class T>
946 inline octave_int<T>
947 mod (const octave_int<T>& x, const octave_int<T>& y)
948 { return octave_int_arith<T>::mod (x.value (), y.value ()); }
949 
950 // No mixed integer binary operations!
951 
952 template <class T>
953 inline bool
955 { return false; }
956 
957 // FIXME: can/should any of these be inline?
958 
959 template <class T>
960 extern OCTAVE_API octave_int<T>
961 pow (const octave_int<T>&, const octave_int<T>&);
962 
963 template <class T>
964 extern OCTAVE_API octave_int<T>
965 pow (const double& a, const octave_int<T>& b);
966 
967 template <class T>
968 extern OCTAVE_API octave_int<T>
969 pow (const octave_int<T>& a, const double& b);
970 
971 template <class T>
972 extern OCTAVE_API octave_int<T>
973 pow (const float& a, const octave_int<T>& b);
974 
975 template <class T>
976 extern OCTAVE_API octave_int<T>
977 pow (const octave_int<T>& a, const float& b);
978 
979 // FIXME: Do we really need a differently named single-precision
980 // function integer power function here instead of an overloaded
981 // one?
982 template <class T>
983 extern OCTAVE_API octave_int<T>
984 powf (const float& a, const octave_int<T>& b);
985 
986 template <class T>
987 extern OCTAVE_API octave_int<T>
988 powf (const octave_int<T>& a, const float& b);
989 
990 // Binary relations
991 
992 #define OCTAVE_INT_CMP_OP(OP, NAME) \
993  template<class T1, class T2> \
994  inline bool \
995  operator OP (const octave_int<T1>& x, const octave_int<T2>& y) \
996  { return octave_int_cmp_op::op<octave_int_cmp_op::NAME, T1, T2> \
997  (x.value (), y.value ()); }
998 
1005 
1006 #undef OCTAVE_INT_CMP_OP
1007 
1008 template <class T>
1009 inline std::ostream&
1010 operator << (std::ostream& os, const octave_int<T>& ival)
1011 {
1012  os << ival.value ();
1013  return os;
1014 }
1015 
1016 template <class T>
1017 inline std::istream&
1018 operator >> (std::istream& is, octave_int<T>& ival)
1019 {
1020  T tmp = 0;
1021  is >> tmp;
1022  ival = tmp;
1023  return is;
1024 }
1025 
1026 // Bitwise operations
1027 
1028 #define OCTAVE_INT_BITCMP_OP(OP) \
1029  template <class T> \
1030  octave_int<T> \
1031  operator OP (const octave_int<T>& x, const octave_int<T>& y) \
1032  { return x.value () OP y.value (); }
1033 
1037 
1038 #undef OCTAVE_INT_BITCMP_OP
1039 
1040 // General bit shift.
1041 template <class T>
1043 bitshift (const octave_int<T>& a, int n,
1044  const octave_int<T>& mask = std::numeric_limits<T>::max ())
1045 {
1046  if (n > 0)
1047  return (a << n) & mask;
1048  else if (n < 0)
1049  return (a >> -n) & mask;
1050  else
1051  return a & mask;
1052 }
1053 
1058 
1063 
1064 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
1065 
1066 #define DECLARE_EXTERNAL_LONG_DOUBLE_OP(T, OP) \
1067  extern OCTAVE_API T \
1068  external_double_ ## T ## _ ## OP (double x, T y); \
1069  extern OCTAVE_API T \
1070  external_ ## T ## _double_ ## OP (T x, double y)
1071 
1072 #define DECLARE_EXTERNAL_LONG_DOUBLE_OPS(T) \
1073  DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, add); \
1074  DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, sub); \
1075  DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, mul); \
1076  DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, div)
1077 
1078 DECLARE_EXTERNAL_LONG_DOUBLE_OPS (octave_int64);
1079 DECLARE_EXTERNAL_LONG_DOUBLE_OPS (octave_uint64);
1080 
1081 #endif
1082 
1083 #define OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
1084  template <class T> \
1085  inline octave_int<T> \
1086  operator OP (const octave_int<T>& x, const double& y) \
1087  { return octave_int<T> (static_cast<double> (x) OP y); } \
1088  template <class T> \
1089  inline octave_int<T> \
1090  operator OP (const double& x, const octave_int<T>& y) \
1091  { return octave_int<T> (x OP static_cast<double> (y)); } \
1092 
1093 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
1094 // Handle mixed op using long double
1095 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
1096 #define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \
1097  OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
1098  template <> \
1099  inline octave_int64 \
1100  operator OP (const double& x, const octave_int64& y) \
1101  { \
1102  return external_double_octave_int64_ ## NAME (x, y); \
1103  } \
1104  template <> \
1105  inline octave_uint64 \
1106  operator OP (const double& x, const octave_uint64& y) \
1107  { \
1108  return external_double_octave_uint64_ ## NAME (x, y); \
1109  } \
1110  template <> \
1111  inline octave_int64 \
1112  operator OP (const octave_int64& x, const double& y) \
1113  { \
1114  return external_octave_int64_double_ ## NAME (x, y); \
1115  } \
1116  template <> \
1117  inline octave_uint64 \
1118  operator OP (const octave_uint64& x, const double& y) \
1119  { \
1120  return external_octave_uint64_double_ ## NAME (x, y); \
1121  }
1122 #else
1123 #define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \
1124  OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
1125  template <> \
1126  inline octave_int64 \
1127  operator OP (const double& x, const octave_int64& y) \
1128  { \
1129  return octave_int64 (x OP static_cast<long double> (y.value ())); \
1130  } \
1131  template <> \
1132  inline octave_uint64 \
1133  operator OP (const double& x, const octave_uint64& y) \
1134  { \
1135  return octave_uint64 (x OP static_cast<long double> (y.value ())); \
1136  } \
1137  template <> \
1138  inline octave_int64 \
1139  operator OP (const octave_int64& x, const double& y) \
1140  { \
1141  return octave_int64 (static_cast<long double> (x.value ()) OP y); \
1142  } \
1143  template <> \
1144  inline octave_uint64 \
1145  operator OP (const octave_uint64& x, const double& y) \
1146  { \
1147  return octave_uint64 (static_cast<long double> (x.value ()) OP y); \
1148  }
1149 #endif
1150 #else
1151 // external handlers
1152 #define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \
1153  OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
1154  template <> \
1155  OCTAVE_API octave_int64 \
1156  operator OP (const double&, const octave_int64&); \
1157  template <> \
1158  OCTAVE_API octave_uint64 \
1159  operator OP (const double&, const octave_uint64&); \
1160  template <> \
1161  OCTAVE_API octave_int64 \
1162  operator OP (const octave_int64&, const double&); \
1163  template <> \
1164  OCTAVE_API octave_uint64 \
1165  operator OP (const octave_uint64&, const double&);
1166 
1167 #endif
1168 
1173 
1174 #undef OCTAVE_INT_DOUBLE_BIN_OP0
1175 #undef OCTAVE_INT_DOUBLE_BIN_OP
1176 #undef DECLARE_EXTERNAL_LONG_DOUBLE_OP
1177 #undef DECLARE_EXTERNAL_LONG_DOUBLE_OPS
1178 
1179 #define OCTAVE_INT_DOUBLE_CMP_OP(OP,NAME) \
1180  template <class T> \
1181  inline bool \
1182  operator OP (const octave_int<T>& x, const double& y) \
1183  { return octave_int_cmp_op::mop<octave_int_cmp_op::NAME> (x.value (), y); } \
1184  template <class T> \
1185  inline bool \
1186  operator OP (const double& x, const octave_int<T>& y) \
1187  { return octave_int_cmp_op::mop<octave_int_cmp_op::NAME> (x, y.value ()); }
1188 
1195 
1196 #undef OCTAVE_INT_DOUBLE_CMP_OP
1197 
1198 // Floats are handled by simply converting to doubles.
1199 
1200 #define OCTAVE_INT_FLOAT_BIN_OP(OP) \
1201  template <class T> \
1202  inline octave_int<T> \
1203  operator OP (const octave_int<T>& x, float y) \
1204  { return x OP static_cast<double> (y); } \
1205  template <class T> \
1206  inline octave_int<T> \
1207  operator OP (float x, const octave_int<T>& y) \
1208  { return static_cast<double> (x) OP y; }
1209 
1214 
1215 #undef OCTAVE_INT_FLOAT_BIN_OP
1216 
1217 #define OCTAVE_INT_FLOAT_CMP_OP(OP) \
1218  template <class T> \
1219  inline bool \
1220  operator OP (const octave_int<T>& x, const float& y) \
1221  { return x OP static_cast<double> (y); } \
1222  template <class T> \
1223  bool \
1224  operator OP (const float& x, const octave_int<T>& y) \
1225  { return static_cast<double> (x) OP y; }
1226 
1233 
1234 #undef OCTAVE_INT_FLOAT_CMP_OP
1235 
1236 template <class T>
1238 xmax (const octave_int<T>& x, const octave_int<T>& y)
1239 {
1240  const T xv = x.value (), yv = y.value ();
1241  return octave_int<T> (xv >= yv ? xv : yv);
1242 }
1243 
1244 template <class T>
1246 xmin (const octave_int<T>& x, const octave_int<T>& y)
1247 {
1248  const T xv = x.value (), yv = y.value ();
1249  return octave_int<T> (xv <= yv ? xv : yv);
1250 }
1251 
1252 #endif