GNU Octave  4.0.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-2015 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); \
85  static const bool gtval = (1 OP 0); \
86  template <class T> \
87  static bool op (T x, T y) { return x OP y; } \
88  }
89 
90 // We also provide two special relations: ct, yielding always true, and cf,
91 // yielding always false.
92 #define REGISTER_OCTAVE_CONST_OP(NM,value) \
93  class NM \
94  { \
95  public: \
96  static const bool ltval = value; \
97  static const bool gtval = value; \
98  template <class T> \
99  static bool op (T, T) { return value; } \
100  }
101 
102 // Handles non-homogeneous integer comparisons. Avoids doing useless tests.
104 {
105  // This determines a suitable promotion type for T1 when meeting T2 in a
106  // binary relation. If promotion to int or T2 is safe, it is used. Otherwise,
107  // the signedness of T1 is preserved and it is widened if T2 is wider.
108  // Notice that if this is applied to both types, they must end up with equal
109  // size.
110  template <class T1, class T2>
111  class prom
112  {
113  // Promote to int?
114  static const bool pint = (sizeof (T1) < sizeof (int)
115  && sizeof (T2) < sizeof (int));
116  static const bool t1sig = std::numeric_limits<T1>::is_signed;
117  static const bool t2sig = std::numeric_limits<T2>::is_signed;
118  static const bool psig =
119  (pint || (sizeof (T2) > sizeof (T1) && t2sig) || t1sig);
120  static const int psize =
121  (pint ? sizeof (int) : (sizeof (T2) > sizeof (T1)
122  ? sizeof (T2) : sizeof (T1)));
123  public:
125  };
126 
127  // Implements comparisons between two types of equal size but
128  // possibly different signedness.
129  template<class xop, int size>
130  class uiop
131  {
134  public:
135  static bool op (utype x, utype y)
136  { return xop::op (x, y); }
137  static bool op (stype x, stype y)
138  { return xop::op (x, y); }
139  static bool op (stype x, utype y)
140  { return (x < 0) ? xop::ltval : xop::op (static_cast<utype> (x), y); }
141  static bool op (utype x, stype y)
142  { return (y < 0) ? xop::gtval : xop::op (x, static_cast<utype> (y)); }
143  };
144 
145 public:
154 
155  // Universal comparison operation.
156  template<class xop, class T1, class T2>
157  static bool
158  op (T1 x, T2 y)
159  {
160  typedef typename prom<T1, T2>::type PT1;
161  typedef typename prom<T2, T1>::type PT2;
162  return uiop<xop, sizeof (PT1)>::op (static_cast<PT1> (x),
163  static_cast<PT2> (y));
164  }
165 
166 public:
167 
168  // Mixed comparisons
169  template <class xop, class T>
170  static bool
171  mop (T x, double y)
172  { return xop::op (static_cast<double> (x), y); }
173 
174  template <class xop, class T>
175  static bool
176  mop (double x, T y)
177  { return xop::op (x, static_cast<double> (y)); }
178 
179 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
180 #define DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS(T) \
181  template <class xop> static OCTAVE_API bool \
182  external_mop (double, T); \
183  template <class xop> static OCTAVE_API bool \
184  external_mop (T, double)
185 
186  DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS (int64_t);
187  DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS (uint64_t);
188 #endif
189 
190  // Typecasting to doubles won't work properly for 64-bit integers --
191  // they lose precision.
192  // If we have long doubles, use them...
193 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
194 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
195 #define DEFINE_LONG_DOUBLE_CMP_OP(T) \
196  template <class xop> \
197  static bool \
198  mop (double x, T y) \
199  { \
200  return external_mop<xop> (x, y); \
201  } \
202  template <class xop> \
203  static bool \
204  mop (T x, double y) \
205  { \
206  return external_mop<xop> (x, y); \
207  }
208 #else
209 #define DEFINE_LONG_DOUBLE_CMP_OP(T) \
210  template <class xop> \
211  static bool \
212  mop (double x, T y) \
213  { \
214  return xop::op (static_cast<long double> (x), \
215  static_cast<long double> (y)); \
216  } \
217  template <class xop> \
218  static bool \
219  mop (T x, double y) \
220  { \
221  return xop::op (static_cast<long double> (x), \
222  static_cast<long double> (y)); \
223  }
224 #endif
225 #else
226  // ... otherwise, use external handlers
227 
228  // FIXME: We could declare directly the mop methods as external,
229  // but we can't do this because bugs in gcc (<= 4.3) prevent
230  // explicit instantiations later in that case.
231 #define DEFINE_LONG_DOUBLE_CMP_OP(T) \
232  template <class xop> static OCTAVE_API bool \
233  emulate_mop (double, T); \
234  template <class xop> \
235  static bool \
236  mop (double x, T y) \
237  { \
238  return emulate_mop<xop> (x, y); \
239  } \
240  template <class xop> static OCTAVE_API bool \
241  emulate_mop (T, double); \
242  template <class xop> \
243  static bool \
244  mop (T x, double y) \
245  { \
246  return emulate_mop<xop> (x, y); \
247  }
248 #endif
249 
252 
253 #undef DEFINE_LONG_DOUBLE_CMP_OP
254 };
255 
256 // Base integer class. No data, just conversion methods and exception flags.
257 template <class T>
259 {
260 public:
261 
262  static T min_val () { return std::numeric_limits<T>:: min (); }
263  static T max_val () { return std::numeric_limits<T>:: max (); }
264 
265  // Convert integer value.
266  template <class S>
267  static T
268  truncate_int (const S& value)
269  {
270  // An exhaustive test whether the max and/or min check can be omitted.
271  static const bool t_is_signed = std::numeric_limits<T>::is_signed;
272  static const bool s_is_signed = std::numeric_limits<S>::is_signed;
273  static const int t_size = sizeof (T);
274  static const int s_size = sizeof (S);
275 
276  static const bool omit_chk_min =
277  (! s_is_signed || (t_is_signed && t_size >= s_size));
278  static const bool omit_chk_max =
279  (t_size > s_size || (t_size == s_size
280  && (! t_is_signed || s_is_signed)));
281  // If the check can be omitted, substitute constant false relation.
282  typedef octave_int_cmp_op::cf cf;
283  typedef octave_int_cmp_op::lt lt;
284  typedef octave_int_cmp_op::gt gt;
285  typedef typename if_then_else<omit_chk_min, cf, lt>::result chk_min;
286  typedef typename if_then_else<omit_chk_max, cf, gt>::result chk_max;
287 
288  // Efficiency of the following depends on inlining and dead code
289  // elimination, but that should be a piece of cake for most compilers.
290  if (chk_min::op (value, static_cast<S> (min_val ())))
291  {
292  return min_val ();
293  }
294  else if (chk_max::op (value, static_cast<S> (max_val ())))
295  {
296  return max_val ();
297  }
298  else
299  return static_cast<T> (value);
300  }
301 
302 private:
303 
304  // Computes a real-valued threshold for a max/min check.
305  template <class S>
306  static S
307  compute_threshold (S val, T orig_val)
308  {
309  val = xround (val); // Fool optimizations (maybe redundant)
310  // If val is even, but orig_val is odd, we're one unit off.
311  if (orig_val % 2 && val / 2 == xround (val / 2))
312  // FIXME: is this always correct?
313  val *= (static_cast<S> (1) - (std::numeric_limits<S>::epsilon () / 2));
314  return val;
315  }
316 
317 public:
318  // Convert a real number (check NaN and non-int).
319  template <class S>
320  static T
321  convert_real (const S& value)
322  {
323  // Compute proper thresholds.
324  static const S thmin = compute_threshold (static_cast<S> (min_val ()),
325  min_val ());
326  static const S thmax = compute_threshold (static_cast<S> (max_val ()),
327  max_val ());
328  if (xisnan (value))
329  {
330  return static_cast<T> (0);
331  }
332  else if (value < thmin)
333  {
334  return min_val ();
335  }
336  else if (value > thmax)
337  {
338  return max_val ();
339  }
340  else
341  {
342  S rvalue = xround (value);
343  return static_cast<T> (rvalue);
344  }
345  }
346 };
347 
348 // Saturated (homogeneous) integer arithmetics. The signed and unsigned
349 // implementations are significantly different, so we implement another layer
350 // and completely specialize. Arithmetics inherits from octave_int_base so that
351 // it can use its exceptions and truncation functions.
352 
353 template <class T, bool is_signed>
355 { };
356 
357 // Unsigned arithmetics. C++ standard requires it to be modular, so the
358 // overflows can be handled efficiently and reliably.
359 template <class T>
361 {
362 public:
363 
364  static T
365  abs (T x) { return x; }
366 
367  static T
368  signum (T x) { return x ? static_cast<T> (1) : static_cast<T> (0); }
369 
370  // Shifts do not overflow.
371  static T
372  rshift (T x, int n) { return x >> n; }
373 
374  static T
375  lshift (T x, int n) { return x << n; }
376 
377  static T
378  minus (T)
379  {
380  return static_cast<T> (0);
381  }
382 
383  // the overflow behaviour for unsigned integers is guaranteed by C/C++,
384  // so the following should always work.
385  static T
386  add (T x, T y)
387  {
388  T u = x + y;
389  if (u < x)
390  {
392  }
393  return u;
394  }
395 
396  static T
397  sub (T x, T y)
398  {
399  T u = x - y;
400  if (u > x)
401  {
402  u = 0;
403  }
404  return u;
405  }
406 
407  // Multiplication is done using promotion to wider integer type. If there is
408  // no suitable promotion type, this operation *MUST* be specialized.
409  static T mul (T x, T y) { return mul_internal (x, y); }
410 
411  static T
412  mul_internal (T x, T y)
413  {
414  // Promotion type for multiplication (if exists).
415  typedef typename query_integer_type<2*sizeof (T), false>::type mptype;
416  return octave_int_base<T>::truncate_int (static_cast<mptype> (x)
417  * static_cast<mptype> (y));
418  }
419 
420  // Division with rounding to nearest. Note that / and % are probably
421  // computed by a single instruction.
422  static T
423  div (T x, T y)
424  {
425  if (y != 0)
426  {
427  T z = x / y;
428  T w = x % y;
429  if (w >= y-w) z += 1;
430  return z;
431  }
432  else
433  {
434  return x ? octave_int_base<T>::max_val () : 0;
435  }
436  }
437 
438  // Remainder.
439  static T
440  rem (T x, T y)
441  {
442  return y != 0 ? x % y : 0;
443  }
444 
445  // Modulus. Note the weird y = 0 case for Matlab compatibility.
446  static T
447  mod (T x, T y)
448  {
449  return y != 0 ? x % y : x;
450  }
451 };
452 
453 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
454 
455 // Handle 64-bit multiply using long double
456 
457 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
458 
459 extern OCTAVE_API uint64_t
460 octave_external_uint64_uint64_mul (uint64_t, uint64_t);
461 
462 #endif
463 
464 template <>
465 inline uint64_t
467 {
468  uint64_t retval;
469 
470  long double p = static_cast<long double> (x) * static_cast<long double> (y);
471 
472  if (p > static_cast<long double> (octave_int_base<uint64_t>::max_val ()))
474  else
475  retval = static_cast<uint64_t> (p);
476 
477  return retval;
478 }
479 
480 template <>
481 inline uint64_t
482 octave_int_arith_base<uint64_t, false>::mul (uint64_t x, uint64_t y)
483 {
484 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
485  return octave_external_uint64_uint64_mul (x, y);
486 #else
487  return mul_internal (x, y);
488 #endif
489 }
490 
491 #else
492 
493 // Special handler for 64-bit integer multiply.
494 template <>
495 OCTAVE_API uint64_t
497 
498 #endif
499 
500 // Signed integer arithmetics.
501 // Rationale: If HAVE_FAST_INT_OPS is defined, the following conditions
502 // should hold:
503 // 1. Signed numbers are represented by twos complement
504 // (see <http://en.wikipedia.org/wiki/Two%27s_complement>)
505 // 2. static_cast to unsigned int counterpart works like interpreting
506 // the signed bit pattern as unsigned (and is thus zero-cost).
507 // 3. Signed addition and subtraction yield the same bit results as unsigned.
508 // (We use casts to prevent optimization interference, so there is no
509 // need for things like -ftrapv).
510 // 4. Bit operations on signed integers work like on unsigned integers,
511 // except for the shifts. Shifts are arithmetic.
512 //
513 // The above conditions are satisfied by most modern platforms. If
514 // HAVE_FAST_INT_OPS is defined, bit tricks and wraparound arithmetics are used
515 // to avoid conditional jumps as much as possible, thus being friendly to
516 // modern pipeline processor architectures.
517 // Otherwise, we fall back to a bullet-proof code that only uses assumptions
518 // guaranteed by the standard.
519 
520 template <class T>
522 {
523  // The corresponding unsigned type.
525 public:
526 
527  // Returns 1 for negative number, 0 otherwise.
528  static T
529  __signbit (T x)
530  {
531 #ifdef HAVE_FAST_INT_OPS
532  return static_cast<UT> (x) >> std::numeric_limits<T>::digits;
533 #else
534  return (x < 0) ? 1 : 0;
535 #endif
536  }
537 
538  static T
539  abs (T x)
540  {
541 #ifdef HAVE_FAST_INT_OPS
542  // This is close to how GCC does std::abs, but we can't just use std::abs,
543  // because its behaviour for INT_MIN is undefined and the compiler could
544  // discard the following test.
545  T m = x >> std::numeric_limits<T>::digits;
546  T y = (x ^ m) - m;
547  if (y < 0)
548  {
550  }
551  return y;
552 #else
553  // -INT_MAX is safe because C++ actually allows only three implementations
554  // of integers: sign & magnitude, ones complement and twos complement.
555  // The first test will, with modest optimizations, evaluate at compile
556  // time, and maybe eliminate the branch completely.
557  T y;
559  && x == octave_int_base<T>::min_val ())
560  {
562  }
563  else
564  y = (x < 0) ? -x : x;
565  return y;
566 #endif
567  }
568 
569  static T
570  signum (T x)
571  {
572  // With modest optimizations, this will compile without a jump.
573  return ((x > 0) ? 1 : 0) - __signbit (x);
574  }
575 
576  // FIXME: we do not have an authority what signed shifts should
577  // exactly do, so we define them the easy way. Note that Matlab does
578  // not define signed shifts.
579 
580  static T
581  rshift (T x, int n) { return x >> n; }
582 
583  static T
584  lshift (T x, int n) { return x << n; }
585 
586  // Minus has problems similar to abs.
587  static T
588  minus (T x)
589  {
590 #ifdef HAVE_FAST_INT_OPS
591  T y = -x;
592  if (y == octave_int_base<T>::min_val ())
593  {
594  --y;
595  }
596  return y;
597 #else
598  T y;
600  && x == octave_int_base<T>::min_val ())
601  {
603  }
604  else
605  y = -x;
606  return y;
607 #endif
608  }
609 
610  static T
611  add (T x, T y)
612  {
613 #ifdef HAVE_FAST_INT_OPS
614  // The typecasts do nothing, but they are here to prevent an optimizing
615  // compiler from interfering. Also, the signed operations on small types
616  // actually return int.
617  T u = static_cast<UT> (x) + static_cast<UT> (y);
618  T ux = u ^ x;
619  T uy = u ^ y;
620  if ((ux & uy) < 0)
621  {
622  u = octave_int_base<T>::max_val () + __signbit (~u);
623  }
624  return u;
625 #else
626  // We shall carefully avoid anything that may overflow.
627  T u;
628  if (y < 0)
629  {
630  if (x < octave_int_base<T>::min_val () - y)
631  {
633  }
634  else
635  u = x + y;
636  }
637  else
638  {
639  if (x > octave_int_base<T>::max_val () - y)
640  {
642  }
643  else
644  u = x + y;
645  }
646 
647  return u;
648 #endif
649  }
650 
651  // This is very similar to addition.
652  static T
653  sub (T x, T y)
654  {
655 #ifdef HAVE_FAST_INT_OPS
656  // The typecasts do nothing, but they are here to prevent an optimizing
657  // compiler from interfering. Also, the signed operations on small types
658  // actually return int.
659  T u = static_cast<UT> (x) - static_cast<UT> (y);
660  T ux = u ^ x;
661  T uy = u ^ ~y;
662  if ((ux & uy) < 0)
663  {
664  u = octave_int_base<T>::max_val () + __signbit (~u);
665  }
666  return u;
667 #else
668  // We shall carefully avoid anything that may overflow.
669  T u;
670  if (y < 0)
671  {
672  if (x > octave_int_base<T>::max_val () + y)
673  {
675  }
676  else
677  u = x - y;
678  }
679  else
680  {
681  if (x < octave_int_base<T>::min_val () + y)
682  {
684  }
685  else
686  u = x - y;
687  }
688 
689  return u;
690 #endif
691  }
692 
693  // Multiplication is done using promotion to wider integer type. If there is
694  // no suitable promotion type, this operation *MUST* be specialized.
695  static T mul (T x, T y) { return mul_internal (x, y); }
696 
697  static T
698  mul_internal (T x, T y)
699  {
700  // Promotion type for multiplication (if exists).
701  typedef typename query_integer_type<2*sizeof (T), true>::type mptype;
702  return octave_int_base<T>::truncate_int (static_cast<mptype> (x)
703  * static_cast<mptype> (y));
704  }
705 
706  // Division.
707  static T
708  div (T x, T y)
709  {
710  T z;
711  if (y == 0)
712  {
713  if (x < 0)
715  else if (x != 0)
717  else
718  z = 0;
719  }
720  else if (y < 0)
721  {
722  // This is a special case that overflows as well.
723  if (y == -1 && x == octave_int_base<T>::min_val ())
724  {
726  }
727  else
728  {
729  z = x / y;
730  // Can't overflow, but std::abs (x) can!
731  T w = -octave_int_abs (x % y);
732  if (w <= y - w)
733  z -= 1 - (__signbit (x) << 1);
734  }
735  }
736  else
737  {
738  z = x / y;
739  // FIXME: this is a workaround due to MSVC's absence of
740  // std::abs (int64_t). The call to octave_int_abs can't
741  // overflow, but std::abs (x) can!
742  T w = octave_int_abs (x % y);
743 
744  if (w >= y - w)
745  z += 1 - (__signbit (x) << 1);
746  }
747  return z;
748  }
749 
750  // Remainder.
751  static T
752  rem (T x, T y)
753  {
754  return y != 0 ? x % y : 0;
755  }
756 
757  // Modulus. Note the weird y = 0 case for Matlab compatibility.
758  static T
759  mod (T x, T y)
760  {
761  if (y != 0)
762  {
763  T r = x % y;
764  return ((r < 0) != (y < 0)) ? r + y : r;
765  }
766  else
767  return x;
768  }
769 };
770 
771 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
772 
773 // Handle 64-bit multiply using long double
774 
775 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
776 
777 extern OCTAVE_API int64_t
778 octave_external_int64_int64_mul (int64_t, int64_t);
779 
780 #endif
781 
782 template <>
783 inline int64_t
785 {
786  int64_t retval;
787 
788  long double p = static_cast<long double> (x) * static_cast<long double> (y);
789 
790  // NOTE: We could maybe do it with a single branch if HAVE_FAST_INT_OPS,
791  // but it would require one more runtime conversion, so the question is
792  // whether it would really be faster.
793  if (p > static_cast<long double> (octave_int_base<int64_t>::max_val ()))
795  else if (p < static_cast<long double> (octave_int_base<int64_t>::min_val ()))
797  else
798  retval = static_cast<int64_t> (p);
799 
800  return retval;
801 }
802 
803 template <>
804 inline int64_t
805 octave_int_arith_base<int64_t, true>::mul (int64_t x, int64_t y)
806 {
807 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
808  return octave_external_int64_int64_mul (x, y);
809 #else
810  return mul_internal (x, y);
811 #endif
812 }
813 
814 #else
815 
816 // Special handler for 64-bit integer multiply.
817 template <>
818 OCTAVE_API int64_t
820 
821 #endif
822 
823 // This class simply selects the proper arithmetics.
824 template<class T>
826  : public octave_int_arith_base<T, std::numeric_limits<T>::is_signed>
827 { };
828 
829 template <class T>
830 class
832 {
833 public:
834  typedef T val_type;
835 
836  octave_int (void) : ival () { }
837 
838  octave_int (T i) : ival (i) { }
839 
840  // Always treat characters as unsigned.
841  octave_int (char c)
842  : ival (octave_int_base<T>::truncate_int (static_cast<unsigned char> (c)))
843  { }
844 
845  octave_int (double d) : ival (octave_int_base<T>::convert_real (d)) { }
846 
847  octave_int (float d) : ival (octave_int_base<T>::convert_real (d)) { }
848 
849 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
850  octave_int (long double d) : ival (octave_int_base<T>::convert_real (d)) { }
851 #endif
852 
853  octave_int (bool b) : ival (b) { }
854 
855  template <class U>
856  octave_int (const U& i) : ival(octave_int_base<T>::truncate_int (i)) { }
857 
858  template <class U>
860  : ival (octave_int_base<T>::truncate_int (i.value ())) { }
861 
862  octave_int (const octave_int<T>& i) : ival (i.ival) { }
863 
864  octave_int& operator = (const octave_int<T>& i)
865  {
866  ival = i.ival;
867  return *this;
868  }
869 
870  T value (void) const { return ival; }
871 
872  const unsigned char * iptr (void) const
873  { return reinterpret_cast<const unsigned char *> (& ival); }
874 
875  bool operator ! (void) const { return ! ival; }
876 
877  bool bool_value (void) const { return static_cast<bool> (value ()); }
878 
879  char char_value (void) const { return static_cast<char> (value ()); }
880 
881  double double_value (void) const { return static_cast<double> (value ()); }
882 
883  float float_value (void) const { return static_cast<float> (value ()); }
884 
885  operator T (void) const { return value (); }
886 
887  // char and bool operators intentionally omitted.
888 
889  operator double (void) const { return double_value (); }
890 
891  operator float (void) const { return float_value (); }
892 
894  operator + () const
895  { return *this; }
896 
897  // unary operators & mappers
898 #define OCTAVE_INT_UN_OP(OPNAME,NAME) \
899  inline octave_int<T> \
900  OPNAME () const \
901  { return octave_int_arith<T>::NAME (ival); }
902 
903  OCTAVE_INT_UN_OP(operator -, minus)
906 
907 #undef OCTAVE_INT_UN_OP
908 
909 // Homogeneous binary integer operations.
910 #define OCTAVE_INT_BIN_OP(OP, NAME, ARGT) \
911  inline octave_int<T> \
912  operator OP (const ARGT& y) const \
913  { return octave_int_arith<T>::NAME (ival, y); } \
914  inline octave_int<T>& \
915  operator OP##= (const ARGT& y) \
916  { \
917  ival = octave_int_arith<T>::NAME (ival, y); \
918  return *this; \
919  }
920 
926  OCTAVE_INT_BIN_OP(<<, lshift, int)
927  OCTAVE_INT_BIN_OP(>>, rshift, int)
928 
929 #undef OCTAVE_INT_BIN_OP
930 
931  static octave_int<T> min (void) { return std::numeric_limits<T>::min (); }
932  static octave_int<T> max (void) { return std::numeric_limits<T>::max (); }
933 
934  static int nbits (void) { return std::numeric_limits<T>::digits; }
935 
936  static int byte_size (void) { return sizeof (T); }
937 
938  static const char *type_name ();
939 
940  // The following are provided for convenience.
941  static const octave_int zero, one;
942 
943  // Unsafe. This function exists to support the MEX interface.
944  // You should not use it anywhere else.
945  void *mex_get_data (void) const { return const_cast<T *> (&ival); }
946 
947 private:
948 
949  T ival;
950 };
951 
952 template <class T>
953 inline octave_int<T>
954 rem (const octave_int<T>& x, const octave_int<T>& y)
955 { return octave_int_arith<T>::rem (x.value (), y.value ()); }
956 
957 template <class T>
958 inline octave_int<T>
959 mod (const octave_int<T>& x, const octave_int<T>& y)
960 { return octave_int_arith<T>::mod (x.value (), y.value ()); }
961 
962 // No mixed integer binary operations!
963 
964 template <class T>
965 inline bool
967 { return false; }
968 
969 // FIXME: can/should any of these be inline?
970 
971 template <class T>
972 extern OCTAVE_API octave_int<T>
973 pow (const octave_int<T>&, const octave_int<T>&);
974 
975 template <class T>
976 extern OCTAVE_API octave_int<T>
977 pow (const double& a, const octave_int<T>& b);
978 
979 template <class T>
980 extern OCTAVE_API octave_int<T>
981 pow (const octave_int<T>& a, const double& b);
982 
983 template <class T>
984 extern OCTAVE_API octave_int<T>
985 pow (const float& a, const octave_int<T>& b);
986 
987 template <class T>
988 extern OCTAVE_API octave_int<T>
989 pow (const octave_int<T>& a, const float& b);
990 
991 // FIXME: Do we really need a differently named single-precision
992 // function integer power function here instead of an overloaded
993 // one?
994 template <class T>
995 extern OCTAVE_API octave_int<T>
996 powf (const float& a, const octave_int<T>& b);
997 
998 template <class T>
999 extern OCTAVE_API octave_int<T>
1000 powf (const octave_int<T>& a, const float& b);
1001 
1002 // Binary relations
1003 
1004 #define OCTAVE_INT_CMP_OP(OP, NAME) \
1005  template<class T1, class T2> \
1006  inline bool \
1007  operator OP (const octave_int<T1>& x, const octave_int<T2>& y) \
1008  { return octave_int_cmp_op::op<octave_int_cmp_op::NAME, T1, T2> \
1009  (x.value (), y.value ()); }
1010 
1017 
1018 #undef OCTAVE_INT_CMP_OP
1019 
1020 template <class T>
1021 inline std::ostream&
1022 operator << (std::ostream& os, const octave_int<T>& ival)
1023 {
1024  os << ival.value ();
1025  return os;
1026 }
1027 
1028 template <class T>
1029 inline std::istream&
1030 operator >> (std::istream& is, octave_int<T>& ival)
1031 {
1032  T tmp = 0;
1033  is >> tmp;
1034  ival = tmp;
1035  return is;
1036 }
1037 
1038 // We need to specialise for char and unsigned char because
1039 // std::operator<< and std::operator>> are overloaded to input and
1040 // output the ASCII character values instead of a representation of
1041 // their numerical value (e.g. os << char(10) outputs a space instead
1042 // of outputting the characters '1' and '0')
1043 
1044 template <>
1045 inline std::ostream&
1046 operator << (std::ostream& os, const octave_int<int8_t>& ival)
1047 {
1048  os << static_cast<int> (ival.value ());
1049  return os;
1050 }
1051 
1052 template <>
1053 inline std::ostream&
1054 operator << (std::ostream& os, const octave_int<uint8_t>& ival)
1055 {
1056  os << static_cast<unsigned int> (ival.value ());
1057  return os;
1058 }
1059 
1060 
1061 template <>
1062 inline std::istream&
1063 operator >> (std::istream& is, octave_int<int8_t>& ival)
1064 {
1065  int tmp = 0;
1066  is >> tmp;
1067  ival = static_cast<int8_t> (tmp);
1068  return is;
1069 }
1070 
1071 template <>
1072 inline std::istream&
1073 operator >> (std::istream& is, octave_int<uint8_t>& ival)
1074 {
1075  unsigned int tmp = 0;
1076  is >> tmp;
1077  ival = static_cast<uint8_t> (tmp);
1078  return is;
1079 }
1080 
1081 
1082 // Bitwise operations
1083 
1084 #define OCTAVE_INT_BITCMP_OP(OP) \
1085  template <class T> \
1086  octave_int<T> \
1087  operator OP (const octave_int<T>& x, const octave_int<T>& y) \
1088  { return x.value () OP y.value (); }
1089 
1093 
1094 #undef OCTAVE_INT_BITCMP_OP
1095 
1096 // General bit shift.
1097 template <class T>
1099 bitshift (const octave_int<T>& a, int n,
1100  const octave_int<T>& mask = std::numeric_limits<T>::max ())
1101 {
1102  if (n > 0)
1103  return (a << n) & mask;
1104  else if (n < 0)
1105  return (a >> -n) & mask;
1106  else
1107  return a & mask;
1108 }
1109 
1114 
1119 
1120 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
1121 
1122 #define DECLARE_EXTERNAL_LONG_DOUBLE_OP(T, OP) \
1123  extern OCTAVE_API T \
1124  external_double_ ## T ## _ ## OP (double x, T y); \
1125  extern OCTAVE_API T \
1126  external_ ## T ## _double_ ## OP (T x, double y)
1127 
1128 #define DECLARE_EXTERNAL_LONG_DOUBLE_OPS(T) \
1129  DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, add); \
1130  DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, sub); \
1131  DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, mul); \
1132  DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, div)
1133 
1134 DECLARE_EXTERNAL_LONG_DOUBLE_OPS (octave_int64);
1135 DECLARE_EXTERNAL_LONG_DOUBLE_OPS (octave_uint64);
1136 
1137 #endif
1138 
1139 #define OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
1140  template <class T> \
1141  inline octave_int<T> \
1142  operator OP (const octave_int<T>& x, const double& y) \
1143  { return octave_int<T> (static_cast<double> (x) OP y); } \
1144  template <class T> \
1145  inline octave_int<T> \
1146  operator OP (const double& x, const octave_int<T>& y) \
1147  { return octave_int<T> (x OP static_cast<double> (y)); }
1148 
1149 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
1150 // Handle mixed op using long double
1151 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
1152 #define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \
1153  OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
1154  template <> \
1155  inline octave_int64 \
1156  operator OP (const double& x, const octave_int64& y) \
1157  { \
1158  return external_double_octave_int64_ ## NAME (x, y); \
1159  } \
1160  template <> \
1161  inline octave_uint64 \
1162  operator OP (const double& x, const octave_uint64& y) \
1163  { \
1164  return external_double_octave_uint64_ ## NAME (x, y); \
1165  } \
1166  template <> \
1167  inline octave_int64 \
1168  operator OP (const octave_int64& x, const double& y) \
1169  { \
1170  return external_octave_int64_double_ ## NAME (x, y); \
1171  } \
1172  template <> \
1173  inline octave_uint64 \
1174  operator OP (const octave_uint64& x, const double& y) \
1175  { \
1176  return external_octave_uint64_double_ ## NAME (x, y); \
1177  }
1178 #else
1179 #define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \
1180  OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
1181  template <> \
1182  inline octave_int64 \
1183  operator OP (const double& x, const octave_int64& y) \
1184  { \
1185  return octave_int64 (x OP static_cast<long double> (y.value ())); \
1186  } \
1187  template <> \
1188  inline octave_uint64 \
1189  operator OP (const double& x, const octave_uint64& y) \
1190  { \
1191  return octave_uint64 (x OP static_cast<long double> (y.value ())); \
1192  } \
1193  template <> \
1194  inline octave_int64 \
1195  operator OP (const octave_int64& x, const double& y) \
1196  { \
1197  return octave_int64 (static_cast<long double> (x.value ()) OP y); \
1198  } \
1199  template <> \
1200  inline octave_uint64 \
1201  operator OP (const octave_uint64& x, const double& y) \
1202  { \
1203  return octave_uint64 (static_cast<long double> (x.value ()) OP y); \
1204  }
1205 #endif
1206 #else
1207 // external handlers
1208 #define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \
1209  OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
1210  template <> \
1211  OCTAVE_API octave_int64 \
1212  operator OP (const double&, const octave_int64&); \
1213  template <> \
1214  OCTAVE_API octave_uint64 \
1215  operator OP (const double&, const octave_uint64&); \
1216  template <> \
1217  OCTAVE_API octave_int64 \
1218  operator OP (const octave_int64&, const double&); \
1219  template <> \
1220  OCTAVE_API octave_uint64 \
1221  operator OP (const octave_uint64&, const double&);
1222 
1223 #endif
1224 
1229 
1230 #undef OCTAVE_INT_DOUBLE_BIN_OP0
1231 #undef OCTAVE_INT_DOUBLE_BIN_OP
1232 #undef DECLARE_EXTERNAL_LONG_DOUBLE_OP
1233 #undef DECLARE_EXTERNAL_LONG_DOUBLE_OPS
1234 
1235 #define OCTAVE_INT_DOUBLE_CMP_OP(OP,NAME) \
1236  template <class T> \
1237  inline bool \
1238  operator OP (const octave_int<T>& x, const double& y) \
1239  { return octave_int_cmp_op::mop<octave_int_cmp_op::NAME> (x.value (), y); } \
1240  template <class T> \
1241  inline bool \
1242  operator OP (const double& x, const octave_int<T>& y) \
1243  { return octave_int_cmp_op::mop<octave_int_cmp_op::NAME> (x, y.value ()); }
1244 
1251 
1252 #undef OCTAVE_INT_DOUBLE_CMP_OP
1253 
1254 // Floats are handled by simply converting to doubles.
1255 
1256 #define OCTAVE_INT_FLOAT_BIN_OP(OP) \
1257  template <class T> \
1258  inline octave_int<T> \
1259  operator OP (const octave_int<T>& x, float y) \
1260  { return x OP static_cast<double> (y); } \
1261  template <class T> \
1262  inline octave_int<T> \
1263  operator OP (float x, const octave_int<T>& y) \
1264  { return static_cast<double> (x) OP y; }
1265 
1270 
1271 #undef OCTAVE_INT_FLOAT_BIN_OP
1272 
1273 #define OCTAVE_INT_FLOAT_CMP_OP(OP) \
1274  template <class T> \
1275  inline bool \
1276  operator OP (const octave_int<T>& x, const float& y) \
1277  { return x OP static_cast<double> (y); } \
1278  template <class T> \
1279  bool \
1280  operator OP (const float& x, const octave_int<T>& y) \
1281  { return static_cast<double> (x) OP y; }
1282 
1289 
1290 #undef OCTAVE_INT_FLOAT_CMP_OP
1291 
1292 template <class T>
1294 xmax (const octave_int<T>& x, const octave_int<T>& y)
1295 {
1296  const T xv = x.value ();
1297  const T yv = y.value ();
1298  return octave_int<T> (xv >= yv ? xv : yv);
1299 }
1300 
1301 template <class T>
1303 xmin (const octave_int<T>& x, const octave_int<T>& y)
1304 {
1305  const T xv = x.value ();
1306  const T yv = y.value ();
1307  return octave_int<T> (xv <= yv ? xv : yv);
1308 }
1309 
1310 #endif
octave_int< uint32_t > octave_uint32
bool bool_value(void) const
Definition: oct-inttypes.h:877
static const bool t2sig
Definition: oct-inttypes.h:117
static const bool registered
Definition: oct-inttypes.h:53
#define OCTAVE_INT_CMP_OP(OP, NAME)
#define OCTAVE_INT_BITCMP_OP(OP)
#define OCTAVE_INT_BIN_OP(OP, NAME, ARGT)
Definition: oct-inttypes.h:910
double xround(double x)
Definition: lo-mappers.cc:63
OCTAVE_API octave_int< T > pow(const octave_int< T > &, const octave_int< T > &)
octave_int< T > xmax(const octave_int< T > &x, const octave_int< T > &y)
#define OCTAVE_INT_FLOAT_BIN_OP(OP)
static bool op(utype x, stype y)
Definition: oct-inttypes.h:141
query_integer_type< size, true >::type stype
Definition: oct-inttypes.h:133
octave_int(float d)
Definition: oct-inttypes.h:847
static int nbits(void)
Definition: oct-inttypes.h:934
static const int psize
Definition: oct-inttypes.h:120
octave_int(char c)
Definition: oct-inttypes.h:841
octave_int(const octave_int< U > &i)
Definition: oct-inttypes.h:859
octave_int< T > mod(const octave_int< T > &x, const octave_int< T > &y)
Definition: oct-inttypes.h:959
double double_value(void) const
Definition: oct-inttypes.h:881
T octave_int_abs(T x)
Definition: oct-inttypes.h:46
octave_int< int16_t > octave_int16
static T min_val()
Definition: oct-inttypes.h:262
std::istream & operator>>(std::istream &is, octave_int< T > &ival)
char char_value(void) const
Definition: oct-inttypes.h:879
static T max_val()
Definition: oct-inttypes.h:263
query_integer_type< sizeof(T), false >::type UT
Definition: oct-inttypes.h:524
static const bool psig
Definition: oct-inttypes.h:118
query_integer_type< psize, psig >::type type
Definition: oct-inttypes.h:124
#define REGISTER_OCTAVE_CMP_OP(NM, OP)
Definition: oct-inttypes.h:80
F77_RET_T const double const double double * d
static T truncate_int(const S &value)
Definition: oct-inttypes.h:268
bool xisnan(const octave_int< T > &)
Definition: oct-inttypes.h:966
octave_int< int32_t > octave_int32
double signum(double x)
Definition: lo-mappers.cc:80
query_integer_type< size, false >::type utype
Definition: oct-inttypes.h:132
octave_int< uint16_t > octave_uint16
static T rshift(T x, int n)
Definition: oct-inttypes.h:581
void * mex_get_data(void) const
Definition: oct-inttypes.h:945
static S compute_threshold(S val, T orig_val)
Definition: oct-inttypes.h:307
static bool op(T1 x, T2 y)
Definition: oct-inttypes.h:158
static bool op(stype x, stype y)
Definition: oct-inttypes.h:137
std::complex< double > w(std::complex< double > z, double relerr=0)
#define OCTAVE_INT_DOUBLE_CMP_OP(OP, NAME)
octave_int< int64_t > octave_int64
OCTAVE_API octave_int< T > powf(const float &a, const octave_int< T > &b)
static octave_int< T > max(void)
Definition: oct-inttypes.h:932
octave_int(void)
Definition: oct-inttypes.h:836
static T convert_real(const S &value)
Definition: oct-inttypes.h:321
static T lshift(T x, int n)
Definition: oct-inttypes.h:584
#define OCTAVE_INT_UN_OP(OPNAME, NAME)
Definition: oct-inttypes.h:898
const unsigned char * iptr(void) const
Definition: oct-inttypes.h:872
#define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME)
octave_int< uint64_t > octave_uint64
#define DEFINE_LONG_DOUBLE_CMP_OP(T)
Definition: oct-inttypes.h:231
T value(void) const
Definition: oct-inttypes.h:870
octave_int< T > xmin(const octave_int< T > &x, const octave_int< T > &y)
static bool op(utype x, utype y)
Definition: oct-inttypes.h:135
static const bool t1sig
Definition: oct-inttypes.h:116
static bool mop(T x, double y)
Definition: oct-inttypes.h:171
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:233
#define REGISTER_OCTAVE_CONST_OP(NM, value)
Definition: oct-inttypes.h:92
#define REGISTER_INT_TYPE(TYPE)
Definition: oct-inttypes.h:58
static octave_int< T > min(void)
Definition: oct-inttypes.h:931
static bool op(stype x, utype y)
Definition: oct-inttypes.h:139
octave_int(double d)
Definition: oct-inttypes.h:845
static const octave_int zero
Definition: oct-inttypes.h:941
octave_int< T > rem(const octave_int< T > &x, const octave_int< T > &y)
Definition: oct-inttypes.h:954
static T mul_internal(T x, T y)
Definition: oct-inttypes.h:698
octave_int< T > bitshift(const octave_int< T > &a, int n, const octave_int< T > &mask=std::numeric_limits< T >::max())
#define OCTAVE_INT_FLOAT_CMP_OP(OP)
octave_int(bool b)
Definition: oct-inttypes.h:853
static int byte_size(void)
Definition: oct-inttypes.h:936
octave_value operator!(const octave_value &a)
Definition: ov.h:1293
octave_int< T > operator+(const octave_int< T > &x, const double &y)
octave_int< uint8_t > octave_uint8
octave_int(T i)
Definition: oct-inttypes.h:838
static const bool pint
Definition: oct-inttypes.h:114
octave_int< int8_t > octave_int8
octave_int(const octave_int< T > &i)
Definition: oct-inttypes.h:862
static bool mop(double x, T y)
Definition: oct-inttypes.h:176
T abs(T x)
Definition: pr-output.cc:3062
uint64_t mul_internal(uint64_t x, uint64_t y)
octave_int(const U &i)
Definition: oct-inttypes.h:856
F77_RET_T const double * x
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:210
float float_value(void) const
Definition: oct-inttypes.h:883