aboutsummaryrefslogtreecommitdiff
path: root/gcc/double-int.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/double-int.c')
-rw-r--r--gcc/double-int.c300
1 files changed, 210 insertions, 90 deletions
diff --git a/gcc/double-int.c b/gcc/double-int.c
index ea518e3..2f48f2b 100644
--- a/gcc/double-int.c
+++ b/gcc/double-int.c
@@ -610,7 +610,7 @@ div_and_round_double (unsigned code, int uns,
/* Returns mask for PREC bits. */
double_int
-double_int_mask (unsigned prec)
+double_int::mask (unsigned prec)
{
unsigned HOST_WIDE_INT m;
double_int mask;
@@ -635,20 +635,20 @@ double_int_mask (unsigned prec)
of precision PREC. */
double_int
-double_int_max_value (unsigned int prec, bool uns)
+double_int::max_value (unsigned int prec, bool uns)
{
- return double_int_mask (prec - (uns ? 0 : 1));
+ return double_int::mask (prec - (uns ? 0 : 1));
}
/* Returns a minimum value for signed or unsigned integer
of precision PREC. */
double_int
-double_int_min_value (unsigned int prec, bool uns)
+double_int::min_value (unsigned int prec, bool uns)
{
if (uns)
return double_int_zero;
- return double_int_lshift (double_int_one, prec - 1, prec, false);
+ return double_int_one.lshift (prec - 1, prec, false);
}
/* Clears the bits of CST over the precision PREC. If UNS is false, the bits
@@ -659,20 +659,21 @@ double_int_min_value (unsigned int prec, bool uns)
of CST, with the given signedness. */
double_int
-double_int_ext (double_int cst, unsigned prec, bool uns)
+double_int::ext (unsigned prec, bool uns) const
{
if (uns)
- return double_int_zext (cst, prec);
+ return this->zext (prec);
else
- return double_int_sext (cst, prec);
+ return this->sext (prec);
}
-/* The same as double_int_ext with UNS = true. */
+/* The same as double_int::ext with UNS = true. */
double_int
-double_int_zext (double_int cst, unsigned prec)
+double_int::zext (unsigned prec) const
{
- double_int mask = double_int_mask (prec);
+ const double_int &cst = *this;
+ double_int mask = double_int::mask (prec);
double_int r;
r.low = cst.low & mask.low;
@@ -681,12 +682,13 @@ double_int_zext (double_int cst, unsigned prec)
return r;
}
-/* The same as double_int_ext with UNS = false. */
+/* The same as double_int::ext with UNS = false. */
double_int
-double_int_sext (double_int cst, unsigned prec)
+double_int::sext (unsigned prec) const
{
- double_int mask = double_int_mask (prec);
+ const double_int &cst = *this;
+ double_int mask = double_int::mask (prec);
double_int r;
unsigned HOST_WIDE_INT snum;
@@ -714,8 +716,9 @@ double_int_sext (double_int cst, unsigned prec)
/* Returns true if CST fits in signed HOST_WIDE_INT. */
bool
-double_int_fits_in_shwi_p (double_int cst)
+double_int::fits_signed () const
{
+ const double_int &cst = *this;
if (cst.high == 0)
return (HOST_WIDE_INT) cst.low >= 0;
else if (cst.high == -1)
@@ -728,19 +731,20 @@ double_int_fits_in_shwi_p (double_int cst)
unsigned HOST_WIDE_INT if UNS is true. */
bool
-double_int_fits_in_hwi_p (double_int cst, bool uns)
+double_int::fits (bool uns) const
{
if (uns)
- return double_int_fits_in_uhwi_p (cst);
+ return this->fits_unsigned ();
else
- return double_int_fits_in_shwi_p (cst);
+ return this->fits_signed ();
}
/* Returns A * B. */
double_int
-double_int_mul (double_int a, double_int b)
+double_int::operator * (double_int b) const
{
+ const double_int &a = *this;
double_int ret;
mul_double (a.low, a.high, b.low, b.high, &ret.low, &ret.high);
return ret;
@@ -750,9 +754,9 @@ double_int_mul (double_int a, double_int b)
*OVERFLOW is set to nonzero. */
double_int
-double_int_mul_with_sign (double_int a, double_int b,
- bool unsigned_p, int *overflow)
+double_int::mul_with_sign (double_int b, bool unsigned_p, int *overflow) const
{
+ const double_int &a = *this;
double_int ret;
*overflow = mul_double_with_sign (a.low, a.high, b.low, b.high,
&ret.low, &ret.high, unsigned_p);
@@ -762,8 +766,9 @@ double_int_mul_with_sign (double_int a, double_int b,
/* Returns A + B. */
double_int
-double_int_add (double_int a, double_int b)
+double_int::operator + (double_int b) const
{
+ const double_int &a = *this;
double_int ret;
add_double (a.low, a.high, b.low, b.high, &ret.low, &ret.high);
return ret;
@@ -772,8 +777,9 @@ double_int_add (double_int a, double_int b)
/* Returns A - B. */
double_int
-double_int_sub (double_int a, double_int b)
+double_int::operator - (double_int b) const
{
+ const double_int &a = *this;
double_int ret;
neg_double (b.low, b.high, &b.low, &b.high);
add_double (a.low, a.high, b.low, b.high, &ret.low, &ret.high);
@@ -783,8 +789,9 @@ double_int_sub (double_int a, double_int b)
/* Returns -A. */
double_int
-double_int_neg (double_int a)
+double_int::operator - () const
{
+ const double_int &a = *this;
double_int ret;
neg_double (a.low, a.high, &ret.low, &ret.high);
return ret;
@@ -796,9 +803,10 @@ double_int_neg (double_int a)
stored to MOD. */
double_int
-double_int_divmod (double_int a, double_int b, bool uns, unsigned code,
- double_int *mod)
+double_int::divmod (double_int b, bool uns, unsigned code,
+ double_int *mod) const
{
+ const double_int &a = *this;
double_int ret;
div_and_round_double (code, uns, a.low, a.high,
@@ -807,20 +815,20 @@ double_int_divmod (double_int a, double_int b, bool uns, unsigned code,
return ret;
}
-/* The same as double_int_divmod with UNS = false. */
+/* The same as double_int::divmod with UNS = false. */
double_int
-double_int_sdivmod (double_int a, double_int b, unsigned code, double_int *mod)
+double_int::sdivmod (double_int b, unsigned code, double_int *mod) const
{
- return double_int_divmod (a, b, false, code, mod);
+ return this->divmod (b, false, code, mod);
}
-/* The same as double_int_divmod with UNS = true. */
+/* The same as double_int::divmod with UNS = true. */
double_int
-double_int_udivmod (double_int a, double_int b, unsigned code, double_int *mod)
+double_int::udivmod (double_int b, unsigned code, double_int *mod) const
{
- return double_int_divmod (a, b, true, code, mod);
+ return this->divmod (b, true, code, mod);
}
/* Returns A / B (computed as unsigned depending on UNS, and rounded as
@@ -828,27 +836,27 @@ double_int_udivmod (double_int a, double_int b, unsigned code, double_int *mod)
must be included before tree.h. */
double_int
-double_int_div (double_int a, double_int b, bool uns, unsigned code)
+double_int::div (double_int b, bool uns, unsigned code) const
{
double_int mod;
- return double_int_divmod (a, b, uns, code, &mod);
+ return this->divmod (b, uns, code, &mod);
}
-/* The same as double_int_div with UNS = false. */
+/* The same as double_int::div with UNS = false. */
double_int
-double_int_sdiv (double_int a, double_int b, unsigned code)
+double_int::sdiv (double_int b, unsigned code) const
{
- return double_int_div (a, b, false, code);
+ return this->div (b, false, code);
}
-/* The same as double_int_div with UNS = true. */
+/* The same as double_int::div with UNS = true. */
double_int
-double_int_udiv (double_int a, double_int b, unsigned code)
+double_int::udiv (double_int b, unsigned code) const
{
- return double_int_div (a, b, true, code);
+ return this->div (b, true, code);
}
/* Returns A % B (computed as unsigned depending on UNS, and rounded as
@@ -856,28 +864,28 @@ double_int_udiv (double_int a, double_int b, unsigned code)
must be included before tree.h. */
double_int
-double_int_mod (double_int a, double_int b, bool uns, unsigned code)
+double_int::mod (double_int b, bool uns, unsigned code) const
{
double_int mod;
- double_int_divmod (a, b, uns, code, &mod);
+ this->divmod (b, uns, code, &mod);
return mod;
}
-/* The same as double_int_mod with UNS = false. */
+/* The same as double_int::mod with UNS = false. */
double_int
-double_int_smod (double_int a, double_int b, unsigned code)
+double_int::smod (double_int b, unsigned code) const
{
- return double_int_mod (a, b, false, code);
+ return this->mod (b, false, code);
}
-/* The same as double_int_mod with UNS = true. */
+/* The same as double_int::mod with UNS = true. */
double_int
-double_int_umod (double_int a, double_int b, unsigned code)
+double_int::umod (double_int b, unsigned code) const
{
- return double_int_mod (a, b, true, code);
+ return this->mod (b, true, code);
}
/* Return TRUE iff PRODUCT is an integral multiple of FACTOR, and return
@@ -885,13 +893,13 @@ double_int_umod (double_int a, double_int b, unsigned code)
unchanged. */
bool
-double_int_multiple_of (double_int product, double_int factor,
- bool unsigned_p, double_int *multiple)
+double_int::multiple_of (double_int factor,
+ bool unsigned_p, double_int *multiple) const
{
double_int remainder;
- double_int quotient = double_int_divmod (product, factor, unsigned_p,
+ double_int quotient = this->divmod (factor, unsigned_p,
TRUNC_DIV_EXPR, &remainder);
- if (double_int_zero_p (remainder))
+ if (remainder.is_zero ())
{
*multiple = quotient;
return true;
@@ -902,8 +910,9 @@ double_int_multiple_of (double_int product, double_int factor,
/* Set BITPOS bit in A. */
double_int
-double_int_setbit (double_int a, unsigned bitpos)
+double_int::set_bit (unsigned bitpos) const
{
+ double_int a = *this;
if (bitpos < HOST_BITS_PER_WIDE_INT)
a.low |= (unsigned HOST_WIDE_INT) 1 << bitpos;
else
@@ -914,8 +923,9 @@ double_int_setbit (double_int a, unsigned bitpos)
/* Count trailing zeros in A. */
int
-double_int_ctz (double_int a)
+double_int::trailing_zeros () const
{
+ const double_int &a = *this;
unsigned HOST_WIDE_INT w = a.low ? a.low : (unsigned HOST_WIDE_INT) a.high;
unsigned bits = a.low ? 0 : HOST_BITS_PER_WIDE_INT;
if (!w)
@@ -929,30 +939,76 @@ double_int_ctz (double_int a)
otherwise use logical shift. */
double_int
-double_int_lshift (double_int a, HOST_WIDE_INT count, unsigned int prec, bool arith)
+double_int::lshift (HOST_WIDE_INT count, unsigned int prec, bool arith) const
{
+ const double_int &a = *this;
double_int ret;
lshift_double (a.low, a.high, count, prec, &ret.low, &ret.high, arith);
return ret;
}
-/* Shift A rigth by COUNT places keeping only PREC bits of result. Shift
+/* Shift A right by COUNT places keeping only PREC bits of result. Shift
left if COUNT is negative. ARITH true specifies arithmetic shifting;
otherwise use logical shift. */
double_int
-double_int_rshift (double_int a, HOST_WIDE_INT count, unsigned int prec, bool arith)
+double_int::rshift (HOST_WIDE_INT count, unsigned int prec, bool arith) const
{
+ const double_int &a = *this;
double_int ret;
lshift_double (a.low, a.high, -count, prec, &ret.low, &ret.high, arith);
return ret;
}
+/* Arithmetic shift A left by COUNT places keeping only PREC bits of result.
+ Shift right if COUNT is negative. */
+
+double_int
+double_int::alshift (HOST_WIDE_INT count, unsigned int prec) const
+{
+ double_int r;
+ lshift_double (low, high, count, prec, &r.low, &r.high, true);
+ return r;
+}
+
+/* Arithmetic shift A right by COUNT places keeping only PREC bits of result.
+ Shift left if COUNT is negative. */
+
+double_int
+double_int::arshift (HOST_WIDE_INT count, unsigned int prec) const
+{
+ double_int r;
+ lshift_double (low, high, -count, prec, &r.low, &r.high, true);
+ return r;
+}
+
+/* Logical shift A left by COUNT places keeping only PREC bits of result.
+ Shift right if COUNT is negative. */
+
+double_int
+double_int::llshift (HOST_WIDE_INT count, unsigned int prec) const
+{
+ double_int r;
+ lshift_double (low, high, count, prec, &r.low, &r.high, false);
+ return r;
+}
+
+/* Logical shift A right by COUNT places keeping only PREC bits of result.
+ Shift left if COUNT is negative. */
+
+double_int
+double_int::lrshift (HOST_WIDE_INT count, unsigned int prec) const
+{
+ double_int r;
+ lshift_double (low, high, -count, prec, &r.low, &r.high, false);
+ return r;
+}
+
/* Rotate A left by COUNT places keeping only PREC bits of result.
Rotate right if COUNT is negative. */
double_int
-double_int_lrotate (double_int a, HOST_WIDE_INT count, unsigned int prec)
+double_int::lrotate (HOST_WIDE_INT count, unsigned int prec) const
{
double_int t1, t2;
@@ -960,17 +1016,17 @@ double_int_lrotate (double_int a, HOST_WIDE_INT count, unsigned int prec)
if (count < 0)
count += prec;
- t1 = double_int_lshift (a, count, prec, false);
- t2 = double_int_rshift (a, prec - count, prec, false);
+ t1 = this->lshift (count, prec, false);
+ t2 = this->rshift (prec - count, prec, false);
- return double_int_ior (t1, t2);
+ return t1 | t2;
}
/* Rotate A rigth by COUNT places keeping only PREC bits of result.
Rotate right if COUNT is negative. */
double_int
-double_int_rrotate (double_int a, HOST_WIDE_INT count, unsigned int prec)
+double_int::rrotate (HOST_WIDE_INT count, unsigned int prec) const
{
double_int t1, t2;
@@ -978,30 +1034,31 @@ double_int_rrotate (double_int a, HOST_WIDE_INT count, unsigned int prec)
if (count < 0)
count += prec;
- t1 = double_int_rshift (a, count, prec, false);
- t2 = double_int_lshift (a, prec - count, prec, false);
+ t1 = this->rshift (count, prec, false);
+ t2 = this->lshift (prec - count, prec, false);
- return double_int_ior (t1, t2);
+ return t1 | t2;
}
/* Returns -1 if A < B, 0 if A == B and 1 if A > B. Signedness of the
comparison is given by UNS. */
int
-double_int_cmp (double_int a, double_int b, bool uns)
+double_int::cmp (double_int b, bool uns) const
{
if (uns)
- return double_int_ucmp (a, b);
+ return this->ucmp (b);
else
- return double_int_scmp (a, b);
+ return this->scmp (b);
}
/* Compares two unsigned values A and B. Returns -1 if A < B, 0 if A == B,
and 1 if A > B. */
int
-double_int_ucmp (double_int a, double_int b)
+double_int::ucmp (double_int b) const
{
+ const double_int &a = *this;
if ((unsigned HOST_WIDE_INT) a.high < (unsigned HOST_WIDE_INT) b.high)
return -1;
if ((unsigned HOST_WIDE_INT) a.high > (unsigned HOST_WIDE_INT) b.high)
@@ -1018,8 +1075,9 @@ double_int_ucmp (double_int a, double_int b)
and 1 if A > B. */
int
-double_int_scmp (double_int a, double_int b)
+double_int::scmp (double_int b) const
{
+ const double_int &a = *this;
if (a.high < b.high)
return -1;
if (a.high > b.high)
@@ -1032,49 +1090,111 @@ double_int_scmp (double_int a, double_int b)
return 0;
}
+/* Compares two unsigned values A and B for less-than. */
+
+bool
+double_int::ult (double_int b) const
+{
+ if ((unsigned HOST_WIDE_INT) high < (unsigned HOST_WIDE_INT) b.high)
+ return true;
+ if ((unsigned HOST_WIDE_INT) high > (unsigned HOST_WIDE_INT) b.high)
+ return false;
+ if (low < b.low)
+ return true;
+ return false;
+}
+
+/* Compares two unsigned values A and B for greater-than. */
+
+bool
+double_int::ugt (double_int b) const
+{
+ if ((unsigned HOST_WIDE_INT) high > (unsigned HOST_WIDE_INT) b.high)
+ return true;
+ if ((unsigned HOST_WIDE_INT) high < (unsigned HOST_WIDE_INT) b.high)
+ return false;
+ if (low > b.low)
+ return true;
+ return false;
+}
+
+/* Compares two signed values A and B for less-than. */
+
+bool
+double_int::slt (double_int b) const
+{
+ if (high < b.high)
+ return true;
+ if (high > b.high)
+ return false;
+ if (low < b.low)
+ return true;
+ return false;
+}
+
+/* Compares two signed values A and B for greater-than. */
+
+bool
+double_int::sgt (double_int b) const
+{
+ if (high > b.high)
+ return true;
+ if (high < b.high)
+ return false;
+ if (low > b.low)
+ return true;
+ return false;
+}
+
+
/* Compares two values A and B. Returns max value. Signedness of the
comparison is given by UNS. */
double_int
-double_int_max (double_int a, double_int b, bool uns)
+double_int::max (double_int b, bool uns)
{
- return (double_int_cmp (a, b, uns) == 1) ? a : b;
+ return (this->cmp (b, uns) == 1) ? *this : b;
}
/* Compares two signed values A and B. Returns max value. */
-double_int double_int_smax (double_int a, double_int b)
+double_int
+double_int::smax (double_int b)
{
- return (double_int_scmp (a, b) == 1) ? a : b;
+ return (this->scmp (b) == 1) ? *this : b;
}
/* Compares two unsigned values A and B. Returns max value. */
-double_int double_int_umax (double_int a, double_int b)
+double_int
+double_int::umax (double_int b)
{
- return (double_int_ucmp (a, b) == 1) ? a : b;
+ return (this->ucmp (b) == 1) ? *this : b;
}
/* Compares two values A and B. Returns mix value. Signedness of the
comparison is given by UNS. */
-double_int double_int_min (double_int a, double_int b, bool uns)
+double_int
+double_int::min (double_int b, bool uns)
{
- return (double_int_cmp (a, b, uns) == -1) ? a : b;
+ return (this->cmp (b, uns) == -1) ? *this : b;
}
/* Compares two signed values A and B. Returns min value. */
-double_int double_int_smin (double_int a, double_int b)
+double_int
+double_int::smin (double_int b)
{
- return (double_int_scmp (a, b) == -1) ? a : b;
+ return (this->scmp (b) == -1) ? *this : b;
}
/* Compares two unsigned values A and B. Returns min value. */
-double_int double_int_umin (double_int a, double_int b)
+double_int
+double_int::umin (double_int b)
{
- return (double_int_ucmp (a, b) == -1) ? a : b;
+ return (this->ucmp (b) == -1) ? *this : b;
}
/* Splits last digit of *CST (taken as unsigned) in BASE and returns it. */
@@ -1102,19 +1222,19 @@ dump_double_int (FILE *file, double_int cst, bool uns)
unsigned digits[100], n;
int i;
- if (double_int_zero_p (cst))
+ if (cst.is_zero ())
{
fprintf (file, "0");
return;
}
- if (!uns && double_int_negative_p (cst))
+ if (!uns && cst.is_negative ())
{
fprintf (file, "-");
- cst = double_int_neg (cst);
+ cst = -cst;
}
- for (n = 0; !double_int_zero_p (cst); n++)
+ for (n = 0; !cst.is_zero (); n++)
digits[n] = double_int_split_digit (&cst, 10);
for (i = n - 1; i >= 0; i--)
fprintf (file, "%u", digits[i]);
@@ -1130,10 +1250,10 @@ mpz_set_double_int (mpz_t result, double_int val, bool uns)
bool negate = false;
unsigned HOST_WIDE_INT vp[2];
- if (!uns && double_int_negative_p (val))
+ if (!uns && val.is_negative ())
{
negate = true;
- val = double_int_neg (val);
+ val = -val;
}
vp[0] = val.low;
@@ -1191,9 +1311,9 @@ mpz_get_double_int (const_tree type, mpz_t val, bool wrap)
res.low = vp[0];
res.high = (HOST_WIDE_INT) vp[1];
- res = double_int_ext (res, TYPE_PRECISION (type), TYPE_UNSIGNED (type));
+ res = res.ext (TYPE_PRECISION (type), TYPE_UNSIGNED (type));
if (mpz_sgn (val) < 0)
- res = double_int_neg (res);
+ res = -res;
return res;
}