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