GNU Octave  3.8.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-2013 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 
135 bitop (const std::string& fname, const octave_value_list& args)
136 {
137  octave_value retval;
138 
139  int nargin = args.length ();
140 
141  if (nargin == 2)
142  {
143  if ((args(0).class_name () == octave_scalar::static_class_name ())
144  || (args(0).class_name () == octave_float_scalar::static_class_name ())
145  || (args(0).class_name () == octave_bool::static_class_name ())
146  || (args(1).class_name () == octave_scalar::static_class_name ())
147  || (args(1).class_name () == octave_float_scalar::static_class_name ())
148  || (args(1).class_name () == octave_bool::static_class_name ()))
149  {
150  bool arg0_is_int = (args(0).class_name () !=
152  args(0).class_name () !=
154  args(0).class_name () !=
156  bool arg1_is_int = (args(1).class_name () !=
158  args(1).class_name () !=
160  args(1).class_name () !=
162  bool arg0_is_float = args(0).class_name () ==
164  bool arg1_is_float = args(1).class_name () ==
166 
167  if (! (arg0_is_int || arg1_is_int))
168  {
169  if (! (arg0_is_float || arg1_is_float))
170  {
171  uint64NDArray x (args(0).array_value ());
172  uint64NDArray y (args(1).array_value ());
173  if (! error_state)
174  retval = bitopx (fname, x, y).array_value ();
175  }
176  else if (arg0_is_float && arg1_is_float)
177  {
178  uint64NDArray x (args(0).float_array_value ());
179  uint64NDArray y (args(1).float_array_value ());
180  if (! error_state)
181  retval = bitopx (fname, x, y).float_array_value ();
182  }
183  else
184  {
185  int p = (arg0_is_float ? 1 : 0);
186  int q = (arg0_is_float ? 0 : 1);
187 
188  uint64NDArray x (args(p).array_value ());
189  uint64NDArray y (args(q).float_array_value ());
190  if (! error_state)
191  retval = bitopx (fname, x, y).float_array_value ();
192  }
193  }
194  else
195  {
196  int p = (arg0_is_int ? 1 : 0);
197  int q = (arg0_is_int ? 0 : 1);
198 
199  NDArray dx = args(p).array_value ();
200 
201  if (args(q).type_id () == octave_uint64_matrix::static_type_id ()
202  || args(q).type_id () == octave_uint64_scalar::static_type_id ())
203  {
204  uint64NDArray x (dx);
205  uint64NDArray y = args(q).uint64_array_value ();
206  if (! error_state)
207  retval = bitopx (fname, x, y);
208  }
209  else if (args(q).type_id () == octave_uint32_matrix::static_type_id ()
210  || args(q).type_id () == octave_uint32_scalar::static_type_id ())
211  {
212  uint32NDArray x (dx);
213  uint32NDArray y = args(q).uint32_array_value ();
214  if (! error_state)
215  retval = bitopx (fname, x, y);
216  }
217  else if (args(q).type_id () == octave_uint16_matrix::static_type_id ()
218  || args(q).type_id () == octave_uint16_scalar::static_type_id ())
219  {
220  uint16NDArray x (dx);
221  uint16NDArray y = args(q).uint16_array_value ();
222  if (! error_state)
223  retval = bitopx (fname, x, y);
224  }
225  else if (args(q).type_id () == octave_uint8_matrix::static_type_id ()
226  || args(q).type_id () == octave_uint8_scalar::static_type_id ())
227  {
228  uint8NDArray x (dx);
229  uint8NDArray y = args(q).uint8_array_value ();
230  if (! error_state)
231  retval = bitopx (fname, x, y);
232  }
233  else if (args(q).type_id () == octave_int64_matrix::static_type_id ()
234  || args(q).type_id () == octave_int64_scalar::static_type_id ())
235  {
236  int64NDArray x (dx);
237  int64NDArray y = args(q).int64_array_value ();
238  if (! error_state)
239  retval = bitopx (fname, x, y);
240  }
241  else if (args(q).type_id () == octave_int32_matrix::static_type_id ()
242  || args(q).type_id () == octave_int32_scalar::static_type_id ())
243  {
244  int32NDArray x (dx);
245  int32NDArray y = args(q).int32_array_value ();
246  if (! error_state)
247  retval = bitopx (fname, x, y);
248  }
249  else if (args(q).type_id () == octave_int16_matrix::static_type_id ()
250  || args(q).type_id () == octave_int16_scalar::static_type_id ())
251  {
252  int16NDArray x (dx);
253  int16NDArray y = args(q).int16_array_value ();
254  if (! error_state)
255  retval = bitopx (fname, x, y);
256  }
257  else if (args(q).type_id () == octave_int8_matrix::static_type_id ()
258  || args(q).type_id () == octave_int8_scalar::static_type_id ())
259  {
260  int8NDArray x (dx);
261  int8NDArray y = args(q).int8_array_value ();
262  if (! error_state)
263  retval = bitopx (fname, x, y);
264  }
265  else
266  error ("%s: invalid operand type", fname.c_str ());
267  }
268  }
269  else if (args(0).class_name () == args(1).class_name ())
270  {
271  if (args(0).type_id () == octave_uint64_matrix::static_type_id ()
272  || args(0).type_id () == octave_uint64_scalar::static_type_id ())
273  {
274  uint64NDArray x = args(0).uint64_array_value ();
275  uint64NDArray y = args(1).uint64_array_value ();
276  if (! error_state)
277  retval = bitopx (fname, x, y);
278  }
279  else if (args(0).type_id () == octave_uint32_matrix::static_type_id ()
280  || args(0).type_id () == octave_uint32_scalar::static_type_id ())
281  {
282  uint32NDArray x = args(0).uint32_array_value ();
283  uint32NDArray y = args(1).uint32_array_value ();
284  if (! error_state)
285  retval = bitopx (fname, x, y);
286  }
287  else if (args(0).type_id () == octave_uint16_matrix::static_type_id ()
288  || args(0).type_id () == octave_uint16_scalar::static_type_id ())
289  {
290  uint16NDArray x = args(0).uint16_array_value ();
291  uint16NDArray y = args(1).uint16_array_value ();
292  if (! error_state)
293  retval = bitopx (fname, x, y);
294  }
295  else if (args(0).type_id () == octave_uint8_matrix::static_type_id ()
296  || args(0).type_id () == octave_uint8_scalar::static_type_id ())
297  {
298  uint8NDArray x = args(0).uint8_array_value ();
299  uint8NDArray y = args(1).uint8_array_value ();
300  if (! error_state)
301  retval = bitopx (fname, x, y);
302  }
303  else if (args(0).type_id () == octave_int64_matrix::static_type_id ()
304  || args(0).type_id () == octave_int64_scalar::static_type_id ())
305  {
306  int64NDArray x = args(0).int64_array_value ();
307  int64NDArray y = args(1).int64_array_value ();
308  if (! error_state)
309  retval = bitopx (fname, x, y);
310  }
311  else if (args(0).type_id () == octave_int32_matrix::static_type_id ()
312  || args(0).type_id () == octave_int32_scalar::static_type_id ())
313  {
314  int32NDArray x = args(0).int32_array_value ();
315  int32NDArray y = args(1).int32_array_value ();
316  if (! error_state)
317  retval = bitopx (fname, x, y);
318  }
319  else if (args(0).type_id () == octave_int16_matrix::static_type_id ()
320  || args(0).type_id () == octave_int16_scalar::static_type_id ())
321  {
322  int16NDArray x = args(0).int16_array_value ();
323  int16NDArray y = args(1).int16_array_value ();
324  if (! error_state)
325  retval = bitopx (fname, x, y);
326  }
327  else if (args(0).type_id () == octave_int8_matrix::static_type_id ()
328  || args(0).type_id () == octave_int8_scalar::static_type_id ())
329  {
330  int8NDArray x = args(0).int8_array_value ();
331  int8NDArray y = args(1).int8_array_value ();
332  if (! error_state)
333  retval = bitopx (fname, x, y);
334  }
335  else
336  error ("%s: invalid operand type", fname.c_str ());
337  }
338  else
339  error ("%s: must have matching operand types", fname.c_str ());
340  }
341  else
342  print_usage ();
343 
344  return retval;
345 }
346 
347 DEFUN (bitand, args, ,
348  "-*- texinfo -*-\n\
349 @deftypefn {Built-in Function} {} bitand (@var{x}, @var{y})\n\
350 Return the bitwise AND of non-negative integers.\n\
351 @var{x}, @var{y} must be in the range [0,bitmax]\n\
352 @seealso{bitor, bitxor, bitset, bitget, bitcmp, bitshift, bitmax}\n\
353 @end deftypefn")
354 {
355  return bitop ("bitand", args);
356 }
357 
358 DEFUN (bitor, args, ,
359  "-*- texinfo -*-\n\
360 @deftypefn {Built-in Function} {} bitor (@var{x}, @var{y})\n\
361 Return the bitwise OR of non-negative integers.\n\
362 @var{x}, @var{y} must be in the range [0,bitmax]\n\
363 @seealso{bitor, bitxor, bitset, bitget, bitcmp, bitshift, bitmax}\n\
364 @end deftypefn")
365 {
366  return bitop ("bitor", args);
367 }
368 
369 DEFUN (bitxor, args, ,
370  "-*- texinfo -*-\n\
371 @deftypefn {Built-in Function} {} bitxor (@var{x}, @var{y})\n\
372 Return the bitwise XOR of non-negative integers.\n\
373 @var{x}, @var{y} must be in the range [0,bitmax]\n\
374 @seealso{bitand, bitor, bitset, bitget, bitcmp, bitshift, bitmax}\n\
375 @end deftypefn")
376 {
377  return bitop ("bitxor", args);
378 }
379 
380 template <typename T>
381 static int64_t
383 {
384  return (static_cast<int64_t> (1) << std::numeric_limits<T>::digits) - 1;
385 }
386 
387 static int64_t
388 bitshift (double a, int n, int64_t mask)
389 {
390  // In the name of bug-for-bug compatibility.
391  if (a < 0)
392  return -bitshift (-a, n, mask);
393 
394  if (n > 0)
395  return (static_cast<int64_t> (a) << n) & mask;
396  else if (n < 0)
397  return (static_cast<int64_t> (a) >> -n) & mask;
398  else
399  return static_cast<int64_t> (a) & mask;
400 }
401 
402 static int64_t
403 bitshift (float a, int n, int64_t mask)
404 {
405  // In the name of bug-for-bug compatibility.
406  if (a < 0)
407  return -bitshift (-a, n, mask);
408 
409  if (n > 0)
410  return (static_cast<int64_t> (a) << n) & mask;
411  else if (n < 0)
412  return (static_cast<int64_t> (a) >> -n) & mask;
413  else
414  return static_cast<int64_t> (a) & mask;
415 }
416 
417 // Note that the bitshift operators are undefined if shifted by more
418 // bits than in the type, so we need to test for the size of the
419 // shift.
420 
421 #define DO_BITSHIFT(T) \
422  if (! error_state) \
423  { \
424  double d1, d2; \
425  \
426  if (n.all_integers (d1, d2)) \
427  { \
428  int m_nel = m.numel (); \
429  int n_nel = n.numel (); \
430  \
431  bool is_scalar_op = (m_nel == 1 || n_nel == 1); \
432  \
433  dim_vector m_dv = m.dims (); \
434  dim_vector n_dv = n.dims (); \
435  \
436  bool is_array_op = (m_dv == n_dv); \
437  \
438  if (is_array_op || is_scalar_op) \
439  { \
440  T ## NDArray result; \
441  \
442  if (m_nel != 1) \
443  result.resize (m_dv); \
444  else \
445  result.resize (n_dv); \
446  \
447  for (int i = 0; i < m_nel; i++) \
448  if (is_scalar_op) \
449  for (int k = 0; k < n_nel; k++) \
450  if (static_cast<int> (n(k)) >= bits_in_type) \
451  result(i+k) = 0; \
452  else \
453  result(i+k) = bitshift (m(i), static_cast<int> (n(k)), mask); \
454  else \
455  if (static_cast<int> (n(i)) >= bits_in_type) \
456  result(i) = 0; \
457  else \
458  result(i) = bitshift (m(i), static_cast<int> (n(i)), mask); \
459  \
460  retval = result; \
461  } \
462  else \
463  error ("bitshift: size of A and N must match, or one operand must be a scalar"); \
464  } \
465  else \
466  error ("bitshift: expecting integer as second argument"); \
467  }
468 
469 #define DO_UBITSHIFT(T, N) \
470  do \
471  { \
472  int bits_in_type = octave_ ## T :: nbits (); \
473  T ## NDArray m = m_arg.T ## _array_value (); \
474  octave_ ## T mask = octave_ ## T::max (); \
475  if ((N) < bits_in_type) \
476  mask = bitshift (mask, (N) - bits_in_type); \
477  else if ((N) < 1) \
478  mask = 0; \
479  DO_BITSHIFT (T); \
480  } \
481  while (0)
482 
483 #define DO_SBITSHIFT(T, N) \
484  do \
485  { \
486  int bits_in_type = octave_ ## T :: nbits (); \
487  T ## NDArray m = m_arg.T ## _array_value (); \
488  octave_ ## T mask = octave_ ## T::max (); \
489  if ((N) < bits_in_type) \
490  mask = bitshift (mask, (N) - bits_in_type); \
491  else if ((N) < 1) \
492  mask = 0; \
493  mask = mask | octave_ ## T :: min (); /* FIXME: 2's complement only? */ \
494  DO_BITSHIFT (T); \
495  } \
496  while (0)
497 
498 DEFUN (bitshift, args, ,
499  "-*- texinfo -*-\n\
500 @deftypefn {Built-in Function} {} bitshift (@var{a}, @var{k})\n\
501 @deftypefnx {Built-in Function} {} bitshift (@var{a}, @var{k}, @var{n})\n\
502 Return a @var{k} bit shift of @var{n}-digit unsigned\n\
503 integers in @var{a}. A positive @var{k} leads to a left shift;\n\
504 A negative value to a right shift. If @var{n} is omitted it defaults\n\
505 to log2(bitmax)+1.\n\
506 @var{n} must be in the range [1,log2(bitmax)+1] usually [1,33].\n\
507 \n\
508 @example\n\
509 @group\n\
510 bitshift (eye (3), 1)\n\
511 @result{}\n\
512 @group\n\
513 2 0 0\n\
514 0 2 0\n\
515 0 0 2\n\
516 @end group\n\
517 \n\
518 bitshift (10, [-2, -1, 0, 1, 2])\n\
519 @result{} 2 5 10 20 40\n\
520 @c FIXME: restore this example when third arg is allowed to be an array.\n\
521 @c\n\
522 @c\n\
523 @c bitshift ([1, 10], 2, [3,4])\n\
524 @c @result{} 4 8\n\
525 @end group\n\
526 @end example\n\
527 @seealso{bitand, bitor, bitxor, bitset, bitget, bitcmp, bitmax}\n\
528 @end deftypefn")
529 {
530  octave_value retval;
531 
532  int nargin = args.length ();
533 
534  if (nargin == 2 || nargin == 3)
535  {
536  int nbits = 64;
537 
538  NDArray n = args(1).array_value ();
539 
540  if (error_state)
541  error ("bitshift: expecting integer as second argument");
542  else
543  {
544  if (nargin == 3)
545  {
546  // FIXME: for compatibility, we should accept an array
547  // or a scalar as the third argument.
548  if (args(2).numel () > 1)
549  error ("bitshift: N must be a scalar integer");
550  else
551  {
552  nbits = args(2).int_value ();
553 
554  if (error_state)
555  error ("bitshift: N must be an integer");
556  else if (nbits < 0)
557  error ("bitshift: N must be positive");
558  }
559  }
560  }
561 
562  if (error_state)
563  return retval;
564 
565  octave_value m_arg = args(0);
566  std::string cname = m_arg.class_name ();
567 
568  if (cname == "uint8")
569  DO_UBITSHIFT (uint8, nbits < 8 ? nbits : 8);
570  else if (cname == "uint16")
571  DO_UBITSHIFT (uint16, nbits < 16 ? nbits : 16);
572  else if (cname == "uint32")
573  DO_UBITSHIFT (uint32, nbits < 32 ? nbits : 32);
574  else if (cname == "uint64")
575  DO_UBITSHIFT (uint64, nbits < 64 ? nbits : 64);
576  else if (cname == "int8")
577  DO_SBITSHIFT (int8, nbits < 8 ? nbits : 8);
578  else if (cname == "int16")
579  DO_SBITSHIFT (int16, nbits < 16 ? nbits : 16);
580  else if (cname == "int32")
581  DO_SBITSHIFT (int32, nbits < 32 ? nbits : 32);
582  else if (cname == "int64")
583  DO_SBITSHIFT (int64, nbits < 64 ? nbits : 64);
584  else if (cname == "double")
585  {
586  static const int bits_in_mantissa
587  = std::numeric_limits<double>::digits;
588 
589  nbits = (nbits < bits_in_mantissa ? nbits : bits_in_mantissa);
590  int64_t mask = max_mantissa_value<double> ();
591  if (nbits < bits_in_mantissa)
592  mask = mask >> (bits_in_mantissa - nbits);
593  else if (nbits < 1)
594  mask = 0;
595  int bits_in_type = sizeof (double)
596  * std::numeric_limits<unsigned char>::digits;
597  NDArray m = m_arg.array_value ();
598  DO_BITSHIFT ( );
599  }
600  else if (cname == "single")
601  {
602  static const int bits_in_mantissa
603  = std::numeric_limits<float>::digits;
604  nbits = (nbits < bits_in_mantissa ? nbits : bits_in_mantissa);
605  int64_t mask = max_mantissa_value<float> ();
606  if (nbits < bits_in_mantissa)
607  mask = mask >> (bits_in_mantissa - nbits);
608  else if (nbits < 1)
609  mask = 0;
610  int bits_in_type = sizeof (float)
611  * std::numeric_limits<unsigned char>::digits;
612  FloatNDArray m = m_arg.float_array_value ();
613  DO_BITSHIFT (Float);
614  }
615  else
616  error ("bitshift: not defined for %s objects", cname.c_str ());
617  }
618  else
619  print_usage ();
620 
621  return retval;
622 }
623 
624 DEFUN (bitmax, args, ,
625  "-*- texinfo -*-\n\
626 @deftypefn {Built-in Function} {} bitmax ()\n\
627 @deftypefnx {Built-in Function} {} bitmax (\"double\")\n\
628 @deftypefnx {Built-in Function} {} bitmax (\"single\")\n\
629 Return the largest integer that can be represented within a floating point\n\
630 value. The default class is @qcode{\"double\"}, but @qcode{\"single\"} is a\n\
631 valid option. On IEEE-754 compatible systems, @code{bitmax} is\n\
632 @w{@math{2^{53} - 1}} for @qcode{\"double\"} and @w{@math{2^{24} -1}} for\n\
633 @qcode{\"single\"}.\n\
634 @seealso{flintmax, intmax, realmax, realmin}\n\
635 @end deftypefn")
636 {
637  octave_value retval;
638  std::string cname = "double";
639  int nargin = args.length ();
640 
641  if (nargin == 1 && args(0).is_string ())
642  cname = args(0).string_value ();
643  else if (nargin != 0)
644  {
645  print_usage ();
646  return retval;
647  }
648 
649  if (cname == "double")
650  retval = (static_cast<double> (max_mantissa_value<double> ()));
651  else if (cname == "single")
652  retval = (static_cast<float> (max_mantissa_value<float> ()));
653  else
654  error ("bitmax: not defined for class '%s'", cname.c_str ());
655 
656  return retval;
657 }
658 
659 DEFUN (flintmax, args, ,
660  "-*- texinfo -*-\n\
661 @deftypefn {Built-in Function} {} flintmax ()\n\
662 @deftypefnx {Built-in Function} {} flintmax (\"double\")\n\
663 @deftypefnx {Built-in Function} {} flintmax (\"single\")\n\
664 Return the largest integer that can be represented consecutively in a\n\
665 floating point value. The default class is @qcode{\"double\"}, but\n\
666 @qcode{\"single\"} is a valid option. On IEEE-754 compatible systems,\n\
667 @code{flintmax} is @w{@math{2^53}} for @qcode{\"double\"} and\n\
668 @w{@math{2^24}} for @qcode{\"single\"}.\n\
669 @seealso{bitmax, intmax, realmax, realmin}\n\
670 @end deftypefn")
671 {
672  octave_value retval;
673  std::string cname = "double";
674  int nargin = args.length ();
675 
676  if (nargin == 1 && args(0).is_string ())
677  cname = args(0).string_value ();
678  else if (nargin != 0)
679  {
680  print_usage ();
681  return retval;
682  }
683 
684  if (cname == "double")
685  retval = (static_cast<double> (max_mantissa_value<double> () + 1));
686  else if (cname == "single")
687  retval = (static_cast<float> (max_mantissa_value<float> () + 1));
688  else
689  error ("flintmax: not defined for class '%s'", cname.c_str ());
690 
691  return retval;
692 }
693 
694 DEFUN (intmax, args, ,
695  "-*- texinfo -*-\n\
696 @deftypefn {Built-in Function} {} intmax (@var{type})\n\
697 Return the largest integer that can be represented in an integer type.\n\
698 The variable @var{type} can be\n\
699 \n\
700 @table @code\n\
701 @item int8\n\
702 signed 8-bit integer.\n\
703 \n\
704 @item int16\n\
705 signed 16-bit integer.\n\
706 \n\
707 @item int32\n\
708 signed 32-bit integer.\n\
709 \n\
710 @item int64\n\
711 signed 64-bit integer.\n\
712 \n\
713 @item uint8\n\
714 unsigned 8-bit integer.\n\
715 \n\
716 @item uint16\n\
717 unsigned 16-bit integer.\n\
718 \n\
719 @item uint32\n\
720 unsigned 32-bit integer.\n\
721 \n\
722 @item uint64\n\
723 unsigned 64-bit integer.\n\
724 @end table\n\
725 \n\
726 The default for @var{type} is @code{int32}.\n\
727 @seealso{intmin, flintmax, bitmax}\n\
728 @end deftypefn")
729 {
730  octave_value retval;
731  std::string cname = "int32";
732  int nargin = args.length ();
733 
734  if (nargin == 1 && args(0).is_string ())
735  cname = args(0).string_value ();
736  else if (nargin != 0)
737  {
738  print_usage ();
739  return retval;
740  }
741 
742  if (cname == "uint8")
744  else if (cname == "uint16")
746  else if (cname == "uint32")
748  else if (cname == "uint64")
750  else if (cname == "int8")
752  else if (cname == "int16")
754  else if (cname == "int32")
756  else if (cname == "int64")
758  else
759  error ("intmax: not defined for '%s' objects", cname.c_str ());
760 
761  return retval;
762 }
763 
764 DEFUN (intmin, args, ,
765  "-*- texinfo -*-\n\
766 @deftypefn {Built-in Function} {} intmin (@var{type})\n\
767 Return the smallest integer that can be represented in an integer type.\n\
768 The variable @var{type} can be\n\
769 \n\
770 @table @code\n\
771 @item int8\n\
772 signed 8-bit integer.\n\
773 \n\
774 @item int16\n\
775 signed 16-bit integer.\n\
776 \n\
777 @item int32\n\
778 signed 32-bit integer.\n\
779 \n\
780 @item int64\n\
781 signed 64-bit integer.\n\
782 \n\
783 @item uint8\n\
784 unsigned 8-bit integer.\n\
785 \n\
786 @item uint16\n\
787 unsigned 16-bit integer.\n\
788 \n\
789 @item uint32\n\
790 unsigned 32-bit integer.\n\
791 \n\
792 @item uint64\n\
793 unsigned 64-bit integer.\n\
794 @end table\n\
795 \n\
796 The default for @var{type} is @code{int32}.\n\
797 @seealso{intmax, flintmax, bitmax}\n\
798 @end deftypefn")
799 {
800  octave_value retval;
801  std::string cname = "int32";
802  int nargin = args.length ();
803 
804  if (nargin == 1 && args(0).is_string ())
805  cname = args(0).string_value ();
806  else if (nargin != 0)
807  {
808  print_usage ();
809  return retval;
810  }
811 
812  if (cname == "uint8")
814  else if (cname == "uint16")
816  else if (cname == "uint32")
818  else if (cname == "uint64")
820  else if (cname == "int8")
822  else if (cname == "int16")
824  else if (cname == "int32")
826  else if (cname == "int64")
828  else
829  error ("intmin: not defined for '%s' objects", cname.c_str ());
830 
831  return retval;
832 }
833 
834 DEFUN (sizemax, args, ,
835  "-*- texinfo -*-\n\
836 @deftypefn {Built-in Function} {} sizemax ()\n\
837 Return the largest value allowed for the size of an array.\n\
838 If Octave is compiled with 64-bit indexing, the result is of class int64,\n\
839 otherwise it is of class int32. The maximum array size is slightly\n\
840 smaller than the maximum value allowable for the relevant class as reported\n\
841 by @code{intmax}.\n\
842 @seealso{intmax}\n\
843 @end deftypefn")
844 {
845  octave_value retval;
846 
847  if (args.length () == 0)
849  else
850  print_usage ();
851 
852  return retval;
853 }