summaryrefslogtreecommitdiff
path: root/gcc/sreal.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/sreal.c')
-rw-r--r--gcc/sreal.c131
1 files changed, 40 insertions, 91 deletions
diff --git a/gcc/sreal.c b/gcc/sreal.c
index 2b5e3ae82be..bc3af2309db 100644
--- a/gcc/sreal.c
+++ b/gcc/sreal.c
@@ -61,13 +61,13 @@ sreal::dump (FILE *file) const
}
DEBUG_FUNCTION void
-debug (sreal &ref)
+debug (const sreal &ref)
{
ref.dump (stderr);
}
DEBUG_FUNCTION void
-debug (sreal *ptr)
+debug (const sreal *ptr)
{
if (ptr)
debug (*ptr);
@@ -91,7 +91,7 @@ sreal::shift_right (int s)
m_exp += s;
- m_sig += (uint64_t) 1 << (s - 1);
+ m_sig += (int64_t) 1 << (s - 1);
m_sig >>= s;
}
@@ -100,43 +100,45 @@ sreal::shift_right (int s)
void
sreal::normalize ()
{
- if (m_sig == 0)
+ int64_t s = m_sig < 0 ? -1 : 1;
+ unsigned HOST_WIDE_INT sig = absu_hwi (m_sig);
+
+ if (sig == 0)
{
- m_negative = 0;
m_exp = -SREAL_MAX_EXP;
}
- else if (m_sig < SREAL_MIN_SIG)
+ else if (sig < SREAL_MIN_SIG)
{
do
{
- m_sig <<= 1;
+ sig <<= 1;
m_exp--;
}
- while (m_sig < SREAL_MIN_SIG);
+ while (sig < SREAL_MIN_SIG);
/* Check underflow. */
if (m_exp < -SREAL_MAX_EXP)
{
m_exp = -SREAL_MAX_EXP;
- m_sig = 0;
+ sig = 0;
}
}
- else if (m_sig > SREAL_MAX_SIG)
+ else if (sig > SREAL_MAX_SIG)
{
int last_bit;
do
{
- last_bit = m_sig & 1;
- m_sig >>= 1;
+ last_bit = sig & 1;
+ sig >>= 1;
m_exp++;
}
- while (m_sig > SREAL_MAX_SIG);
+ while (sig > SREAL_MAX_SIG);
/* Round the number. */
- m_sig += last_bit;
- if (m_sig > SREAL_MAX_SIG)
+ sig += last_bit;
+ if (sig > SREAL_MAX_SIG)
{
- m_sig >>= 1;
+ sig >>= 1;
m_exp++;
}
@@ -144,9 +146,11 @@ sreal::normalize ()
if (m_exp > SREAL_MAX_EXP)
{
m_exp = SREAL_MAX_EXP;
- m_sig = SREAL_MAX_SIG;
+ sig = SREAL_MAX_SIG;
}
}
+
+ m_sig = s * sig;
}
/* Return integer value of *this. */
@@ -154,17 +158,17 @@ sreal::normalize ()
int64_t
sreal::to_int () const
{
- int64_t sign = m_negative ? -1 : 1;
+ int64_t sign = m_sig < 0 ? -1 : 1;
if (m_exp <= -SREAL_BITS)
return 0;
if (m_exp >= SREAL_PART_BITS)
return sign * INTTYPE_MAXIMUM (int64_t);
if (m_exp > 0)
- return sign * (m_sig << m_exp);
+ return m_sig << m_exp;
if (m_exp < 0)
- return sign * (m_sig >> -m_exp);
- return sign * m_sig;
+ return m_sig >> -m_exp;
+ return m_sig;
}
/* Return *this + other. */
@@ -172,36 +176,10 @@ sreal::to_int () const
sreal
sreal::operator+ (const sreal &other) const
{
- const sreal *a_p = this, *b_p = &other;
-
- if (a_p->m_negative && !b_p->m_negative)
- std::swap (a_p, b_p);
-
- /* a + -b => a - b. */
- if (!a_p->m_negative && b_p->m_negative)
- {
- sreal tmp = -(*b_p);
- if (*a_p < tmp)
- return signedless_minus (tmp, *a_p, true);
- else
- return signedless_minus (*a_p, tmp, false);
- }
-
- gcc_checking_assert (a_p->m_negative == b_p->m_negative);
-
- sreal r = signedless_plus (*a_p, *b_p, a_p->m_negative);
-
- return r;
-}
-
-sreal
-sreal::signedless_plus (const sreal &a, const sreal &b, bool negative)
-{
- const sreal *bb;
- sreal r, tmp;
int dexp;
- const sreal *a_p = &a;
- const sreal *b_p = &b;
+ sreal tmp, r;
+
+ const sreal *a_p = this, *b_p = &other, *bb;
if (a_p->m_exp < b_p->m_exp)
std::swap (a_p, b_p);
@@ -211,7 +189,6 @@ sreal::signedless_plus (const sreal &a, const sreal &b, bool negative)
if (dexp > SREAL_BITS)
{
r.m_sig = a_p->m_sig;
- r.m_negative = negative;
return r;
}
@@ -226,56 +203,32 @@ sreal::signedless_plus (const sreal &a, const sreal &b, bool negative)
r.m_sig = a_p->m_sig + bb->m_sig;
r.normalize ();
-
- r.m_negative = negative;
return r;
}
+
/* Return *this - other. */
sreal
sreal::operator- (const sreal &other) const
{
- /* -a - b => -a + (-b). */
- if (m_negative && !other.m_negative)
- return signedless_plus (*this, -other, true);
-
- /* a - (-b) => a + b. */
- if (!m_negative && other.m_negative)
- return signedless_plus (*this, -other, false);
-
- gcc_checking_assert (m_negative == other.m_negative);
-
- /* We want to substract a smaller number from bigger
- for nonegative numbers. */
- if (!m_negative && *this < other)
- return signedless_minus (other, *this, true);
-
- /* Example: -2 - (-3) => 3 - 2 */
- if (m_negative && *this > other)
- return signedless_minus (-other, -(*this), false);
-
- sreal r = signedless_minus (*this, other, m_negative);
-
- return r;
-}
-
-sreal
-sreal::signedless_minus (const sreal &a, const sreal &b, bool negative)
-{
int dexp;
sreal tmp, r;
const sreal *bb;
- const sreal *a_p = &a;
- const sreal *b_p = &b;
+ const sreal *a_p = this, *b_p = &other;
- dexp = a_p->m_exp - b_p->m_exp;
+ int64_t sign = 1;
+ if (a_p->m_exp < b_p->m_exp)
+ {
+ sign = -1;
+ std::swap (a_p, b_p);
+ }
+ dexp = a_p->m_exp - b_p->m_exp;
r.m_exp = a_p->m_exp;
if (dexp > SREAL_BITS)
{
- r.m_sig = a_p->m_sig;
- r.m_negative = negative;
+ r.m_sig = sign * a_p->m_sig;
return r;
}
if (dexp == 0)
@@ -287,10 +240,8 @@ sreal::signedless_minus (const sreal &a, const sreal &b, bool negative)
bb = &tmp;
}
- r.m_sig = a_p->m_sig - bb->m_sig;
+ r.m_sig = sign * (a_p->m_sig - bb->m_sig);
r.normalize ();
-
- r.m_negative = negative;
return r;
}
@@ -300,7 +251,7 @@ sreal
sreal::operator* (const sreal &other) const
{
sreal r;
- if (m_sig < SREAL_MIN_SIG || other.m_sig < SREAL_MIN_SIG)
+ if (std::abs (m_sig) < SREAL_MIN_SIG || std::abs (other.m_sig) < SREAL_MIN_SIG)
{
r.m_sig = 0;
r.m_exp = -SREAL_MAX_EXP;
@@ -312,7 +263,6 @@ sreal::operator* (const sreal &other) const
r.normalize ();
}
- r.m_negative = m_negative ^ other.m_negative;
return r;
}
@@ -325,7 +275,6 @@ sreal::operator/ (const sreal &other) const
sreal r;
r.m_sig = (m_sig << SREAL_PART_BITS) / other.m_sig;
r.m_exp = m_exp - other.m_exp - SREAL_PART_BITS;
- r.m_negative = m_negative ^ other.m_negative;
r.normalize ();
return r;
}