try more robust di_fast code

This commit is contained in:
fredrik 2021-12-08 18:31:26 +01:00
parent 3fe73a8524
commit 85cdf7ea0b
5 changed files with 60 additions and 16 deletions

View file

@ -32,6 +32,13 @@ typedef struct
} }
di_t; di_t;
#define DI_CHECK(__x) \
if (!(__x.a <= __x.b)) \
{ \
flint_printf("di_t endpoints %g, %g not ordered\n", __x.a, __x.b); \
flint_abort(); \
} \
DOUBLE_INTERVAL_INLINE DOUBLE_INTERVAL_INLINE
di_t di_interval(double a, double b) di_t di_interval(double a, double b)
{ {
@ -53,12 +60,22 @@ double _di_below(double x)
{ {
double t; double t;
t = x; if (x <= 1e300)
if (t < 0.0) {
t = -t; t = x;
if (t < 0.0)
t = -t;
t += 1e-300; t += 1e-300;
return x - t * 4.440892098500626e-16; return x - t * 4.440892098500626e-16;
}
else
{
if (x != x)
return -D_INF;
return 1e300;
}
} }
DOUBLE_INTERVAL_INLINE DOUBLE_INTERVAL_INLINE
@ -66,12 +83,22 @@ double _di_above(double x)
{ {
double t; double t;
t = x; if (x >= -1e300)
if (t < 0.0) {
t = -t; t = x;
if (t < 0.0)
t = -t;
t += 1e-300; t += 1e-300;
return x + t * 4.440892098500626e-16; return x + t * 4.440892098500626e-16;
}
else
{
if (x != x)
return D_INF;
return -1e300;
}
} }
DOUBLE_INTERVAL_INLINE DOUBLE_INTERVAL_INLINE

View file

@ -15,22 +15,22 @@ di_t di_fast_mul(di_t x, di_t y)
{ {
di_t res; di_t res;
if (x.a >= 0 && y.a >= 0) if (x.a > 0 && y.a > 0)
{ {
res.a = x.a * y.a; res.a = x.a * y.a;
res.b = x.b * y.b; res.b = x.b * y.b;
} }
else if (x.a >= 0 && y.b <= 0) else if (x.a > 0 && y.b < 0)
{ {
res.a = x.b * y.a; res.a = x.b * y.a;
res.b = x.a * y.b; res.b = x.a * y.b;
} }
else if (x.b <= 0 && y.a >= 0) else if (x.b < 0 && y.a > 0)
{ {
res.a = x.a * y.b; res.a = x.a * y.b;
res.b = x.b * y.a; res.b = x.b * y.a;
} }
else if (x.b <= 0 && y.b <= 0) else if (x.b < 0 && y.b < 0)
{ {
res.a = x.b * y.b; res.a = x.b * y.b;
res.b = x.a * y.a; res.b = x.a * y.a;

View file

@ -37,6 +37,8 @@ int main()
z = di_fast_add(x, y); z = di_fast_add(x, y);
DI_CHECK(z)
arf_set_d(a, x.a); arf_set_d(a, x.a);
arf_set_d(t, y.a); arf_set_d(t, y.a);
arf_add(a, a, t, ARF_PREC_EXACT, ARF_RND_DOWN); arf_add(a, a, t, ARF_PREC_EXACT, ARF_RND_DOWN);

View file

@ -58,6 +58,8 @@ int main()
y = di_randtest(state); y = di_randtest(state);
z = di_fast_div(x, y); z = di_fast_div(x, y);
DI_CHECK(z)
arf_set_d(a, x.a); arf_set_d(a, x.a);
arf_set_d(b, x.b); arf_set_d(b, x.b);
arf_set_d(c, y.a); arf_set_d(c, y.a);

View file

@ -54,10 +54,23 @@ int main()
arf_init(za); arf_init(za);
arf_init(zb); arf_init(zb);
x = di_randtest(state); if (iter == 0)
y = di_randtest(state); {
x.a = 3.5835915908219665e+103;
x.b = 4.0874812242073031e+295;
y.a = -8.3711609938763647e+298;
y.b = -3.414037107833399e+243;
}
else
{
x = di_randtest(state);
y = di_randtest(state);
}
z = di_fast_mul(x, y); z = di_fast_mul(x, y);
DI_CHECK(z)
arf_set_d(a, x.a); arf_set_d(a, x.a);
arf_set_d(b, x.b); arf_set_d(b, x.b);
arf_set_d(c, y.a); arf_set_d(c, y.a);