mirror of
https://github.com/vale981/arb
synced 2025-03-04 17:01:40 -05:00
helpers for double interval arithmetic
This commit is contained in:
parent
22fff3bb87
commit
3345c7839c
14 changed files with 868 additions and 1 deletions
|
@ -15,7 +15,7 @@ AT=@
|
||||||
BUILD_DIRS = fmpr arf mag arb arb_mat arb_poly arb_calc acb acb_mat acb_poly \
|
BUILD_DIRS = fmpr arf mag arb arb_mat arb_poly arb_calc acb acb_mat acb_poly \
|
||||||
acb_dft acb_calc acb_hypgeom acb_elliptic acb_modular dirichlet acb_dirichlet \
|
acb_dft acb_calc acb_hypgeom acb_elliptic acb_modular dirichlet acb_dirichlet \
|
||||||
arb_hypgeom bernoulli hypgeom fmpz_extras bool_mat partitions dlog \
|
arb_hypgeom bernoulli hypgeom fmpz_extras bool_mat partitions dlog \
|
||||||
arb_fmpz_poly arb_fpwrap \
|
double_interval arb_fmpz_poly arb_fpwrap \
|
||||||
$(EXTRA_BUILD_DIRS)
|
$(EXTRA_BUILD_DIRS)
|
||||||
|
|
||||||
TEMPLATE_DIRS =
|
TEMPLATE_DIRS =
|
||||||
|
|
98
doc/source/double_interval.rst
Normal file
98
doc/source/double_interval.rst
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
.. _double_interval:
|
||||||
|
|
||||||
|
**double_interval.h** -- double-precision interval arithmetic and helpers
|
||||||
|
===============================================================================
|
||||||
|
|
||||||
|
This module provides helper functions for computing fast enclosures
|
||||||
|
using ``double`` arithmetic.
|
||||||
|
|
||||||
|
|
||||||
|
Types, macros and constants
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
.. type:: di_t
|
||||||
|
|
||||||
|
Holds two ``double`` endpoints ``a`` and ``b`` representing
|
||||||
|
the extended real interval `[a, b]`. We generally assume that
|
||||||
|
`a \le b` and that neither endpoint is NaN.
|
||||||
|
|
||||||
|
Basic manipulation
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
.. function:: di_t di_interval(double a, double b)
|
||||||
|
|
||||||
|
Returns the interval `[a, b]`. We require that the endpoints
|
||||||
|
are ordered and not NaN.
|
||||||
|
|
||||||
|
.. function:: di_t arb_get_di(const arb_t x)
|
||||||
|
|
||||||
|
Returns the ball *x* converted to a double-precision interval.
|
||||||
|
|
||||||
|
.. function:: void arb_set_di(arb_t res, di_t x, slong prec)
|
||||||
|
|
||||||
|
Sets the ball *res* to the double-precision interval *x*,
|
||||||
|
rounded to *prec* bits.
|
||||||
|
|
||||||
|
.. function:: void di_print(di_t x)
|
||||||
|
|
||||||
|
Prints *x* to standard output. This simply prints decimal
|
||||||
|
representations of the floating-point endpoints; the
|
||||||
|
decimals are not guaranteed to be rounded outward.
|
||||||
|
|
||||||
|
.. function:: double d_randtest2(flint_rand_t state)
|
||||||
|
|
||||||
|
Returns a random non-NaN ``double`` with any exponent.
|
||||||
|
The value can be infinite or subnormal.
|
||||||
|
|
||||||
|
.. function:: di_t di_randtest(flint_rand_t state)
|
||||||
|
|
||||||
|
Returns an interval with random endpoints.
|
||||||
|
|
||||||
|
Arithmetic
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
.. function:: di_t di_neg(di_t x)
|
||||||
|
|
||||||
|
Returns the exact negation of *x*.
|
||||||
|
|
||||||
|
Fast arithmetic
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
The following methods perform fast but sloppy interval arithmetic:
|
||||||
|
we manipulate the endpoints with default rounding and then add
|
||||||
|
or subtract generic perturbations regardless of whether the
|
||||||
|
operations were exact.
|
||||||
|
It is currently assumed that the CPU rounding mode is to nearest.
|
||||||
|
|
||||||
|
.. function:: di_t di_fast_add(di_t x, di_t y)
|
||||||
|
di_t di_fast_sub(di_t x, di_t y)
|
||||||
|
di_t di_fast_mul(di_t x, di_t y)
|
||||||
|
di_t di_fast_div(di_t x, di_t y)
|
||||||
|
|
||||||
|
Returns the sum, difference, product or quotient of *x* and *y*.
|
||||||
|
Division by zero is currently defined to return `[-\infty, +\infty]`.
|
||||||
|
|
||||||
|
.. function:: di_t di_fast_sqr(di_t x)
|
||||||
|
|
||||||
|
Returns the square of *x*. The output is clamped to
|
||||||
|
be nonnegative.
|
||||||
|
|
||||||
|
.. function:: di_t di_fast_add_d(di_t x, double y)
|
||||||
|
di_t di_fast_sub_d(di_t x, double y)
|
||||||
|
di_t di_fast_mul_d(di_t x, double y)
|
||||||
|
di_t di_fast_div_d(di_t x, double y)
|
||||||
|
|
||||||
|
Arithmetic with an exact ``double`` operand.
|
||||||
|
|
||||||
|
.. function:: di_t di_fast_log_nonnegative(di_t x)
|
||||||
|
|
||||||
|
Returns an enclosure of `\log(x)`. The lower endpoint of *x*
|
||||||
|
is rounded up to 0 if it is negative.
|
||||||
|
|
||||||
|
.. function:: di_t di_fast_mid(di_t x)
|
||||||
|
|
||||||
|
Returns an enclosure of the midpoint of *x*.
|
||||||
|
|
||||||
|
.. function:: double di_fast_ubound_radius(di_t x)
|
||||||
|
|
||||||
|
Returns an upper bound for the radius of *x*.
|
|
@ -217,6 +217,7 @@ Mainly for internal use.
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
|
double_interval.rst
|
||||||
fmpz_extras.rst
|
fmpz_extras.rst
|
||||||
bool_mat.rst
|
bool_mat.rst
|
||||||
dlog.rst
|
dlog.rst
|
||||||
|
|
193
double_interval.h
Normal file
193
double_interval.h
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2021 Fredrik Johansson
|
||||||
|
|
||||||
|
This file is part of Arb.
|
||||||
|
|
||||||
|
Arb is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||||
|
by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version. See <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DOUBLE_INTERVAL_H
|
||||||
|
#define DOUBLE_INTERVAL_H
|
||||||
|
|
||||||
|
#ifdef DOUBLE_INTERVAL_INLINES_C
|
||||||
|
#define DOUBLE_INTERVAL_INLINE
|
||||||
|
#else
|
||||||
|
#define DOUBLE_INTERVAL_INLINE static __inline__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "flint/double_extras.h"
|
||||||
|
#include "arb.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
double a;
|
||||||
|
double b;
|
||||||
|
}
|
||||||
|
di_t;
|
||||||
|
|
||||||
|
DOUBLE_INTERVAL_INLINE
|
||||||
|
di_t di_interval(double a, double b)
|
||||||
|
{
|
||||||
|
di_t res;
|
||||||
|
|
||||||
|
if (!(a < b))
|
||||||
|
{
|
||||||
|
flint_printf("di_interval endpoints not ordered\n");
|
||||||
|
flint_abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
res.a = a;
|
||||||
|
res.b = b;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_INTERVAL_INLINE
|
||||||
|
double _di_below(double x)
|
||||||
|
{
|
||||||
|
double t;
|
||||||
|
|
||||||
|
t = x;
|
||||||
|
if (t < 0.0)
|
||||||
|
t = -t;
|
||||||
|
|
||||||
|
t += 1e-300;
|
||||||
|
return x - t * 4.440892098500626e-16;
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_INTERVAL_INLINE
|
||||||
|
double _di_above(double x)
|
||||||
|
{
|
||||||
|
double t;
|
||||||
|
|
||||||
|
t = x;
|
||||||
|
if (t < 0.0)
|
||||||
|
t = -t;
|
||||||
|
|
||||||
|
t += 1e-300;
|
||||||
|
return x + t * 4.440892098500626e-16;
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_INTERVAL_INLINE
|
||||||
|
di_t di_neg(di_t x)
|
||||||
|
{
|
||||||
|
di_t res;
|
||||||
|
res.a = -x.b;
|
||||||
|
res.b = -x.a;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_INTERVAL_INLINE
|
||||||
|
di_t di_fast_add(di_t x, di_t y)
|
||||||
|
{
|
||||||
|
di_t res;
|
||||||
|
res.a = _di_below(x.a + y.a);
|
||||||
|
res.b = _di_above(x.b + y.b);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_INTERVAL_INLINE
|
||||||
|
di_t di_fast_sub(di_t x, di_t y)
|
||||||
|
{
|
||||||
|
di_t res;
|
||||||
|
res.a = _di_below(x.a - y.b);
|
||||||
|
res.b = _di_above(x.b - y.a);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
di_t di_fast_mul(di_t x, di_t y);
|
||||||
|
di_t di_fast_sqr(di_t x);
|
||||||
|
di_t di_fast_div(di_t x, di_t y);
|
||||||
|
|
||||||
|
DOUBLE_INTERVAL_INLINE
|
||||||
|
di_t di_fast_add_d(di_t x, double y)
|
||||||
|
{
|
||||||
|
return di_fast_add(x, di_interval(y, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_INTERVAL_INLINE
|
||||||
|
di_t di_fast_sub_d(di_t x, double y)
|
||||||
|
{
|
||||||
|
return di_fast_sub(x, di_interval(y, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_INTERVAL_INLINE
|
||||||
|
di_t di_fast_mul_d(di_t x, double y)
|
||||||
|
{
|
||||||
|
return di_fast_mul(x, di_interval(y, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_INTERVAL_INLINE
|
||||||
|
di_t di_fast_div_d(di_t x, double y)
|
||||||
|
{
|
||||||
|
return di_fast_div(x, di_interval(y, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
di_t di_fast_log_nonnegative(di_t x);
|
||||||
|
|
||||||
|
DOUBLE_INTERVAL_INLINE
|
||||||
|
di_t di_fast_mid(di_t x)
|
||||||
|
{
|
||||||
|
di_t a, b;
|
||||||
|
a = di_interval(x.a, x.a);
|
||||||
|
b = di_interval(x.b, x.b);
|
||||||
|
return di_fast_mul_d(di_fast_add(a, b), 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_INTERVAL_INLINE
|
||||||
|
double di_fast_ubound_radius(di_t x)
|
||||||
|
{
|
||||||
|
return _di_above((x.b - x.a) * 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_INTERVAL_INLINE
|
||||||
|
void di_print(di_t x)
|
||||||
|
{
|
||||||
|
flint_printf("[%.17g, %.17g]", x.a, x.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
di_t arb_get_di(const arb_t x);
|
||||||
|
void arb_set_di(arb_t res, di_t x, slong prec);
|
||||||
|
|
||||||
|
DOUBLE_INTERVAL_INLINE
|
||||||
|
double d_randtest2(flint_rand_t state)
|
||||||
|
{
|
||||||
|
double x;
|
||||||
|
|
||||||
|
x = d_randtest(state);
|
||||||
|
if (n_randint(state, 2))
|
||||||
|
x = -x;
|
||||||
|
|
||||||
|
return ldexp(x, n_randint(state, 2400) - 1200);
|
||||||
|
}
|
||||||
|
|
||||||
|
DOUBLE_INTERVAL_INLINE
|
||||||
|
di_t di_randtest(flint_rand_t state)
|
||||||
|
{
|
||||||
|
di_t res;
|
||||||
|
|
||||||
|
res.a = d_randtest2(state);
|
||||||
|
res.b = d_randtest2(state);
|
||||||
|
|
||||||
|
if (res.a > res.b)
|
||||||
|
{
|
||||||
|
double t = res.a;
|
||||||
|
res.a = res.b;
|
||||||
|
res.b = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
34
double_interval/arb_get_di.c
Normal file
34
double_interval/arb_get_di.c
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2021 Fredrik Johansson
|
||||||
|
|
||||||
|
This file is part of Arb.
|
||||||
|
|
||||||
|
Arb is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||||
|
by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version. See <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "double_interval.h"
|
||||||
|
|
||||||
|
di_t
|
||||||
|
arb_get_di(const arb_t x)
|
||||||
|
{
|
||||||
|
di_t res;
|
||||||
|
if (arf_is_nan(arb_midref(x)))
|
||||||
|
{
|
||||||
|
res.a = -D_INF;
|
||||||
|
res.b = D_INF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
arf_t t;
|
||||||
|
arf_init(t);
|
||||||
|
arb_get_lbound_arf(t, x, 53);
|
||||||
|
res.a = arf_get_d(t, ARF_RND_FLOOR);
|
||||||
|
arb_get_ubound_arf(t, x, 53);
|
||||||
|
res.b = arf_get_d(t, ARF_RND_CEIL);
|
||||||
|
arf_clear(t);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
25
double_interval/arb_set_di.c
Normal file
25
double_interval/arb_set_di.c
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2021 Fredrik Johansson
|
||||||
|
|
||||||
|
This file is part of Arb.
|
||||||
|
|
||||||
|
Arb is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||||
|
by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version. See <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "double_interval.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
arb_set_di(arb_t res, di_t x, slong prec)
|
||||||
|
{
|
||||||
|
arf_t t, u;
|
||||||
|
arf_init(t);
|
||||||
|
arf_init(u);
|
||||||
|
arf_set_d(t, x.a);
|
||||||
|
arf_set_d(u, x.b);
|
||||||
|
arb_set_interval_arf(res, t, u, prec);
|
||||||
|
arf_clear(t);
|
||||||
|
arf_clear(u);
|
||||||
|
}
|
64
double_interval/fast_div.c
Normal file
64
double_interval/fast_div.c
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2021 Fredrik Johansson
|
||||||
|
|
||||||
|
This file is part of Arb.
|
||||||
|
|
||||||
|
Arb is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||||
|
by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version. See <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "double_interval.h"
|
||||||
|
|
||||||
|
di_t di_fast_div(di_t x, di_t y)
|
||||||
|
{
|
||||||
|
di_t res;
|
||||||
|
|
||||||
|
if (y.a > 0)
|
||||||
|
{
|
||||||
|
if (x.a >= 0)
|
||||||
|
{
|
||||||
|
res.a = x.a / y.b;
|
||||||
|
res.b = x.b / y.a;
|
||||||
|
}
|
||||||
|
else if (x.b <= 0)
|
||||||
|
{
|
||||||
|
res.a = x.a / y.a;
|
||||||
|
res.b = x.b / y.b;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res.a = x.a / y.a;
|
||||||
|
res.b = x.b / y.a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (y.b < 0)
|
||||||
|
{
|
||||||
|
if (x.a >= 0)
|
||||||
|
{
|
||||||
|
res.a = x.b / y.b;
|
||||||
|
res.b = x.a / y.a;
|
||||||
|
}
|
||||||
|
else if (x.b <= 0)
|
||||||
|
{
|
||||||
|
res.a = x.b / y.a;
|
||||||
|
res.b = x.a / y.b;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res.a = x.b / y.b;
|
||||||
|
res.b = x.a / y.b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res.a = -D_INF;
|
||||||
|
res.b = D_INF;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.a = _di_below(res.a);
|
||||||
|
res.b = _di_above(res.b);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
30
double_interval/fast_log_nonnegative.c
Normal file
30
double_interval/fast_log_nonnegative.c
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2021 Fredrik Johansson
|
||||||
|
|
||||||
|
This file is part of Arb.
|
||||||
|
|
||||||
|
Arb is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||||
|
by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version. See <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "double_interval.h"
|
||||||
|
#include "mag.h"
|
||||||
|
|
||||||
|
double mag_d_log_lower_bound(double x);
|
||||||
|
double mag_d_log_upper_bound(double x);
|
||||||
|
|
||||||
|
di_t di_fast_log_nonnegative(di_t x)
|
||||||
|
{
|
||||||
|
di_t res;
|
||||||
|
|
||||||
|
if (x.a <= 0.0)
|
||||||
|
res.a = -D_INF;
|
||||||
|
else
|
||||||
|
res.a = mag_d_log_lower_bound(x.a);
|
||||||
|
|
||||||
|
res.b = mag_d_log_upper_bound(x.b);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
64
double_interval/fast_mul.c
Normal file
64
double_interval/fast_mul.c
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2021 Fredrik Johansson
|
||||||
|
|
||||||
|
This file is part of Arb.
|
||||||
|
|
||||||
|
Arb is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||||
|
by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version. See <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "double_interval.h"
|
||||||
|
|
||||||
|
di_t di_fast_mul(di_t x, di_t y)
|
||||||
|
{
|
||||||
|
di_t res;
|
||||||
|
|
||||||
|
if (x.a >= 0 && y.a >= 0)
|
||||||
|
{
|
||||||
|
res.a = x.a * y.a;
|
||||||
|
res.b = x.b * y.b;
|
||||||
|
}
|
||||||
|
else if (x.a >= 0 && y.b <= 0)
|
||||||
|
{
|
||||||
|
res.a = x.b * y.a;
|
||||||
|
res.b = x.a * y.b;
|
||||||
|
}
|
||||||
|
else if (x.b <= 0 && y.a >= 0)
|
||||||
|
{
|
||||||
|
res.a = x.a * y.b;
|
||||||
|
res.b = x.b * y.a;
|
||||||
|
}
|
||||||
|
else if (x.b <= 0 && y.b <= 0)
|
||||||
|
{
|
||||||
|
res.a = x.b * y.b;
|
||||||
|
res.b = x.a * y.a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double a, b, c, d;
|
||||||
|
|
||||||
|
a = x.a * y.a;
|
||||||
|
b = x.a * y.b;
|
||||||
|
c = x.b * y.a;
|
||||||
|
d = x.b * y.b;
|
||||||
|
|
||||||
|
if (a != a || b != b || c != c || d != d)
|
||||||
|
{
|
||||||
|
res.a = -D_INF;
|
||||||
|
res.b = D_INF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res.a = FLINT_MIN(FLINT_MIN(a, b), FLINT_MIN(c, d));
|
||||||
|
res.b = FLINT_MAX(FLINT_MAX(a, b), FLINT_MAX(c, d));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res.a = _di_below(res.a);
|
||||||
|
res.b = _di_above(res.b);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
41
double_interval/fast_sqr.c
Normal file
41
double_interval/fast_sqr.c
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2021 Fredrik Johansson
|
||||||
|
|
||||||
|
This file is part of Arb.
|
||||||
|
|
||||||
|
Arb is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||||
|
by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version. See <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "double_interval.h"
|
||||||
|
|
||||||
|
di_t di_fast_sqr(di_t x)
|
||||||
|
{
|
||||||
|
di_t res;
|
||||||
|
|
||||||
|
if (x.a >= 0)
|
||||||
|
{
|
||||||
|
res.a = x.a * x.a;
|
||||||
|
res.b = x.b * x.b;
|
||||||
|
}
|
||||||
|
else if (x.b <= 0)
|
||||||
|
{
|
||||||
|
res.a = x.b * x.b;
|
||||||
|
res.b = x.a * x.a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res.a = 0.0;
|
||||||
|
res.b = FLINT_MAX(x.a * x.a, x.b * x.b);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.a != 0.0)
|
||||||
|
res.a = _di_below(res.a);
|
||||||
|
|
||||||
|
res.b = _di_above(res.b);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
14
double_interval/inlines.c
Normal file
14
double_interval/inlines.c
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2021 Fredrik Johansson
|
||||||
|
|
||||||
|
This file is part of Arb.
|
||||||
|
|
||||||
|
Arb is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||||
|
by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version. See <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DOUBLE_INTERVAL_INLINES_C
|
||||||
|
#include "double_interval.h"
|
||||||
|
|
75
double_interval/test/t-fast_add.c
Normal file
75
double_interval/test/t-fast_add.c
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2021 Fredrik Johansson
|
||||||
|
|
||||||
|
This file is part of Arb.
|
||||||
|
|
||||||
|
Arb is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||||
|
by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version. See <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "double_interval.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
slong iter;
|
||||||
|
flint_rand_t state;
|
||||||
|
|
||||||
|
flint_printf("fast_add....");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
flint_randinit(state);
|
||||||
|
|
||||||
|
for (iter = 0; iter < 1000000 * arb_test_multiplier(); iter++)
|
||||||
|
{
|
||||||
|
di_t x, y, z;
|
||||||
|
arf_t a, b, t, za, zb;
|
||||||
|
|
||||||
|
arf_init(a);
|
||||||
|
arf_init(b);
|
||||||
|
arf_init(t);
|
||||||
|
arf_init(za);
|
||||||
|
arf_init(zb);
|
||||||
|
|
||||||
|
x = di_randtest(state);
|
||||||
|
y = di_randtest(state);
|
||||||
|
|
||||||
|
z = di_fast_add(x, y);
|
||||||
|
|
||||||
|
arf_set_d(a, x.a);
|
||||||
|
arf_set_d(t, y.a);
|
||||||
|
arf_add(a, a, t, ARF_PREC_EXACT, ARF_RND_DOWN);
|
||||||
|
arf_set_d(b, x.b);
|
||||||
|
arf_set_d(t, y.b);
|
||||||
|
arf_add(b, b, t, ARF_PREC_EXACT, ARF_RND_DOWN);
|
||||||
|
|
||||||
|
arf_set_d(za, z.a);
|
||||||
|
arf_set_d(zb, z.b);
|
||||||
|
|
||||||
|
if (arf_cmp(a, za) < 0 || arf_cmp(b, zb) > 0)
|
||||||
|
{
|
||||||
|
flint_printf("FAIL\n");
|
||||||
|
flint_printf("x = "); di_print(x); printf("\n");
|
||||||
|
flint_printf("y = "); di_print(y); printf("\n");
|
||||||
|
flint_printf("z = "); di_print(z); printf("\n");
|
||||||
|
flint_printf("a = "); arf_printd(a, 20); printf("\n");
|
||||||
|
flint_printf("b = "); arf_printd(b, 20); printf("\n");
|
||||||
|
flint_printf("za = "); arf_printd(za, 20); printf("\n");
|
||||||
|
flint_printf("zb = "); arf_printd(zb, 20); printf("\n");
|
||||||
|
flint_abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
arf_clear(a);
|
||||||
|
arf_clear(b);
|
||||||
|
arf_clear(t);
|
||||||
|
arf_clear(za);
|
||||||
|
arf_clear(zb);
|
||||||
|
}
|
||||||
|
|
||||||
|
flint_randclear(state);
|
||||||
|
flint_cleanup();
|
||||||
|
flint_printf("PASS\n");
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
114
double_interval/test/t-fast_div.c
Normal file
114
double_interval/test/t-fast_div.c
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2021 Fredrik Johansson
|
||||||
|
|
||||||
|
This file is part of Arb.
|
||||||
|
|
||||||
|
Arb is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||||
|
by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version. See <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "double_interval.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
arf_min2(arf_t res, const arf_t x, const arf_t y)
|
||||||
|
{
|
||||||
|
if (arf_is_nan(x))
|
||||||
|
arf_set(res, y);
|
||||||
|
else if (arf_is_nan(y))
|
||||||
|
arf_set(res, x);
|
||||||
|
else
|
||||||
|
arf_min(res, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
arf_max2(arf_t res, const arf_t x, const arf_t y)
|
||||||
|
{
|
||||||
|
if (arf_is_nan(x))
|
||||||
|
arf_set(res, y);
|
||||||
|
else if (arf_is_nan(y))
|
||||||
|
arf_set(res, x);
|
||||||
|
else
|
||||||
|
arf_max(res, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
slong iter;
|
||||||
|
flint_rand_t state;
|
||||||
|
|
||||||
|
flint_printf("fast_div....");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
flint_randinit(state);
|
||||||
|
|
||||||
|
for (iter = 0; iter < 1000000 * arb_test_multiplier(); iter++)
|
||||||
|
{
|
||||||
|
di_t x, y, z;
|
||||||
|
arf_t a, b, c, d, ra, rb, rc, rd, va, vb, za, zb;
|
||||||
|
|
||||||
|
arf_init(a); arf_init(b); arf_init(c); arf_init(d);
|
||||||
|
arf_init(ra); arf_init(rb); arf_init(rc); arf_init(rd);
|
||||||
|
arf_init(va); arf_init(vb);
|
||||||
|
arf_init(za);
|
||||||
|
arf_init(zb);
|
||||||
|
|
||||||
|
x = di_randtest(state);
|
||||||
|
y = di_randtest(state);
|
||||||
|
z = di_fast_div(x, y);
|
||||||
|
|
||||||
|
arf_set_d(a, x.a);
|
||||||
|
arf_set_d(b, x.b);
|
||||||
|
arf_set_d(c, y.a);
|
||||||
|
arf_set_d(d, y.b);
|
||||||
|
|
||||||
|
arf_div(ra, a, c, 106, ARF_RND_DOWN);
|
||||||
|
arf_div(rb, a, d, 106, ARF_RND_DOWN);
|
||||||
|
arf_div(rc, b, c, 106, ARF_RND_DOWN);
|
||||||
|
arf_div(rd, b, d, 106, ARF_RND_DOWN);
|
||||||
|
|
||||||
|
arf_min2(va, ra, rb);
|
||||||
|
arf_min2(va, va, rc);
|
||||||
|
arf_min2(va, va, rd);
|
||||||
|
arf_max2(vb, ra, rb);
|
||||||
|
arf_max2(vb, vb, rc);
|
||||||
|
arf_max2(vb, vb, rd);
|
||||||
|
|
||||||
|
arf_set_d(za, z.a);
|
||||||
|
arf_set_d(zb, z.b);
|
||||||
|
|
||||||
|
if (arf_cmp(va, za) < 0 || arf_cmp(vb, zb) > 0)
|
||||||
|
{
|
||||||
|
flint_printf("FAIL\n");
|
||||||
|
flint_printf("x = "); di_print(x); printf("\n");
|
||||||
|
flint_printf("y = "); di_print(y); printf("\n");
|
||||||
|
flint_printf("z = "); di_print(z); printf("\n");
|
||||||
|
flint_printf("a = "); arf_printd(a, 20); printf("\n");
|
||||||
|
flint_printf("b = "); arf_printd(b, 20); printf("\n");
|
||||||
|
flint_printf("c = "); arf_printd(c, 20); printf("\n");
|
||||||
|
flint_printf("d = "); arf_printd(d, 20); printf("\n");
|
||||||
|
flint_printf("ra = "); arf_printd(ra, 20); printf("\n");
|
||||||
|
flint_printf("rb = "); arf_printd(rb, 20); printf("\n");
|
||||||
|
flint_printf("rc = "); arf_printd(rc, 20); printf("\n");
|
||||||
|
flint_printf("rd = "); arf_printd(rd, 20); printf("\n");
|
||||||
|
flint_printf("va = "); arf_printd(va, 20); printf("\n");
|
||||||
|
flint_printf("vb = "); arf_printd(vb, 20); printf("\n");
|
||||||
|
flint_printf("za = "); arf_printd(za, 20); printf("\n");
|
||||||
|
flint_printf("zb = "); arf_printd(zb, 20); printf("\n");
|
||||||
|
flint_abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
arf_clear(a); arf_clear(b); arf_clear(c); arf_clear(d);
|
||||||
|
arf_clear(ra); arf_clear(rb); arf_clear(rc); arf_clear(rd);
|
||||||
|
arf_clear(va); arf_clear(vb);
|
||||||
|
arf_clear(za);
|
||||||
|
arf_clear(zb);
|
||||||
|
}
|
||||||
|
|
||||||
|
flint_randclear(state);
|
||||||
|
flint_cleanup();
|
||||||
|
flint_printf("PASS\n");
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
114
double_interval/test/t-fast_mul.c
Normal file
114
double_interval/test/t-fast_mul.c
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2021 Fredrik Johansson
|
||||||
|
|
||||||
|
This file is part of Arb.
|
||||||
|
|
||||||
|
Arb is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU Lesser General Public License (LGPL) as published
|
||||||
|
by the Free Software Foundation; either version 2.1 of the License, or
|
||||||
|
(at your option) any later version. See <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "double_interval.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
arf_min2(arf_t res, const arf_t x, const arf_t y)
|
||||||
|
{
|
||||||
|
if (arf_is_nan(x))
|
||||||
|
arf_set(res, y);
|
||||||
|
else if (arf_is_nan(y))
|
||||||
|
arf_set(res, x);
|
||||||
|
else
|
||||||
|
arf_min(res, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
arf_max2(arf_t res, const arf_t x, const arf_t y)
|
||||||
|
{
|
||||||
|
if (arf_is_nan(x))
|
||||||
|
arf_set(res, y);
|
||||||
|
else if (arf_is_nan(y))
|
||||||
|
arf_set(res, x);
|
||||||
|
else
|
||||||
|
arf_max(res, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
slong iter;
|
||||||
|
flint_rand_t state;
|
||||||
|
|
||||||
|
flint_printf("fast_mul....");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
flint_randinit(state);
|
||||||
|
|
||||||
|
for (iter = 0; iter < 1000000 * arb_test_multiplier(); iter++)
|
||||||
|
{
|
||||||
|
di_t x, y, z;
|
||||||
|
arf_t a, b, c, d, ra, rb, rc, rd, va, vb, za, zb;
|
||||||
|
|
||||||
|
arf_init(a); arf_init(b); arf_init(c); arf_init(d);
|
||||||
|
arf_init(ra); arf_init(rb); arf_init(rc); arf_init(rd);
|
||||||
|
arf_init(va); arf_init(vb);
|
||||||
|
arf_init(za);
|
||||||
|
arf_init(zb);
|
||||||
|
|
||||||
|
x = di_randtest(state);
|
||||||
|
y = di_randtest(state);
|
||||||
|
z = di_fast_mul(x, y);
|
||||||
|
|
||||||
|
arf_set_d(a, x.a);
|
||||||
|
arf_set_d(b, x.b);
|
||||||
|
arf_set_d(c, y.a);
|
||||||
|
arf_set_d(d, y.b);
|
||||||
|
|
||||||
|
arf_mul(ra, a, c, ARF_PREC_EXACT, ARF_RND_DOWN);
|
||||||
|
arf_mul(rb, a, d, ARF_PREC_EXACT, ARF_RND_DOWN);
|
||||||
|
arf_mul(rc, b, c, ARF_PREC_EXACT, ARF_RND_DOWN);
|
||||||
|
arf_mul(rd, b, d, ARF_PREC_EXACT, ARF_RND_DOWN);
|
||||||
|
|
||||||
|
arf_min2(va, ra, rb);
|
||||||
|
arf_min2(va, va, rc);
|
||||||
|
arf_min2(va, va, rd);
|
||||||
|
arf_max2(vb, ra, rb);
|
||||||
|
arf_max2(vb, vb, rc);
|
||||||
|
arf_max2(vb, vb, rd);
|
||||||
|
|
||||||
|
arf_set_d(za, z.a);
|
||||||
|
arf_set_d(zb, z.b);
|
||||||
|
|
||||||
|
if (arf_cmp(va, za) < 0 || arf_cmp(vb, zb) > 0)
|
||||||
|
{
|
||||||
|
flint_printf("FAIL\n");
|
||||||
|
flint_printf("x = "); di_print(x); printf("\n");
|
||||||
|
flint_printf("y = "); di_print(y); printf("\n");
|
||||||
|
flint_printf("z = "); di_print(z); printf("\n");
|
||||||
|
flint_printf("a = "); arf_printd(a, 20); printf("\n");
|
||||||
|
flint_printf("b = "); arf_printd(b, 20); printf("\n");
|
||||||
|
flint_printf("c = "); arf_printd(c, 20); printf("\n");
|
||||||
|
flint_printf("d = "); arf_printd(d, 20); printf("\n");
|
||||||
|
flint_printf("ra = "); arf_printd(ra, 20); printf("\n");
|
||||||
|
flint_printf("rb = "); arf_printd(rb, 20); printf("\n");
|
||||||
|
flint_printf("rc = "); arf_printd(rc, 20); printf("\n");
|
||||||
|
flint_printf("rd = "); arf_printd(rd, 20); printf("\n");
|
||||||
|
flint_printf("va = "); arf_printd(va, 20); printf("\n");
|
||||||
|
flint_printf("vb = "); arf_printd(vb, 20); printf("\n");
|
||||||
|
flint_printf("za = "); arf_printd(za, 20); printf("\n");
|
||||||
|
flint_printf("zb = "); arf_printd(zb, 20); printf("\n");
|
||||||
|
flint_abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
arf_clear(a); arf_clear(b); arf_clear(c); arf_clear(d);
|
||||||
|
arf_clear(ra); arf_clear(rb); arf_clear(rc); arf_clear(rd);
|
||||||
|
arf_clear(va); arf_clear(vb);
|
||||||
|
arf_clear(za);
|
||||||
|
arf_clear(zb);
|
||||||
|
}
|
||||||
|
|
||||||
|
flint_randclear(state);
|
||||||
|
flint_cleanup();
|
||||||
|
flint_printf("PASS\n");
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue