GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
bitfcns.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 2004-2025 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)
55
56template <typename T>
57struct bit_and
58{
59public:
60 T operator() (const T& op1, const T& op2) const { return (op1 & op2); }
61};
62
63template <typename T>
64struct bit_or
65{
66public:
67 T operator() (const T& op1, const T& op2) const { return (op1 | op2); }
68};
69
70template <typename T>
71struct bit_xor
72{
73public:
74 T operator() (const T& op1, const T& op2) const { return (op1 ^ op2); }
75};
76
77OCTAVE_END_NAMESPACE(std)
78#endif
79
81
82template <typename OP, typename T>
84bitopxx (const OP& op, const std::string& fname,
85 const Array<T>& x, const Array<T>& y)
86{
87 int nelx = x.numel ();
88 int nely = y.numel ();
89
90 bool is_scalar_op = (nelx == 1 || nely == 1);
91
92 const dim_vector& dvx = x.dims ();
93 const dim_vector& dvy = y.dims ();
94
95 bool is_array_op = (dvx == dvy);
96
97 if (! is_array_op && ! is_scalar_op)
98 error ("%s: size of X and Y must match, or one operand must be a scalar",
99 fname.c_str ());
100
101 Array<T> result;
102
103 if (nelx != 1)
104 result.resize (dvx);
105 else
106 result.resize (dvy);
107
108 for (int i = 0; i < nelx; i++)
109 if (is_scalar_op)
110 for (int k = 0; k < nely; k++)
111 result(i+k) = op (x(i), y(k));
112 else
113 result(i) = op (x(i), y(i));
114
115 return result;
116}
117
118// Trampoline function, instantiates the proper template above, with
119// reflective information hardwired. We can't hardwire this information
120// in Fbitxxx DEFUNs below, because at that moment, we still don't have
121// information about which integer types we need to instantiate.
122template <typename T>
124bitopx (const std::string& fname, const Array<T>& x, const Array<T>& y)
125{
126 if (fname == "bitand")
127 return bitopxx (std::bit_and<T>(), fname, x, y);
128 if (fname == "bitor")
129 return bitopxx (std::bit_or<T>(), fname, x, y);
130
131 //else (fname == "bitxor")
132 return bitopxx (std::bit_xor<T>(), fname, x, y);
133}
134
135static inline int
136bitop_arg_is_int (const octave_value& arg)
137{
141}
142
143static inline int
144bitop_arg_is_bool (const octave_value& arg)
145{
146 return arg.class_name () == octave_bool::static_class_name ();
147}
148
149static inline int
150bitop_arg_is_float (const octave_value& arg)
151{
153}
154
156bitop (const std::string& fname, const octave_value_list& args)
157{
158 if (args.length () != 2)
159 print_usage ();
160
161 octave_value retval;
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 return retval;
361}
362
363DEFUN (bitand, args, ,
364 doc: /* -*- texinfo -*-
365@deftypefn {} {@var{z} =} bitand (@var{x}, @var{y})
366Return the bitwise AND of non-negative integers.
367
368@var{x}, @var{y} must be in the range [0,intmax]
369@seealso{bitor, bitxor, bitset, bitget, bitcmp, bitshift, intmax, flintmax}
370@end deftypefn */)
371{
372 return bitop ("bitand", args);
373}
374
375/*
376%!# Function bitand is tested as part of bitxor BIST tests
377*/
378
379DEFUN (bitor, args, ,
380 doc: /* -*- texinfo -*-
381@deftypefn {} {@var{z} =} bitor (@var{x}, @var{y})
382Return the bitwise OR of non-negative integers @var{x} and @var{y}.
383
384@seealso{bitor, bitxor, bitset, bitget, bitcmp, bitshift, intmax, flintmax}
385@end deftypefn */)
386{
387 return bitop ("bitor", args);
388}
389
390/*
391%!# Function bitor is tested as part of bitxor BIST tests
392*/
393
394DEFUN (bitxor, args, ,
395 doc: /* -*- texinfo -*-
396@deftypefn {} {@var{z} =} bitxor (@var{x}, @var{y})
397Return the bitwise XOR of non-negative integers @var{x} and @var{y}.
398
399@seealso{bitand, bitor, bitset, bitget, bitcmp, bitshift, intmax, flintmax}
400@end deftypefn */)
401{
402 return bitop ("bitxor", args);
403}
404
405/*
406%!assert (bitand (true, false), false)
407%!assert (bitor (true, false), true)
408%!assert (bitxor (true, false), true)
409
410%!assert (bitand (true, true), true)
411%!assert (bitor (true, true), true)
412%!assert (bitxor (true, true), false)
413
414%!assert (bitand (true, 5), 1)
415
416%!assert (bitand (true, false), false)
417%!assert (bitand (true, true), true)
418%!assert (bitand (true, false), false)
419%!assert (bitand (true, false), false)
420
421## Test idx_arg.length () == 0
422%!error <size of X and Y must match> bitand ([0 0 0], [1 0])
423%!error <size of X and Y must match> bitand ([0; 0; 0], [0 0 0])
424*/
425
426template <typename T>
427static int64_t
428max_mantissa_value ()
429{
430 return (static_cast<int64_t> (1) << std::numeric_limits<T>::digits) - 1;
431}
432
433static int64_t
434bitshift (double a, int n, int64_t mask)
435{
436 // In the name of bug-for-bug compatibility.
437 if (a < 0)
438 return -bitshift (-a, n, mask);
439
440 if (n > 0)
441 return (static_cast<int64_t> (a) << n) & mask;
442 else if (n < 0)
443 return (static_cast<int64_t> (a) >> -n) & mask;
444 else
445 return static_cast<int64_t> (a) & mask;
446}
447
448static int64_t
449bitshift (float a, int n, int64_t mask)
450{
451 // In the name of bug-for-bug compatibility.
452 if (a < 0)
453 return -bitshift (-a, n, mask);
454
455 if (n > 0)
456 return (static_cast<int64_t> (a) << n) & mask;
457 else if (n < 0)
458 return (static_cast<int64_t> (a) >> -n) & mask;
459 else
460 return static_cast<int64_t> (a) & mask;
461}
462
463// Note that the bitshift operators are undefined if shifted by more
464// bits than in the type, so we need to test for the size of the
465// shift.
466
467#define DO_BITSHIFT(T) \
468 double d1, d2; \
469 \
470 if (! n.all_integers (d1, d2)) \
471 error ("bitshift: K must be a scalar or array of integers"); \
472 \
473 int m_nel = m.numel (); \
474 int n_nel = n.numel (); \
475 \
476 bool is_scalar_op = (m_nel == 1 || n_nel == 1); \
477 \
478 const dim_vector& m_dv = m.dims (); \
479 const dim_vector& n_dv = n.dims (); \
480 \
481 bool is_array_op = (m_dv == n_dv); \
482 \
483 if (! is_array_op && ! is_scalar_op) \
484 error ("bitshift: size of A and N must match, or one operand must be a scalar"); \
485 \
486 T ## NDArray result; \
487 \
488 if (m_nel != 1) \
489 result.resize (m_dv); \
490 else \
491 result.resize (n_dv); \
492 \
493 for (int i = 0; i < m_nel; i++) \
494 if (is_scalar_op) \
495 for (int k = 0; k < n_nel; k++) \
496 if (static_cast<int> (n(k)) >= bits_in_type) \
497 result(i+k) = 0; \
498 else \
499 result(i+k) = bitshift (m(i), static_cast<int> (n(k)), mask); \
500 else \
501 if (static_cast<int> (n(i)) >= bits_in_type) \
502 result(i) = 0; \
503 else \
504 result(i) = bitshift (m(i), static_cast<int> (n(i)), mask); \
505 \
506 retval = result;
507
508#define DO_UBITSHIFT(T, N) \
509 do \
510 { \
511 int bits_in_type = octave_ ## T :: nbits (); \
512 T ## NDArray m = m_arg.T ## _array_value (); \
513 octave_ ## T mask = octave_ ## T::max (); \
514 if ((N) < bits_in_type) \
515 mask = bitshift (mask, (N) - bits_in_type); \
516 else if ((N) < 1) \
517 mask = 0; \
518 DO_BITSHIFT (T); \
519 } \
520 while (0)
521
522#define DO_SBITSHIFT(T, N) \
523 do \
524 { \
525 int bits_in_type = octave_ ## T :: nbits (); \
526 T ## NDArray m = m_arg.T ## _array_value (); \
527 octave_ ## T mask = octave_ ## T::max (); \
528 if ((N) < bits_in_type) \
529 mask = bitshift (mask, (N) - bits_in_type); \
530 else if ((N) < 1) \
531 mask = 0; \
532 /* FIXME: 2's complement only? */ \
533 mask = mask | octave_ ## T :: min (); \
534 DO_BITSHIFT (T); \
535 } \
536 while (0)
537
538DEFUN (bitshift, args, ,
539 doc: /* -*- texinfo -*-
540@deftypefn {} {@var{B} =} bitshift (@var{A}, @var{k})
541@deftypefnx {} {@var{B} =} bitshift (@var{A}, @var{k}, @var{n})
542Return a @var{k} bit shift of @var{n}-digit unsigned integers in @var{A}.
543
544A positive @var{k} leads to a left shift; A negative value to a right shift.
545
546If @var{n} is omitted it defaults to 64. @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).strict_int_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 {} {@var{Imax} =} flintmax ()
662@deftypefnx {} {@var{Imax} =} flintmax ("double")
663@deftypefnx {} {@var{Imax} =} flintmax ("single")
664@deftypefnx {} {@var{Imax} =} 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 {} {@var{Imax} =} intmax ()
730@deftypefnx {} {@var{Imax} =} intmax ("@var{type}")
731@deftypefnx {} {@var{Imax} =} 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")
799 retval = octave_uint8 (std::numeric_limits<uint8_t>::max ());
800 else if (cname == "uint16")
801 retval = octave_uint16 (std::numeric_limits<uint16_t>::max ());
802 else if (cname == "uint32")
803 retval = octave_uint32 (std::numeric_limits<uint32_t>::max ());
804 else if (cname == "uint64")
805 retval = octave_uint64 (std::numeric_limits<uint64_t>::max ());
806 else if (cname == "int8")
807 retval = octave_int8 (std::numeric_limits<int8_t>::max ());
808 else if (cname == "int16")
809 retval = octave_int16 (std::numeric_limits<int16_t>::max ());
810 else if (cname == "int32")
811 retval = octave_int32 (std::numeric_limits<int32_t>::max ());
812 else if (cname == "int64")
813 retval = octave_int64 (std::numeric_limits<int64_t>::max ());
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 {} {@var{Imin} =} intmin ()
844@deftypefnx {} {@var{Imin} =} intmin ("@var{type}")
845@deftypefnx {} {@var{Imin} =} 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")
913 retval = octave_uint8 (std::numeric_limits<uint8_t>::min ());
914 else if (cname == "uint16")
915 retval = octave_uint16 (std::numeric_limits<uint16_t>::min ());
916 else if (cname == "uint32")
917 retval = octave_uint32 (std::numeric_limits<uint32_t>::min ());
918 else if (cname == "uint64")
919 retval = octave_uint64 (std::numeric_limits<uint64_t>::min ());
920 else if (cname == "int8")
921 retval = octave_int8 (std::numeric_limits<int8_t>::min ());
922 else if (cname == "int16")
923 retval = octave_int16 (std::numeric_limits<int16_t>::min ());
924 else if (cname == "int32")
925 retval = octave_int32 (std::numeric_limits<int32_t>::min ());
926 else if (cname == "int64")
927 retval = octave_int64 (std::numeric_limits<int64_t>::min ());
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 {} {@var{max_numel} =} 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 smaller
962than the maximum value allowable for the relevant class as reported by
963@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_END_NAMESPACE(octave)
octave_value bitop(const std::string &fname, const octave_value_list &args)
Definition bitfcns.cc:156
octave_value bitopxx(const OP &op, const std::string &fname, const Array< T > &x, const Array< T > &y)
Definition bitfcns.cc:84
octave_value bitopx(const std::string &fname, const Array< T > &x, const Array< T > &y)
Definition bitfcns.cc:124
#define DO_BITSHIFT(T)
Definition bitfcns.cc:467
#define DO_UBITSHIFT(T, N)
Definition bitfcns.cc:508
#define DO_SBITSHIFT(T, N)
Definition bitfcns.cc:522
N Dimensional Array with copy-on-write semantics.
Definition Array.h:130
const dim_vector & dims() const
Return a const-reference so that dims ()(i) works efficiently.
Definition Array.h:507
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
octave_idx_type numel() const
Number of elements in the array.
Definition Array.h:418
Vector representing the dimensions (size) of an Array.
Definition dim-vector.h:90
static octave_idx_type dim_max()
Definition dim-vector.cc:44
static std::string static_class_name()
Definition ov-bool.h:261
static std::string static_class_name()
Definition ov-float.h:277
static std::string static_class_name()
Definition ov-scalar.h:290
static int static_type_id()
Definition ov-intx.h:386
static int static_type_id()
Definition ov-intx.h:701
Array< octave_value > array_value() const
Definition ovl.h:88
octave_idx_type length() const
Definition ovl.h:111
boolNDArray bool_array_value(bool warn=false) const
Definition ov.h:900
std::string class_name() const
Definition ov.h:1362
octave_idx_type numel() const
Definition ov.h:559
NDArray array_value(bool frc_str_conv=false) const
Definition ov.h:865
octave_idx_type length() const
FloatNDArray float_array_value(bool frc_str_conv=false) const
Definition ov.h:868
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void print_usage()
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:1003
bool isinteger(double x)
Definition lo-mappers.h:225
F77_RET_T const F77_DBLE * x
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
template octave_int< int8_t > bitshift(const octave_int< int8_t > &, int, const octave_int< int8_t > &)
T::size_type numel(const T &str)
Definition oct-string.cc:74
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition ovl.h:217