GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
oct-inttypes.h
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2004-2018 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
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License 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 <https://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if ! defined (octave_oct_inttypes_h)
25 #define octave_oct_inttypes_h 1
26 
27 #include "octave-config.h"
28 
29 #include <cmath>
30 #include <cstdlib>
31 
32 #include <iosfwd>
33 #include <limits>
34 
35 #include "lo-mappers.h"
36 #include "lo-traits.h"
37 
38 template <typename T> class octave_int;
39 
44 
49 
50 #if defined (OCTAVE_INT_USE_LONG_DOUBLE)
51 
52 namespace octave
53 {
54  namespace math
55  {
56  inline long double round (long double x) { return std::roundl (x); }
57 
58  inline long double isnan (long double x) { return isnan (static_cast<double> (x)); }
59  }
60 }
61 
62 #if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
63 
64 OCTAVE_DEPRECATED (4.2, "use 'octave::math::round' instead")
65 inline long double xround (long double x) { return octave::math::round (x); }
66 
67 OCTAVE_DEPRECATED (4.2, "use 'octave::math::isnan' instead")
68 inline bool xisnan (long double x) { return octave::math::isnan (x); }
69 
70 #endif
71 
72 #endif
73 
74 // FIXME: we define this by our own because some compilers, such as
75 // MSVC, do not provide std::abs (int64_t) and std::abs (uint64_t). In
76 // the future, it should go away in favor of std::abs.
77 template <typename T>
78 inline T octave_int_abs (T x) { return (x >= 0 ? x : -x); }
79 
80 // Query for an integer type of certain sizeof, and signedness.
81 template <int qsize, bool qsigned>
83 {
84 public:
85  static const bool registered = false;
86  typedef void type; // Void shall result in a compile-time error if we
87  // attempt to use it in computations.
88 };
89 
90 #define REGISTER_INT_TYPE(TYPE) \
91  template <> \
92  class query_integer_type<sizeof (TYPE), std::numeric_limits<TYPE>::is_signed> \
93  { \
94  public: \
95  static const bool registered = true; \
96  typedef TYPE type; \
97  }
98 
99 // No two registered integers can share sizeof and signedness.
103 REGISTER_INT_TYPE (uint16_t);
105 REGISTER_INT_TYPE (uint32_t);
107 REGISTER_INT_TYPE (uint64_t);
108 
109 // Rationale: Comparators have a single static method, rel(), that returns the
110 // result of the binary relation. They also have two static boolean fields:
111 // ltval, gtval determine the value of x OP y if x < y, x > y, respectively.
112 #define REGISTER_OCTAVE_CMP_OP(NM,OP) \
113  class NM \
114  { \
115  public: \
116  static const bool ltval = (0 OP 1); \
117  static const bool gtval = (1 OP 0); \
118  template <typename T> \
119  static bool op (T x, T y) { return x OP y; } \
120  }
121 
122 // We also provide two special relations: ct, yielding always true, and cf,
123 // yielding always false.
124 #define REGISTER_OCTAVE_CONST_OP(NM,value) \
125  class NM \
126  { \
127  public: \
128  static const bool ltval = value; \
129  static const bool gtval = value; \
130  template <typename T> \
131  static bool op (T, T) { return value; } \
132  }
133 
134 // Handles non-homogeneous integer comparisons. Avoids doing useless tests.
136 {
137  // This determines a suitable promotion type for T1 when meeting T2 in a
138  // binary relation. If promotion to int or T2 is safe, it is used.
139  // Otherwise, the signedness of T1 is preserved and it is widened if T2 is
140  // wider.
141  // Notice that if this is applied to both types, they must end up with equal
142  // size.
143  template <typename T1, typename T2>
144  class prom
145  {
146  // Promote to int?
147  static const bool pint = (sizeof (T1) < sizeof (int)
148  && sizeof (T2) < sizeof (int));
149  static const bool t1sig = std::numeric_limits<T1>::is_signed;
150  static const bool t2sig = std::numeric_limits<T2>::is_signed;
151  static const bool psig =
152  (pint || (sizeof (T2) > sizeof (T1) && t2sig) || t1sig);
153  static const int psize =
154  (pint ? sizeof (int) : (sizeof (T2) > sizeof (T1)
155  ? sizeof (T2) : sizeof (T1)));
156  public:
158  };
159 
160  // Implements comparisons between two types of equal size but
161  // possibly different signedness.
162  template <typename xop, int size>
163  class uiop
164  {
167  public:
168  static bool op (utype x, utype y)
169  { return xop::op (x, y); }
170  static bool op (stype x, stype y)
171  { return xop::op (x, y); }
172  static bool op (stype x, utype y)
173  { return (x < 0) ? xop::ltval : xop::op (static_cast<utype> (x), y); }
174  static bool op (utype x, stype y)
175  { return (y < 0) ? xop::gtval : xop::op (x, static_cast<utype> (y)); }
176  };
177 
178 public:
187 
188  // Universal comparison operation.
189  template <typename xop, typename T1, typename T2>
190  static bool
191  op (T1 x, T2 y)
192  {
193  typedef typename prom<T1, T2>::type PT1;
194  typedef typename prom<T2, T1>::type PT2;
195  return uiop<xop, sizeof (PT1)>::op (static_cast<PT1> (x),
196  static_cast<PT2> (y));
197  }
198 
199 public:
200 
201  // Mixed comparisons
202  template <typename xop, typename T>
203  static bool
204  mop (T x, double y)
205  { return xop::op (static_cast<double> (x), y); }
206 
207  template <typename xop, typename T>
208  static bool
209  mop (double x, T y)
210  { return xop::op (x, static_cast<double> (y)); }
211 
212 #if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED)
213 # define DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS(T) \
214  template <typename xop> static OCTAVE_API bool \
215  external_mop (double, T); \
216  template <typename xop> static OCTAVE_API bool \
217  external_mop (T, double)
218 
219  DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS (int64_t);
220  DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS (uint64_t);
221 #endif
222 
223  // Typecasting to doubles won't work properly for 64-bit integers --
224  // they lose precision.
225  // If we have long doubles, use them...
226 #if defined (OCTAVE_INT_USE_LONG_DOUBLE)
227 # if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED)
228 # define DEFINE_LONG_DOUBLE_CMP_OP(T) \
229  template <typename xop> \
230  static bool \
231  mop (double x, T y) \
232  { \
233  return external_mop<xop> (x, y); \
234  } \
235  template <typename xop> \
236  static bool \
237  mop (T x, double y) \
238  { \
239  return external_mop<xop> (x, y); \
240  }
241 # else
242 # define DEFINE_LONG_DOUBLE_CMP_OP(T) \
243  template <typename xop> \
244  static bool \
245  mop (double x, T y) \
246  { \
247  return xop::op (static_cast<long double> (x), \
248  static_cast<long double> (y)); \
249  } \
250  template <typename xop> \
251  static bool \
252  mop (T x, double y) \
253  { \
254  return xop::op (static_cast<long double> (x), \
255  static_cast<long double> (y)); \
256  }
257 # endif
258 #else
259  // ... otherwise, use external handlers
260 
261  // FIXME: We could declare directly the mop methods as external,
262  // but we can't do this because bugs in gcc (<= 4.3) prevent
263  // explicit instantiations later in that case.
264 # define DEFINE_LONG_DOUBLE_CMP_OP(T) \
265  template <typename xop> static OCTAVE_API bool \
266  emulate_mop (double, T); \
267  template <typename xop> \
268  static bool \
269  mop (double x, T y) \
270  { \
271  return emulate_mop<xop> (x, y); \
272  } \
273  template <typename xop> static OCTAVE_API bool \
274  emulate_mop (T, double); \
275  template <typename xop> \
276  static bool \
277  mop (T x, double y) \
278  { \
279  return emulate_mop<xop> (x, y); \
280  }
281 #endif
282 
285 
286 #undef DEFINE_LONG_DOUBLE_CMP_OP
287 };
288 
289 // Base integer class. No data, just conversion methods and exception flags.
290 template <typename T>
292 {
293 public:
294 
295  static T min_val () { return std::numeric_limits<T>::min (); }
296  static T max_val () { return std::numeric_limits<T>::max (); }
297 
298  // Convert integer value.
299  template <typename S>
300  static T
301  truncate_int (const S& value)
302  {
303  // An exhaustive test whether the max and/or min check can be omitted.
304  static const bool t_is_signed = std::numeric_limits<T>::is_signed;
305  static const bool s_is_signed = std::numeric_limits<S>::is_signed;
306  static const int t_size = sizeof (T);
307  static const int s_size = sizeof (S);
308 
309  static const bool omit_chk_min =
310  (! s_is_signed || (t_is_signed && t_size >= s_size));
311  static const bool omit_chk_max =
312  (t_size > s_size || (t_size == s_size
313  && (! t_is_signed || s_is_signed)));
314  // If the check can be omitted, substitute constant false relation.
315  typedef octave_int_cmp_op::cf cf;
316  typedef octave_int_cmp_op::lt lt;
317  typedef octave_int_cmp_op::gt gt;
318  typedef typename if_then_else<omit_chk_min, cf, lt>::result chk_min;
319  typedef typename if_then_else<omit_chk_max, cf, gt>::result chk_max;
320 
321  // Efficiency of the following depends on inlining and dead code
322  // elimination, but that should be a piece of cake for most compilers.
323  if (chk_min::op (value, static_cast<S> (min_val ())))
324  {
325  return min_val ();
326  }
327  else if (chk_max::op (value, static_cast<S> (max_val ())))
328  {
329  return max_val ();
330  }
331  else
332  return static_cast<T> (value);
333  }
334 
335 private:
336 
337  // Computes a real-valued threshold for a max/min check.
338  template <typename S>
339  static S
340  compute_threshold (S val, T orig_val)
341  {
342  val = octave::math::round (val); // Fool optimizations (maybe redundant)
343  // If val is even, but orig_val is odd, we're one unit off.
344  if (orig_val % 2 && val / 2 == octave::math::round (val / 2))
345  // FIXME: is this always correct?
346  val *= (static_cast<S> (1) - (std::numeric_limits<S>::epsilon () / 2));
347  return val;
348  }
349 
350 public:
351 
352  // Convert a real number (check NaN and non-int).
353  template <typename S>
354  static T
355  convert_real (const S& value);
356 };
357 
358 // Saturated (homogeneous) integer arithmetics. The signed and unsigned
359 // implementations are significantly different, so we implement another layer
360 // and completely specialize. Arithmetics inherits from octave_int_base so
361 // that it can use its exceptions and truncation functions.
362 
363 template <typename T, bool is_signed>
365 { };
366 
367 // Unsigned arithmetics. C++ standard requires it to be modular, so the
368 // overflows can be handled efficiently and reliably.
369 template <typename T>
371 {
372 public:
373 
374  static T
375  abs (T x) { return x; }
376 
377  static T
378  signum (T x) { return x ? static_cast<T> (1) : static_cast<T> (0); }
379 
380  // Shifts do not overflow.
381  static T
382  rshift (T x, int n) { return x >> n; }
383 
384  static T
385  lshift (T x, int n) { return x << n; }
386 
387  static T
388  minus (T)
389  {
390  return static_cast<T> (0);
391  }
392 
393  // the overflow behavior for unsigned integers is guaranteed by C/C++,
394  // so the following should always work.
395  static T
396  add (T x, T y)
397  {
398  T u = x + y;
399  if (u < x)
400  {
402  }
403  return u;
404  }
405 
406  static T
407  sub (T x, T y)
408  {
409  T u = x - y;
410  if (u > x)
411  {
412  u = 0;
413  }
414  return u;
415  }
416 
417  // Multiplication is done using promotion to wider integer type. If there is
418  // no suitable promotion type, this operation *MUST* be specialized.
419  static T mul (T x, T y) { return mul_internal (x, y); }
420 
421  static T
422  mul_internal (T x, T y)
423  {
424  // Promotion type for multiplication (if exists).
425  typedef typename query_integer_type<2*sizeof (T), false>::type mptype;
426  return octave_int_base<T>::truncate_int (static_cast<mptype> (x)
427  * static_cast<mptype> (y));
428  }
429 
430  // Division with rounding to nearest. Note that / and % are probably
431  // computed by a single instruction.
432  static T
433  div (T x, T y)
434  {
435  if (y != 0)
436  {
437  T z = x / y;
438  T w = x % y;
439  if (w >= y-w) z += 1;
440  return z;
441  }
442  else
443  {
444  return x ? octave_int_base<T>::max_val () : 0;
445  }
446  }
447 
448  // Remainder.
449  static T
450  rem (T x, T y)
451  {
452  return y != 0 ? x % y : 0;
453  }
454 
455  // Modulus. Note the weird y = 0 case for Matlab compatibility.
456  static T
457  mod (T x, T y)
458  {
459  return y != 0 ? x % y : x;
460  }
461 };
462 
463 #if defined (OCTAVE_INT_USE_LONG_DOUBLE)
464 
465 // Handle 64-bit multiply using long double
466 
467 #if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED)
468 
469 extern OCTAVE_API uint64_t
470 octave_external_uint64_uint64_mul (uint64_t, uint64_t);
471 
472 #endif
473 
474 template <>
475 inline uint64_t
477 {
478  uint64_t retval;
479 
480  long double p = static_cast<long double> (x) * static_cast<long double> (y);
481 
482  if (p > static_cast<long double> (octave_int_base<uint64_t>::max_val ()))
484  else
485  retval = static_cast<uint64_t> (p);
486 
487  return retval;
488 }
489 
490 template <>
491 inline uint64_t
493 {
494 #if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED)
495  return octave_external_uint64_uint64_mul (x, y);
496 #else
497  return mul_internal (x, y);
498 #endif
499 }
500 
501 #else
502 
503 // Special handler for 64-bit integer multiply.
504 template <>
505 OCTAVE_API uint64_t
507 
508 #endif
509 
510 template <typename T>
512 {
513  // The corresponding unsigned type.
515 public:
516 
517  // Returns 1 for negative number, 0 otherwise.
518  static T
520  {
521  return (x < 0) ? 1 : 0;
522  }
523 
524  static T
525  abs (T x)
526  {
527  // -INT_MAX is safe because C++ actually allows only three
528  // implementations of integers: sign & magnitude, ones complement
529  // and twos complement. The first test will, with modest
530  // optimizations, evaluate at compile time, and maybe eliminate
531  // the branch completely.
532 
536  : ((x < 0) ? -x : x));
537  }
538 
539  static T
540  signum (T x)
541  {
542  // With modest optimizations, this will compile without a jump.
543  return ((x > 0) ? 1 : 0) - __signbit (x);
544  }
545 
546  // FIXME: we do not have an authority what signed shifts should
547  // exactly do, so we define them the easy way. Note that Matlab does
548  // not define signed shifts.
549 
550  static T
551  rshift (T x, int n) { return x >> n; }
552 
553  static T
554  lshift (T x, int n) { return x << n; }
555 
556  // Minus has problems similar to abs.
557 
558  static T
559  minus (T x)
560  {
564  : -x);
565  }
566 
567  static T
568  add (T x, T y)
569  {
570  // Avoid anything that may overflow.
571 
572  return (y < 0
575  : x + y)
578  : x + y));
579  }
580 
581  static T
582  sub (T x, T y)
583  {
584  // Avoid anything that may overflow.
585 
586  return (y < 0
589  : x - y)
592  : x - y));
593  }
594 
595  // Multiplication is done using promotion to wider integer type. If there is
596  // no suitable promotion type, this operation *MUST* be specialized.
597  static T mul (T x, T y) { return mul_internal (x, y); }
598 
599  static T
600  mul_internal (T x, T y)
601  {
602  // Promotion type for multiplication (if exists).
603  typedef typename query_integer_type<2*sizeof (T), true>::type mptype;
604  return octave_int_base<T>::truncate_int (static_cast<mptype> (x)
605  * static_cast<mptype> (y));
606  }
607 
608  // Division.
609  static T
610  div (T x, T y)
611  {
612  T z;
613  if (y == 0)
614  {
615  if (x < 0)
617  else if (x != 0)
619  else
620  z = 0;
621  }
622  else if (y < 0)
623  {
624  // This is a special case that overflows as well.
625  if (y == -1 && x == octave_int_base<T>::min_val ())
626  {
628  }
629  else
630  {
631  z = x / y;
632  // Can't overflow, but std::abs (x) can!
633  T w = -octave_int_abs (x % y);
634  if (w <= y - w)
635  z -= 1 - (__signbit (x) << 1);
636  }
637  }
638  else
639  {
640  z = x / y;
641  // FIXME: this is a workaround due to MSVC's absence of
642  // std::abs (int64_t). The call to octave_int_abs can't
643  // overflow, but std::abs (x) can!
644  T w = octave_int_abs (x % y);
645 
646  if (w >= y - w)
647  z += 1 - (__signbit (x) << 1);
648  }
649  return z;
650  }
651 
652  // Remainder.
653  static T
654  rem (T x, T y)
655  {
656  return y != 0 ? x % y : 0;
657  }
658 
659  // Modulus. Note the weird y = 0 case for Matlab compatibility.
660  static T
661  mod (T x, T y)
662  {
663  if (y != 0)
664  {
665  T r = x % y;
666  return ((r < 0) != (y < 0)) ? r + y : r;
667  }
668  else
669  return x;
670  }
671 };
672 
673 #if defined (OCTAVE_INT_USE_LONG_DOUBLE)
674 
675 // Handle 64-bit multiply using long double
676 
677 #if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED)
678 
679 extern OCTAVE_API int64_t
680 octave_external_int64_int64_mul (int64_t, int64_t);
681 
682 #endif
683 
684 template <>
685 inline int64_t
687 {
688  int64_t retval;
689 
690  long double p = static_cast<long double> (x) * static_cast<long double> (y);
691 
692  if (p > static_cast<long double> (octave_int_base<int64_t>::max_val ()))
694  else if (p < static_cast<long double> (octave_int_base<int64_t>::min_val ()))
696  else
697  retval = static_cast<int64_t> (p);
698 
699  return retval;
700 }
701 
702 template <>
703 inline int64_t
705 {
706 #if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED)
707  return octave_external_int64_int64_mul (x, y);
708 #else
709  return mul_internal (x, y);
710 #endif
711 }
712 
713 #else
714 
715 // Special handler for 64-bit integer multiply.
716 template <>
717 OCTAVE_API int64_t
719 
720 #endif
721 
722 // This class simply selects the proper arithmetics.
723 template <typename T>
725 : public octave_int_arith_base<T, std::numeric_limits<T>::is_signed>
726 { };
727 
728 template <typename T>
729 class
731 {
732 public:
733  typedef T val_type;
734 
735  octave_int (void) : ival () { }
736 
737  octave_int (T i) : ival (i) { }
738 
739 #if defined (OCTAVE_HAVE_OVERLOAD_CHAR_INT8_TYPES)
740  // Always treat characters as unsigned.
741  octave_int (char c)
742  : ival (octave_int_base<T>::truncate_int (static_cast<unsigned char> (c)))
743  { }
744 #endif
745 
746  octave_int (double d) : ival (octave_int_base<T>::convert_real (d)) { }
747 
748  octave_int (float d) : ival (octave_int_base<T>::convert_real (d)) { }
749 
750 #if defined (OCTAVE_INT_USE_LONG_DOUBLE)
751  octave_int (long double d) : ival (octave_int_base<T>::convert_real (d)) { }
752 #endif
753 
754  octave_int (bool b) : ival (b) { }
755 
756  template <typename U>
757  octave_int (const U& i) : ival(octave_int_base<T>::truncate_int (i)) { }
758 
759  template <typename U>
761  : ival (octave_int_base<T>::truncate_int (i.value ())) { }
762 
763  octave_int (const octave_int<T>& i) : ival (i.ival) { }
764 
765  octave_int& operator = (const octave_int<T>& i)
766  {
767  ival = i.ival;
768  return *this;
769  }
770 
771  T value (void) const { return ival; }
772 
773  const unsigned char * iptr (void) const
774  { return reinterpret_cast<const unsigned char *> (& ival); }
775 
776  bool operator ! (void) const { return ! ival; }
777 
778  bool bool_value (void) const { return static_cast<bool> (value ()); }
779 
780  char char_value (void) const { return static_cast<char> (value ()); }
781 
782  double double_value (void) const { return static_cast<double> (value ()); }
783 
784  float float_value (void) const { return static_cast<float> (value ()); }
785 
786  operator T (void) const { return value (); }
787 
789  operator + () const
790  { return *this; }
791 
792  // unary operators & mappers
793 #define OCTAVE_INT_UN_OP(OPNAME,NAME) \
794  inline octave_int<T> \
795  OPNAME () const \
796  { \
797  return octave_int_arith<T>::NAME (ival); \
798  }
799 
800  OCTAVE_INT_UN_OP(operator -, minus)
803 
804 #undef OCTAVE_INT_UN_OP
805 
806 // Homogeneous binary integer operations.
807 #define OCTAVE_INT_BIN_OP(OP, NAME, ARGT) \
808  inline octave_int<T> \
809  operator OP (const ARGT& y) const \
810  { \
811  return octave_int_arith<T>::NAME (ival, y); \
812  } \
813  inline octave_int<T>& \
814  operator OP##= (const ARGT& y) \
815  { \
816  ival = octave_int_arith<T>::NAME (ival, y); \
817  return *this; \
818  }
819 
825  OCTAVE_INT_BIN_OP(<<, lshift, int)
826  OCTAVE_INT_BIN_OP(>>, rshift, int)
827 
828 #undef OCTAVE_INT_BIN_OP
829 
830  static octave_int<T> min (void) { return std::numeric_limits<T>::min (); }
831  static octave_int<T> max (void) { return std::numeric_limits<T>::max (); }
832 
833  static int nbits (void) { return std::numeric_limits<T>::digits; }
834 
835  static int byte_size (void) { return sizeof (T); }
836 
837  static const char * type_name ();
838 
839  // The following are provided for convenience.
840  static const octave_int zero, one;
841 
842  // Unsafe. This function exists to support the MEX interface.
843  // You should not use it anywhere else.
844  void * mex_get_data (void) const { return const_cast<T *> (&ival); }
845 
846 private:
847 
848  T ival;
849 };
850 
851 template <typename T>
852 inline octave_int<T>
854 {
855  return octave_int_arith<T>::rem (x.value (), y.value ());
856 }
857 
858 template <typename T>
859 inline octave_int<T>
861 {
862  return octave_int_arith<T>::mod (x.value (), y.value ());
863 }
864 
865 // No mixed integer binary operations!
866 
867 namespace octave
868 {
869  namespace math
870  {
871  template <typename T>
872  bool
874  {
875  return false;
876  }
877  }
878 }
879 
880 #if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS)
881 
882 template <typename T>
883 OCTAVE_DEPRECATED (4.2, "use 'octave::math::isnan' instead")
884 bool
885 xisnan (const octave_int<T>& x)
886 {
887  return octave::math::isnan (x);
888 }
889 
890 #endif
891 
892 // FIXME: can/should any of these be inline?
893 
894 template <typename T>
895 extern OCTAVE_API octave_int<T>
896 pow (const octave_int<T>&, const octave_int<T>&);
897 
898 template <typename T>
899 extern OCTAVE_API octave_int<T>
900 pow (const double& a, const octave_int<T>& b);
901 
902 template <typename T>
903 extern OCTAVE_API octave_int<T>
904 pow (const octave_int<T>& a, const double& b);
905 
906 template <typename T>
907 extern OCTAVE_API octave_int<T>
908 pow (const float& a, const octave_int<T>& b);
909 
910 template <typename T>
911 extern OCTAVE_API octave_int<T>
912 pow (const octave_int<T>& a, const float& b);
913 
914 // FIXME: Do we really need a differently named single-precision
915 // function integer power function here instead of an overloaded
916 // one?
917 template <typename T>
918 extern OCTAVE_API octave_int<T>
919 powf (const float& a, const octave_int<T>& b);
920 
921 template <typename T>
922 extern OCTAVE_API octave_int<T>
923 powf (const octave_int<T>& a, const float& b);
924 
925 // Binary relations
926 
927 #define OCTAVE_INT_CMP_OP(OP, NAME) \
928  template <typename T1, typename T2> \
929  inline bool \
930  operator OP (const octave_int<T1>& x, const octave_int<T2>& y) \
931  { \
932  return octave_int_cmp_op::op<octave_int_cmp_op::NAME, T1, T2> (x.value (), y.value ()); \
933  }
934 
941 
942 #undef OCTAVE_INT_CMP_OP
943 
944 template <typename T>
945 inline std::ostream&
946 operator << (std::ostream& os, const octave_int<T>& ival)
947 {
948  os << ival.value ();
949  return os;
950 }
951 
952 template <typename T>
953 inline std::istream&
954 operator >> (std::istream& is, octave_int<T>& ival)
955 {
956  T tmp = 0;
957  is >> tmp;
958  ival = tmp;
959  return is;
960 }
961 
962 // We need to specialise for char and unsigned char because
963 // std::operator<< and std::operator>> are overloaded to input and
964 // output the ASCII character values instead of a representation of
965 // their numerical value (e.g., os << char(10) outputs a space instead
966 // of outputting the characters '1' and '0')
967 
968 template <>
969 inline std::ostream&
970 operator << (std::ostream& os, const octave_int<int8_t>& ival)
971 {
972  os << static_cast<int> (ival.value ());
973  return os;
974 }
975 
976 template <>
977 inline std::ostream&
978 operator << (std::ostream& os, const octave_int<uint8_t>& ival)
979 {
980  os << static_cast<unsigned int> (ival.value ());
981  return os;
982 }
983 
984 template <>
985 inline std::istream&
986 operator >> (std::istream& is, octave_int<int8_t>& ival)
987 {
988  int tmp = 0;
989  is >> tmp;
990  ival = static_cast<int8_t> (tmp);
991  return is;
992 }
993 
994 template <>
995 inline std::istream&
996 operator >> (std::istream& is, octave_int<uint8_t>& ival)
997 {
998  unsigned int tmp = 0;
999  is >> tmp;
1000  ival = static_cast<uint8_t> (tmp);
1001  return is;
1002 }
1003 
1004 // Bitwise operations
1005 
1006 #define OCTAVE_INT_BITCMP_OP(OP) \
1007  template <typename T> \
1008  octave_int<T> \
1009  operator OP (const octave_int<T>& x, const octave_int<T>& y) \
1010  { \
1011  return x.value () OP y.value (); \
1012  }
1013 
1017 
1018 #undef OCTAVE_INT_BITCMP_OP
1019 
1020 // General bit shift.
1021 template <typename T>
1023 bitshift (const octave_int<T>& a, int n,
1024  const octave_int<T>& mask = std::numeric_limits<T>::max ())
1025 {
1026  if (n > 0)
1027  return (a << n) & mask;
1028  else if (n < 0)
1029  return (a >> -n) & mask;
1030  else
1031  return a & mask;
1032 }
1033 
1034 #if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED)
1035 
1036 #define DECLARE_EXTERNAL_LONG_DOUBLE_OP(T, OP) \
1037  extern OCTAVE_API T \
1038  external_double_ ## T ## _ ## OP (double x, T y); \
1039  extern OCTAVE_API T \
1040  external_ ## T ## _double_ ## OP (T x, double y)
1041 
1042 #define DECLARE_EXTERNAL_LONG_DOUBLE_OPS(T) \
1043  DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, add); \
1044  DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, sub); \
1045  DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, mul); \
1046  DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, div)
1047 
1048 DECLARE_EXTERNAL_LONG_DOUBLE_OPS (octave_int64);
1049 DECLARE_EXTERNAL_LONG_DOUBLE_OPS (octave_uint64);
1050 
1051 #endif
1052 
1053 #define OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
1054  template <typename T> \
1055  inline octave_int<T> \
1056  operator OP (const octave_int<T>& x, const double& y) \
1057  { \
1058  return octave_int<T> (static_cast<double> (x) OP y); \
1059  } \
1060  template <typename T> \
1061  inline octave_int<T> \
1062  operator OP (const double& x, const octave_int<T>& y) \
1063  { \
1064  return octave_int<T> (x OP static_cast<double> (y)); \
1065  }
1066 
1067 #if defined (OCTAVE_INT_USE_LONG_DOUBLE)
1068 // Handle mixed op using long double
1069 #if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED)
1070 # define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \
1071  OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
1072  template <> \
1073  inline octave_int64 \
1074  operator OP (const double& x, const octave_int64& y) \
1075  { \
1076  return external_double_octave_int64_ ## NAME (x, y); \
1077  } \
1078  template <> \
1079  inline octave_uint64 \
1080  operator OP (const double& x, const octave_uint64& y) \
1081  { \
1082  return external_double_octave_uint64_ ## NAME (x, y); \
1083  } \
1084  template <> \
1085  inline octave_int64 \
1086  operator OP (const octave_int64& x, const double& y) \
1087  { \
1088  return external_octave_int64_double_ ## NAME (x, y); \
1089  } \
1090  template <> \
1091  inline octave_uint64 \
1092  operator OP (const octave_uint64& x, const double& y) \
1093  { \
1094  return external_octave_uint64_double_ ## NAME (x, y); \
1095  }
1096 #else
1097 # define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \
1098  OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
1099  template <> \
1100  inline octave_int64 \
1101  operator OP (const double& x, const octave_int64& y) \
1102  { \
1103  return octave_int64 (x OP static_cast<long double> (y.value ())); \
1104  } \
1105  template <> \
1106  inline octave_uint64 \
1107  operator OP (const double& x, const octave_uint64& y) \
1108  { \
1109  return octave_uint64 (x OP static_cast<long double> (y.value ())); \
1110  } \
1111  template <> \
1112  inline octave_int64 \
1113  operator OP (const octave_int64& x, const double& y) \
1114  { \
1115  return octave_int64 (static_cast<long double> (x.value ()) OP y); \
1116  } \
1117  template <> \
1118  inline octave_uint64 \
1119  operator OP (const octave_uint64& x, const double& y) \
1120  { \
1121  return octave_uint64 (static_cast<long double> (x.value ()) OP y); \
1122  }
1123 #endif
1124 #else
1125 // external handlers
1126 #define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \
1127  OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
1128  template <> \
1129  OCTAVE_API octave_int64 \
1130  operator OP (const double&, const octave_int64&); \
1131  template <> \
1132  OCTAVE_API octave_uint64 \
1133  operator OP (const double&, const octave_uint64&); \
1134  template <> \
1135  OCTAVE_API octave_int64 \
1136  operator OP (const octave_int64&, const double&); \
1137  template <> \
1138  OCTAVE_API octave_uint64 \
1139  operator OP (const octave_uint64&, const double&);
1140 
1141 #endif
1142 
1147 
1148 #undef OCTAVE_INT_DOUBLE_BIN_OP0
1149 #undef OCTAVE_INT_DOUBLE_BIN_OP
1150 #undef DECLARE_EXTERNAL_LONG_DOUBLE_OP
1151 #undef DECLARE_EXTERNAL_LONG_DOUBLE_OPS
1152 
1153 #define OCTAVE_INT_DOUBLE_CMP_OP(OP,NAME) \
1154  template <typename T> \
1155  inline bool \
1156  operator OP (const octave_int<T>& x, const double& y) \
1157  { \
1158  return octave_int_cmp_op::mop<octave_int_cmp_op::NAME> (x.value (), y); \
1159  } \
1160  template <typename T> \
1161  inline bool \
1162  operator OP (const double& x, const octave_int<T>& y) \
1163  { \
1164  return octave_int_cmp_op::mop<octave_int_cmp_op::NAME> (x, y.value ()); \
1165  }
1166 
1173 
1174 #undef OCTAVE_INT_DOUBLE_CMP_OP
1175 
1176 // Floats are handled by simply converting to doubles.
1177 
1178 #define OCTAVE_INT_FLOAT_BIN_OP(OP) \
1179  template <typename T> \
1180  inline octave_int<T> \
1181  operator OP (const octave_int<T>& x, float y) \
1182  { \
1183  return x OP static_cast<double> (y); \
1184  } \
1185  template <typename T> \
1186  inline octave_int<T> \
1187  operator OP (float x, const octave_int<T>& y) \
1188  { \
1189  return static_cast<double> (x) OP y; \
1190  }
1191 
1196 
1197 #undef OCTAVE_INT_FLOAT_BIN_OP
1198 
1199 #define OCTAVE_INT_FLOAT_CMP_OP(OP) \
1200  template <typename T> \
1201  inline bool \
1202  operator OP (const octave_int<T>& x, const float& y) \
1203  { \
1204  return x OP static_cast<double> (y); \
1205  } \
1206  template <typename T> \
1207  bool \
1208  operator OP (const float& x, const octave_int<T>& y) \
1209  { \
1210  return static_cast<double> (x) OP y; \
1211  }
1212 
1219 
1220 #undef OCTAVE_INT_FLOAT_CMP_OP
1221 
1222 template <typename T>
1225 {
1226  const T xv = x.value ();
1227  const T yv = y.value ();
1228  return octave_int<T> (xv >= yv ? xv : yv);
1229 }
1230 
1231 template <typename T>
1234 {
1235  const T xv = x.value ();
1236  const T yv = y.value ();
1237  return octave_int<T> (xv <= yv ? xv : yv);
1238 }
1239 
1240 #endif
octave_int< uint32_t > octave_uint32
Definition: oct-inttypes.h:47
static const bool t2sig
Definition: oct-inttypes.h:150
static const bool registered
Definition: oct-inttypes.h:85
#define OCTAVE_INT_CMP_OP(OP, NAME)
Definition: oct-inttypes.h:927
#define OCTAVE_INT_BITCMP_OP(OP)
#define OCTAVE_INT_BIN_OP(OP, NAME, ARGT)
Definition: oct-inttypes.h:807
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:174
query_integer_type< size, true >::type stype
Definition: oct-inttypes.h:166
octave_int(float d)
Definition: oct-inttypes.h:748
static int nbits(void)
Definition: oct-inttypes.h:833
static const int psize
Definition: oct-inttypes.h:153
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:4986
octave_int(const octave_int< U > &i)
Definition: oct-inttypes.h:760
octave_int< T > mod(const octave_int< T > &x, const octave_int< T > &y)
Definition: oct-inttypes.h:860
bool isnan(bool)
Definition: lo-mappers.h:187
T octave_int_abs(T x)
Definition: oct-inttypes.h:78
octave_int< int16_t > octave_int16
Definition: oct-inttypes.h:41
static T abs(T x)
Definition: pr-output.cc:1696
static T min_val()
Definition: oct-inttypes.h:295
std::istream & operator>>(std::istream &is, octave_int< T > &ival)
Definition: oct-inttypes.h:954
T value(void) const
Definition: oct-inttypes.h:771
u
Definition: lu.cc:138
float float_value(void) const
Definition: oct-inttypes.h:784
static T max_val()
Definition: oct-inttypes.h:296
nd example oindent opens the file binary numeric values will be read assuming they are stored in IEEE format with the least significant bit and then converted to the native representation Opening a file that is already open simply opens it again and returns a separate file id It is not an error to open a file several though writing to the same file through several different file ids may produce unexpected results The possible values of text mode reading and writing automatically converts linefeeds to the appropriate line end character for the you may append a you must also open the file in binary mode The parameter conversions are currently only supported for and permissions will be set to and then everything is written in a single operation This is very efficient and improves performance c
Definition: file-io.cc:587
query_integer_type< sizeof(T), false >::type UT
Definition: oct-inttypes.h:514
static const bool psig
Definition: oct-inttypes.h:151
const unsigned char * iptr(void) const
Definition: oct-inttypes.h:773
query_integer_type< psize, psig >::type type
Definition: oct-inttypes.h:157
#define REGISTER_OCTAVE_CMP_OP(NM, OP)
Definition: oct-inttypes.h:112
static T truncate_int(const S &value)
Definition: oct-inttypes.h:301
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
calling an anonymous function involves an overhead quite comparable to the overhead of an m file function Passing a handle to a built in function is because the interpreter is not involved in the internal loop For a
Definition: cellfun.cc:400
octave_int< int32_t > octave_int32
Definition: oct-inttypes.h:42
query_integer_type< size, false >::type utype
Definition: oct-inttypes.h:165
octave_int< uint16_t > octave_uint16
Definition: oct-inttypes.h:46
static T rshift(T x, int n)
Definition: oct-inttypes.h:551
static S compute_threshold(S val, T orig_val)
Definition: oct-inttypes.h:340
static bool op(T1 x, T2 y)
Definition: oct-inttypes.h:191
static bool op(stype x, stype y)
Definition: oct-inttypes.h:170
std::complex< double > w(std::complex< double > z, double relerr=0)
double signum(double x)
Definition: lo-mappers.h:244
#define OCTAVE_INT_DOUBLE_CMP_OP(OP, NAME)
octave_int< int64_t > octave_int64
Definition: oct-inttypes.h:43
OCTAVE_API octave_int< T > powf(const float &a, const octave_int< T > &b)
double tmp
Definition: data.cc:6252
is false
Definition: cellfun.cc:400
static octave_int< T > max(void)
Definition: oct-inttypes.h:831
octave_value retval
Definition: data.cc:6246
octave_int(void)
Definition: oct-inttypes.h:735
static T lshift(T x, int n)
Definition: oct-inttypes.h:554
#define OCTAVE_INT_UN_OP(OPNAME, NAME)
Definition: oct-inttypes.h:793
#define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME)
octave_int< uint64_t > octave_uint64
Definition: oct-inttypes.h:48
#define DEFINE_LONG_DOUBLE_CMP_OP(T)
Definition: oct-inttypes.h:264
char char_value(void) const
Definition: oct-inttypes.h:780
octave_int< T > xmin(const octave_int< T > &x, const octave_int< T > &y)
bool bool_value(void) const
Definition: oct-inttypes.h:778
static bool op(utype x, utype y)
Definition: oct-inttypes.h:168
static const bool t1sig
Definition: oct-inttypes.h:149
static bool mop(T x, double y)
Definition: oct-inttypes.h:204
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:227
#define REGISTER_OCTAVE_CONST_OP(NM, value)
Definition: oct-inttypes.h:124
#define REGISTER_INT_TYPE(TYPE)
Definition: oct-inttypes.h:90
void * mex_get_data(void) const
Definition: oct-inttypes.h:844
static octave_int< T > min(void)
Definition: oct-inttypes.h:830
static bool op(stype x, utype y)
Definition: oct-inttypes.h:172
octave_int(double d)
Definition: oct-inttypes.h:746
p
Definition: lu.cc:138
static const octave_int zero
Definition: oct-inttypes.h:840
double double_value(void) const
Definition: oct-inttypes.h:782
octave_int< T > rem(const octave_int< T > &x, const octave_int< T > &y)
Definition: oct-inttypes.h:853
the element is set to zero In other the statement xample y
Definition: data.cc:5264
b
Definition: cellfun.cc:400
static T mul_internal(T x, T y)
Definition: oct-inttypes.h:600
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)
double round(double x)
Definition: lo-mappers.h:145
octave_int(bool b)
Definition: oct-inttypes.h:754
for i
Definition: data.cc:5264
static int byte_size(void)
Definition: oct-inttypes.h:835
octave_value operator!(const octave_value &a)
Definition: ov.h:1573
static T convert_real(const S &value)
Definition: oct-inttypes.cc:56
octave_int< T > operator+(const octave_int< T > &x, const double &y)
write the output to stdout if nargout is
Definition: load-save.cc:1612
octave_int< uint8_t > octave_uint8
Definition: oct-inttypes.h:45
octave_int(T i)
Definition: oct-inttypes.h:737
static const bool pint
Definition: oct-inttypes.h:147
octave_int< int8_t > octave_int8
Definition: oct-inttypes.h:38
octave_int(const octave_int< T > &i)
Definition: oct-inttypes.h:763
static bool mop(double x, T y)
Definition: oct-inttypes.h:209
nd group nd example For each display the value
Definition: sysdep.cc:866
uint64_t mul_internal(uint64_t x, uint64_t y)
octave::stream os
Definition: file-io.cc:627
octave_int(const U &i)
Definition: oct-inttypes.h:757
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE * x
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:204