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