arb/examples/real_roots.c
2016-11-16 22:49:45 +01:00

418 lines
9.9 KiB
C

/* This file is public domain. Author: Fredrik Johansson. */
#include <string.h>
#include "arb_calc.h"
#include "acb_hypgeom.h"
#include "acb_dirichlet.h"
#include "flint/profiler.h"
slong eval_count = 0;
typedef struct
{
dirichlet_group_t * G;
dirichlet_char_t * chi;
}
z_param_struct;
int
z_function(arb_ptr out, const arb_t inp, void * params, slong order, slong prec)
{
z_param_struct * par = params;
if (par->G == NULL)
{
arb_struct x[2];
arb_init(x);
arb_init(x + 1);
arb_set(x, inp);
arb_one(x + 1);
_arb_poly_riemann_siegel_z_series(out, x, FLINT_MIN(2, order), order, prec);
arb_clear(x);
arb_clear(x + 1);
}
else
{
acb_ptr tmp;
slong k;
tmp = _acb_vec_init(order);
acb_set_arb(tmp, inp);
acb_dirichlet_hardy_z(tmp, tmp, *(par->G), *(par->chi), order, prec);
for (k = 0; k < order; k++)
arb_set(out + k, acb_realref(tmp + k));
_acb_vec_clear(tmp, order);
}
eval_count++;
return 0;
}
int
sin_x(arb_ptr out, const arb_t inp, void * params, slong order, slong prec)
{
int xlen = FLINT_MIN(2, order);
arb_set(out, inp);
if (xlen > 1)
arb_one(out + 1);
_arb_poly_sin_series(out, out, xlen, order, prec);
eval_count++;
return 0;
}
int
sin_x2(arb_ptr out, const arb_t inp, void * params, slong order, slong prec)
{
arb_ptr x;
int xlen = FLINT_MIN(2, order);
int ylen = FLINT_MIN(3, order);
x = _arb_vec_init(xlen);
arb_set(x, inp);
if (xlen > 1)
arb_one(x + 1);
_arb_poly_mullow(out, x, xlen, x, xlen, ylen, prec);
_arb_poly_sin_series(out, out, ylen, order, prec);
_arb_vec_clear(x, xlen);
eval_count++;
return 0;
}
int
sin_1x(arb_ptr out, const arb_t inp, void * params, slong order, slong prec)
{
arb_ptr x;
int xlen = FLINT_MIN(2, order);
x = _arb_vec_init(xlen);
arb_set(x, inp);
if (xlen > 1)
arb_one(x + 1);
_arb_poly_inv_series(out, x, xlen, order, prec);
_arb_poly_sin_series(out, out, order, order, prec);
_arb_vec_clear(x, xlen);
eval_count++;
return 0;
}
int
airy(arb_ptr out, const arb_t inp, void * params, slong order, slong prec)
{
acb_t t, u;
int which = ((int *) params)[0];
int xlen = FLINT_MIN(2, order);
acb_init(t);
acb_init(u);
acb_set_arb(t, inp);
if (xlen == 1)
{
if (which == 0)
acb_hypgeom_airy(t, NULL, NULL, NULL, t, prec);
else if (which == 1)
acb_hypgeom_airy(NULL, t, NULL, NULL, t, prec);
else if (which == 2)
acb_hypgeom_airy(NULL, NULL, t, NULL, t, prec);
else
acb_hypgeom_airy(NULL, NULL, NULL, t, t, prec);
arb_set(out, acb_realref(t));
}
else
{
if (which == 0 || which == 1)
acb_hypgeom_airy(t, u, NULL, NULL, t, prec);
else
acb_hypgeom_airy(NULL, NULL, t, u, t, prec);
if (which == 0 || which == 2)
{
arb_set(out + 0, acb_realref(t));
arb_set(out + 1, acb_realref(u));
/* f''(z) = z f(z) */
if (xlen == 3)
arb_mul(out + 2, out + 0, inp, prec);
}
else
{
arb_set(out + 0, acb_realref(u));
arb_mul(out + 1, acb_realref(t), inp, prec);
/* f'''(z) = f(z) + z f'(z) */
if (xlen == 3)
{
arb_mul(out + 2, out + 0, inp, prec);
arb_add(out + 2, out + 2, acb_realref(t), prec);
}
}
}
acb_clear(t);
acb_clear(u);
eval_count++;
return 0;
}
int main(int argc, char *argv[])
{
arf_interval_ptr blocks;
arb_calc_func_t function;
int * info;
void * params;
int param1;
z_param_struct param2;
dirichlet_group_t G;
dirichlet_char_t chi;
slong digits, low_prec, high_prec, i, num, found_roots, found_unknown;
slong maxdepth, maxeval, maxfound;
int refine;
double a, b;
arf_t C;
arf_interval_t t, interval;
arb_t v, w, z;
if (argc < 4)
{
flint_printf("real_roots function a b [-refine d] [-verbose] "
"[-maxdepth n] [-maxeval n] [-maxfound n] [-prec n]\n");
flint_printf("available functions:\n");
flint_printf(" 0 Z(x), Z-function (Riemann zeta or Dirichlet L-function)\n");
flint_printf(" 1 sin(x)\n");
flint_printf(" 2 sin(x^2)\n");
flint_printf(" 3 sin(1/x)\n");
flint_printf(" 4 Ai(x), Airy function\n");
flint_printf(" 5 Ai'(x), Airy function\n");
flint_printf(" 6 Bi(x), Airy function\n");
flint_printf(" 7 Bi'(x), Airy function\n");
flint_printf("With 0, specify optional Dirichlet character with [-character q n]\n");
return 1;
}
param1 = 0;
param2.G = NULL;
param2.chi = NULL;
params = &param1;
switch (atoi(argv[1]))
{
case 0:
function = z_function;
params = &param2;
break;
case 1:
function = sin_x;
break;
case 2:
function = sin_x2;
break;
case 3:
function = sin_1x;
break;
case 4:
function = airy;
param1 = 0;
break;
case 5:
function = airy;
param1 = 1;
break;
case 6:
function = airy;
param1 = 2;
break;
case 7:
function = airy;
param1 = 3;
break;
default:
flint_printf("require a function 0-7\n");
return 1;
}
a = atof(argv[2]);
b = atof(argv[3]);
if (a >= b)
{
flint_printf("require a < b!\n");
return 1;
}
refine = 0;
digits = 0;
maxdepth = 30;
maxeval = 100000;
maxfound = 100000;
low_prec = 30;
for (i = 4; i < argc; i++)
{
if (!strcmp(argv[i], "-refine"))
{
refine = 1;
digits = atol(argv[i+1]);
}
else if (!strcmp(argv[i], "-verbose"))
{
arb_calc_verbose = 1;
}
else if (!strcmp(argv[i], "-maxdepth"))
{
maxdepth = atol(argv[i+1]);
}
else if (!strcmp(argv[i], "-maxeval"))
{
maxeval = atol(argv[i+1]);
}
else if (!strcmp(argv[i], "-maxfound"))
{
maxfound = atol(argv[i+1]);
}
else if (!strcmp(argv[i], "-prec"))
{
low_prec = atol(argv[i+1]);
}
else if (!strcmp(argv[i], "-character"))
{
dirichlet_group_init(G, atol(argv[i+1]));
dirichlet_char_init(chi, G);
dirichlet_char_log(chi, G, atol(argv[i+2]));
param2.G = &G;
param2.chi = &chi;
}
}
high_prec = digits * 3.32192809488736 + 10;
found_roots = 0;
found_unknown = 0;
arf_init(C);
arf_interval_init(t);
arf_interval_init(interval);
arb_init(v);
arb_init(w);
arb_init(z);
arf_set_d(&interval->a, a);
arf_set_d(&interval->b, b);
flint_printf("interval: "); arf_interval_printd(interval, 15); flint_printf("\n");
flint_printf("maxdepth = %wd, maxeval = %wd, maxfound = %wd, low_prec = %wd\n",
maxdepth, maxeval, maxfound, low_prec);
TIMEIT_ONCE_START
num = arb_calc_isolate_roots(&blocks, &info, function,
params, interval, maxdepth, maxeval, maxfound, low_prec);
for (i = 0; i < num; i++)
{
if (info[i] != 1)
{
if (arb_calc_verbose)
{
flint_printf("unable to count roots in ");
arf_interval_printd(blocks + i, 15);
flint_printf("\n");
}
found_unknown++;
continue;
}
found_roots++;
if (!refine)
continue;
if (arb_calc_refine_root_bisect(t,
function, params, blocks + i, 5, low_prec)
!= ARB_CALC_SUCCESS)
{
flint_printf("warning: some bisection steps failed!\n");
}
if (arb_calc_verbose)
{
flint_printf("after bisection 1: ");
arf_interval_printd(t, 15);
flint_printf("\n");
}
if (arb_calc_refine_root_bisect(blocks + i,
function, params, t, 5, low_prec)
!= ARB_CALC_SUCCESS)
{
flint_printf("warning: some bisection steps failed!\n");
}
if (arb_calc_verbose)
{
flint_printf("after bisection 2: ");
arf_interval_printd(blocks + i, 15);
flint_printf("\n");
}
arf_interval_get_arb(v, t, high_prec);
arb_calc_newton_conv_factor(C, function, params, v, low_prec);
arf_interval_get_arb(w, blocks + i, high_prec);
if (arb_calc_refine_root_newton(z, function, params,
w, v, C, 10, high_prec) != ARB_CALC_SUCCESS)
{
flint_printf("warning: some newton steps failed!\n");
}
flint_printf("refined root (%wd/%wd):\n", i, num);
arb_printn(z, digits + 2, 0);
flint_printf("\n\n");
}
flint_printf("---------------------------------------------------------------\n");
flint_printf("Found roots: %wd\n", found_roots);
flint_printf("Subintervals possibly containing undetected roots: %wd\n", found_unknown);
flint_printf("Function evaluations: %wd\n", eval_count);
TIMEIT_ONCE_STOP
SHOW_MEMORY_USAGE
for (i = 0; i < num; i++)
arf_interval_clear(blocks + i);
flint_free(blocks);
flint_free(info);
if (param2.G != NULL)
{
dirichlet_group_clear(G);
dirichlet_char_clear(chi);
}
arf_interval_clear(t);
arf_interval_clear(interval);
arf_clear(C);
arb_clear(v);
arb_clear(w);
arb_clear(z);
flint_cleanup();
return 0;
}