Corrected mpf_get_2exp_d on Win64 when the exponent in limbs fits in mp_bit_cnt but the exponent in bits (as returned by this API) does not
This commit is contained in:
parent
36cdf4ad96
commit
5aab0cf7b0
@ -47,7 +47,7 @@ mpf_get_2exp_d (double *r, mpf_srcptr src)
|
||||
|
||||
*r = mpn_get_d (ptr, abs_size, size,
|
||||
(long) - (abs_size * GMP_NUMB_BITS - cnt));
|
||||
return EXP(src) * GMP_NUMB_BITS - cnt;
|
||||
return (mpir_si)EXP(src) * GMP_NUMB_BITS - cnt;
|
||||
}
|
||||
|
||||
double
|
||||
|
@ -107,7 +107,7 @@ namespace MPIR.Tests.HugeFloatTests
|
||||
using (var a = new HugeFloat())
|
||||
{
|
||||
a.SetTo(-123.25);
|
||||
var exp = 0;
|
||||
var exp = Platform.Si(0, 0);
|
||||
double c = a.ToDouble(out exp);
|
||||
Assert.IsTrue(c.Equals(-0.962890625));
|
||||
Assert.AreEqual(7L, exp);
|
||||
@ -116,6 +116,30 @@ namespace MPIR.Tests.HugeFloatTests
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void FloatFromDoubleWithLargeExponent()
|
||||
{
|
||||
using (var a = new HugeFloat())
|
||||
{
|
||||
var exp = Platform.Si(0, 0);
|
||||
double mantissa;
|
||||
|
||||
a.SetTo(3);
|
||||
a.Value = a << Platform.Ui(0x1F65432FD9, 0x7F654329);
|
||||
|
||||
mantissa = a.ToDouble(out exp);
|
||||
Assert.IsTrue(mantissa.Equals(0.75));
|
||||
Assert.AreEqual(Platform.Si(0x1F65432FDB, 0x7F65432B), exp);
|
||||
|
||||
a.SetTo(-3);
|
||||
a.Value = a >> Platform.Ui(0x1F65432FDD, 0x7F65432D);
|
||||
|
||||
mantissa = a.ToDouble(out exp);
|
||||
Assert.IsTrue(mantissa.Equals(-0.75));
|
||||
Assert.AreEqual(Platform.Si(-0x1F65432FDB, -0x7F65432B), exp);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void FloatToAndFromFloat()
|
||||
{
|
||||
@ -196,12 +220,12 @@ namespace MPIR.Tests.HugeFloatTests
|
||||
using(var a = new HugeFloat())
|
||||
{
|
||||
a.SetTo(-123.45e20);
|
||||
var exp = 0;
|
||||
var exp = Platform.Si(0, 0);
|
||||
var zillion = Platform.Si(10000000000, 1000000000);
|
||||
a.Value = a + a;
|
||||
double c = a.ToDouble(out exp);
|
||||
|
||||
Assert.AreEqual(75, exp);
|
||||
Assert.AreEqual(Platform.Si(75, 75), exp);
|
||||
c *= Math.Pow(2, exp);
|
||||
|
||||
Assert.IsTrue(a + zillion >= c);
|
||||
|
@ -1025,12 +1025,11 @@ namespace MPIR
|
||||
/// </para></summary>
|
||||
/// <param name="exp">variable to store the exponent in.</param>
|
||||
/// <returns>The mantissa of the value as a double, possibly truncated.</returns>
|
||||
double ToDouble([Out] mp_exp_t% exp)
|
||||
double ToDouble([Out] mpir_si% exp)
|
||||
{
|
||||
mp_exp_t x;
|
||||
auto result = MP(get_d_2exp)(&x, _value);
|
||||
exp = x;
|
||||
return result;
|
||||
double x;
|
||||
exp = MP(get_2exp_d)(&x, _value);
|
||||
return x;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
@ -109,6 +109,43 @@ check_round (void)
|
||||
tests_hardware_setround (old_rnd_mode);
|
||||
}
|
||||
|
||||
static void
|
||||
check_large_exponent(void)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
static const mpir_si data[] = { 0x1F789ABCDE, 0x1FFFFFFFBF, -0x1FEDCBA987, -0x1FFFFFFFC1 };
|
||||
mpf_t f;
|
||||
double got;
|
||||
mpir_si got_exp;
|
||||
unsigned int i;
|
||||
|
||||
mpf_init2 (f, 1024L);
|
||||
|
||||
for (i = 0; i < numberof (data); i++)
|
||||
{
|
||||
mpf_set_ui (f, 1L);
|
||||
if (data[i] > 0)
|
||||
{
|
||||
mpf_mul_2exp(f, f, data[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
mpf_div_2exp(f, f, -data[i]);
|
||||
}
|
||||
got_exp = mpf_get_2exp_d (&got, f);
|
||||
if (got != 0.5 || got_exp != data[i] + 1)
|
||||
{
|
||||
printf ("mpf_get_2exp_d bad on 2**%lld\n", data[i]);
|
||||
printf ("result incorrect, expect mantissa = 0.5, exp = %lld\n", data[i] + 1);
|
||||
mpf_trace (" f ", f);
|
||||
d_trace (" got ", got);
|
||||
printf (" got exp %lld\n", got_exp);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
mpf_clear (f);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
@ -118,6 +155,7 @@ main (void)
|
||||
|
||||
check_onebit ();
|
||||
check_round ();
|
||||
check_large_exponent ();
|
||||
|
||||
tests_end ();
|
||||
exit (0);
|
||||
|
Loading…
Reference in New Issue
Block a user