24 #if !defined (octave_oct_inttypes_h)
25 #define octave_oct_inttypes_h 1
36 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
37 inline long double xround (
long double x) {
return roundl (x); }
38 inline long double xisnan (
long double x)
39 {
return xisnan (static_cast<double> (x)); }
49 template<
int qsize,
bool q
signed>
58 #define REGISTER_INT_TYPE(TYPE) \
60 class query_integer_type<sizeof (TYPE), std::numeric_limits<TYPE>::is_signed> \
63 static const bool registered = true; \
80 #define REGISTER_OCTAVE_CMP_OP(NM,OP) \
84 static const bool ltval = (0 OP 1), gtval = (1 OP 0); \
86 static bool op (T x, T y) { return x OP y; } \
91 #define REGISTER_OCTAVE_CONST_OP(NM,value) \
95 static const bool ltval = value, gtval = value; \
97 static bool op (T, T) { return value; } \
108 template <
class T1,
class T2>
112 static const bool pint = (
sizeof (T1) <
sizeof (
int)
113 &&
sizeof (T2) <
sizeof (
int));
114 static const bool t1sig = std::numeric_limits<T1>::is_signed;
115 static const bool t2sig = std::numeric_limits<T2>::is_signed;
119 (
pint ?
sizeof (
int) : (
sizeof (T2) >
sizeof (T1)
120 ?
sizeof (T2) :
sizeof (T1)));
127 template<
class xop,
int size>
138 {
return (x < 0) ? xop::ltval :
xop::op (static_cast<utype> (x), y); }
140 {
return (y < 0) ? xop::gtval :
xop::op (x, static_cast<utype> (y)); }
154 template<
class xop,
class T1,
class T2>
161 static_cast<PT2> (y));
167 template <
class xop,
class T>
170 {
return xop::op (static_cast<double> (x), y); }
172 template <
class xop,
class T>
175 {
return xop::op (x, static_cast<double> (y)); }
177 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
178 #define DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS(T) \
179 template <class xop> static OCTAVE_API bool \
180 external_mop (double, T); \
181 template <class xop> static OCTAVE_API bool \
182 external_mop (T, double)
184 DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS (int64_t);
185 DECLARE_EXTERNAL_LONG_DOUBLE_CMP_OPS (uint64_t);
191 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
192 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
193 #define DEFINE_LONG_DOUBLE_CMP_OP(T) \
194 template <class xop> \
196 mop (double x, T y) \
198 return external_mop<xop> (x, y); \
200 template <class xop> \
202 mop (T x, double y) \
204 return external_mop<xop> (x, y); \
207 #define DEFINE_LONG_DOUBLE_CMP_OP(T) \
208 template <class xop> \
210 mop (double x, T y) \
212 return xop::op (static_cast<long double> (x), \
213 static_cast<long double> (y)); \
215 template <class xop> \
217 mop (T x, double y) \
219 return xop::op (static_cast<long double> (x), \
220 static_cast<long double> (y)); \
229 #define DEFINE_LONG_DOUBLE_CMP_OP(T) \
230 template <class xop> static OCTAVE_API bool \
231 emulate_mop (double, T); \
232 template <class xop> \
234 mop (double x, T y) \
236 return emulate_mop<xop> (x, y); \
238 template <class xop> static OCTAVE_API bool \
239 emulate_mop (T, double); \
240 template <class xop> \
242 mop (T x, double y) \
244 return emulate_mop<xop> (x, y); \
251 #undef DEFINE_LONG_DOUBLE_CMP_OP
269 static const bool t_is_signed = std::numeric_limits<T>::is_signed;
270 static const bool s_is_signed = std::numeric_limits<S>::is_signed;
271 static const int t_size =
sizeof (T), s_size =
sizeof (S);
272 static const bool omit_chk_min =
273 (! s_is_signed || (t_is_signed && t_size >= s_size));
274 static const bool omit_chk_max =
275 (t_size > s_size || (t_size == s_size
276 && (! t_is_signed || s_is_signed)));
281 typedef typename if_then_else<omit_chk_min, cf, lt>::result chk_min;
282 typedef typename if_then_else<omit_chk_max, cf, gt>::result chk_max;
286 if (chk_min::op (value, static_cast<S> (
min_val ())))
290 else if (chk_max::op (value, static_cast<S> (
max_val ())))
295 return static_cast<T
> (value);
307 if (orig_val % 2 && val / 2 ==
xround (val / 2))
309 val *= (
static_cast<S
>(1) - (std::numeric_limits<S>::epsilon () / 2));
326 return static_cast<T
> (0);
328 else if (value < thmin)
332 else if (value > thmax)
338 S rvalue =
xround (value);
339 return static_cast<T
> (rvalue);
349 template <
class T,
bool is_
signed>
364 signum (T x) {
return x ?
static_cast<T
> (1) : static_cast<T> (0); }
376 return static_cast<T
> (0);
413 * static_cast<mptype> (y));
423 T z = x / y,
w = x % y;
424 if (w >= y-w) z += 1;
437 return y != 0 ? x % y : 0;
444 return y != 0 ? x % y :
x;
448 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
452 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
454 extern OCTAVE_API uint64_t
455 octave_external_uint64_uint64_mul (uint64_t, uint64_t);
465 long double p =
static_cast<long double> (
x) * static_cast<long double> (y);
470 retval =
static_cast<uint64_t
> (p);
479 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
480 return octave_external_uint64_uint64_mul (x, y);
482 return mul_internal (x, y);
526 #ifdef HAVE_FAST_INT_OPS
527 return static_cast<UT> (
x) >> std::numeric_limits<T>::digits;
529 return (x < 0) ? 1 : 0;
536 #ifdef HAVE_FAST_INT_OPS
540 T m = x >> std::numeric_limits<T>::digits;
559 y = (x < 0) ? -x : x;
568 return ((x > 0) ? 1 : 0) - __signbit (x);
585 #ifdef HAVE_FAST_INT_OPS
608 #ifdef HAVE_FAST_INT_OPS
612 T u =
static_cast<UT> (
x) + static_cast<UT> (y);
613 T ux = u ^
x, uy = u ^ y;
649 #ifdef HAVE_FAST_INT_OPS
653 T u =
static_cast<UT> (
x) - static_cast<UT> (y);
654 T ux = u ^
x, uy = u ^ ~y;
696 * static_cast<mptype> (y));
726 z -= 1 - (__signbit (x) << 1);
738 z += 1 - (__signbit (x) << 1);
747 return y != 0 ? x % y : 0;
757 return ((r < 0) != (y < 0)) ? r + y : r;
764 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
768 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
770 extern OCTAVE_API int64_t
771 octave_external_int64_int64_mul (int64_t, int64_t);
781 long double p =
static_cast<long double> (
x) * static_cast<long double> (y);
791 retval =
static_cast<int64_t
> (p);
800 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
801 return octave_external_int64_int64_mul (x, y);
803 return mul_internal (x, y);
837 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
858 T
value (
void)
const {
return ival; }
860 const unsigned char * iptr (
void)
const
861 {
return reinterpret_cast<const unsigned char *
> (& ival); }
865 bool bool_value (
void)
const {
return static_cast<bool> (value ()); }
867 char char_value (
void)
const {
return static_cast<char> (value ()); }
869 double double_value (
void)
const {
return static_cast<double> (value ()); }
871 float float_value (
void)
const {
return static_cast<float> (value ()); }
873 operator T (
void)
const {
return value (); }
877 operator double (
void)
const {
return double_value (); }
879 operator float (
void)
const {
return float_value (); }
886 #define OCTAVE_INT_UN_OP(OPNAME,NAME) \
887 inline octave_int<T> \
889 { return octave_int_arith<T>::NAME (ival); }
895 #undef OCTAVE_INT_UN_OP
898 #define OCTAVE_INT_BIN_OP(OP, NAME, ARGT) \
899 inline octave_int<T> \
900 operator OP (const ARGT& y) const \
901 { return octave_int_arith<T>::NAME (ival, y); } \
902 inline octave_int<T>& \
903 operator OP##= (const ARGT& y) \
905 ival = octave_int_arith<T>::NAME (ival, y); \
917 #undef OCTAVE_INT_BIN_OP
922 static int nbits (
void) {
return std::numeric_limits<T>::digits; }
926 static const char *type_name ();
992 #define OCTAVE_INT_CMP_OP(OP, NAME) \
993 template<class T1, class T2> \
995 operator OP (const octave_int<T1>& x, const octave_int<T2>& y) \
996 { return octave_int_cmp_op::op<octave_int_cmp_op::NAME, T1, T2> \
997 (x.value (), y.value ()); }
1006 #undef OCTAVE_INT_CMP_OP
1009 inline std::ostream&
1010 operator << (std::ostream& os, const octave_int<T>& ival)
1012 os << ival.value ();
1017 inline std::istream&
1028 #define OCTAVE_INT_BITCMP_OP(OP) \
1029 template <class T> \
1031 operator OP (const octave_int<T>& x, const octave_int<T>& y) \
1032 { return x.value () OP y.value (); }
1038 #undef OCTAVE_INT_BITCMP_OP
1047 return (a << n) & mask;
1049 return (a >> -n) & mask;
1064 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
1066 #define DECLARE_EXTERNAL_LONG_DOUBLE_OP(T, OP) \
1067 extern OCTAVE_API T \
1068 external_double_ ## T ## _ ## OP (double x, T y); \
1069 extern OCTAVE_API T \
1070 external_ ## T ## _double_ ## OP (T x, double y)
1072 #define DECLARE_EXTERNAL_LONG_DOUBLE_OPS(T) \
1073 DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, add); \
1074 DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, sub); \
1075 DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, mul); \
1076 DECLARE_EXTERNAL_LONG_DOUBLE_OP (T, div)
1078 DECLARE_EXTERNAL_LONG_DOUBLE_OPS (octave_int64);
1079 DECLARE_EXTERNAL_LONG_DOUBLE_OPS (octave_uint64);
1083 #define OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
1084 template <class T> \
1085 inline octave_int<T> \
1086 operator OP (const octave_int<T>& x, const double& y) \
1087 { return octave_int<T> (static_cast<double> (x) OP y); } \
1088 template <class T> \
1089 inline octave_int<T> \
1090 operator OP (const double& x, const octave_int<T>& y) \
1091 { return octave_int<T> (x OP static_cast<double> (y)); } \
1093 #ifdef OCTAVE_INT_USE_LONG_DOUBLE
1095 #ifdef OCTAVE_ENSURE_LONG_DOUBLE_OPERATIONS_ARE_NOT_TRUNCATED
1096 #define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \
1097 OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
1099 inline octave_int64 \
1100 operator OP (const double& x, const octave_int64& y) \
1102 return external_double_octave_int64_ ## NAME (x, y); \
1105 inline octave_uint64 \
1106 operator OP (const double& x, const octave_uint64& y) \
1108 return external_double_octave_uint64_ ## NAME (x, y); \
1111 inline octave_int64 \
1112 operator OP (const octave_int64& x, const double& y) \
1114 return external_octave_int64_double_ ## NAME (x, y); \
1117 inline octave_uint64 \
1118 operator OP (const octave_uint64& x, const double& y) \
1120 return external_octave_uint64_double_ ## NAME (x, y); \
1123 #define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \
1124 OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
1126 inline octave_int64 \
1127 operator OP (const double& x, const octave_int64& y) \
1129 return octave_int64 (x OP static_cast<long double> (y.value ())); \
1132 inline octave_uint64 \
1133 operator OP (const double& x, const octave_uint64& y) \
1135 return octave_uint64 (x OP static_cast<long double> (y.value ())); \
1138 inline octave_int64 \
1139 operator OP (const octave_int64& x, const double& y) \
1141 return octave_int64 (static_cast<long double> (x.value ()) OP y); \
1144 inline octave_uint64 \
1145 operator OP (const octave_uint64& x, const double& y) \
1147 return octave_uint64 (static_cast<long double> (x.value ()) OP y); \
1152 #define OCTAVE_INT_DOUBLE_BIN_OP(OP, NAME) \
1153 OCTAVE_INT_DOUBLE_BIN_OP0(OP) \
1155 OCTAVE_API octave_int64 \
1156 operator OP (const double&, const octave_int64&); \
1158 OCTAVE_API octave_uint64 \
1159 operator OP (const double&, const octave_uint64&); \
1161 OCTAVE_API octave_int64 \
1162 operator OP (const octave_int64&, const double&); \
1164 OCTAVE_API octave_uint64 \
1165 operator OP (const octave_uint64&, const double&);
1174 #undef OCTAVE_INT_DOUBLE_BIN_OP0
1175 #undef OCTAVE_INT_DOUBLE_BIN_OP
1176 #undef DECLARE_EXTERNAL_LONG_DOUBLE_OP
1177 #undef DECLARE_EXTERNAL_LONG_DOUBLE_OPS
1179 #define OCTAVE_INT_DOUBLE_CMP_OP(OP,NAME) \
1180 template <class T> \
1182 operator OP (const octave_int<T>& x, const double& y) \
1183 { return octave_int_cmp_op::mop<octave_int_cmp_op::NAME> (x.value (), y); } \
1184 template <class T> \
1186 operator OP (const double& x, const octave_int<T>& y) \
1187 { return octave_int_cmp_op::mop<octave_int_cmp_op::NAME> (x, y.value ()); }
1196 #undef OCTAVE_INT_DOUBLE_CMP_OP
1200 #define OCTAVE_INT_FLOAT_BIN_OP(OP) \
1201 template <class T> \
1202 inline octave_int<T> \
1203 operator OP (const octave_int<T>& x, float y) \
1204 { return x OP static_cast<double> (y); } \
1205 template <class T> \
1206 inline octave_int<T> \
1207 operator OP (float x, const octave_int<T>& y) \
1208 { return static_cast<double> (x) OP y; }
1215 #undef OCTAVE_INT_FLOAT_BIN_OP
1217 #define OCTAVE_INT_FLOAT_CMP_OP(OP) \
1218 template <class T> \
1220 operator OP (const octave_int<T>& x, const float& y) \
1221 { return x OP static_cast<double> (y); } \
1222 template <class T> \
1224 operator OP (const float& x, const octave_int<T>& y) \
1225 { return static_cast<double> (x) OP y; }
1234 #undef OCTAVE_INT_FLOAT_CMP_OP