Fix sreal::to_int and implement sreal::to_nearest_int
while exploring new loop estimate dumps, I noticed that loop iterating 1.8 times by profile is etimated as iterating once instead of 2 by nb_estimate. While nb_estimate should really be a sreal and I will convert it incrementally, I found problem is in previous patch doing: + *nit = (snit + 0.5).to_int (); this does not work for sreal because it has only constructor from integer, so first 0.5 is rounded to 0 and then added to snit. Some code uses sreal(1, -1) which produces 0.5, but it reuqires unnecessary addition, so I decided to add to_nearest_int. Testing it I noticed that to_int is buggy: (sreal(3)/2).to_int () == 1 while (sreal(-3)/2).to_int () == -2 Fix is easy, we need to correctly shift in positive values. This patch fixes it and adds the to_nearest_int alternative. gcc/ChangeLog: * sreal.cc (sreal::to_nearest_int): New. (sreal_verify_basics): Verify also to_nearest_int. (verify_aritmetics): Likewise. (sreal_verify_conversions): New. (sreal_cc_tests): Call sreal_verify_conversions. * sreal.h: (sreal::to_nearest_int): Declare
This commit is contained in:
parent
65ff4a45b1
commit
e35d297fc9
2 changed files with 55 additions and 1 deletions
55
gcc/sreal.cc
55
gcc/sreal.cc
|
@ -116,7 +116,26 @@ sreal::to_int () const
|
|||
if (m_exp > 0)
|
||||
return sign * (SREAL_ABS ((int64_t)m_sig) << m_exp);
|
||||
if (m_exp < 0)
|
||||
return m_sig >> -m_exp;
|
||||
return sign * (SREAL_ABS ((int64_t)m_sig) >> -m_exp);
|
||||
return m_sig;
|
||||
}
|
||||
|
||||
/* Return nearest integer value of *this. */
|
||||
|
||||
int64_t
|
||||
sreal::to_nearest_int () const
|
||||
{
|
||||
int64_t sign = SREAL_SIGN (m_sig);
|
||||
|
||||
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 * (SREAL_ABS ((int64_t)m_sig) << m_exp);
|
||||
if (m_exp < 0)
|
||||
return sign * ((SREAL_ABS ((int64_t)m_sig) >> -m_exp)
|
||||
+ ((SREAL_ABS (m_sig) >> (-m_exp - 1)) & 1));
|
||||
return m_sig;
|
||||
}
|
||||
|
||||
|
@ -286,6 +305,8 @@ sreal_verify_basics (void)
|
|||
|
||||
ASSERT_EQ (INT_MIN/2, minimum.to_int ());
|
||||
ASSERT_EQ (INT_MAX/2, maximum.to_int ());
|
||||
ASSERT_EQ (INT_MIN/2, minimum.to_nearest_int ());
|
||||
ASSERT_EQ (INT_MAX/2, maximum.to_nearest_int ());
|
||||
|
||||
ASSERT_FALSE (minus_two < minus_two);
|
||||
ASSERT_FALSE (seven < seven);
|
||||
|
@ -315,6 +336,10 @@ verify_aritmetics (int64_t a, int64_t b)
|
|||
ASSERT_EQ (a - b, (sreal (a) - sreal (b)).to_int ());
|
||||
ASSERT_EQ (b + a, (sreal (b) + sreal (a)).to_int ());
|
||||
ASSERT_EQ (b - a, (sreal (b) - sreal (a)).to_int ());
|
||||
ASSERT_EQ (a + b, (sreal (a) + sreal (b)).to_nearest_int ());
|
||||
ASSERT_EQ (a - b, (sreal (a) - sreal (b)).to_nearest_int ());
|
||||
ASSERT_EQ (b + a, (sreal (b) + sreal (a)).to_nearest_int ());
|
||||
ASSERT_EQ (b - a, (sreal (b) - sreal (a)).to_nearest_int ());
|
||||
}
|
||||
|
||||
/* Verify arithmetics for interesting numbers. */
|
||||
|
@ -377,6 +402,33 @@ sreal_verify_negative_division (void)
|
|||
ASSERT_EQ (sreal (1234567) / sreal (-1234567), sreal (-1));
|
||||
}
|
||||
|
||||
static void
|
||||
sreal_verify_conversions (void)
|
||||
{
|
||||
ASSERT_EQ ((sreal (11) / sreal (3)).to_int (), 3);
|
||||
ASSERT_EQ ((sreal (11) / sreal (3)).to_nearest_int (), 4);
|
||||
ASSERT_EQ ((sreal (10) / sreal (3)).to_int (), 3);
|
||||
ASSERT_EQ ((sreal (10) / sreal (3)).to_nearest_int (), 3);
|
||||
ASSERT_EQ ((sreal (9) / sreal (3)).to_int (), 3);
|
||||
ASSERT_EQ ((sreal (9) / sreal (3)).to_nearest_int (), 3);
|
||||
ASSERT_EQ ((sreal (-11) / sreal (3)).to_int (), -3);
|
||||
ASSERT_EQ ((sreal (-11) / sreal (3)).to_nearest_int (), -4);
|
||||
ASSERT_EQ ((sreal (-10) / sreal (3)).to_int (), -3);
|
||||
ASSERT_EQ ((sreal (-10) / sreal (3)).to_nearest_int (), -3);
|
||||
ASSERT_EQ ((sreal (-3)).to_int (), -3);
|
||||
ASSERT_EQ ((sreal (-3)).to_nearest_int (), -3);
|
||||
for (int i = -100000 ; i < 100000; i += 123)
|
||||
for (int j = -10000 ; j < 100000; j += 71)
|
||||
if (j != 0)
|
||||
{
|
||||
sreal sval = ((sreal)i) / (sreal)j;
|
||||
double val = (double)i / (double)j;
|
||||
ASSERT_EQ ((fabs (sval.to_double () - val) < 0.00001), true);
|
||||
ASSERT_EQ (sval.to_int (), (int)val);
|
||||
ASSERT_EQ (sval.to_nearest_int (), lround (val));
|
||||
}
|
||||
}
|
||||
|
||||
/* Run all of the selftests within this file. */
|
||||
|
||||
void sreal_cc_tests ()
|
||||
|
@ -385,6 +437,7 @@ void sreal_cc_tests ()
|
|||
sreal_verify_arithmetics ();
|
||||
sreal_verify_shifting ();
|
||||
sreal_verify_negative_division ();
|
||||
sreal_verify_conversions ();
|
||||
}
|
||||
|
||||
} // namespace selftest
|
||||
|
|
|
@ -51,6 +51,7 @@ public:
|
|||
|
||||
void dump (FILE *) const;
|
||||
int64_t to_int () const;
|
||||
int64_t to_nearest_int () const;
|
||||
double to_double () const;
|
||||
void stream_out (struct output_block *);
|
||||
static sreal stream_in (class lto_input_block *);
|
||||
|
|
Loading…
Add table
Reference in a new issue