50 #if !defined (HAVE_CXX_BITWISE_OP_TEMPLATES)
57 T
operator() (
const T & op1,
const T & op2)
const {
return (op1 & op2); }
64 T
operator() (
const T & op1,
const T & op2)
const {
return (op1 | op2); }
71 T
operator() (
const T & op1,
const T & op2)
const {
return (op1 ^ op2); }
76 template <
typename OP,
typename T>
78 bitopxx (
const OP& op,
const std::string& fname,
81 int nelx = x.
numel ();
82 int nely = y.
numel ();
84 bool is_scalar_op = (nelx == 1 || nely == 1);
89 bool is_array_op = (dvx == dvy);
92 if (is_array_op || is_scalar_op)
101 for (
int i = 0; i < nelx; i++)
103 for (
int k = 0; k < nely; k++)
104 result(i+k) = op (
x(i), y(k));
106 result(i) = op (
x(i), y(i));
111 error (
"%s: size of X and Y must match, or one operand must be a scalar",
125 if (fname ==
"bitand")
127 if (fname ==
"bitor")
139 int nargin = args.
length ();
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 () ==
167 if (! (arg0_is_int || arg1_is_int))
169 if (! (arg0_is_float || arg1_is_float))
176 else if (arg0_is_float && arg1_is_float)
185 int p = (arg0_is_float ? 1 : 0);
186 int q = (arg0_is_float ? 0 : 1);
196 int p = (arg0_is_int ? 1 : 0);
197 int q = (arg0_is_int ? 0 : 1);
201 if (args(q).type_id () == octave_uint64_matrix::static_type_id ()
202 || args(q).type_id () == octave_uint64_scalar::static_type_id ())
207 retval =
bitopx (fname, x, y);
209 else if (args(q).type_id () == octave_uint32_matrix::static_type_id ()
210 || args(q).type_id () == octave_uint32_scalar::static_type_id ())
215 retval =
bitopx (fname, x, y);
217 else if (args(q).type_id () == octave_uint16_matrix::static_type_id ()
218 || args(q).type_id () == octave_uint16_scalar::static_type_id ())
223 retval =
bitopx (fname, x, y);
225 else if (args(q).type_id () == octave_uint8_matrix::static_type_id ()
226 || args(q).type_id () == octave_uint8_scalar::static_type_id ())
231 retval =
bitopx (fname, x, y);
233 else if (args(q).type_id () == octave_int64_matrix::static_type_id ()
234 || args(q).type_id () == octave_int64_scalar::static_type_id ())
239 retval =
bitopx (fname, x, y);
241 else if (args(q).type_id () == octave_int32_matrix::static_type_id ()
242 || args(q).type_id () == octave_int32_scalar::static_type_id ())
247 retval =
bitopx (fname, x, y);
249 else if (args(q).type_id () == octave_int16_matrix::static_type_id ()
250 || args(q).type_id () == octave_int16_scalar::static_type_id ())
255 retval =
bitopx (fname, x, y);
257 else if (args(q).type_id () == octave_int8_matrix::static_type_id ()
258 || args(q).type_id () == octave_int8_scalar::static_type_id ())
263 retval =
bitopx (fname, x, y);
266 error (
"%s: invalid operand type", fname.c_str ());
269 else if (args(0).class_name () == args(1).class_name ())
271 if (args(0).type_id () == octave_uint64_matrix::static_type_id ()
272 || args(0).type_id () == octave_uint64_scalar::static_type_id ())
277 retval =
bitopx (fname, x, y);
279 else if (args(0).type_id () == octave_uint32_matrix::static_type_id ()
280 || args(0).type_id () == octave_uint32_scalar::static_type_id ())
285 retval =
bitopx (fname, x, y);
287 else if (args(0).type_id () == octave_uint16_matrix::static_type_id ()
288 || args(0).type_id () == octave_uint16_scalar::static_type_id ())
293 retval =
bitopx (fname, x, y);
295 else if (args(0).type_id () == octave_uint8_matrix::static_type_id ()
296 || args(0).type_id () == octave_uint8_scalar::static_type_id ())
301 retval =
bitopx (fname, x, y);
303 else if (args(0).type_id () == octave_int64_matrix::static_type_id ()
304 || args(0).type_id () == octave_int64_scalar::static_type_id ())
309 retval =
bitopx (fname, x, y);
311 else if (args(0).type_id () == octave_int32_matrix::static_type_id ()
312 || args(0).type_id () == octave_int32_scalar::static_type_id ())
317 retval =
bitopx (fname, x, y);
319 else if (args(0).type_id () == octave_int16_matrix::static_type_id ()
320 || args(0).type_id () == octave_int16_scalar::static_type_id ())
325 retval =
bitopx (fname, x, y);
327 else if (args(0).type_id () == octave_int8_matrix::static_type_id ()
328 || args(0).type_id () == octave_int8_scalar::static_type_id ())
333 retval =
bitopx (fname, x, y);
336 error (
"%s: invalid operand type", fname.c_str ());
339 error (
"%s: must have matching operand types", fname.c_str ());
347 DEFUN (bitand, args, ,
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\
355 return bitop (
"bitand", args);
358 DEFUN (bitor, args, ,
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\
366 return bitop (
"bitor", args);
369 DEFUN (bitxor, args, ,
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\
377 return bitop (
"bitxor", args);
380 template <
typename T>
384 return (static_cast<int64_t> (1) << std::numeric_limits<T>::digits) - 1;
395 return (static_cast<int64_t> (a) << n) & mask;
397 return (static_cast<int64_t> (a) >> -n) & mask;
399 return static_cast<int64_t
> (a) & mask;
410 return (static_cast<int64_t> (a) << n) & mask;
412 return (static_cast<int64_t> (a) >> -n) & mask;
414 return static_cast<int64_t
> (a) & mask;
421 #define DO_BITSHIFT(T) \
426 if (n.all_integers (d1, d2)) \
428 int m_nel = m.numel (); \
429 int n_nel = n.numel (); \
431 bool is_scalar_op = (m_nel == 1 || n_nel == 1); \
433 dim_vector m_dv = m.dims (); \
434 dim_vector n_dv = n.dims (); \
436 bool is_array_op = (m_dv == n_dv); \
438 if (is_array_op || is_scalar_op) \
440 T ## NDArray result; \
443 result.resize (m_dv); \
445 result.resize (n_dv); \
447 for (int i = 0; i < m_nel; i++) \
449 for (int k = 0; k < n_nel; k++) \
450 if (static_cast<int> (n(k)) >= bits_in_type) \
453 result(i+k) = bitshift (m(i), static_cast<int> (n(k)), mask); \
455 if (static_cast<int> (n(i)) >= bits_in_type) \
458 result(i) = bitshift (m(i), static_cast<int> (n(i)), mask); \
463 error ("bitshift: size of A and N must match, or one operand must be a scalar"); \
466 error ("bitshift: expecting integer as second argument"); \
469 #define DO_UBITSHIFT(T, N) \
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); \
483 #define DO_SBITSHIFT(T, N) \
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); \
493 mask = mask | octave_ ## T :: min (); \
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\
510 bitshift (eye (3), 1)\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\
523 @c bitshift ([1, 10], 2, [3,4])\n\
527 @seealso{bitand, bitor, bitxor, bitset, bitget, bitcmp, bitmax}\n\
532 int nargin = args.
length ();
534 if (nargin == 2 || nargin == 3)
538 NDArray n = args(1).array_value ();
541 error (
"bitshift: expecting integer as second argument");
548 if (args(2).numel () > 1)
549 error (
"bitshift: N must be a scalar integer");
552 nbits = args(2).int_value ();
555 error (
"bitshift: N must be an integer");
557 error (
"bitshift: N must be positive");
568 if (cname ==
"uint8")
570 else if (cname ==
"uint16")
572 else if (cname ==
"uint32")
574 else if (cname ==
"uint64")
576 else if (cname ==
"int8")
578 else if (cname ==
"int16")
580 else if (cname ==
"int32")
582 else if (cname ==
"int64")
584 else if (cname ==
"double")
586 static const int bits_in_mantissa
587 = std::numeric_limits<double>::digits;
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);
595 int bits_in_type =
sizeof (
double)
596 * std::numeric_limits<unsigned char>::digits;
600 else if (cname ==
"single")
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);
610 int bits_in_type =
sizeof (
float)
611 * std::numeric_limits<unsigned char>::digits;
616 error (
"bitshift: not defined for %s objects", cname.c_str ());
624 DEFUN (bitmax, args, ,
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\
638 std::string cname =
"double";
639 int nargin = args.
length ();
641 if (nargin == 1 && args(0).is_string ())
642 cname = args(0).string_value ();
643 else if (nargin != 0)
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> ()));
654 error (
"bitmax: not defined for class '%s'", cname.c_str ());
659 DEFUN (flintmax, args, ,
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\
673 std::string cname =
"double";
674 int nargin = args.
length ();
676 if (nargin == 1 && args(0).is_string ())
677 cname = args(0).string_value ();
678 else if (nargin != 0)
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));
689 error (
"flintmax: not defined for class '%s'", cname.c_str ());
694 DEFUN (intmax, args, ,
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\
702 signed 8-bit integer.\n\
705 signed 16-bit integer.\n\
708 signed 32-bit integer.\n\
711 signed 64-bit integer.\n\
714 unsigned 8-bit integer.\n\
717 unsigned 16-bit integer.\n\
720 unsigned 32-bit integer.\n\
723 unsigned 64-bit integer.\n\
726 The default for @var{type} is @code{int32}.\n\
727 @seealso{intmin, flintmax, bitmax}\n\
731 std::string cname =
"int32";
732 int nargin = args.
length ();
734 if (nargin == 1 && args(0).is_string ())
735 cname = args(0).string_value ();
736 else if (nargin != 0)
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")
759 error (
"intmax: not defined for '%s' objects", cname.c_str ());
764 DEFUN (intmin, args, ,
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\
772 signed 8-bit integer.\n\
775 signed 16-bit integer.\n\
778 signed 32-bit integer.\n\
781 signed 64-bit integer.\n\
784 unsigned 8-bit integer.\n\
787 unsigned 16-bit integer.\n\
790 unsigned 32-bit integer.\n\
793 unsigned 64-bit integer.\n\
796 The default for @var{type} is @code{int32}.\n\
797 @seealso{intmax, flintmax, bitmax}\n\
801 std::string cname =
"int32";
802 int nargin = args.
length ();
804 if (nargin == 1 && args(0).is_string ())
805 cname = args(0).string_value ();
806 else if (nargin != 0)
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")
829 error (
"intmin: not defined for '%s' objects", cname.c_str ());
834 DEFUN (sizemax, args, ,
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\
847 if (args.length () == 0)