Mercurial > octave
view libinterp/corefcn/bitfcns.cc @ 27627:2890a931e647
Deprecated sizemax function (bug #47469).
* scripts/deprecated/sizemax.m: New m-file to produce a warning and provide
sizemax() behavior for the next two Octave releases.
* scripts/deprecated/module.mk: Add sizemax.m to build system.
* bitfcns.cc (Fsizemax): Remove function.
* dim-vector.h (dim_max): Add OCTAVE_DEPRECATED macro to function.
* dim-vector.cc (safe_numel): Call std::numeric_limits<octave_idx_type>::max
rather than dim_max().
* __sprand__.m: Replace sizemax() invocation with new code.
* numbers.txi: Remove DOCSTRING entry for sizemax and add text explaining
actual size limitation imposed by size of index pointers when Octave was
compiled.
author | Rik <rik@octave.org> |
---|---|
date | Mon, 04 Nov 2019 08:09:37 -0800 |
parents | 183c6e9443b5 |
children | 31b95261c7d2 |
line wrap: on
line source
/* Copyright (C) 2004-2019 John W. Eaton This file is part of Octave. Octave is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Octave is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Octave; see the file COPYING. If not, see <https://www.gnu.org/licenses/>. */ #if defined (HAVE_CONFIG_H) # include "config.h" #endif #include <limits> #include "str-vec.h" #include "quit.h" #include "defun.h" #include "error.h" #include "ov.h" #include "ov-uint64.h" #include "ov-uint32.h" #include "ov-uint16.h" #include "ov-uint8.h" #include "ov-int64.h" #include "ov-int32.h" #include "ov-int16.h" #include "ov-int8.h" #include "ov-float.h" #include "ov-scalar.h" #include "ov-re-mat.h" #include "ov-bool.h" #include <functional> #if ! defined (HAVE_CXX_BITWISE_OP_TEMPLATES) namespace std { template <typename T> struct bit_and { public: T operator() (const T & op1, const T & op2) const { return (op1 & op2); } }; template <typename T> struct bit_or { public: T operator() (const T & op1, const T & op2) const { return (op1 | op2); } }; template <typename T> struct bit_xor { public: T operator() (const T & op1, const T & op2) const { return (op1 ^ op2); } }; } #endif template <typename OP, typename T> octave_value bitopxx (const OP& op, const std::string& fname, const Array<T>& x, const Array<T>& y) { int nelx = x.numel (); int nely = y.numel (); bool is_scalar_op = (nelx == 1 || nely == 1); dim_vector dvx = x.dims (); dim_vector dvy = y.dims (); bool is_array_op = (dvx == dvy); if (! is_array_op && ! is_scalar_op) error ("%s: size of X and Y must match, or one operand must be a scalar", fname.c_str ()); Array<T> result; if (nelx != 1) result.resize (dvx); else result.resize (dvy); for (int i = 0; i < nelx; i++) if (is_scalar_op) for (int k = 0; k < nely; k++) result(i+k) = op (x(i), y(k)); else result(i) = op (x(i), y(i)); return result; } // Trampoline function, instantiates the proper template above, with // reflective information hardwired. We can't hardwire this information // in Fbitxxx DEFUNs below, because at that moment, we still don't have // information about which integer types we need to instantiate. template <typename T> octave_value bitopx (const std::string& fname, const Array<T>& x, const Array<T>& y) { if (fname == "bitand") return bitopxx (std::bit_and<T>(), fname, x, y); if (fname == "bitor") return bitopxx (std::bit_or<T>(), fname, x, y); //else (fname == "bitxor") return bitopxx (std::bit_xor<T>(), fname, x, y); } static inline int bitop_arg_is_int (const octave_value& arg) { return (arg.class_name () != octave_scalar::static_class_name () && arg.class_name () != octave_float_scalar::static_class_name () && arg.class_name () != octave_bool::static_class_name ()); } static inline int bitop_arg_is_bool (const octave_value& arg) { return arg.class_name () == octave_bool::static_class_name (); } static inline int bitop_arg_is_float (const octave_value& arg) { return arg.class_name () == octave_float_scalar::static_class_name (); } octave_value bitop (const std::string& fname, const octave_value_list& args) { if (args.length () != 2) print_usage (); octave_value retval; if (args(0).class_name () == octave_scalar::static_class_name () || args(0).class_name () == octave_float_scalar::static_class_name () || args(0).class_name () == octave_bool::static_class_name () || args(1).class_name () == octave_scalar::static_class_name () || args(1).class_name () == octave_float_scalar::static_class_name () || args(1).class_name () == octave_bool::static_class_name ()) { bool arg0_is_int = bitop_arg_is_int (args(0)); bool arg1_is_int = bitop_arg_is_int (args(1)); bool arg0_is_bool = bitop_arg_is_bool (args(0)); bool arg1_is_bool = bitop_arg_is_bool (args(1)); bool arg0_is_float = bitop_arg_is_float (args(0)); bool arg1_is_float = bitop_arg_is_float (args(1)); if (! (arg0_is_int || arg1_is_int)) { if (arg0_is_bool && arg1_is_bool) { boolNDArray x (args(0).bool_array_value ()); boolNDArray y (args(1).bool_array_value ()); retval = bitopx (fname, x, y).bool_array_value (); } else if (arg0_is_float && arg1_is_float) { uint64NDArray x (args(0).float_array_value ()); uint64NDArray y (args(1).float_array_value ()); retval = bitopx (fname, x, y).float_array_value (); } else if (! (arg0_is_float || arg1_is_float)) { uint64NDArray x (args(0).array_value ()); uint64NDArray y (args(1).array_value ()); retval = bitopx (fname, x, y).array_value (); } else { int p = (arg0_is_float ? 1 : 0); int q = (arg0_is_float ? 0 : 1); uint64NDArray x (args(p).array_value ()); uint64NDArray y (args(q).float_array_value ()); retval = bitopx (fname, x, y).float_array_value (); } } else { int p = (arg0_is_int ? 1 : 0); int q = (arg0_is_int ? 0 : 1); NDArray dx = args(p).array_value (); if (args(q).type_id () == octave_uint64_matrix::static_type_id () || args(q).type_id () == octave_uint64_scalar::static_type_id ()) { uint64NDArray x (dx); uint64NDArray y = args(q).uint64_array_value (); retval = bitopx (fname, x, y); } else if (args(q).type_id () == octave_uint32_matrix::static_type_id () || args(q).type_id () == octave_uint32_scalar::static_type_id ()) { uint32NDArray x (dx); uint32NDArray y = args(q).uint32_array_value (); retval = bitopx (fname, x, y); } else if (args(q).type_id () == octave_uint16_matrix::static_type_id () || args(q).type_id () == octave_uint16_scalar::static_type_id ()) { uint16NDArray x (dx); uint16NDArray y = args(q).uint16_array_value (); retval = bitopx (fname, x, y); } else if (args(q).type_id () == octave_uint8_matrix::static_type_id () || args(q).type_id () == octave_uint8_scalar::static_type_id ()) { uint8NDArray x (dx); uint8NDArray y = args(q).uint8_array_value (); retval = bitopx (fname, x, y); } else if (args(q).type_id () == octave_int64_matrix::static_type_id () || args(q).type_id () == octave_int64_scalar::static_type_id ()) { int64NDArray x (dx); int64NDArray y = args(q).int64_array_value (); retval = bitopx (fname, x, y); } else if (args(q).type_id () == octave_int32_matrix::static_type_id () || args(q).type_id () == octave_int32_scalar::static_type_id ()) { int32NDArray x (dx); int32NDArray y = args(q).int32_array_value (); retval = bitopx (fname, x, y); } else if (args(q).type_id () == octave_int16_matrix::static_type_id () || args(q).type_id () == octave_int16_scalar::static_type_id ()) { int16NDArray x (dx); int16NDArray y = args(q).int16_array_value (); retval = bitopx (fname, x, y); } else if (args(q).type_id () == octave_int8_matrix::static_type_id () || args(q).type_id () == octave_int8_scalar::static_type_id ()) { int8NDArray x (dx); int8NDArray y = args(q).int8_array_value (); retval = bitopx (fname, x, y); } else error ("%s: invalid operand type", fname.c_str ()); } } else if (args(0).class_name () == args(1).class_name ()) { if (args(0).type_id () == octave_uint64_matrix::static_type_id () || args(0).type_id () == octave_uint64_scalar::static_type_id ()) { uint64NDArray x = args(0).uint64_array_value (); uint64NDArray y = args(1).uint64_array_value (); retval = bitopx (fname, x, y); } else if (args(0).type_id () == octave_uint32_matrix::static_type_id () || args(0).type_id () == octave_uint32_scalar::static_type_id ()) { uint32NDArray x = args(0).uint32_array_value (); uint32NDArray y = args(1).uint32_array_value (); retval = bitopx (fname, x, y); } else if (args(0).type_id () == octave_uint16_matrix::static_type_id () || args(0).type_id () == octave_uint16_scalar::static_type_id ()) { uint16NDArray x = args(0).uint16_array_value (); uint16NDArray y = args(1).uint16_array_value (); retval = bitopx (fname, x, y); } else if (args(0).type_id () == octave_uint8_matrix::static_type_id () || args(0).type_id () == octave_uint8_scalar::static_type_id ()) { uint8NDArray x = args(0).uint8_array_value (); uint8NDArray y = args(1).uint8_array_value (); retval = bitopx (fname, x, y); } else if (args(0).type_id () == octave_int64_matrix::static_type_id () || args(0).type_id () == octave_int64_scalar::static_type_id ()) { int64NDArray x = args(0).int64_array_value (); int64NDArray y = args(1).int64_array_value (); retval = bitopx (fname, x, y); } else if (args(0).type_id () == octave_int32_matrix::static_type_id () || args(0).type_id () == octave_int32_scalar::static_type_id ()) { int32NDArray x = args(0).int32_array_value (); int32NDArray y = args(1).int32_array_value (); retval = bitopx (fname, x, y); } else if (args(0).type_id () == octave_int16_matrix::static_type_id () || args(0).type_id () == octave_int16_scalar::static_type_id ()) { int16NDArray x = args(0).int16_array_value (); int16NDArray y = args(1).int16_array_value (); retval = bitopx (fname, x, y); } else if (args(0).type_id () == octave_int8_matrix::static_type_id () || args(0).type_id () == octave_int8_scalar::static_type_id ()) { int8NDArray x = args(0).int8_array_value (); int8NDArray y = args(1).int8_array_value (); retval = bitopx (fname, x, y); } else error ("%s: invalid operand type", fname.c_str ()); } else error ("%s: must have matching operand types", fname.c_str ()); return retval; } DEFUN (bitand, args, , doc: /* -*- texinfo -*- @deftypefn {} {} bitand (@var{x}, @var{y}) Return the bitwise AND of non-negative integers. @var{x}, @var{y} must be in the range [0,intmax] @seealso{bitor, bitxor, bitset, bitget, bitcmp, bitshift, intmax, flintmax} @end deftypefn */) { return bitop ("bitand", args); } /* %!# Function bitand is tested as part of bitxor BIST tests */ DEFUN (bitor, args, , doc: /* -*- texinfo -*- @deftypefn {} {} bitor (@var{x}, @var{y}) Return the bitwise OR of non-negative integers @var{x} and @var{y}. @seealso{bitor, bitxor, bitset, bitget, bitcmp, bitshift, intmax, flintmax} @end deftypefn */) { return bitop ("bitor", args); } /* %!# Function bitor is tested as part of bitxor BIST tests */ DEFUN (bitxor, args, , doc: /* -*- texinfo -*- @deftypefn {} {} bitxor (@var{x}, @var{y}) Return the bitwise XOR of non-negative integers @var{x} and @var{y}. @seealso{bitand, bitor, bitset, bitget, bitcmp, bitshift, intmax, flintmax} @end deftypefn */) { return bitop ("bitxor", args); } /* %!assert (bitand (true, false), false) %!assert (bitor (true, false), true) %!assert (bitxor (true, false), true) %!assert (bitand (true, true), true) %!assert (bitor (true, true), true) %!assert (bitxor (true, true), false) %!assert (bitand (true, 5), 1) %!assert (bitand (true, false), false) %!assert (bitand (true, true), true) %!assert (bitand (true, false), false) %!assert (bitand (true, false), false) ## Test idx_arg.length () == 0 %!error <size of X and Y must match> bitand ([0 0 0], [1 0]) %!error <size of X and Y must match> bitand ([0; 0; 0], [0 0 0]) */ template <typename T> static int64_t max_mantissa_value () { return (static_cast<int64_t> (1) << std::numeric_limits<T>::digits) - 1; } static int64_t bitshift (double a, int n, int64_t mask) { // In the name of bug-for-bug compatibility. if (a < 0) return -bitshift (-a, n, mask); if (n > 0) return (static_cast<int64_t> (a) << n) & mask; else if (n < 0) return (static_cast<int64_t> (a) >> -n) & mask; else return static_cast<int64_t> (a) & mask; } static int64_t bitshift (float a, int n, int64_t mask) { // In the name of bug-for-bug compatibility. if (a < 0) return -bitshift (-a, n, mask); if (n > 0) return (static_cast<int64_t> (a) << n) & mask; else if (n < 0) return (static_cast<int64_t> (a) >> -n) & mask; else return static_cast<int64_t> (a) & mask; } // Note that the bitshift operators are undefined if shifted by more // bits than in the type, so we need to test for the size of the // shift. #define DO_BITSHIFT(T) \ double d1, d2; \ \ if (! n.all_integers (d1, d2)) \ error ("bitshift: K must be a scalar or array of integers"); \ \ int m_nel = m.numel (); \ int n_nel = n.numel (); \ \ bool is_scalar_op = (m_nel == 1 || n_nel == 1); \ \ dim_vector m_dv = m.dims (); \ dim_vector n_dv = n.dims (); \ \ bool is_array_op = (m_dv == n_dv); \ \ if (! is_array_op && ! is_scalar_op) \ error ("bitshift: size of A and N must match, or one operand must be a scalar"); \ \ T ## NDArray result; \ \ if (m_nel != 1) \ result.resize (m_dv); \ else \ result.resize (n_dv); \ \ for (int i = 0; i < m_nel; i++) \ if (is_scalar_op) \ for (int k = 0; k < n_nel; k++) \ if (static_cast<int> (n(k)) >= bits_in_type) \ result(i+k) = 0; \ else \ result(i+k) = bitshift (m(i), static_cast<int> (n(k)), mask); \ else \ if (static_cast<int> (n(i)) >= bits_in_type) \ result(i) = 0; \ else \ result(i) = bitshift (m(i), static_cast<int> (n(i)), mask); \ \ retval = result; #define DO_UBITSHIFT(T, N) \ do \ { \ int bits_in_type = octave_ ## T :: nbits (); \ T ## NDArray m = m_arg.T ## _array_value (); \ octave_ ## T mask = octave_ ## T::max (); \ if ((N) < bits_in_type) \ mask = bitshift (mask, (N) - bits_in_type); \ else if ((N) < 1) \ mask = 0; \ DO_BITSHIFT (T); \ } \ while (0) #define DO_SBITSHIFT(T, N) \ do \ { \ int bits_in_type = octave_ ## T :: nbits (); \ T ## NDArray m = m_arg.T ## _array_value (); \ octave_ ## T mask = octave_ ## T::max (); \ if ((N) < bits_in_type) \ mask = bitshift (mask, (N) - bits_in_type); \ else if ((N) < 1) \ mask = 0; \ /* FIXME: 2's complement only? */ \ mask = mask | octave_ ## T :: min (); \ DO_BITSHIFT (T); \ } \ while (0) DEFUN (bitshift, args, , doc: /* -*- texinfo -*- @deftypefn {} {} bitshift (@var{a}, @var{k}) @deftypefnx {} {} bitshift (@var{a}, @var{k}, @var{n}) Return a @var{k} bit shift of @var{n}-digit unsigned integers in @var{a}. A positive @var{k} leads to a left shift; A negative value to a right shift. If @var{n} is omitted it defaults to 64. @var{n} must be in the range [1,64]. @example @group bitshift (eye (3), 1) @result{} @group 2 0 0 0 2 0 0 0 2 @end group bitshift (10, [-2, -1, 0, 1, 2]) @result{} 2 5 10 20 40 @c FIXME: restore this example when third arg is allowed to be an array. @c @c @c bitshift ([1, 10], 2, [3,4]) @c @result{} 4 8 @end group @end example @seealso{bitand, bitor, bitxor, bitset, bitget, bitcmp, intmax, flintmax} @end deftypefn */) { int nargin = args.length (); if (nargin < 2 || nargin > 3) print_usage (); NDArray n = args(1).xarray_value ("bitshift: K must be a scalar or array of integers"); int nbits = 64; if (nargin == 3) { // FIXME: for compatibility, we should accept an array or a scalar // as the third argument. if (args(2).numel () > 1) error ("bitshift: N must be a scalar integer"); nbits = args(2).xint_value ("bitshift: N must be an integer"); if (nbits < 0) error ("bitshift: N must be positive"); } octave_value retval; octave_value m_arg = args(0); std::string cname = m_arg.class_name (); if (cname == "double") { static const int bits_in_mantissa = std::numeric_limits<double>::digits; nbits = (nbits < bits_in_mantissa ? nbits : bits_in_mantissa); int64_t mask = max_mantissa_value<double> (); if (nbits < bits_in_mantissa) mask = mask >> (bits_in_mantissa - nbits); int bits_in_type = sizeof (double) * std::numeric_limits<unsigned char>::digits; NDArray m = m_arg.array_value (); DO_BITSHIFT (); } else if (cname == "uint8") DO_UBITSHIFT (uint8, nbits < 8 ? nbits : 8); else if (cname == "uint16") DO_UBITSHIFT (uint16, nbits < 16 ? nbits : 16); else if (cname == "uint32") DO_UBITSHIFT (uint32, nbits < 32 ? nbits : 32); else if (cname == "uint64") DO_UBITSHIFT (uint64, nbits < 64 ? nbits : 64); else if (cname == "int8") DO_SBITSHIFT (int8, nbits < 8 ? nbits : 8); else if (cname == "int16") DO_SBITSHIFT (int16, nbits < 16 ? nbits : 16); else if (cname == "int32") DO_SBITSHIFT (int32, nbits < 32 ? nbits : 32); else if (cname == "int64") DO_SBITSHIFT (int64, nbits < 64 ? nbits : 64); else if (cname == "single") { static const int bits_in_mantissa = std::numeric_limits<float>::digits; nbits = (nbits < bits_in_mantissa ? nbits : bits_in_mantissa); int64_t mask = max_mantissa_value<float> (); if (nbits < bits_in_mantissa) mask = mask >> (bits_in_mantissa - nbits); int bits_in_type = sizeof (float) * std::numeric_limits<unsigned char>::digits; FloatNDArray m = m_arg.float_array_value (); DO_BITSHIFT (Float); } else error ("bitshift: not defined for %s objects", cname.c_str ()); return retval; } /* %!assert (bitshift (uint8 (16), 1), uint8 ( 32)) %!assert (bitshift (uint16 (16), 2), uint16 ( 64)) %!assert (bitshift (uint32 (16), 3), uint32 (128)) %!assert (bitshift (uint64 (16), 4), uint64 (256)) %!assert (bitshift (uint8 (255), 1), uint8 (254)) %!error <K must be a scalar or array of integers> bitshift (16, 1.5) %!error bitshift (16, {1}) %!error <N must be a scalar integer> bitshift (10, [-2 -1 0 1 2], [1 1 1 1 1]) %!error <N must be positive> bitshift (10, [-2 -1 0 1 2], -1) */ DEFUN (flintmax, args, , doc: /* -*- texinfo -*- @deftypefn {} {} flintmax () @deftypefnx {} {} flintmax ("double") @deftypefnx {} {} flintmax ("single") @deftypefnx {} {} flintmax (@var{var}) Return the largest integer that can be represented consecutively in a floating point value. The input is either a string specifying a floating point type, or it is an existing floating point variable @var{var}. The default type is @qcode{"double"}, but @qcode{"single"} is a valid option. On IEEE 754 compatible systems, @code{flintmax} is @w{@math{2^{53}}} for @qcode{"double"} and @w{@math{2^{24}}} for @qcode{"single"}. Example Code - query an existing variable @example @group x = single (1); flintmax (x) @result{} 16777216 @end group @end example @seealso{intmax, realmax, realmin} @end deftypefn */) { int nargin = args.length (); if (nargin > 1) print_usage (); std::string cname = "double"; if (nargin == 1) { if (args(0).is_string ()) cname = args(0).string_value (); else if (args(0).isfloat ()) cname = args(0).class_name (); else error ("intmin: argument must be a string or floating point variable"); } if (cname == "double") return ovl (static_cast<double> (max_mantissa_value<double> () + 1)); else if (cname == "single") return ovl (static_cast<float> (max_mantissa_value<float> () + 1)); else error ("flintmax: not defined for class '%s'", cname.c_str ()); } /* %!assert (flintmax (), 2^53) %!assert (flintmax ("double"), 2^53) %!assert (flintmax ("single"), single (2^24)) %!test %! x = single (1); %! assert (flintmax (x), single (16777216)); %!error flintmax ("double", 0) %!error <must be a string or floating point variable> flintmax (int8 (1)) %!error <not defined for class 'int8'> flintmax ("int8") %!error <not defined for class 'char'> flintmax ("char") */ DEFUN (intmax, args, , doc: /* -*- texinfo -*- @deftypefn {} {} intmax () @deftypefnx {} {} intmax ("@var{type}") @deftypefnx {} {} intmax (@var{var}) Return the largest integer that can be represented by a specific integer type. The input is either a string @qcode{"@var{type}"} specifying an integer type, or it is an existing integer variable @var{var}. Possible values for @var{type} are @table @asis @item @qcode{"int8"} signed 8-bit integer. @item @qcode{"int16"} signed 16-bit integer. @item @qcode{"int32"} signed 32-bit integer. @item @qcode{"int64"} signed 64-bit integer. @item @qcode{"uint8"} unsigned 8-bit integer. @item @qcode{"uint16"} unsigned 16-bit integer. @item @qcode{"uint32"} unsigned 32-bit integer. @item @qcode{"uint64"} unsigned 64-bit integer. @end table The default for @var{type} is @qcode{"int32"}. Example Code - query an existing variable @example @group x = int8 (1); intmax (x) @result{} 127 @end group @end example @seealso{intmin, flintmax} @end deftypefn */) { int nargin = args.length (); if (nargin > 1) print_usage (); std::string cname = "int32"; if (nargin == 1) { if (args(0).is_string ()) cname = args(0).string_value (); else if (args(0).isinteger ()) cname = args(0).class_name (); else error ("intmax: argument must be a string or integer variable"); } octave_value retval; if (cname == "uint8") retval = octave_uint8 (std::numeric_limits<uint8_t>::max ()); else if (cname == "uint16") retval = octave_uint16 (std::numeric_limits<uint16_t>::max ()); else if (cname == "uint32") retval = octave_uint32 (std::numeric_limits<uint32_t>::max ()); else if (cname == "uint64") retval = octave_uint64 (std::numeric_limits<uint64_t>::max ()); else if (cname == "int8") retval = octave_int8 (std::numeric_limits<int8_t>::max ()); else if (cname == "int16") retval = octave_int16 (std::numeric_limits<int16_t>::max ()); else if (cname == "int32") retval = octave_int32 (std::numeric_limits<int32_t>::max ()); else if (cname == "int64") retval = octave_int64 (std::numeric_limits<int64_t>::max ()); else error ("intmax: not defined for '%s' objects", cname.c_str ()); return retval; } /* %!assert (intmax (), int32 (2^31 - 1)) %!assert (intmax ("int8"), int8 (2^7 - 1)) %!assert (intmax ("uint8"), uint8 (2^8 - 1)) %!assert (intmax ("int16"), int16 (2^15 - 1)) %!assert (intmax ("uint16"), uint16 (2^16 - 1)) %!assert (intmax ("int32"), int32 (2^31 - 1)) %!assert (intmax ("uint32"), uint32 (2^32 - 1)) %!assert (intmax ("int64"), int64 (2^63 - 1)) %!assert (intmax ("uint64"), uint64 (2^64 - 1)) %!test %! x = int8 (1); %! assert (intmax (x), int8 (127)); %!error intmax ("int32", 0) %!error <must be a string or integer variable> intmax (1.0) %!error <not defined for 'double' objects> intmax ("double") %!error <not defined for 'char' objects> intmax ("char") */ DEFUN (intmin, args, , doc: /* -*- texinfo -*- @deftypefn {} {} intmin () @deftypefnx {} {} intmin ("@var{type}") @deftypefnx {} {} intmin (@var{var}) Return the smallest integer that can be represented by a specific integer type. The input is either a string @qcode{"@var{type}"} specifying an integer type, or it is an existing integer variable @var{var}. Possible values for @var{type} are @table @asis @item @qcode{"int8"} signed 8-bit integer. @item @qcode{"int16"} signed 16-bit integer. @item @qcode{"int32"} signed 32-bit integer. @item @qcode{"int64"} signed 64-bit integer. @item @qcode{"uint8"} unsigned 8-bit integer. @item @qcode{"uint16"} unsigned 16-bit integer. @item @qcode{"uint32"} unsigned 32-bit integer. @item @qcode{"uint64"} unsigned 64-bit integer. @end table The default for @var{type} is @qcode{"int32"}. Example Code - query an existing variable @example @group x = int8 (1); intmin (x) @result{} -128 @end group @end example @seealso{intmax, flintmax} @end deftypefn */) { int nargin = args.length (); if (nargin > 1) print_usage (); std::string cname = "int32"; if (nargin == 1) { if (args(0).is_string ()) cname = args(0).string_value (); else if (args(0).isinteger ()) cname = args(0).class_name (); else error ("intmin: argument must be a string or integer variable"); } octave_value retval; if (cname == "uint8") retval = octave_uint8 (std::numeric_limits<uint8_t>::min ()); else if (cname == "uint16") retval = octave_uint16 (std::numeric_limits<uint16_t>::min ()); else if (cname == "uint32") retval = octave_uint32 (std::numeric_limits<uint32_t>::min ()); else if (cname == "uint64") retval = octave_uint64 (std::numeric_limits<uint64_t>::min ()); else if (cname == "int8") retval = octave_int8 (std::numeric_limits<int8_t>::min ()); else if (cname == "int16") retval = octave_int16 (std::numeric_limits<int16_t>::min ()); else if (cname == "int32") retval = octave_int32 (std::numeric_limits<int32_t>::min ()); else if (cname == "int64") retval = octave_int64 (std::numeric_limits<int64_t>::min ()); else error ("intmin: not defined for '%s' objects", cname.c_str ()); return retval; } /* %!assert (intmin (), int32 (-2^31)) %!assert (intmin ("int8"), int8 (-2^7)) %!assert (intmin ("uint8"), uint8 (-2^8)) %!assert (intmin ("int16"), int16 (-2^15)) %!assert (intmin ("uint16"), uint16 (-2^16)) %!assert (intmin ("int32"), int32 (-2^31)) %!assert (intmin ("uint32"), uint32 (-2^32)) %!assert (intmin ("int64"), int64 (-2^63)) %!assert (intmin ("uint64"), uint64 (-2^64)) %!test %! x = int8 (1); %! assert (intmin (x), int8 (-128)); %!error intmin ("int32", 0) %!error <must be a string or integer variable> intmin (1.0) %!error <not defined for 'double' objects> intmin ("double") %!error <not defined for 'char' objects> intmin ("char") */