GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
bitfcns.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2004-2015 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include <limits>
28 
29 #include "str-vec.h"
30 #include "quit.h"
31 
32 #include "defun.h"
33 #include "error.h"
34 #include "ov.h"
35 #include "ov-uint64.h"
36 #include "ov-uint32.h"
37 #include "ov-uint16.h"
38 #include "ov-uint8.h"
39 #include "ov-int64.h"
40 #include "ov-int32.h"
41 #include "ov-int16.h"
42 #include "ov-int8.h"
43 #include "ov-float.h"
44 #include "ov-scalar.h"
45 #include "ov-re-mat.h"
46 #include "ov-bool.h"
47 
48 #include <functional>
49 
50 #if !defined (HAVE_CXX_BITWISE_OP_TEMPLATES)
51 namespace std
52 {
53  template <typename T>
54  struct bit_and
55  {
56  public:
57  T operator() (const T & op1, const T & op2) const { return (op1 & op2); }
58  };
59 
60  template <typename T>
61  struct bit_or
62  {
63  public:
64  T operator() (const T & op1, const T & op2) const { return (op1 | op2); }
65  };
66 
67  template <typename T>
68  struct bit_xor
69  {
70  public:
71  T operator() (const T & op1, const T & op2) const { return (op1 ^ op2); }
72  };
73 }
74 #endif
75 
76 template <typename OP, typename T>
78 bitopxx (const OP& op, const std::string& fname,
79  const Array<T>& x, const Array<T>& y)
80 {
81  int nelx = x.numel ();
82  int nely = y.numel ();
83 
84  bool is_scalar_op = (nelx == 1 || nely == 1);
85 
86  dim_vector dvx = x.dims ();
87  dim_vector dvy = y.dims ();
88 
89  bool is_array_op = (dvx == dvy);
90 
91  octave_value retval;
92  if (is_array_op || is_scalar_op)
93  {
94  Array<T> result;
95 
96  if (nelx != 1)
97  result.resize (dvx);
98  else
99  result.resize (dvy);
100 
101  for (int i = 0; i < nelx; i++)
102  if (is_scalar_op)
103  for (int k = 0; k < nely; k++)
104  result(i+k) = op (x(i), y(k));
105  else
106  result(i) = op (x(i), y(i));
107 
108  retval = result;
109  }
110  else
111  error ("%s: size of X and Y must match, or one operand must be a scalar",
112  fname.c_str ());
113 
114  return retval;
115 }
116 
117 // Trampoline function, instantiates the proper template above, with
118 // reflective information hardwired. We can't hardwire this information
119 // in Fbitxxx DEFUNs below, because at that moment, we still don't have
120 // information about which integer types we need to instantiate.
121 template<typename T>
123 bitopx (const std::string& fname, const Array<T>& x, const Array<T>& y)
124 {
125  if (fname == "bitand")
126  return bitopxx (std::bit_and<T>(), fname, x, y);
127  if (fname == "bitor")
128  return bitopxx (std::bit_or<T>(), fname, x, y);
129 
130  //else (fname == "bitxor")
131  return bitopxx (std::bit_xor<T>(), fname, x, y);
132 }
133 
134 static inline int
136 {
137  return (arg.class_name () != octave_scalar::static_class_name ()
140 }
141 
142 static inline int
144 {
145  return arg.class_name () == octave_bool::static_class_name ();
146 }
147 
148 static inline int
150 {
152 }
153 
155 bitop (const std::string& fname, const octave_value_list& args)
156 {
157  octave_value retval;
158 
159  int nargin = args.length ();
160 
161  if (nargin == 2)
162  {
163  if (args(0).class_name () == octave_scalar::static_class_name ()
164  || args(0).class_name () == octave_float_scalar::static_class_name ()
165  || args(0).class_name () == octave_bool::static_class_name ()
166  || args(1).class_name () == octave_scalar::static_class_name ()
167  || args(1).class_name () == octave_float_scalar::static_class_name ()
168  || args(1).class_name () == octave_bool::static_class_name ())
169  {
170  bool arg0_is_int = bitop_arg_is_int (args(0));
171  bool arg1_is_int = bitop_arg_is_int (args(1));
172 
173  bool arg0_is_bool = bitop_arg_is_bool (args(0));
174  bool arg1_is_bool = bitop_arg_is_bool (args(1));
175 
176  bool arg0_is_float = bitop_arg_is_float (args(0));
177  bool arg1_is_float = bitop_arg_is_float (args(1));
178 
179  if (! (arg0_is_int || arg1_is_int))
180  {
181  if (arg0_is_bool && arg1_is_bool)
182  {
183  boolNDArray x (args(0).bool_array_value ());
184  boolNDArray y (args(1).bool_array_value ());
185  if (! error_state)
186  retval = bitopx (fname, x, y).bool_array_value ();
187  }
188  else if (arg0_is_float && arg1_is_float)
189  {
190  uint64NDArray x (args(0).float_array_value ());
191  uint64NDArray y (args(1).float_array_value ());
192  if (! error_state)
193  retval = bitopx (fname, x, y).float_array_value ();
194  }
195  else if (! (arg0_is_float || arg1_is_float))
196  {
197  uint64NDArray x (args(0).array_value ());
198  uint64NDArray y (args(1).array_value ());
199  if (! error_state)
200  retval = bitopx (fname, x, y).array_value ();
201  }
202  else
203  {
204  int p = (arg0_is_float ? 1 : 0);
205  int q = (arg0_is_float ? 0 : 1);
206 
207  uint64NDArray x (args(p).array_value ());
208  uint64NDArray y (args(q).float_array_value ());
209  if (! error_state)
210  retval = bitopx (fname, x, y).float_array_value ();
211  }
212  }
213  else
214  {
215  int p = (arg0_is_int ? 1 : 0);
216  int q = (arg0_is_int ? 0 : 1);
217 
218  NDArray dx = args(p).array_value ();
219 
220  if (args(q).type_id () == octave_uint64_matrix::static_type_id ()
221  || args(q).type_id () == octave_uint64_scalar::static_type_id ())
222  {
223  uint64NDArray x (dx);
224  uint64NDArray y = args(q).uint64_array_value ();
225  if (! error_state)
226  retval = bitopx (fname, x, y);
227  }
228  else if (args(q).type_id () == octave_uint32_matrix::static_type_id ()
229  || args(q).type_id () == octave_uint32_scalar::static_type_id ())
230  {
231  uint32NDArray x (dx);
232  uint32NDArray y = args(q).uint32_array_value ();
233  if (! error_state)
234  retval = bitopx (fname, x, y);
235  }
236  else if (args(q).type_id () == octave_uint16_matrix::static_type_id ()
237  || args(q).type_id () == octave_uint16_scalar::static_type_id ())
238  {
239  uint16NDArray x (dx);
240  uint16NDArray y = args(q).uint16_array_value ();
241  if (! error_state)
242  retval = bitopx (fname, x, y);
243  }
244  else if (args(q).type_id () == octave_uint8_matrix::static_type_id ()
245  || args(q).type_id () == octave_uint8_scalar::static_type_id ())
246  {
247  uint8NDArray x (dx);
248  uint8NDArray y = args(q).uint8_array_value ();
249  if (! error_state)
250  retval = bitopx (fname, x, y);
251  }
252  else if (args(q).type_id () == octave_int64_matrix::static_type_id ()
253  || args(q).type_id () == octave_int64_scalar::static_type_id ())
254  {
255  int64NDArray x (dx);
256  int64NDArray y = args(q).int64_array_value ();
257  if (! error_state)
258  retval = bitopx (fname, x, y);
259  }
260  else if (args(q).type_id () == octave_int32_matrix::static_type_id ()
261  || args(q).type_id () == octave_int32_scalar::static_type_id ())
262  {
263  int32NDArray x (dx);
264  int32NDArray y = args(q).int32_array_value ();
265  if (! error_state)
266  retval = bitopx (fname, x, y);
267  }
268  else if (args(q).type_id () == octave_int16_matrix::static_type_id ()
269  || args(q).type_id () == octave_int16_scalar::static_type_id ())
270  {
271  int16NDArray x (dx);
272  int16NDArray y = args(q).int16_array_value ();
273  if (! error_state)
274  retval = bitopx (fname, x, y);
275  }
276  else if (args(q).type_id () == octave_int8_matrix::static_type_id ()
277  || args(q).type_id () == octave_int8_scalar::static_type_id ())
278  {
279  int8NDArray x (dx);
280  int8NDArray y = args(q).int8_array_value ();
281  if (! error_state)
282  retval = bitopx (fname, x, y);
283  }
284  else
285  error ("%s: invalid operand type", fname.c_str ());
286  }
287  }
288  else if (args(0).class_name () == args(1).class_name ())
289  {
290  if (args(0).type_id () == octave_uint64_matrix::static_type_id ()
291  || args(0).type_id () == octave_uint64_scalar::static_type_id ())
292  {
293  uint64NDArray x = args(0).uint64_array_value ();
294  uint64NDArray y = args(1).uint64_array_value ();
295  if (! error_state)
296  retval = bitopx (fname, x, y);
297  }
298  else if (args(0).type_id () == octave_uint32_matrix::static_type_id ()
299  || args(0).type_id () == octave_uint32_scalar::static_type_id ())
300  {
301  uint32NDArray x = args(0).uint32_array_value ();
302  uint32NDArray y = args(1).uint32_array_value ();
303  if (! error_state)
304  retval = bitopx (fname, x, y);
305  }
306  else if (args(0).type_id () == octave_uint16_matrix::static_type_id ()
307  || args(0).type_id () == octave_uint16_scalar::static_type_id ())
308  {
309  uint16NDArray x = args(0).uint16_array_value ();
310  uint16NDArray y = args(1).uint16_array_value ();
311  if (! error_state)
312  retval = bitopx (fname, x, y);
313  }
314  else if (args(0).type_id () == octave_uint8_matrix::static_type_id ()
315  || args(0).type_id () == octave_uint8_scalar::static_type_id ())
316  {
317  uint8NDArray x = args(0).uint8_array_value ();
318  uint8NDArray y = args(1).uint8_array_value ();
319  if (! error_state)
320  retval = bitopx (fname, x, y);
321  }
322  else if (args(0).type_id () == octave_int64_matrix::static_type_id ()
323  || args(0).type_id () == octave_int64_scalar::static_type_id ())
324  {
325  int64NDArray x = args(0).int64_array_value ();
326  int64NDArray y = args(1).int64_array_value ();
327  if (! error_state)
328  retval = bitopx (fname, x, y);
329  }
330  else if (args(0).type_id () == octave_int32_matrix::static_type_id ()
331  || args(0).type_id () == octave_int32_scalar::static_type_id ())
332  {
333  int32NDArray x = args(0).int32_array_value ();
334  int32NDArray y = args(1).int32_array_value ();
335  if (! error_state)
336  retval = bitopx (fname, x, y);
337  }
338  else if (args(0).type_id () == octave_int16_matrix::static_type_id ()
339  || args(0).type_id () == octave_int16_scalar::static_type_id ())
340  {
341  int16NDArray x = args(0).int16_array_value ();
342  int16NDArray y = args(1).int16_array_value ();
343  if (! error_state)
344  retval = bitopx (fname, x, y);
345  }
346  else if (args(0).type_id () == octave_int8_matrix::static_type_id ()
347  || args(0).type_id () == octave_int8_scalar::static_type_id ())
348  {
349  int8NDArray x = args(0).int8_array_value ();
350  int8NDArray y = args(1).int8_array_value ();
351  if (! error_state)
352  retval = bitopx (fname, x, y);
353  }
354  else
355  error ("%s: invalid operand type", fname.c_str ());
356  }
357  else
358  error ("%s: must have matching operand types", fname.c_str ());
359  }
360  else
361  print_usage ();
362 
363  return retval;
364 }
365 
366 DEFUN (bitand, args, ,
367  "-*- texinfo -*-\n\
368 @deftypefn {Built-in Function} {} bitand (@var{x}, @var{y})\n\
369 Return the bitwise AND of non-negative integers.\n\
370 \n\
371 @var{x}, @var{y} must be in the range [0,bitmax]\n\
372 @seealso{bitor, bitxor, bitset, bitget, bitcmp, bitshift, bitmax}\n\
373 @end deftypefn")
374 {
375  return bitop ("bitand", args);
376 }
377 
378 DEFUN (bitor, args, ,
379  "-*- texinfo -*-\n\
380 @deftypefn {Built-in Function} {} bitor (@var{x}, @var{y})\n\
381 Return the bitwise OR of non-negative integers.\n\
382 \n\
383 @var{x}, @var{y} must be in the range [0,bitmax]\n\
384 @seealso{bitor, bitxor, bitset, bitget, bitcmp, bitshift, bitmax}\n\
385 @end deftypefn")
386 {
387  return bitop ("bitor", args);
388 }
389 
390 DEFUN (bitxor, args, ,
391  "-*- texinfo -*-\n\
392 @deftypefn {Built-in Function} {} bitxor (@var{x}, @var{y})\n\
393 Return the bitwise XOR of non-negative integers.\n\
394 \n\
395 @var{x}, @var{y} must be in the range [0,bitmax]\n\
396 @seealso{bitand, bitor, bitset, bitget, bitcmp, bitshift, bitmax}\n\
397 @end deftypefn")
398 {
399  return bitop ("bitxor", args);
400 }
401 
402 /*
403 %!assert (bitand (true, false), false)
404 %!assert (bitor (true, false), true)
405 %!assert (bitxor (true, false), true)
406 
407 %!assert (bitand (true, true), true)
408 %!assert (bitor (true, true), true)
409 %!assert (bitxor (true, true), false)
410 
411 %!assert (bitand (true, 5), 1)
412 
413 %!assert (bitand (true, false), false)
414 %!assert (bitand (true, true), true)
415 %!assert (bitand (true, false), false)
416 %!assert (bitand (true, false), false)
417 
418 ## Test idx_arg.length () == 0
419 %!error <size of X and Y must match> bitand ([0 0 0], [1 0])
420 %!error <size of X and Y must match> bitand ([0; 0; 0], [0 0 0])
421 */
422 
423 template <typename T>
424 static int64_t
426 {
427  return (static_cast<int64_t> (1) << std::numeric_limits<T>::digits) - 1;
428 }
429 
430 static int64_t
431 bitshift (double a, int n, int64_t mask)
432 {
433  // In the name of bug-for-bug compatibility.
434  if (a < 0)
435  return -bitshift (-a, n, mask);
436 
437  if (n > 0)
438  return (static_cast<int64_t> (a) << n) & mask;
439  else if (n < 0)
440  return (static_cast<int64_t> (a) >> -n) & mask;
441  else
442  return static_cast<int64_t> (a) & mask;
443 }
444 
445 static int64_t
446 bitshift (float a, int n, int64_t mask)
447 {
448  // In the name of bug-for-bug compatibility.
449  if (a < 0)
450  return -bitshift (-a, n, mask);
451 
452  if (n > 0)
453  return (static_cast<int64_t> (a) << n) & mask;
454  else if (n < 0)
455  return (static_cast<int64_t> (a) >> -n) & mask;
456  else
457  return static_cast<int64_t> (a) & mask;
458 }
459 
460 // Note that the bitshift operators are undefined if shifted by more
461 // bits than in the type, so we need to test for the size of the
462 // shift.
463 
464 #define DO_BITSHIFT(T) \
465  if (! error_state) \
466  { \
467  double d1, d2; \
468  \
469  if (n.all_integers (d1, d2)) \
470  { \
471  int m_nel = m.numel (); \
472  int n_nel = n.numel (); \
473  \
474  bool is_scalar_op = (m_nel == 1 || n_nel == 1); \
475  \
476  dim_vector m_dv = m.dims (); \
477  dim_vector n_dv = n.dims (); \
478  \
479  bool is_array_op = (m_dv == n_dv); \
480  \
481  if (is_array_op || is_scalar_op) \
482  { \
483  T ## NDArray result; \
484  \
485  if (m_nel != 1) \
486  result.resize (m_dv); \
487  else \
488  result.resize (n_dv); \
489  \
490  for (int i = 0; i < m_nel; i++) \
491  if (is_scalar_op) \
492  for (int k = 0; k < n_nel; k++) \
493  if (static_cast<int> (n(k)) >= bits_in_type) \
494  result(i+k) = 0; \
495  else \
496  result(i+k) = bitshift (m(i), static_cast<int> (n(k)), mask); \
497  else \
498  if (static_cast<int> (n(i)) >= bits_in_type) \
499  result(i) = 0; \
500  else \
501  result(i) = bitshift (m(i), static_cast<int> (n(i)), mask); \
502  \
503  retval = result; \
504  } \
505  else \
506  error ("bitshift: size of A and N must match, or one operand must be a scalar"); \
507  } \
508  else \
509  error ("bitshift: expecting integer as second argument"); \
510  }
511 
512 #define DO_UBITSHIFT(T, N) \
513  do \
514  { \
515  int bits_in_type = octave_ ## T :: nbits (); \
516  T ## NDArray m = m_arg.T ## _array_value (); \
517  octave_ ## T mask = octave_ ## T::max (); \
518  if ((N) < bits_in_type) \
519  mask = bitshift (mask, (N) - bits_in_type); \
520  else if ((N) < 1) \
521  mask = 0; \
522  DO_BITSHIFT (T); \
523  } \
524  while (0)
525 
526 #define DO_SBITSHIFT(T, N) \
527  do \
528  { \
529  int bits_in_type = octave_ ## T :: nbits (); \
530  T ## NDArray m = m_arg.T ## _array_value (); \
531  octave_ ## T mask = octave_ ## T::max (); \
532  if ((N) < bits_in_type) \
533  mask = bitshift (mask, (N) - bits_in_type); \
534  else if ((N) < 1) \
535  mask = 0; \
536  mask = mask | octave_ ## T :: min (); /* FIXME: 2's complement only? */ \
537  DO_BITSHIFT (T); \
538  } \
539  while (0)
540 
541 DEFUN (bitshift, args, ,
542  "-*- texinfo -*-\n\
543 @deftypefn {Built-in Function} {} bitshift (@var{a}, @var{k})\n\
544 @deftypefnx {Built-in Function} {} bitshift (@var{a}, @var{k}, @var{n})\n\
545 Return a @var{k} bit shift of @var{n}-digit unsigned integers in @var{a}.\n\
546 \n\
547 A positive @var{k} leads to a left shift; A negative value to a right shift.\n\
548 \n\
549 If @var{n} is omitted it defaults to log2(bitmax)+1.\n\
550 @var{n} must be in the range [1,log2(bitmax)+1] usually [1,33].\n\
551 \n\
552 @example\n\
553 @group\n\
554 bitshift (eye (3), 1)\n\
555 @result{}\n\
556 @group\n\
557 2 0 0\n\
558 0 2 0\n\
559 0 0 2\n\
560 @end group\n\
561 \n\
562 bitshift (10, [-2, -1, 0, 1, 2])\n\
563 @result{} 2 5 10 20 40\n\
564 @c FIXME: restore this example when third arg is allowed to be an array.\n\
565 @c\n\
566 @c\n\
567 @c bitshift ([1, 10], 2, [3,4])\n\
568 @c @result{} 4 8\n\
569 @end group\n\
570 @end example\n\
571 @seealso{bitand, bitor, bitxor, bitset, bitget, bitcmp, bitmax}\n\
572 @end deftypefn")
573 {
574  octave_value retval;
575 
576  int nargin = args.length ();
577 
578  if (nargin == 2 || nargin == 3)
579  {
580  int nbits = 64;
581 
582  NDArray n = args(1).array_value ();
583 
584  if (error_state)
585  error ("bitshift: expecting integer as second argument");
586  else
587  {
588  if (nargin == 3)
589  {
590  // FIXME: for compatibility, we should accept an array
591  // or a scalar as the third argument.
592  if (args(2).numel () > 1)
593  error ("bitshift: N must be a scalar integer");
594  else
595  {
596  nbits = args(2).int_value ();
597 
598  if (error_state)
599  error ("bitshift: N must be an integer");
600  else if (nbits < 0)
601  error ("bitshift: N must be positive");
602  }
603  }
604  }
605 
606  if (error_state)
607  return retval;
608 
609  octave_value m_arg = args(0);
610  std::string cname = m_arg.class_name ();
611 
612  if (cname == "uint8")
613  DO_UBITSHIFT (uint8, nbits < 8 ? nbits : 8);
614  else if (cname == "uint16")
615  DO_UBITSHIFT (uint16, nbits < 16 ? nbits : 16);
616  else if (cname == "uint32")
617  DO_UBITSHIFT (uint32, nbits < 32 ? nbits : 32);
618  else if (cname == "uint64")
619  DO_UBITSHIFT (uint64, nbits < 64 ? nbits : 64);
620  else if (cname == "int8")
621  DO_SBITSHIFT (int8, nbits < 8 ? nbits : 8);
622  else if (cname == "int16")
623  DO_SBITSHIFT (int16, nbits < 16 ? nbits : 16);
624  else if (cname == "int32")
625  DO_SBITSHIFT (int32, nbits < 32 ? nbits : 32);
626  else if (cname == "int64")
627  DO_SBITSHIFT (int64, nbits < 64 ? nbits : 64);
628  else if (cname == "double")
629  {
630  static const int bits_in_mantissa
631  = std::numeric_limits<double>::digits;
632 
633  nbits = (nbits < bits_in_mantissa ? nbits : bits_in_mantissa);
634  int64_t mask = max_mantissa_value<double> ();
635  if (nbits < bits_in_mantissa)
636  mask = mask >> (bits_in_mantissa - nbits);
637  else if (nbits < 1)
638  mask = 0;
639  int bits_in_type = sizeof (double)
640  * std::numeric_limits<unsigned char>::digits;
641  NDArray m = m_arg.array_value ();
642  DO_BITSHIFT ();
643  }
644  else if (cname == "single")
645  {
646  static const int bits_in_mantissa
647  = std::numeric_limits<float>::digits;
648  nbits = (nbits < bits_in_mantissa ? nbits : bits_in_mantissa);
649  int64_t mask = max_mantissa_value<float> ();
650  if (nbits < bits_in_mantissa)
651  mask = mask >> (bits_in_mantissa - nbits);
652  else if (nbits < 1)
653  mask = 0;
654  int bits_in_type = sizeof (float)
655  * std::numeric_limits<unsigned char>::digits;
656  FloatNDArray m = m_arg.float_array_value ();
657  DO_BITSHIFT (Float);
658  }
659  else
660  error ("bitshift: not defined for %s objects", cname.c_str ());
661  }
662  else
663  print_usage ();
664 
665  return retval;
666 }
667 
668 /*
669 %!assert (bitshift (uint8 (16), 1), uint8 ( 32))
670 %!assert (bitshift (uint16 (16), 2), uint16 ( 64))
671 %!assert (bitshift (uint32 (16), 3), uint32 (128))
672 %!assert (bitshift (uint64 (16), 4), uint64 (256))
673 %!assert (bitshift (uint8 (255), 1), uint8 (254))
674 
675 %!error <expecting integer as second argument> bitshift (16, 1.5)
676 %!error bitshift (16, {1})
677 %!error <N must be a scalar integer> bitshift (10, [-2 -1 0 1 2], [1 1 1 1 1])
678 %!error <N must be positive> bitshift (10, [-2 -1 0 1 2], -1)
679 */
680 
681 DEFUN (bitmax, args, ,
682  "-*- texinfo -*-\n\
683 @deftypefn {Built-in Function} {} bitmax ()\n\
684 @deftypefnx {Built-in Function} {} bitmax (\"double\")\n\
685 @deftypefnx {Built-in Function} {} bitmax (\"single\")\n\
686 Return the largest integer that can be represented within a floating point\n\
687 value.\n\
688 \n\
689 The default class is @qcode{\"double\"}, but @qcode{\"single\"} is a\n\
690 valid option. On IEEE-754 compatible systems, @code{bitmax} is\n\
691 @w{@math{2^{53} - 1}} for @qcode{\"double\"} and @w{@math{2^{24} -1}} for\n\
692 @qcode{\"single\"}.\n\
693 @seealso{flintmax, intmax, realmax, realmin}\n\
694 @end deftypefn")
695 {
696  octave_value retval;
697  std::string cname = "double";
698  int nargin = args.length ();
699 
700  if (nargin == 1 && args(0).is_string ())
701  cname = args(0).string_value ();
702  else if (nargin != 0)
703  {
704  print_usage ();
705  return retval;
706  }
707 
708  if (cname == "double")
709  retval = (static_cast<double> (max_mantissa_value<double> ()));
710  else if (cname == "single")
711  retval = (static_cast<float> (max_mantissa_value<float> ()));
712  else
713  error ("bitmax: not defined for class '%s'", cname.c_str ());
714 
715  return retval;
716 }
717 
718 DEFUN (flintmax, args, ,
719  "-*- texinfo -*-\n\
720 @deftypefn {Built-in Function} {} flintmax ()\n\
721 @deftypefnx {Built-in Function} {} flintmax (\"double\")\n\
722 @deftypefnx {Built-in Function} {} flintmax (\"single\")\n\
723 Return the largest integer that can be represented consecutively in a\n\
724 floating point value.\n\
725 \n\
726 The default class is @qcode{\"double\"}, but @qcode{\"single\"} is a valid\n\
727 option. On IEEE-754 compatible systems, @code{flintmax} is @w{@math{2^53}}\n\
728 for @qcode{\"double\"} and @w{@math{2^24}} for @qcode{\"single\"}.\n\
729 @seealso{bitmax, intmax, realmax, realmin}\n\
730 @end deftypefn")
731 {
732  octave_value retval;
733  std::string cname = "double";
734  int nargin = args.length ();
735 
736  if (nargin == 1 && args(0).is_string ())
737  cname = args(0).string_value ();
738  else if (nargin != 0)
739  {
740  print_usage ();
741  return retval;
742  }
743 
744  if (cname == "double")
745  retval = (static_cast<double> (max_mantissa_value<double> () + 1));
746  else if (cname == "single")
747  retval = (static_cast<float> (max_mantissa_value<float> () + 1));
748  else
749  error ("flintmax: not defined for class '%s'", cname.c_str ());
750 
751  return retval;
752 }
753 
754 DEFUN (intmax, args, ,
755  "-*- texinfo -*-\n\
756 @deftypefn {Built-in Function} {} intmax (@var{type})\n\
757 Return the largest integer that can be represented in an integer type.\n\
758 \n\
759 The variable @var{type} can be\n\
760 \n\
761 @table @code\n\
762 @item int8\n\
763 signed 8-bit integer.\n\
764 \n\
765 @item int16\n\
766 signed 16-bit integer.\n\
767 \n\
768 @item int32\n\
769 signed 32-bit integer.\n\
770 \n\
771 @item int64\n\
772 signed 64-bit integer.\n\
773 \n\
774 @item uint8\n\
775 unsigned 8-bit integer.\n\
776 \n\
777 @item uint16\n\
778 unsigned 16-bit integer.\n\
779 \n\
780 @item uint32\n\
781 unsigned 32-bit integer.\n\
782 \n\
783 @item uint64\n\
784 unsigned 64-bit integer.\n\
785 @end table\n\
786 \n\
787 The default for @var{type} is @code{int32}.\n\
788 @seealso{intmin, flintmax, bitmax}\n\
789 @end deftypefn")
790 {
791  octave_value retval;
792  std::string cname = "int32";
793  int nargin = args.length ();
794 
795  if (nargin == 1 && args(0).is_string ())
796  cname = args(0).string_value ();
797  else if (nargin != 0)
798  {
799  print_usage ();
800  return retval;
801  }
802 
803  if (cname == "uint8")
805  else if (cname == "uint16")
807  else if (cname == "uint32")
809  else if (cname == "uint64")
811  else if (cname == "int8")
813  else if (cname == "int16")
815  else if (cname == "int32")
817  else if (cname == "int64")
819  else
820  error ("intmax: not defined for '%s' objects", cname.c_str ());
821 
822  return retval;
823 }
824 
825 DEFUN (intmin, args, ,
826  "-*- texinfo -*-\n\
827 @deftypefn {Built-in Function} {} intmin (@var{type})\n\
828 Return the smallest integer that can be represented in an integer type.\n\
829 \n\
830 The variable @var{type} can be\n\
831 \n\
832 @table @code\n\
833 @item int8\n\
834 signed 8-bit integer.\n\
835 \n\
836 @item int16\n\
837 signed 16-bit integer.\n\
838 \n\
839 @item int32\n\
840 signed 32-bit integer.\n\
841 \n\
842 @item int64\n\
843 signed 64-bit integer.\n\
844 \n\
845 @item uint8\n\
846 unsigned 8-bit integer.\n\
847 \n\
848 @item uint16\n\
849 unsigned 16-bit integer.\n\
850 \n\
851 @item uint32\n\
852 unsigned 32-bit integer.\n\
853 \n\
854 @item uint64\n\
855 unsigned 64-bit integer.\n\
856 @end table\n\
857 \n\
858 The default for @var{type} is @code{int32}.\n\
859 @seealso{intmax, flintmax, bitmax}\n\
860 @end deftypefn")
861 {
862  octave_value retval;
863  std::string cname = "int32";
864  int nargin = args.length ();
865 
866  if (nargin == 1 && args(0).is_string ())
867  cname = args(0).string_value ();
868  else if (nargin != 0)
869  {
870  print_usage ();
871  return retval;
872  }
873 
874  if (cname == "uint8")
876  else if (cname == "uint16")
878  else if (cname == "uint32")
880  else if (cname == "uint64")
882  else if (cname == "int8")
884  else if (cname == "int16")
886  else if (cname == "int32")
888  else if (cname == "int64")
890  else
891  error ("intmin: not defined for '%s' objects", cname.c_str ());
892 
893  return retval;
894 }
895 
896 DEFUN (sizemax, args, ,
897  "-*- texinfo -*-\n\
898 @deftypefn {Built-in Function} {} sizemax ()\n\
899 Return the largest value allowed for the size of an array.\n\
900 \n\
901 If Octave is compiled with 64-bit indexing, the result is of class int64,\n\
902 otherwise it is of class int32. The maximum array size is slightly\n\
903 smaller than the maximum value allowable for the relevant class as reported\n\
904 by @code{intmax}.\n\
905 @seealso{intmax}\n\
906 @end deftypefn")
907 {
908  octave_value retval;
909 
910  if (args.length () == 0)
912  else
913  print_usage ();
914 
915  return retval;
916 }
octave_int< uint32_t > octave_uint32
T operator()(const T &op1, const T &op2) const
Definition: bitfcns.cc:64
static int64_t bitshift(double a, int n, int64_t mask)
Definition: bitfcns.cc:431
static int64_t max_mantissa_value()
Definition: bitfcns.cc:425
octave_value bitopx(const std::string &fname, const Array< T > &x, const Array< T > &y)
Definition: bitfcns.cc:123
T operator()(const T &op1, const T &op2) const
Definition: bitfcns.cc:57
static std::string static_class_name(void)
Definition: ov-bool.h:245
OCTINTERP_API void print_usage(void)
Definition: defun.cc:51
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:275
octave_idx_type length(void) const
Definition: oct-obj.h:89
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:44
void error(const char *fmt,...)
Definition: error.cc:476
STL namespace.
octave_int< int16_t > octave_int16
boolNDArray bool_array_value(bool warn=false) const
Definition: ov.h:811
octave_int< int32_t > octave_int32
#define DO_SBITSHIFT(T, N)
Definition: bitfcns.cc:526
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:337
octave_int< uint16_t > octave_uint16
FloatNDArray float_array_value(bool frc_str_conv=false) const
Definition: ov.h:782
static std::string static_class_name(void)
Definition: ov-scalar.h:254
octave_int< int64_t > octave_int64
#define DO_BITSHIFT(T)
Definition: bitfcns.cc:464
int error_state
Definition: error.cc:101
void resize(const dim_vector &dv, const T &rfv)
Definition: Array.cc:1033
octave_value bitop(const std::string &fname, const octave_value_list &args)
Definition: bitfcns.cc:155
static std::string static_class_name(void)
Definition: ov-float.h:255
octave_int< uint64_t > octave_uint64
octave_idx_type length(void) const
Definition: ov.cc:1525
T operator()(const T &op1, const T &op2) const
Definition: bitfcns.cc:71
octave_value bitopxx(const OP &op, const std::string &fname, const Array< T > &x, const Array< T > &y)
Definition: bitfcns.cc:78
static int bitop_arg_is_float(const octave_value &arg)
Definition: bitfcns.cc:149
double arg(double x)
Definition: lo-mappers.h:37
#define DO_UBITSHIFT(T, N)
Definition: bitfcns.cc:512
Handles the reference counting for all the derived classes.
Definition: Array.h:45
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:233
NDArray array_value(bool frc_str_conv=false) const
Definition: ov.h:779
Array< octave_value > array_value(void) const
Definition: oct-obj.h:79
std::string class_name(void) const
Definition: ov.h:1049
static int bitop_arg_is_bool(const octave_value &arg)
Definition: bitfcns.cc:143
static octave_idx_type dim_max(void)
Definition: dim-vector.cc:37
static int bitop_arg_is_int(const octave_value &arg)
Definition: bitfcns.cc:135
octave_int< uint8_t > octave_uint8
octave_int< int8_t > octave_int8
F77_RET_T const double * x
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:210