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")
159 int nargin = args.
length ();
179 if (! (arg0_is_int || arg1_is_int))
181 if (arg0_is_bool && arg1_is_bool)
188 else if (arg0_is_float && arg1_is_float)
195 else if (! (arg0_is_float || arg1_is_float))
204 int p = (arg0_is_float ? 1 : 0);
205 int q = (arg0_is_float ? 0 : 1);
215 int p = (arg0_is_int ? 1 : 0);
216 int q = (arg0_is_int ? 0 : 1);
220 if (args(q).type_id () == octave_uint64_matrix::static_type_id ()
221 || args(q).type_id () == octave_uint64_scalar::static_type_id ())
226 retval =
bitopx (fname, x, y);
228 else if (args(q).type_id () == octave_uint32_matrix::static_type_id ()
229 || args(q).type_id () == octave_uint32_scalar::static_type_id ())
234 retval =
bitopx (fname, x, y);
236 else if (args(q).type_id () == octave_uint16_matrix::static_type_id ()
237 || args(q).type_id () == octave_uint16_scalar::static_type_id ())
242 retval =
bitopx (fname, x, y);
244 else if (args(q).type_id () == octave_uint8_matrix::static_type_id ()
245 || args(q).type_id () == octave_uint8_scalar::static_type_id ())
250 retval =
bitopx (fname, x, y);
252 else if (args(q).type_id () == octave_int64_matrix::static_type_id ()
253 || args(q).type_id () == octave_int64_scalar::static_type_id ())
258 retval =
bitopx (fname, x, y);
260 else if (args(q).type_id () == octave_int32_matrix::static_type_id ()
261 || args(q).type_id () == octave_int32_scalar::static_type_id ())
266 retval =
bitopx (fname, x, y);
268 else if (args(q).type_id () == octave_int16_matrix::static_type_id ()
269 || args(q).type_id () == octave_int16_scalar::static_type_id ())
274 retval =
bitopx (fname, x, y);
276 else if (args(q).type_id () == octave_int8_matrix::static_type_id ()
277 || args(q).type_id () == octave_int8_scalar::static_type_id ())
282 retval =
bitopx (fname, x, y);
285 error (
"%s: invalid operand type", fname.c_str ());
288 else if (args(0).class_name () == args(1).class_name ())
290 if (args(0).type_id () == octave_uint64_matrix::static_type_id ()
291 || args(0).type_id () == octave_uint64_scalar::static_type_id ())
296 retval =
bitopx (fname, x, y);
298 else if (args(0).type_id () == octave_uint32_matrix::static_type_id ()
299 || args(0).type_id () == octave_uint32_scalar::static_type_id ())
304 retval =
bitopx (fname, x, y);
306 else if (args(0).type_id () == octave_uint16_matrix::static_type_id ()
307 || args(0).type_id () == octave_uint16_scalar::static_type_id ())
312 retval =
bitopx (fname, x, y);
314 else if (args(0).type_id () == octave_uint8_matrix::static_type_id ()
315 || args(0).type_id () == octave_uint8_scalar::static_type_id ())
320 retval =
bitopx (fname, x, y);
322 else if (args(0).type_id () == octave_int64_matrix::static_type_id ()
323 || args(0).type_id () == octave_int64_scalar::static_type_id ())
328 retval =
bitopx (fname, x, y);
330 else if (args(0).type_id () == octave_int32_matrix::static_type_id ()
331 || args(0).type_id () == octave_int32_scalar::static_type_id ())
336 retval =
bitopx (fname, x, y);
338 else if (args(0).type_id () == octave_int16_matrix::static_type_id ()
339 || args(0).type_id () == octave_int16_scalar::static_type_id ())
344 retval =
bitopx (fname, x, y);
346 else if (args(0).type_id () == octave_int8_matrix::static_type_id ()
347 || args(0).type_id () == octave_int8_scalar::static_type_id ())
352 retval =
bitopx (fname, x, y);
355 error (
"%s: invalid operand type", fname.c_str ());
358 error (
"%s: must have matching operand types", fname.c_str ());
366 DEFUN (bitand, args, ,
368 @deftypefn {Built-in Function} {} bitand (@var{x}, @var{y})\n\
369 Return the bitwise AND of non-negative integers.\n\
371 @var{x}, @var{y} must be in the range [0,bitmax]\n\
372 @seealso{bitor, bitxor, bitset, bitget, bitcmp, bitshift, bitmax}\n\
375 return bitop (
"bitand", args);
378 DEFUN (bitor, args, ,
380 @deftypefn {Built-in Function} {} bitor (@var{x}, @var{y})\n\
381 Return the bitwise OR of non-negative integers.\n\
383 @var{x}, @var{y} must be in the range [0,bitmax]\n\
384 @seealso{bitor, bitxor, bitset, bitget, bitcmp, bitshift, bitmax}\n\
387 return bitop (
"bitor", args);
390 DEFUN (bitxor, args, ,
392 @deftypefn {Built-in Function} {} bitxor (@var{x}, @var{y})\n\
393 Return the bitwise XOR of non-negative integers.\n\
395 @var{x}, @var{y} must be in the range [0,bitmax]\n\
396 @seealso{bitand, bitor, bitset, bitget, bitcmp, bitshift, bitmax}\n\
399 return bitop (
"bitxor", args);
423 template <
typename T>
427 return (static_cast<int64_t> (1) << std::numeric_limits<T>::digits) - 1;
438 return (static_cast<int64_t> (a) << n) & mask;
440 return (static_cast<int64_t> (a) >> -n) & mask;
442 return static_cast<int64_t
> (a) & mask;
453 return (static_cast<int64_t> (a) << n) & mask;
455 return (static_cast<int64_t> (a) >> -n) & mask;
457 return static_cast<int64_t
> (a) & mask;
464 #define DO_BITSHIFT(T) \
469 if (n.all_integers (d1, d2)) \
471 int m_nel = m.numel (); \
472 int n_nel = n.numel (); \
474 bool is_scalar_op = (m_nel == 1 || n_nel == 1); \
476 dim_vector m_dv = m.dims (); \
477 dim_vector n_dv = n.dims (); \
479 bool is_array_op = (m_dv == n_dv); \
481 if (is_array_op || is_scalar_op) \
483 T ## NDArray result; \
486 result.resize (m_dv); \
488 result.resize (n_dv); \
490 for (int i = 0; i < m_nel; i++) \
492 for (int k = 0; k < n_nel; k++) \
493 if (static_cast<int> (n(k)) >= bits_in_type) \
496 result(i+k) = bitshift (m(i), static_cast<int> (n(k)), mask); \
498 if (static_cast<int> (n(i)) >= bits_in_type) \
501 result(i) = bitshift (m(i), static_cast<int> (n(i)), mask); \
506 error ("bitshift: size of A and N must match, or one operand must be a scalar"); \
509 error ("bitshift: expecting integer as second argument"); \
512 #define DO_UBITSHIFT(T, N) \
515 int bits_in_type = octave_ ## T :: nbits (); \
516 T ## NDArray m = m_arg.T ## _array_value (); \
517 octave_ ## T mask = octave_ ## T::max (); \
518 if ((N) < bits_in_type) \
519 mask = bitshift (mask, (N) - bits_in_type); \
526 #define DO_SBITSHIFT(T, N) \
529 int bits_in_type = octave_ ## T :: nbits (); \
530 T ## NDArray m = m_arg.T ## _array_value (); \
531 octave_ ## T mask = octave_ ## T::max (); \
532 if ((N) < bits_in_type) \
533 mask = bitshift (mask, (N) - bits_in_type); \
536 mask = mask | octave_ ## T :: min (); \
543 @deftypefn {Built-in Function} {} bitshift (@var{a}, @var{k})\n\
544 @deftypefnx {Built-in Function} {} bitshift (@var{a}, @var{k}, @var{n})\n\
545 Return a @var{k} bit shift of @var{n}-digit unsigned integers in @var{a}.\n\
547 A positive @var{k} leads to a left shift; A negative value to a right shift.\n\
549 If @var{n} is omitted it defaults to log2(bitmax)+1.\n\
550 @var{n} must be in the range [1,log2(bitmax)+1] usually [1,33].\n\
554 bitshift (eye (3), 1)\n\
562 bitshift (10, [-2, -1, 0, 1, 2])\n\
563 @result{} 2 5 10 20 40\n\
564 @c FIXME: restore this example when third arg is allowed to be an array.\n\
567 @c bitshift ([1, 10], 2, [3,4])\n\
571 @seealso{bitand, bitor, bitxor, bitset, bitget, bitcmp, bitmax}\n\
576 int nargin = args.
length ();
578 if (nargin == 2 || nargin == 3)
582 NDArray n = args(1).array_value ();
585 error (
"bitshift: expecting integer as second argument");
592 if (args(2).numel () > 1)
593 error (
"bitshift: N must be a scalar integer");
596 nbits = args(2).int_value ();
599 error (
"bitshift: N must be an integer");
601 error (
"bitshift: N must be positive");
612 if (cname ==
"uint8")
614 else if (cname ==
"uint16")
616 else if (cname ==
"uint32")
618 else if (cname ==
"uint64")
620 else if (cname ==
"int8")
622 else if (cname ==
"int16")
624 else if (cname ==
"int32")
626 else if (cname ==
"int64")
628 else if (cname ==
"double")
630 static const int bits_in_mantissa
631 = std::numeric_limits<double>::digits;
633 nbits = (nbits < bits_in_mantissa ? nbits : bits_in_mantissa);
634 int64_t mask = max_mantissa_value<double> ();
635 if (nbits < bits_in_mantissa)
636 mask = mask >> (bits_in_mantissa - nbits);
639 int bits_in_type =
sizeof (
double)
640 * std::numeric_limits<unsigned char>::digits;
644 else if (cname ==
"single")
646 static const int bits_in_mantissa
647 = std::numeric_limits<float>::digits;
648 nbits = (nbits < bits_in_mantissa ? nbits : bits_in_mantissa);
649 int64_t mask = max_mantissa_value<float> ();
650 if (nbits < bits_in_mantissa)
651 mask = mask >> (bits_in_mantissa - nbits);
654 int bits_in_type =
sizeof (
float)
655 * std::numeric_limits<unsigned char>::digits;
660 error (
"bitshift: not defined for %s objects", cname.c_str ());
681 DEFUN (bitmax, args, ,
683 @deftypefn {Built-in Function} {} bitmax ()\n\
684 @deftypefnx {Built-in Function} {} bitmax (\"double\")\n\
685 @deftypefnx {Built-in Function} {} bitmax (\"single\")\n\
686 Return the largest integer that can be represented within a floating point\n\
689 The default class is @qcode{\"double\"}, but @qcode{\"single\"} is a\n\
690 valid option. On IEEE-754 compatible systems, @code{bitmax} is\n\
691 @w{@math{2^{53} - 1}} for @qcode{\"double\"} and @w{@math{2^{24} -1}} for\n\
692 @qcode{\"single\"}.\n\
693 @seealso{flintmax, intmax, realmax, realmin}\n\
697 std::string cname =
"double";
698 int nargin = args.
length ();
700 if (nargin == 1 && args(0).is_string ())
701 cname = args(0).string_value ();
702 else if (nargin != 0)
708 if (cname ==
"double")
709 retval = (
static_cast<double> (max_mantissa_value<double> ()));
710 else if (cname ==
"single")
711 retval = (
static_cast<float> (max_mantissa_value<float> ()));
713 error (
"bitmax: not defined for class '%s'", cname.c_str ());
718 DEFUN (flintmax, args, ,
720 @deftypefn {Built-in Function} {} flintmax ()\n\
721 @deftypefnx {Built-in Function} {} flintmax (\"double\")\n\
722 @deftypefnx {Built-in Function} {} flintmax (\"single\")\n\
723 Return the largest integer that can be represented consecutively in a\n\
724 floating point value.\n\
726 The default class is @qcode{\"double\"}, but @qcode{\"single\"} is a valid\n\
727 option. On IEEE-754 compatible systems, @code{flintmax} is @w{@math{2^53}}\n\
728 for @qcode{\"double\"} and @w{@math{2^24}} for @qcode{\"single\"}.\n\
729 @seealso{bitmax, intmax, realmax, realmin}\n\
733 std::string cname =
"double";
734 int nargin = args.
length ();
736 if (nargin == 1 && args(0).is_string ())
737 cname = args(0).string_value ();
738 else if (nargin != 0)
744 if (cname ==
"double")
745 retval = (
static_cast<double> (max_mantissa_value<double> () + 1));
746 else if (cname ==
"single")
747 retval = (
static_cast<float> (max_mantissa_value<float> () + 1));
749 error (
"flintmax: not defined for class '%s'", cname.c_str ());
754 DEFUN (intmax, args, ,
756 @deftypefn {Built-in Function} {} intmax (@var{type})\n\
757 Return the largest integer that can be represented in an integer type.\n\
759 The variable @var{type} can be\n\
763 signed 8-bit integer.\n\
766 signed 16-bit integer.\n\
769 signed 32-bit integer.\n\
772 signed 64-bit integer.\n\
775 unsigned 8-bit integer.\n\
778 unsigned 16-bit integer.\n\
781 unsigned 32-bit integer.\n\
784 unsigned 64-bit integer.\n\
787 The default for @var{type} is @code{int32}.\n\
788 @seealso{intmin, flintmax, bitmax}\n\
792 std::string cname =
"int32";
793 int nargin = args.
length ();
795 if (nargin == 1 && args(0).is_string ())
796 cname = args(0).string_value ();
797 else if (nargin != 0)
803 if (cname ==
"uint8")
805 else if (cname ==
"uint16")
807 else if (cname ==
"uint32")
809 else if (cname ==
"uint64")
811 else if (cname ==
"int8")
813 else if (cname ==
"int16")
815 else if (cname ==
"int32")
817 else if (cname ==
"int64")
820 error (
"intmax: not defined for '%s' objects", cname.c_str ());
825 DEFUN (intmin, args, ,
827 @deftypefn {Built-in Function} {} intmin (@var{type})\n\
828 Return the smallest integer that can be represented in an integer type.\n\
830 The variable @var{type} can be\n\
834 signed 8-bit integer.\n\
837 signed 16-bit integer.\n\
840 signed 32-bit integer.\n\
843 signed 64-bit integer.\n\
846 unsigned 8-bit integer.\n\
849 unsigned 16-bit integer.\n\
852 unsigned 32-bit integer.\n\
855 unsigned 64-bit integer.\n\
858 The default for @var{type} is @code{int32}.\n\
859 @seealso{intmax, flintmax, bitmax}\n\
863 std::string cname =
"int32";
864 int nargin = args.
length ();
866 if (nargin == 1 && args(0).is_string ())
867 cname = args(0).string_value ();
868 else if (nargin != 0)
874 if (cname ==
"uint8")
876 else if (cname ==
"uint16")
878 else if (cname ==
"uint32")
880 else if (cname ==
"uint64")
882 else if (cname ==
"int8")
884 else if (cname ==
"int16")
886 else if (cname ==
"int32")
888 else if (cname ==
"int64")
891 error (
"intmin: not defined for '%s' objects", cname.c_str ());
896 DEFUN (sizemax, args, ,
898 @deftypefn {Built-in Function} {} sizemax ()\n\
899 Return the largest value allowed for the size of an array.\n\
901 If Octave is compiled with 64-bit indexing, the result is of class int64,\n\
902 otherwise it is of class int32. The maximum array size is slightly\n\
903 smaller than the maximum value allowable for the relevant class as reported\n\
910 if (args.length () == 0)
octave_int< uint32_t > octave_uint32
T operator()(const T &op1, const T &op2) const
static int64_t bitshift(double a, int n, int64_t mask)
static int64_t max_mantissa_value()
octave_value bitopx(const std::string &fname, const Array< T > &x, const Array< T > &y)
T operator()(const T &op1, const T &op2) const
static std::string static_class_name(void)
OCTINTERP_API void print_usage(void)
octave_idx_type numel(void) const
Number of elements in the array.
octave_idx_type length(void) const
#define DEFUN(name, args_name, nargout_name, doc)
void error(const char *fmt,...)
octave_int< int16_t > octave_int16
boolNDArray bool_array_value(bool warn=false) const
octave_int< int32_t > octave_int32
#define DO_SBITSHIFT(T, N)
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
octave_int< uint16_t > octave_uint16
FloatNDArray float_array_value(bool frc_str_conv=false) const
static std::string static_class_name(void)
octave_int< int64_t > octave_int64
void resize(const dim_vector &dv, const T &rfv)
octave_value bitop(const std::string &fname, const octave_value_list &args)
static std::string static_class_name(void)
octave_int< uint64_t > octave_uint64
octave_idx_type length(void) const
T operator()(const T &op1, const T &op2) const
octave_value bitopxx(const OP &op, const std::string &fname, const Array< T > &x, const Array< T > &y)
static int bitop_arg_is_float(const octave_value &arg)
#define DO_UBITSHIFT(T, N)
Handles the reference counting for all the derived classes.
charNDArray max(char d, const charNDArray &m)
NDArray array_value(bool frc_str_conv=false) const
Array< octave_value > array_value(void) const
std::string class_name(void) const
static int bitop_arg_is_bool(const octave_value &arg)
static octave_idx_type dim_max(void)
static int bitop_arg_is_int(const octave_value &arg)
octave_int< uint8_t > octave_uint8
octave_int< int8_t > octave_int8
F77_RET_T const double * x
charNDArray min(char d, const charNDArray &m)