GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
oct-inttypes.cc
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 (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include "fpucw-wrappers.h"
31 #include "lo-error.h"
32 #include "oct-inttypes.h"
33 
34 template <typename T>
35 const octave_int<T> octave_int<T>::zero (static_cast<T> (0));
36 
37 template <typename T>
38 const octave_int<T> octave_int<T>::one (static_cast<T> (1));
39 
40 // Define type names.
41 
42 #define DEFINE_OCTAVE_INT_TYPENAME(TYPE, TYPENAME) \
43  template <> \
44  OCTAVE_API const char * \
45  octave_int<TYPE>::type_name (void) { return TYPENAME; }
46 
48 DEFINE_OCTAVE_INT_TYPENAME (int16_t, "int16")
49 DEFINE_OCTAVE_INT_TYPENAME (int32_t, "int32")
50 DEFINE_OCTAVE_INT_TYPENAME (int64_t, "int64")
51 DEFINE_OCTAVE_INT_TYPENAME (uint8_t, "uint8")
52 DEFINE_OCTAVE_INT_TYPENAME (uint16_t, "uint16")
53 DEFINE_OCTAVE_INT_TYPENAME (uint32_t, "uint32")
54 DEFINE_OCTAVE_INT_TYPENAME (uint64_t, "uint64")
55 
56 template <class T>
57 template <class S>
58 T
59 octave_int_base<T>::convert_real (const S& value)
60 {
61  // Compute proper thresholds.
62  static const S thmin = compute_threshold (static_cast<S> (min_val ()),
63  min_val ());
64  static const S thmax = compute_threshold (static_cast<S> (max_val ()),
65  max_val ());
66  if (octave::math::isnan (value))
67  return static_cast<T> (0);
68  else if (value < thmin)
69  return min_val ();
70  else if (value > thmax)
71  return max_val ();
72  else
73  {
74  S rvalue = octave::math::round (value);
75  return static_cast<T> (rvalue);
76  }
77 }
78 
79 #define INSTANTIATE_CONVERT_REAL_1(T, S) \
80  template \
81  OCTAVE_API \
82  T \
83  octave_int_base<T>::convert_real (const S&)
84 
85 #define INSTANTIATE_CONVERT_REAL(S) \
86  INSTANTIATE_CONVERT_REAL_1 (int8_t, S); \
87  INSTANTIATE_CONVERT_REAL_1 (uint8_t, S); \
88  INSTANTIATE_CONVERT_REAL_1 (int16_t, S); \
89  INSTANTIATE_CONVERT_REAL_1 (uint16_t, S); \
90  INSTANTIATE_CONVERT_REAL_1 (int32_t, S); \
91  INSTANTIATE_CONVERT_REAL_1 (uint32_t, S); \
92  INSTANTIATE_CONVERT_REAL_1 (int64_t, S); \
93  INSTANTIATE_CONVERT_REAL_1 (uint64_t, S)
94 
97 #if defined (OCTAVE_INT_USE_LONG_DOUBLE)
98 INSTANTIATE_CONVERT_REAL (long double);
99 #endif
100 
101 #if defined (OCTAVE_INT_USE_LONG_DOUBLE)
102 
103 # if defined (OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED)
104 
105 # define DEFINE_OCTAVE_LONG_DOUBLE_CMP_OP_TEMPLATES(T) \
106  template <typename xop> \
107  bool \
108  octave_int_cmp_op::external_mop (double x, T y) \
109  { \
110  unsigned int oldcw = octave_begin_long_double_rounding (); \
111  \
112  bool retval = xop::op (static_cast<long double> (x), \
113  static_cast<long double> (y)); \
114  \
115  octave_end_long_double_rounding (oldcw); \
116  \
117  return retval; \
118  } \
119  \
120  template <typename xop> \
121  bool \
122  octave_int_cmp_op::external_mop (T x, double y) \
123  { \
124  unsigned int oldcw = octave_begin_long_double_rounding (); \
125  \
126  bool retval = xop::op (static_cast<long double> (x), \
127  static_cast<long double> (y)); \
128  \
129  octave_end_long_double_rounding (oldcw); \
130  \
131  return retval; \
132  }
133 
134 DEFINE_OCTAVE_LONG_DOUBLE_CMP_OP_TEMPLATES (int64_t)
135 DEFINE_OCTAVE_LONG_DOUBLE_CMP_OP_TEMPLATES (uint64_t)
136 
137 # define INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP(OP, T) \
138  template OCTAVE_API bool \
139  octave_int_cmp_op::external_mop<octave_int_cmp_op::OP> (double, T); \
140  \
141  template OCTAVE_API bool \
142  octave_int_cmp_op::external_mop<octave_int_cmp_op::OP> (T, double)
143 
144 # define INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OPS(T) \
145  INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (lt, T); \
146  INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (le, T); \
147  INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (gt, T); \
148  INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (ge, T); \
149  INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (eq, T); \
150  INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OP (ne, T)
151 
152 INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OPS (int64_t);
153 INSTANTIATE_LONG_DOUBLE_LONG_DOUBLE_CMP_OPS (uint64_t);
154 
155 uint64_t
156 octave_external_uint64_uint64_mul (uint64_t x, uint64_t y)
157 {
158  unsigned int oldcw = octave_begin_long_double_rounding ();
159 
161 
163 
164  return retval;
165 }
166 
167 int64_t
168 octave_external_int64_int64_mul (int64_t x, int64_t y)
169 {
170  unsigned int oldcw = octave_begin_long_double_rounding ();
171 
173 
175 
176  return retval;
177 }
178 
179 // Note that if we return long double it is apparently possible for
180 // truncation to happen at the point of storing the result in retval,
181 // which can happen after we end long double rounding. Attempt to avoid
182 // that problem by storing the full precision temporary value in the
183 // integer value before we end the long double rounding mode.
184 // Similarly, the conversion from the 64-bit integer type to long double
185 // must also occur in long double rounding mode.
186 
187 # define DEFINE_OCTAVE_LONG_DOUBLE_OP(T, OP, NAME) \
188  T \
189  external_double_ ## T ## _ ## NAME (double x, T y) \
190  { \
191  unsigned int oldcw = octave_begin_long_double_rounding (); \
192  \
193  T retval = T (x OP static_cast<long double> (y.value ())); \
194  \
195  octave_end_long_double_rounding (oldcw); \
196  \
197  return retval; \
198  } \
199  \
200  T \
201  external_ ## T ## _double_ ## NAME (T x, double y) \
202  { \
203  unsigned int oldcw = octave_begin_long_double_rounding (); \
204  \
205  T retval = T (static_cast<long double> (x.value ()) OP y); \
206  \
207  octave_end_long_double_rounding (oldcw); \
208  \
209  return retval; \
210  }
211 
212 # define DEFINE_OCTAVE_LONG_DOUBLE_OPS(T) \
213  DEFINE_OCTAVE_LONG_DOUBLE_OP (T, +, add); \
214  DEFINE_OCTAVE_LONG_DOUBLE_OP (T, -, sub); \
215  DEFINE_OCTAVE_LONG_DOUBLE_OP (T, *, mul); \
216  DEFINE_OCTAVE_LONG_DOUBLE_OP (T, /, div)
217 
218 DEFINE_OCTAVE_LONG_DOUBLE_OPS (octave_int64);
219 DEFINE_OCTAVE_LONG_DOUBLE_OPS (octave_uint64);
220 
221 # endif
222 
223 #else
224 
225 // Define comparison operators
226 
227 template <typename xop>
228 bool
229 octave_int_cmp_op::emulate_mop (uint64_t x, double y)
230 {
231  static const double xxup = std::numeric_limits<uint64_t>::max ();
232  // This converts to the nearest double. Unless there's an equality, the
233  // result is clear.
234  double xx = x;
235  if (xx != y)
236  return xop::op (xx, y);
237  else
238  {
239  // If equality occurred we compare as integers.
240  if (xx == xxup)
241  return xop::gtval;
242  else
243  return xop::op (x, static_cast<uint64_t> (xx));
244  }
245 }
246 
247 template <typename xop>
248 bool
250 {
251  static const double xxup = std::numeric_limits<int64_t>::max ();
252  static const double xxlo = std::numeric_limits<int64_t>::min ();
253  // This converts to the nearest double. Unless there's an equality, the
254  // result is clear.
255  double xx = x;
256  if (xx != y)
257  return xop::op (xx, y);
258  else
259  {
260  // If equality occurred we compare as integers.
261  if (xx == xxup)
262  return xop::gtval;
263  else if (xx == xxlo)
264  return xop::ltval;
265  else
266  return xop::op (x, static_cast<int64_t> (xx));
267  }
268 
269 }
270 
271 // We define double-int operations by reverting the operator
272 
273 // A trait class reverting the operator
274 template <typename xop>
275 class rev_op
276 {
277 public:
278  typedef xop op;
279 };
280 
281 #define DEFINE_REVERTED_OPERATOR(OP1, OP2) \
282  template <> \
283  class rev_op<octave_int_cmp_op::OP1> \
284  { \
285  public: \
286  typedef octave_int_cmp_op::OP2 op; \
287  }
288 
293 
294 template <typename xop>
295 bool
296 octave_int_cmp_op::emulate_mop (double x, uint64_t y)
297 {
298  typedef typename rev_op<xop>::op rop;
299  return mop<rop> (y, x);
300 }
301 
302 template <typename xop>
303 bool
305 {
306  typedef typename rev_op<xop>::op rop;
307  return mop<rop> (y, x);
308 }
309 
310 // Define handlers for (u)int64 multiplication.
311 
312 template <>
313 uint64_t
315 {
316  // Get upper words
317  uint64_t ux = x >> 32;
318  uint64_t uy = y >> 32;
319  uint64_t res;
320  if (ux)
321  {
322  if (uy)
323  goto overflow;
324  else
325  {
326  uint64_t ly = static_cast<uint32_t> (y);
327  uint64_t uxly = ux*ly;
328  if (uxly >> 32)
329  goto overflow;
330  uxly <<= 32; // never overflows
331  uint64_t lx = static_cast<uint32_t> (x);
332  uint64_t lxly = lx*ly;
333  res = add (uxly, lxly);
334  }
335  }
336  else if (uy)
337  {
338  uint64_t lx = static_cast<uint32_t> (x);
339  uint64_t uylx = uy*lx;
340  if (uylx >> 32)
341  goto overflow;
342  uylx <<= 32; // never overflows
343  uint64_t ly = static_cast<uint32_t> (y);
344  uint64_t lylx = ly*lx;
345  res = add (uylx, lylx);
346  }
347  else
348  {
349  uint64_t lx = static_cast<uint32_t> (x);
350  uint64_t ly = static_cast<uint32_t> (y);
351  res = lx*ly;
352  }
353 
354  return res;
355 
356 overflow:
357  return max_val ();
358 }
359 
360 template <>
361 int64_t
363 {
364  // The signed case is far worse. The problem is that even if neither
365  // integer fits into signed 32-bit range, the result may still be OK.
366  // Uh oh.
367 
368  // Essentially, what we do is compute sign, multiply absolute values
369  // (as above) and impose the sign.
370 
371  uint64_t usx = octave_int_abs (x);
372  uint64_t usy = octave_int_abs (y);
373  bool positive = (x < 0) == (y < 0);
374 
375  // Get upper words
376  uint64_t ux = usx >> 32;
377  uint64_t uy = usy >> 32;
378  uint64_t res;
379  if (ux)
380  {
381  if (uy)
382  goto overflow;
383  else
384  {
385  uint64_t ly = static_cast<uint32_t> (usy);
386  uint64_t uxly = ux*ly;
387  if (uxly >> 32)
388  goto overflow;
389  uxly <<= 32; // never overflows
390  uint64_t lx = static_cast<uint32_t> (usx);
391  uint64_t lxly = lx*ly;
392  res = uxly + lxly;
393  if (res < uxly)
394  goto overflow;
395  }
396  }
397  else if (uy)
398  {
399  uint64_t lx = static_cast<uint32_t> (usx);
400  uint64_t uylx = uy*lx;
401  if (uylx >> 32)
402  goto overflow;
403  uylx <<= 32; // never overflows
404  uint64_t ly = static_cast<uint32_t> (usy);
405  uint64_t lylx = ly*lx;
406  res = uylx + lylx;
407  if (res < uylx)
408  goto overflow;
409  }
410  else
411  {
412  uint64_t lx = static_cast<uint32_t> (usx);
413  uint64_t ly = static_cast<uint32_t> (usy);
414  res = lx*ly;
415  }
416 
417  if (positive)
418  {
419  if (res > static_cast<uint64_t> (max_val ()))
420  return max_val ();
421  else
422  return static_cast<int64_t> (res);
423  }
424  else
425  {
426  if (res > static_cast<uint64_t> (min_val ()))
427  return min_val ();
428  else
429  return -static_cast<int64_t> (res);
430  }
431 
432 overflow:
433  return positive ? max_val () : min_val ();
434 
435 }
436 
437 template <>
438 OCTAVE_API octave_uint64
439 operator + (const octave_uint64& x, const double& y)
440 {
441  return (y < 0) ? x - octave_uint64 (-y) : x + octave_uint64 (y);
442 }
443 
444 template <>
445 OCTAVE_API octave_uint64
446 operator + (const double& x, const octave_uint64& y)
447 {
448  return y + x;
449 }
450 
451 template <>
452 OCTAVE_API octave_int64
453 operator + (const octave_int64& x, const double& y)
454 {
455  if (fabs (y) < static_cast<double> (octave_int64::max ()))
456  return x + octave_int64 (y);
457  else
458  {
459  // If the number is within the int64 range (the most common case,
460  // probably), the above will work as expected. If not, it's more
461  // complicated - as long as y is within _twice_ the signed range, the
462  // result may still be an integer. An instance of such an operation is
463  // 3*2**62 + (1+intmin ('int64')) that should yield int64 (2**62) + 1.
464  // So what we do is to try to convert y/2 and add it twice. Note that
465  // if y/2 overflows, the result must overflow as well, and that y/2
466  // cannot be a fractional number.
467  octave_int64 y2 (y / 2);
468  return (x + y2) + y2;
469  }
470 }
471 
472 template <>
473 OCTAVE_API octave_int64
474 operator + (const double& x, const octave_int64& y)
475 {
476  return y + x;
477 }
478 
479 template <>
480 OCTAVE_API octave_uint64
481 operator - (const octave_uint64& x, const double& y)
482 {
483  return x + (-y);
484 }
485 
486 template <>
487 OCTAVE_API octave_uint64
488 operator - (const double& x, const octave_uint64& y)
489 {
490  if (x <= static_cast<double> (octave_uint64::max ()))
491  return octave_uint64 (x) - y;
492  else
493  {
494  // Again a trick to get the corner cases right. Things like
495  // 3**2**63 - intmax ('uint64') should produce the correct result, i.e.
496  // int64 (2**63) + 1.
497  const double p2_64 = std::pow (2.0, 64);
498  if (y.bool_value ())
499  {
500  const uint64_t p2_64my = (~y.value ()) + 1; // Equals 2**64 - y
501  return octave_uint64 (x - p2_64) + octave_uint64 (p2_64my);
502  }
503  else
504  return octave_uint64 (p2_64);
505  }
506 }
507 
508 template <>
509 OCTAVE_API octave_int64
510 operator - (const octave_int64& x, const double& y)
511 {
512  return x + (-y);
513 }
514 
515 template <>
516 OCTAVE_API octave_int64
517 operator - (const double& x, const octave_int64& y)
518 {
519  static const bool twosc = (std::numeric_limits<int64_t>::min ()
521  // In case of symmetric integers (not two's complement), this will probably
522  // be eliminated at compile time.
523  if (twosc && y.value () == std::numeric_limits<int64_t>::min ())
524  return octave_int64 (x + std::pow (2.0, 63));
525  else
526  return x + (-y);
527 }
528 
529 // NOTE:
530 // Emulated mixed multiplications are tricky due to possible precision loss.
531 // Here, after sorting out common cases for speed, we follow the strategy
532 // of converting the double number into the form sign * 64-bit integer *
533 // 2**exponent, multiply the 64-bit integers to get a 128-bit number, split that
534 // number into 32-bit words and form 4 double-valued summands (none of which
535 // loses precision), then convert these into integers and sum them. Though it
536 // is not immediately obvious, this should work even w.r.t. rounding (none of
537 // the summands lose precision).
538 
539 // Multiplies two unsigned 64-bit ints to get a 128-bit number represented
540 // as four 32-bit words.
541 static void
542 umul128 (uint64_t x, uint64_t y, uint32_t w[4])
543 {
544  uint64_t lx = static_cast<uint32_t> (x);
545  uint64_t ux = x >> 32;
546  uint64_t ly = static_cast<uint32_t> (y);
547  uint64_t uy = y >> 32;
548  uint64_t a = lx * ly;
549  w[0] = a; a >>= 32;
550  uint64_t uxly = ux*ly;
551  uint64_t uylx = uy*lx;
552  a += static_cast<uint32_t> (uxly); uxly >>= 32;
553  a += static_cast<uint32_t> (uylx); uylx >>= 32;
554  w[1] = a; a >>= 32;
555  uint64_t uxuy = ux * uy;
556  a += uxly; a += uylx; a += uxuy;
557  w[2] = a; a >>= 32;
558  w[3] = a;
559 }
560 
561 // Splits a double into bool sign, unsigned 64-bit mantissa and int exponent
562 static void
563 dblesplit (double x, bool& sign, uint64_t& mtis, int& exp)
564 {
565  sign = x < 0; x = fabs (x);
566  x = octave::math::frexp (x, &exp);
567  exp -= 52;
568  mtis = static_cast<uint64_t> (ldexp (x, 52));
569 }
570 
571 // Gets a double number from a
572 // 32-bit unsigned integer mantissa, exponent, and sign.
573 static double
574 dbleget (bool sign, uint32_t mtis, int exp)
575 {
576  double x = ldexp (static_cast<double> (mtis), exp);
577  return sign ? -x : x;
578 }
579 
580 template <>
581 OCTAVE_API octave_uint64
582 operator * (const octave_uint64& x, const double& y)
583 {
584  if (y >= 0 && y < octave_uint64::max () && y == octave::math::fix (y))
585  return x * octave_uint64 (static_cast<uint64_t> (y));
586  else if (y == 0.5)
587  return x / octave_uint64 (static_cast<uint64_t> (2));
588  else if (y < 0 || octave::math::isnan (y) || octave::math::isinf (y))
589  return octave_uint64 (x.value () * y);
590  else
591  {
592  bool sign;
593  uint64_t my;
594  int e;
595  dblesplit (y, sign, my, e);
596  uint32_t w[4];
597  umul128 (x.value (), my, w);
599  for (short i = 0; i < 4; i++)
600  {
601  res += octave_uint64 (dbleget (sign, w[i], e));
602  e += 32;
603  }
604  return res;
605  }
606 }
607 
608 template <>
609 OCTAVE_API octave_uint64
610 operator * (const double& x, const octave_uint64& y)
611 {
612  return y * x;
613 }
614 
615 template <>
616 OCTAVE_API octave_int64
617 operator * (const octave_int64& x, const double& y)
618 {
619  if (fabs (y) < octave_int64::max () && y == octave::math::fix (y))
620  return x * octave_int64 (static_cast<int64_t> (y));
621  else if (fabs (y) == 0.5)
622  return x / octave_int64 (static_cast<uint64_t> (4*y));
623  else if (octave::math::isnan (y) || octave::math::isinf (y))
624  return octave_int64 (x.value () * y);
625  else
626  {
627  bool sign;
628  uint64_t my;
629  int e;
630  dblesplit (y, sign, my, e);
631  uint32_t w[4];
632  sign = (sign != (x.value () < 0));
633  umul128 (octave_int_abs (x.value ()), my, w);
635  for (short i = 0; i < 4; i++)
636  {
637  res += octave_int64 (dbleget (sign, w[i], e));
638  e += 32;
639  }
640  return res;
641  }
642 }
643 
644 template <>
645 OCTAVE_API octave_int64
646 operator * (const double& x, const octave_int64& y)
647 {
648  return y * x;
649 }
650 
651 template <>
652 OCTAVE_API octave_uint64
653 operator / (const double& x, const octave_uint64& y)
654 {
655  return octave_uint64 (x / static_cast<double> (y));
656 }
657 
658 template <>
659 OCTAVE_API octave_int64
660 operator / (const double& x, const octave_int64& y)
661 {
662  return octave_int64 (x / static_cast<double> (y));
663 }
664 
665 template <>
666 OCTAVE_API octave_uint64
667 operator / (const octave_uint64& x, const double& y)
668 {
669  if (y >= 0 && y < octave_uint64::max () && y == octave::math::fix (y))
670  return x / octave_uint64 (y);
671  else
672  return x * (1.0/y);
673 }
674 
675 template <>
676 OCTAVE_API octave_int64
677 operator / (const octave_int64& x, const double& y)
678 {
679  if (fabs (y) < octave_int64::max () && y == octave::math::fix (y))
680  return x / octave_int64 (y);
681  else
682  return x * (1.0/y);
683 }
684 
685 #define INSTANTIATE_INT64_DOUBLE_CMP_OP0(OP, T1, T2) \
686  template OCTAVE_API bool \
687  octave_int_cmp_op::emulate_mop<octave_int_cmp_op::OP> (T1 x, T2 y)
688 
689 #define INSTANTIATE_INT64_DOUBLE_CMP_OP(OP) \
690  INSTANTIATE_INT64_DOUBLE_CMP_OP0 (OP, double, int64_t); \
691  INSTANTIATE_INT64_DOUBLE_CMP_OP0 (OP, double, uint64_t); \
692  INSTANTIATE_INT64_DOUBLE_CMP_OP0 (OP, int64_t, double); \
693  INSTANTIATE_INT64_DOUBLE_CMP_OP0 (OP, uint64_t, double)
694 
701 
702 #endif
703 
704 template <typename T>
706 pow (const octave_int<T>& a, const octave_int<T>& b)
707 {
709 
710  const octave_int<T> zero = octave_int<T>::zero;
711  const octave_int<T> one = octave_int<T>::one;
712 
713  if (b == zero || a == one)
714  retval = one;
715  else if (b < zero)
716  {
717  if (a == -one)
718  retval = (b.value () % 2) ? a : one;
719  else
720  retval = zero;
721  }
722  else
723  {
724  octave_int<T> a_val = a;
725  T b_val = b; // no need to do saturation on b
726 
727  retval = a;
728 
729  b_val -= 1;
730 
731  while (b_val != 0)
732  {
733  if (b_val & 1)
734  retval = retval * a_val;
735 
736  b_val = b_val >> 1;
737 
738  if (b_val)
739  a_val = a_val * a_val;
740  }
741  }
742 
743  return retval;
744 }
745 
746 template <typename T>
748 pow (const double& a, const octave_int<T>& b)
749 { return octave_int<T> (std::pow (a, b.double_value ())); }
750 
751 template <typename T>
753 pow (const octave_int<T>& a, const double& b)
754 {
755  return ((b >= 0 && b < std::numeric_limits<T>::digits
756  && b == octave::math::fix (b))
757  ? pow (a, octave_int<T> (static_cast<T> (b)))
758  : octave_int<T> (std::pow (a.double_value (), b)));
759 }
760 
761 template <typename T>
763 pow (const float& a, const octave_int<T>& b)
764 { return octave_int<T> (std::pow (a, b.float_value ())); }
765 
766 template <typename T>
768 pow (const octave_int<T>& a, const float& b)
769 {
770  return ((b >= 0 && b < std::numeric_limits<T>::digits
771  && b == octave::math::fix (b))
772  ? pow (a, octave_int<T> (static_cast<T> (b)))
774  static_cast<double> (b))));
775 }
776 
777 // FIXME: Do we really need a differently named single-precision function
778 // integer power function here instead of an overloaded one?
779 template <typename T>
781 powf (const float& a, const octave_int<T>& b)
782 { return octave_int<T> (pow (a, b.float_value ())); }
783 
784 template <typename T>
786 powf (const octave_int<T>& a, const float& b)
787 {
788  return ((b >= 0 && b < std::numeric_limits<T>::digits
789  && b == octave::math::fix (b))
790  ? pow (a, octave_int<T> (static_cast<T> (b)))
792  static_cast<double> (b))));
793 }
794 
795 #define INSTANTIATE_INTTYPE(T) \
796  template class OCTAVE_API octave_int<T>; \
797  \
798  template OCTAVE_API octave_int<T> \
799  pow (const octave_int<T>&, const octave_int<T>&); \
800  \
801  template OCTAVE_API octave_int<T> \
802  pow (const double&, const octave_int<T>&); \
803  \
804  template OCTAVE_API octave_int<T> \
805  pow (const octave_int<T>&, const double&); \
806  \
807  template OCTAVE_API octave_int<T> \
808  pow (const float&, const octave_int<T>&); \
809  \
810  template OCTAVE_API octave_int<T> \
811  pow (const octave_int<T>&, const float&); \
812  \
813  template OCTAVE_API octave_int<T> \
814  powf (const float&, const octave_int<T>&); \
815  \
816  template OCTAVE_API octave_int<T> \
817  powf (const octave_int<T>&, const float&); \
818  \
819  template OCTAVE_API octave_int<T> \
820  bitshift (const octave_int<T>&, int, const octave_int<T>&);
821 
826 
831 
832 /*
833 
834 %!assert (intmax ("int64") / intmin ("int64"), int64 (-1))
835 %!assert (intmin ("int64") / int64 (-1), intmax ("int64"))
836 %!assert (int64 (2**63), intmax ("int64"))
837 %!assert (uint64 (2**64), intmax ("uint64"))
838 %!test
839 %! a = 1.9*2^61; b = uint64 (a); b++; assert (b > a);
840 %!test
841 %! a = -1.9*2^61; b = int64 (a); b++; assert (b > a);
842 %!test
843 %! a = int64 (-2**60) + 2; assert (1.25*a == (5*a)/4);
844 %!test
845 %! a = uint64 (2**61) + 2; assert (1.25*a == (5*a)/4);
846 %!assert (int32 (2**31+0.5), intmax ("int32"))
847 %!assert (int32 (-2**31-0.5), intmin ("int32"))
848 %!assert ((int64 (2**62)+1)**1, int64 (2**62)+1)
849 %!assert ((int64 (2**30)+1)**2, int64 (2**60+2**31) + 1)
850 
851 %!assert <54382> (uint8 (char (128)), uint8 (128))
852 %!assert <54382> (uint8 (char (255)), uint8 (255))
853 %!assert <54382> (int8 (char (128)), int8 (128))
854 %!assert <54382> (int8 (char (255)), int8 (255))
855 
856 %!assert <54382> (uint16 (char (128)), uint16 (128))
857 %!assert <54382> (uint16 (char (255)), uint16 (255))
858 %!assert <54382> (int16 (char (128)), int16 (128))
859 %!assert <54382> (int16 (char (255)), int16 (255))
860 
861 %!assert <54382> (uint32 (char (128)), uint32 (128))
862 %!assert <54382> (uint32 (char (255)), uint32 (255))
863 %!assert <54382> (int32 (char (128)), int32 (128))
864 %!assert <54382> (int32 (char (255)), int32 (255))
865 
866 %!assert <54382> (uint64 (char (128)), uint64 (128))
867 %!assert <54382> (uint64 (char (255)), uint64 (255))
868 %!assert <54382> (int64 (char (128)), int64 (128))
869 %!assert <54382> (int64 (char (255)), int64 (255))
870 */
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:230
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:207
uint64_t mul_internal(uint64_t x, uint64_t y)
static OCTAVE_API bool emulate_mop(double, int64_t)
static octave_int< T > max(void)
Definition: oct-inttypes.h:903
bool bool_value(void) const
Definition: oct-inttypes.h:851
static const octave_int zero
Definition: oct-inttypes.h:912
double double_value(void) const
Definition: oct-inttypes.h:855
float float_value(void) const
Definition: oct-inttypes.h:857
T value(void) const
Definition: oct-inttypes.h:842
static const octave_int one
Definition: oct-inttypes.h:912
unsigned int octave_begin_long_double_rounding(void)
void octave_end_long_double_rounding(unsigned int oldcw)
F77_RET_T const F77_DBLE * x
std::complex< double > w(std::complex< double > z, double relerr=0)
double fix(double x)
Definition: lo-mappers.h:118
double frexp(double x, int *expptr)
Definition: lo-mappers.cc:128
bool isnan(bool)
Definition: lo-mappers.h:178
bool isinf(double x)
Definition: lo-mappers.h:203
double round(double x)
Definition: lo-mappers.h:136
octave_int< int64_t > octave_int64
octave_int< uint64_t > octave_uint64
static void umul128(uint64_t x, uint64_t y, uint32_t w[4])
#define INSTANTIATE_INTTYPE(T)
OCTAVE_API octave_uint64 operator-(const octave_uint64 &x, const double &y)
OCTAVE_API octave_uint64 operator+(const octave_uint64 &x, const double &y)
static double dbleget(bool sign, uint32_t mtis, int exp)
OCTAVE_API octave_uint64 operator*(const octave_uint64 &x, const double &y)
#define INSTANTIATE_INT64_DOUBLE_CMP_OP(OP)
static void dblesplit(double x, bool &sign, uint64_t &mtis, int &exp)
octave_int< T > powf(const float &a, const octave_int< T > &b)
OCTAVE_API octave_uint64 operator/(const double &x, const octave_uint64 &y)
#define DEFINE_OCTAVE_INT_TYPENAME(TYPE, TYPENAME)
Definition: oct-inttypes.cc:42
#define DEFINE_REVERTED_OPERATOR(OP1, OP2)
#define INSTANTIATE_CONVERT_REAL(S)
Definition: oct-inttypes.cc:85
octave_int< T > pow(const octave_int< T > &a, const octave_int< T > &b)
T octave_int_abs(T x)
Definition: oct-inttypes.h:78
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811