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