/*
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 .
*/
#include
#include "arb.h"
#include "acb.h"
#include "arb_fpwrap.h"
#include "arb_hypgeom.h"
#include "acb_hypgeom.h"
#include "acb_dirichlet.h"
#include "acb_elliptic.h"
#include "acb_modular.h"
static int
_acb_vec_is_finite(acb_srcptr x, slong len)
{
slong i;
for (i = 0; i < len; i++)
if (!acb_is_finite(x + i))
return 0;
return 1;
}
int
arb_accurate_enough_d(const arb_t x, int flags)
{
if (flags & FPWRAP_CORRECT_ROUNDING)
{
return arb_can_round_arf(x, 53, ARF_RND_NEAR);
}
if (arb_rel_accuracy_bits(x) >= 53 + 1)
return 1;
/* Rounding will give +/- 0 (we don't worry which) */
if (mag_cmp_2exp_si(arb_radref(x), -1077) < 0 &&
arf_cmpabs_2exp_si(arb_midref(x), -1077) < 0)
{
return 1;
}
/* Rounding will give +/- inf */
if (arb_rel_accuracy_bits(x) > 2 &&
arf_cmpabs_2exp_si(arb_midref(x), 1024) > 0)
{
return 1;
}
return 0;
}
int
acb_accurate_enough_d(const acb_t x, int flags)
{
if (flags & FPWRAP_CORRECT_ROUNDING)
{
return arb_can_round_arf(acb_realref(x), 53, ARF_RND_NEAR) &&
arb_can_round_arf(acb_imagref(x), 53, ARF_RND_NEAR);
}
if (flags & FPWRAP_ACCURATE_PARTS)
{
return arb_accurate_enough_d(acb_realref(x), flags) &&
arb_accurate_enough_d(acb_imagref(x), flags);
}
if (acb_rel_accuracy_bits(x) >= 53 + 1)
return 1;
/* Rounding will give +/- 0 (we don't worry which) */
if (mag_cmp_2exp_si(arb_radref(acb_realref(x)), -1077) < 0 &&
arf_cmpabs_2exp_si(arb_midref(acb_realref(x)), -1077) < 0 &&
mag_cmp_2exp_si(arb_radref(acb_imagref(x)), -1077) < 0 &&
arf_cmpabs_2exp_si(arb_midref(acb_imagref(x)), -1077) < 0)
{
return 1;
}
/* Rounding will give +/- inf */
if (acb_rel_accuracy_bits(x) > 2 &&
(arf_cmpabs_2exp_si(arb_midref(acb_realref(x)), 1024) > 0 ||
arf_cmpabs_2exp_si(arb_midref(acb_imagref(x)), 1024) > 0))
{
return 1;
}
return 0;
}
#define WP_INITIAL 64
#define DOUBLE_CHECK_RESULT \
if (arb_accurate_enough_d(arb_res, flags)) \
{ \
*res = arf_get_d(arb_midref(arb_res), ARF_RND_NEAR); \
status = FPWRAP_SUCCESS; \
break; \
} \
if (wp >= double_wp_max(flags)) \
{ \
*res = D_NAN; \
status = FPWRAP_UNABLE; \
break; \
} \
#define DOUBLE_CHECK_RESULT2 \
if (arb_accurate_enough_d(arb_res1, flags) && arb_accurate_enough_d(arb_res2, flags)) \
{ \
*res1 = arf_get_d(arb_midref(arb_res1), ARF_RND_NEAR); \
*res2 = arf_get_d(arb_midref(arb_res2), ARF_RND_NEAR); \
status = FPWRAP_SUCCESS; \
break; \
} \
if (wp >= double_wp_max(flags)) \
{ \
*res1 = D_NAN; \
*res2 = D_NAN; \
status = FPWRAP_UNABLE; \
break; \
} \
#define CDOUBLE_CHECK_RESULT \
if (acb_accurate_enough_d(acb_res, flags)) \
{ \
res->real = arf_get_d(arb_midref(acb_realref(acb_res)), ARF_RND_NEAR); \
res->imag = arf_get_d(arb_midref(acb_imagref(acb_res)), ARF_RND_NEAR); \
status = FPWRAP_SUCCESS; \
break; \
} \
if (wp >= double_wp_max(flags)) \
{ \
res->real = D_NAN; \
res->imag = D_NAN; \
status = FPWRAP_UNABLE; \
break; \
}
static slong
double_wp_max(int flags)
{
int iters;
iters = flags / FPWRAP_WORK_LIMIT;
if (iters <= 0)
return 64 << 7;
if (iters >= 25)
return 64 << 24;
return 64 << iters;
}
typedef void (*arb_func_1)(arb_t, const arb_t, slong prec);
typedef void (*arb_func_2)(arb_t, const arb_t, const arb_t, slong prec);
typedef void (*arb_func_3)(arb_t, const arb_t, const arb_t, const arb_t, slong prec);
typedef void (*arb_func_4)(arb_t, const arb_t, const arb_t, const arb_t, const arb_t, slong prec);
typedef void (*acb_func_1)(acb_t, const acb_t, slong prec);
typedef void (*acb_func_2)(acb_t, const acb_t, const acb_t, slong prec);
typedef void (*acb_func_3)(acb_t, const acb_t, const acb_t, const acb_t, slong prec);
typedef void (*acb_func_4)(acb_t, const acb_t, const acb_t, const acb_t, const acb_t, slong prec);
typedef void (*arb_func_1_int)(arb_t, const arb_t, int, slong prec);
typedef void (*arb_func_2_int)(arb_t, const arb_t, const arb_t, int, slong prec);
typedef void (*arb_func_3_int)(arb_t, const arb_t, const arb_t, const arb_t, int, slong prec);
typedef void (*arb_func_4_int)(arb_t, const arb_t, const arb_t, const arb_t, const arb_t, int, slong prec);
typedef void (*acb_func_1_int)(acb_t, const acb_t, int, slong prec);
typedef void (*acb_func_2_int)(acb_t, const acb_t, const acb_t, int, slong prec);
typedef void (*acb_func_3_int)(acb_t, const acb_t, const acb_t, const acb_t, int, slong prec);
typedef void (*acb_func_4_int)(acb_t, const acb_t, const acb_t, const acb_t, const acb_t, int, slong prec);
int arb_fpwrap_double_1(double * res, arb_func_1 func, double x, int flags)
{
arb_t arb_res, arb_x;
slong wp;
int status;
arb_init(arb_res);
arb_init(arb_x);
arb_set_d(arb_x, x);
if (!arb_is_finite(arb_x))
{
*res = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
func(arb_res, arb_x, wp);
DOUBLE_CHECK_RESULT
}
}
arb_clear(arb_x);
arb_clear(arb_res);
return status;
}
int arb_fpwrap_double_2(double * res, arb_func_2 func, double x1, double x2, int flags)
{
arb_t arb_res, arb_x1, arb_x2;
slong wp;
int status;
arb_init(arb_res);
arb_init(arb_x1);
arb_init(arb_x2);
arb_set_d(arb_x1, x1);
arb_set_d(arb_x2, x2);
if (!arb_is_finite(arb_x1) || !arb_is_finite(arb_x2))
{
*res = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
func(arb_res, arb_x1, arb_x2, wp);
DOUBLE_CHECK_RESULT
}
}
arb_clear(arb_x1);
arb_clear(arb_x2);
arb_clear(arb_res);
return status;
}
int arb_fpwrap_double_3(double * res, arb_func_3 func, double x1, double x2, double x3, int flags)
{
arb_t arb_res, arb_x1, arb_x2, arb_x3;
slong wp;
int status;
arb_init(arb_res);
arb_init(arb_x1);
arb_init(arb_x2);
arb_init(arb_x3);
arb_set_d(arb_x1, x1);
arb_set_d(arb_x2, x2);
arb_set_d(arb_x3, x3);
if (!arb_is_finite(arb_x1) || !arb_is_finite(arb_x2) || !arb_is_finite(arb_x3))
{
*res = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
func(arb_res, arb_x1, arb_x2, arb_x3, wp);
DOUBLE_CHECK_RESULT
}
}
arb_clear(arb_x1);
arb_clear(arb_x2);
arb_clear(arb_x3);
arb_clear(arb_res);
return status;
}
int arb_fpwrap_double_4(double * res, arb_func_4 func, double x1, double x2, double x3, double x4, int flags)
{
arb_t arb_res, arb_x1, arb_x2, arb_x3, arb_x4;
slong wp;
int status;
arb_init(arb_res);
arb_init(arb_x1);
arb_init(arb_x2);
arb_init(arb_x3);
arb_init(arb_x4);
arb_set_d(arb_x1, x1);
arb_set_d(arb_x2, x2);
arb_set_d(arb_x3, x3);
arb_set_d(arb_x3, x4);
if (!arb_is_finite(arb_x1) || !arb_is_finite(arb_x2) || !arb_is_finite(arb_x3) || !arb_is_finite(arb_x4))
{
*res = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
func(arb_res, arb_x1, arb_x2, arb_x3, arb_x4, wp);
DOUBLE_CHECK_RESULT
}
}
arb_clear(arb_x1);
arb_clear(arb_x2);
arb_clear(arb_x3);
arb_clear(arb_x4);
arb_clear(arb_res);
return status;
}
int arb_fpwrap_cdouble_1(complex_double * res, acb_func_1 func, complex_double x, int flags)
{
acb_t acb_res, acb_x;
slong wp;
int status;
acb_init(acb_res);
acb_init(acb_x);
acb_set_d_d(acb_x, x.real, x.imag);
if (!acb_is_finite(acb_x))
{
res->real = D_NAN;
res->imag = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
func(acb_res, acb_x, wp);
CDOUBLE_CHECK_RESULT
}
}
acb_clear(acb_x);
acb_clear(acb_res);
return status;
}
int arb_fpwrap_cdouble_2(complex_double * res, acb_func_2 func, complex_double x1, complex_double x2, int flags)
{
acb_t acb_res, acb_x1, acb_x2;
slong wp;
int status;
acb_init(acb_res);
acb_init(acb_x1);
acb_init(acb_x2);
acb_set_d_d(acb_x1, x1.real, x1.imag);
acb_set_d_d(acb_x2, x2.real, x2.imag);
if (!acb_is_finite(acb_x1) || !acb_is_finite(acb_x2))
{
res->real = D_NAN;
res->imag = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
func(acb_res, acb_x1, acb_x2, wp);
CDOUBLE_CHECK_RESULT
}
}
acb_clear(acb_x1);
acb_clear(acb_x2);
acb_clear(acb_res);
return status;
}
int arb_fpwrap_cdouble_3(complex_double * res, acb_func_3 func, complex_double x1, complex_double x2, complex_double x3, int flags)
{
acb_t acb_res, acb_x1, acb_x2, acb_x3;
slong wp;
int status;
acb_init(acb_res);
acb_init(acb_x1);
acb_init(acb_x2);
acb_init(acb_x3);
acb_set_d_d(acb_x1, x1.real, x1.imag);
acb_set_d_d(acb_x2, x2.real, x2.imag);
acb_set_d_d(acb_x3, x3.real, x3.imag);
if (!acb_is_finite(acb_x1) || !acb_is_finite(acb_x2) || !acb_is_finite(acb_x3))
{
res->real = D_NAN;
res->imag = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
func(acb_res, acb_x1, acb_x2, acb_x3, wp);
CDOUBLE_CHECK_RESULT
}
}
acb_clear(acb_x1);
acb_clear(acb_x2);
acb_clear(acb_x3);
acb_clear(acb_res);
return status;
}
int arb_fpwrap_cdouble_4(complex_double * res, acb_func_4 func, complex_double x1, complex_double x2, complex_double x3, complex_double x4, int flags)
{
acb_t acb_res, acb_x1, acb_x2, acb_x3, acb_x4;
slong wp;
int status;
acb_init(acb_res);
acb_init(acb_x1);
acb_init(acb_x2);
acb_init(acb_x3);
acb_init(acb_x4);
acb_set_d_d(acb_x1, x1.real, x1.imag);
acb_set_d_d(acb_x2, x2.real, x2.imag);
acb_set_d_d(acb_x3, x3.real, x3.imag);
acb_set_d_d(acb_x4, x4.real, x4.imag);
if (!acb_is_finite(acb_x1) || !acb_is_finite(acb_x2) || !acb_is_finite(acb_x3) || !acb_is_finite(acb_x4))
{
res->real = D_NAN;
res->imag = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
func(acb_res, acb_x1, acb_x2, acb_x3, acb_x4, wp);
CDOUBLE_CHECK_RESULT
}
}
acb_clear(acb_x1);
acb_clear(acb_x2);
acb_clear(acb_x3);
acb_clear(acb_x4);
acb_clear(acb_res);
return status;
}
int arb_fpwrap_double_1_int(double * res, arb_func_1_int func, double x, int intx, int flags)
{
arb_t arb_res, arb_x;
slong wp;
int status;
arb_init(arb_res);
arb_init(arb_x);
arb_set_d(arb_x, x);
if (!arb_is_finite(arb_x))
{
*res = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
func(arb_res, arb_x, intx, wp);
DOUBLE_CHECK_RESULT
}
}
arb_clear(arb_x);
arb_clear(arb_res);
return status;
}
int arb_fpwrap_double_2_int(double * res, arb_func_2_int func, double x1, double x2, int intx, int flags)
{
arb_t arb_res, arb_x1, arb_x2;
slong wp;
int status;
arb_init(arb_res);
arb_init(arb_x1);
arb_init(arb_x2);
arb_set_d(arb_x1, x1);
arb_set_d(arb_x2, x2);
if (!arb_is_finite(arb_x1) || !arb_is_finite(arb_x2))
{
*res = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
func(arb_res, arb_x1, arb_x2, intx, wp);
DOUBLE_CHECK_RESULT
}
}
arb_clear(arb_x1);
arb_clear(arb_x2);
arb_clear(arb_res);
return status;
}
int arb_fpwrap_double_3_int(double * res, arb_func_3_int func, double x1, double x2, double x3, int intx, int flags)
{
arb_t arb_res, arb_x1, arb_x2, arb_x3;
slong wp;
int status;
arb_init(arb_res);
arb_init(arb_x1);
arb_init(arb_x2);
arb_init(arb_x3);
arb_set_d(arb_x1, x1);
arb_set_d(arb_x2, x2);
arb_set_d(arb_x3, x3);
if (!arb_is_finite(arb_x1) || !arb_is_finite(arb_x2) || !arb_is_finite(arb_x3))
{
*res = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
func(arb_res, arb_x1, arb_x2, arb_x3, intx, wp);
DOUBLE_CHECK_RESULT
}
}
arb_clear(arb_x1);
arb_clear(arb_x2);
arb_clear(arb_x3);
arb_clear(arb_res);
return status;
}
int arb_fpwrap_double_4_int(double * res, arb_func_4_int func, double x1, double x2, double x3, double x4, int intx, int flags)
{
arb_t arb_res, arb_x1, arb_x2, arb_x3, arb_x4;
slong wp;
int status;
arb_init(arb_res);
arb_init(arb_x1);
arb_init(arb_x2);
arb_init(arb_x3);
arb_init(arb_x4);
arb_set_d(arb_x1, x1);
arb_set_d(arb_x2, x2);
arb_set_d(arb_x3, x3);
arb_set_d(arb_x4, x4);
if (!arb_is_finite(arb_x1) || !arb_is_finite(arb_x2) || !arb_is_finite(arb_x3) || !arb_is_finite(arb_x4))
{
*res = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
func(arb_res, arb_x1, arb_x2, arb_x3, arb_x4, intx, wp);
DOUBLE_CHECK_RESULT
}
}
arb_clear(arb_x1);
arb_clear(arb_x2);
arb_clear(arb_x3);
arb_clear(arb_x4);
arb_clear(arb_res);
return status;
}
int arb_fpwrap_cdouble_1_int(complex_double * res, acb_func_1_int func, complex_double x, int intx, int flags)
{
acb_t acb_res, acb_x;
slong wp;
int status;
acb_init(acb_res);
acb_init(acb_x);
acb_set_d_d(acb_x, x.real, x.imag);
if (!acb_is_finite(acb_x))
{
res->real = D_NAN;
res->imag = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
func(acb_res, acb_x, intx, wp);
CDOUBLE_CHECK_RESULT
}
}
acb_clear(acb_x);
acb_clear(acb_res);
return status;
}
int arb_fpwrap_cdouble_2_int(complex_double * res, acb_func_2_int func, complex_double x1, complex_double x2, int intx, int flags)
{
acb_t acb_res, acb_x1, acb_x2;
slong wp;
int status;
acb_init(acb_res);
acb_init(acb_x1);
acb_init(acb_x2);
acb_set_d_d(acb_x1, x1.real, x1.imag);
acb_set_d_d(acb_x2, x2.real, x2.imag);
if (!acb_is_finite(acb_x1) || !acb_is_finite(acb_x2))
{
res->real = D_NAN;
res->imag = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
func(acb_res, acb_x1, acb_x2, intx, wp);
CDOUBLE_CHECK_RESULT
}
}
acb_clear(acb_x1);
acb_clear(acb_x2);
acb_clear(acb_res);
return status;
}
int arb_fpwrap_cdouble_3_int(complex_double * res, acb_func_3_int func, complex_double x1, complex_double x2, complex_double x3, int intx, int flags)
{
acb_t acb_res, acb_x1, acb_x2, acb_x3;
slong wp;
int status;
acb_init(acb_res);
acb_init(acb_x1);
acb_init(acb_x2);
acb_init(acb_x3);
acb_set_d_d(acb_x1, x1.real, x1.imag);
acb_set_d_d(acb_x2, x2.real, x2.imag);
acb_set_d_d(acb_x3, x3.real, x3.imag);
if (!acb_is_finite(acb_x1) || !acb_is_finite(acb_x2) || !acb_is_finite(acb_x3))
{
res->real = D_NAN;
res->imag = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
func(acb_res, acb_x1, acb_x2, acb_x3, intx, wp);
CDOUBLE_CHECK_RESULT
}
}
acb_clear(acb_x1);
acb_clear(acb_x2);
acb_clear(acb_x3);
acb_clear(acb_res);
return status;
}
int arb_fpwrap_cdouble_4_int(complex_double * res, acb_func_4_int func, complex_double x1, complex_double x2, complex_double x3, complex_double x4, int intx, int flags)
{
acb_t acb_res, acb_x1, acb_x2, acb_x3, acb_x4;
slong wp;
int status;
acb_init(acb_res);
acb_init(acb_x1);
acb_init(acb_x2);
acb_init(acb_x3);
acb_init(acb_x4);
acb_set_d_d(acb_x1, x1.real, x1.imag);
acb_set_d_d(acb_x2, x2.real, x2.imag);
acb_set_d_d(acb_x3, x3.real, x3.imag);
acb_set_d_d(acb_x4, x4.real, x4.imag);
if (!acb_is_finite(acb_x1) || !acb_is_finite(acb_x2) || !acb_is_finite(acb_x3) || !acb_is_finite(acb_x4))
{
res->real = D_NAN;
res->imag = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
func(acb_res, acb_x1, acb_x2, acb_x3, acb_x4, intx, wp);
CDOUBLE_CHECK_RESULT
}
}
acb_clear(acb_x1);
acb_clear(acb_x2);
acb_clear(acb_x3);
acb_clear(acb_x4);
acb_clear(acb_res);
return status;
}
#define DEF_DOUBLE_FUN_1(name, arb_fun) \
int arb_fpwrap_double_ ## name(double * res, double x, int flags) \
{ \
return arb_fpwrap_double_1(res, arb_fun, x, flags); \
} \
#define DEF_DOUBLE_FUN_2(name, arb_fun) \
int arb_fpwrap_double_ ## name(double * res, double x1, double x2, int flags) \
{ \
return arb_fpwrap_double_2(res, arb_fun, x1, x2, flags); \
} \
#define DEF_DOUBLE_FUN_3(name, arb_fun) \
int arb_fpwrap_double_ ## name(double * res, double x1, double x2, double x3, int flags) \
{ \
return arb_fpwrap_double_3(res, arb_fun, x1, x2, x3, flags); \
} \
#define DEF_DOUBLE_FUN_4(name, arb_fun) \
int arb_fpwrap_double_ ## name(double * res, double x1, double x2, double x3, double x4, int flags) \
{ \
return arb_fpwrap_double_4(res, arb_fun, x1, x2, x3, x4, flags); \
} \
#define DEF_CDOUBLE_FUN_1(name, acb_fun) \
int arb_fpwrap_cdouble_ ## name(complex_double * res, complex_double x, int flags) \
{ \
return arb_fpwrap_cdouble_1(res, acb_fun, x, flags); \
} \
#define DEF_CDOUBLE_FUN_2(name, acb_fun) \
int arb_fpwrap_cdouble_ ## name(complex_double * res, complex_double x1, complex_double x2, int flags) \
{ \
return arb_fpwrap_cdouble_2(res, acb_fun, x1, x2, flags); \
} \
#define DEF_CDOUBLE_FUN_3(name, acb_fun) \
int arb_fpwrap_cdouble_ ## name(complex_double * res, complex_double x1, complex_double x2, complex_double x3, int flags) \
{ \
return arb_fpwrap_cdouble_3(res, acb_fun, x1, x2, x3, flags); \
} \
#define DEF_CDOUBLE_FUN_4(name, acb_fun) \
int arb_fpwrap_cdouble_ ## name(complex_double * res, complex_double x1, complex_double x2, complex_double x3, complex_double x4, int flags) \
{ \
return arb_fpwrap_cdouble_4(res, acb_fun, x1, x2, x3, x4, flags); \
} \
#define DEF_DOUBLE_FUN_1_INT(name, arb_fun) \
int arb_fpwrap_double_ ## name(double * res, double x, int intx, int flags) \
{ \
return arb_fpwrap_double_1_int(res, arb_fun, x, intx, flags); \
} \
#define DEF_DOUBLE_FUN_2_INT(name, arb_fun) \
int arb_fpwrap_double_ ## name(double * res, double x1, double x2, int intx, int flags) \
{ \
return arb_fpwrap_double_2_int(res, arb_fun, x1, x2, intx, flags); \
} \
#define DEF_DOUBLE_FUN_3_INT(name, arb_fun) \
int arb_fpwrap_double_ ## name(double * res, double x1, double x2, double x3, int intx, int flags) \
{ \
return arb_fpwrap_double_3_int(res, arb_fun, x1, x2, x3, intx, flags); \
} \
#define DEF_DOUBLE_FUN_4_INT(name, arb_fun) \
int arb_fpwrap_double_ ## name(double * res, double x1, double x2, double x3, double x4, int intx, int flags) \
{ \
return arb_fpwrap_double_4_int(res, arb_fun, x1, x2, x3, x4, intx, flags); \
} \
#define DEF_CDOUBLE_FUN_1_INT(name, acb_fun) \
int arb_fpwrap_cdouble_ ## name(complex_double * res, complex_double x, int intx, int flags) \
{ \
return arb_fpwrap_cdouble_1_int(res, acb_fun, x, intx, flags); \
} \
#define DEF_CDOUBLE_FUN_2_INT(name, acb_fun) \
int arb_fpwrap_cdouble_ ## name(complex_double * res, complex_double x1, complex_double x2, int intx, int flags) \
{ \
return arb_fpwrap_cdouble_2_int(res, acb_fun, x1, x2, intx, flags); \
} \
#define DEF_CDOUBLE_FUN_3_INT(name, acb_fun) \
int arb_fpwrap_cdouble_ ## name(complex_double * res, complex_double x1, complex_double x2, complex_double x3, int intx, int flags) \
{ \
return arb_fpwrap_cdouble_3_int(res, acb_fun, x1, x2, x3, intx, flags); \
} \
#define DEF_CDOUBLE_FUN_4_INT(name, acb_fun) \
int arb_fpwrap_cdouble_ ## name(complex_double * res, complex_double x1, complex_double x2, complex_double x3, complex_double x4, int intx, int flags) \
{ \
return arb_fpwrap_cdouble_4_int(res, acb_fun, x1, x2, x3, x4, intx, flags); \
} \
DEF_DOUBLE_FUN_1(exp, arb_exp)
DEF_CDOUBLE_FUN_1(exp, acb_exp)
DEF_DOUBLE_FUN_1(expm1, arb_expm1)
DEF_CDOUBLE_FUN_1(expm1, acb_expm1)
DEF_DOUBLE_FUN_1(log, arb_log)
DEF_CDOUBLE_FUN_1(log, acb_log)
DEF_DOUBLE_FUN_1(log1p, arb_log1p)
DEF_CDOUBLE_FUN_1(log1p, acb_log1p)
DEF_DOUBLE_FUN_2(pow, arb_pow)
DEF_CDOUBLE_FUN_2(pow, acb_pow)
DEF_DOUBLE_FUN_1(sqrt, arb_sqrt)
DEF_CDOUBLE_FUN_1(sqrt, acb_sqrt)
DEF_DOUBLE_FUN_1(rsqrt, arb_rsqrt)
DEF_CDOUBLE_FUN_1(rsqrt, acb_rsqrt)
static void _arb_cbrt(arb_t res, const arb_t x, slong prec) { arb_root_ui(res, x, 3, prec); }
static void _acb_cbrt(acb_t res, const acb_t x, slong prec) { acb_root_ui(res, x, 3, prec); }
DEF_DOUBLE_FUN_1(cbrt, _arb_cbrt)
DEF_CDOUBLE_FUN_1(cbrt, _acb_cbrt)
DEF_DOUBLE_FUN_1(sin, arb_sin)
DEF_CDOUBLE_FUN_1(sin, acb_sin)
DEF_DOUBLE_FUN_1(cos, arb_cos)
DEF_CDOUBLE_FUN_1(cos, acb_cos)
DEF_DOUBLE_FUN_1(tan, arb_tan)
DEF_CDOUBLE_FUN_1(tan, acb_tan)
DEF_DOUBLE_FUN_1(cot, arb_cot)
DEF_CDOUBLE_FUN_1(cot, acb_cot)
DEF_DOUBLE_FUN_1(sec, arb_sec)
DEF_CDOUBLE_FUN_1(sec, acb_sec)
DEF_DOUBLE_FUN_1(csc, arb_csc)
DEF_CDOUBLE_FUN_1(csc, acb_csc)
DEF_DOUBLE_FUN_1(sinc, arb_sinc)
DEF_CDOUBLE_FUN_1(sinc, acb_sinc)
DEF_DOUBLE_FUN_1(sin_pi, arb_sin_pi)
DEF_CDOUBLE_FUN_1(sin_pi, acb_sin_pi)
DEF_DOUBLE_FUN_1(cos_pi, arb_cos_pi)
DEF_CDOUBLE_FUN_1(cos_pi, acb_cos_pi)
DEF_DOUBLE_FUN_1(tan_pi, arb_tan_pi)
DEF_CDOUBLE_FUN_1(tan_pi, acb_tan_pi)
DEF_DOUBLE_FUN_1(cot_pi, arb_cot_pi)
DEF_CDOUBLE_FUN_1(cot_pi, acb_cot_pi)
DEF_DOUBLE_FUN_1(sinc_pi, arb_sinc_pi)
DEF_CDOUBLE_FUN_1(sinc_pi, acb_sinc_pi)
DEF_DOUBLE_FUN_1(asin, arb_asin)
DEF_CDOUBLE_FUN_1(asin, acb_asin)
DEF_DOUBLE_FUN_1(acos, arb_acos)
DEF_CDOUBLE_FUN_1(acos, acb_acos)
DEF_DOUBLE_FUN_1(atan, arb_atan)
DEF_CDOUBLE_FUN_1(atan, acb_atan)
DEF_DOUBLE_FUN_2(atan2, arb_atan2)
DEF_DOUBLE_FUN_1(asinh, arb_asinh)
DEF_CDOUBLE_FUN_1(asinh, acb_asinh)
DEF_DOUBLE_FUN_1(acosh, arb_acosh)
DEF_CDOUBLE_FUN_1(acosh, acb_acosh)
DEF_DOUBLE_FUN_1(atanh, arb_atanh)
DEF_CDOUBLE_FUN_1(atanh, acb_atanh)
DEF_DOUBLE_FUN_2(rising, arb_rising)
DEF_CDOUBLE_FUN_2(rising, acb_rising)
DEF_DOUBLE_FUN_1(gamma, arb_gamma)
DEF_CDOUBLE_FUN_1(gamma, acb_gamma)
DEF_DOUBLE_FUN_1(rgamma, arb_rgamma)
DEF_CDOUBLE_FUN_1(rgamma, acb_rgamma)
DEF_DOUBLE_FUN_1(lgamma, arb_lgamma)
DEF_CDOUBLE_FUN_1(lgamma, acb_lgamma)
DEF_DOUBLE_FUN_1(digamma, arb_digamma)
DEF_CDOUBLE_FUN_1(digamma, acb_digamma)
DEF_DOUBLE_FUN_1(zeta, arb_zeta)
DEF_CDOUBLE_FUN_1(zeta, acb_zeta)
DEF_DOUBLE_FUN_2(hurwitz_zeta, arb_hurwitz_zeta)
DEF_CDOUBLE_FUN_2(hurwitz_zeta, acb_hurwitz_zeta)
static void
_arb_polygamma(arb_t res, const arb_t s, const arb_t z, slong prec)
{
acb_t t, u, v;
acb_init(t);
acb_init(u);
acb_init(v);
acb_set_arb(t, s);
acb_set_arb(u, z);
acb_polygamma(v, t, u, prec);
if (acb_is_real(v))
arb_set(res, acb_realref(v));
else
arb_indeterminate(res);
acb_clear(t);
acb_clear(u);
acb_clear(v);
}
static void
_arb_barnes_g(arb_t res, const arb_t x, slong prec)
{
acb_t t, u;
acb_init(t);
acb_init(u);
acb_set_arb(t, x);
acb_barnes_g(u, t, prec);
arb_set(res, acb_realref(u));
acb_clear(t);
acb_clear(u);
}
static void
_arb_log_barnes_g(arb_t res, const arb_t x, slong prec)
{
if (!arb_is_positive(x))
{
arb_indeterminate(res);
}
else
{
acb_t t, u;
acb_init(t);
acb_init(u);
acb_set_arb(t, x);
acb_log_barnes_g(u, t, prec);
arb_set(res, acb_realref(u));
acb_clear(t);
acb_clear(u);
}
}
DEF_DOUBLE_FUN_1(barnes_g, _arb_barnes_g)
DEF_CDOUBLE_FUN_1(barnes_g, acb_barnes_g)
DEF_DOUBLE_FUN_1(log_barnes_g, _arb_log_barnes_g)
DEF_CDOUBLE_FUN_1(log_barnes_g, acb_log_barnes_g)
DEF_DOUBLE_FUN_2(polygamma, _arb_polygamma)
DEF_CDOUBLE_FUN_2(polygamma, acb_polygamma)
DEF_DOUBLE_FUN_2(polylog, arb_polylog)
DEF_CDOUBLE_FUN_2(polylog, acb_polylog)
DEF_DOUBLE_FUN_1(dilog, arb_hypgeom_dilog)
DEF_CDOUBLE_FUN_1(dilog, acb_hypgeom_dilog)
DEF_DOUBLE_FUN_1(erf, arb_hypgeom_erf)
DEF_CDOUBLE_FUN_1(erf, acb_hypgeom_erf)
DEF_DOUBLE_FUN_1(erfc, arb_hypgeom_erfc)
DEF_CDOUBLE_FUN_1(erfc, acb_hypgeom_erfc)
DEF_DOUBLE_FUN_1(erfi, arb_hypgeom_erfi)
DEF_CDOUBLE_FUN_1(erfi, acb_hypgeom_erfi)
DEF_DOUBLE_FUN_1(erfinv, arb_hypgeom_erfinv)
DEF_DOUBLE_FUN_1(erfcinv, arb_hypgeom_erfcinv)
static void _arb_hypgeom_fresnel_s(arb_t res, const arb_t x, int normalized, slong prec) { arb_hypgeom_fresnel(res, NULL, x, normalized, prec); }
static void _arb_hypgeom_fresnel_c(arb_t res, const arb_t x, int normalized, slong prec) { arb_hypgeom_fresnel(NULL, res, x, normalized, prec); }
static void _acb_hypgeom_fresnel_s(acb_t res, const acb_t x, int normalized, slong prec) { acb_hypgeom_fresnel(res, NULL, x, normalized, prec); }
static void _acb_hypgeom_fresnel_c(acb_t res, const acb_t x, int normalized, slong prec) { acb_hypgeom_fresnel(NULL, res, x, normalized, prec); }
DEF_DOUBLE_FUN_1_INT(fresnel_s, _arb_hypgeom_fresnel_s)
DEF_CDOUBLE_FUN_1_INT(fresnel_s, _acb_hypgeom_fresnel_s)
DEF_DOUBLE_FUN_1_INT(fresnel_c, _arb_hypgeom_fresnel_c)
DEF_CDOUBLE_FUN_1_INT(fresnel_c, _acb_hypgeom_fresnel_c)
DEF_DOUBLE_FUN_2_INT(gamma_upper, arb_hypgeom_gamma_upper)
DEF_CDOUBLE_FUN_2_INT(gamma_upper, acb_hypgeom_gamma_upper)
DEF_DOUBLE_FUN_2_INT(gamma_lower, arb_hypgeom_gamma_lower)
DEF_CDOUBLE_FUN_2_INT(gamma_lower, acb_hypgeom_gamma_lower)
DEF_DOUBLE_FUN_3_INT(beta_lower, arb_hypgeom_beta_lower)
DEF_CDOUBLE_FUN_3_INT(beta_lower, acb_hypgeom_beta_lower)
DEF_DOUBLE_FUN_2(exp_integral_e, arb_hypgeom_expint)
DEF_CDOUBLE_FUN_2(exp_integral_e, acb_hypgeom_expint)
DEF_DOUBLE_FUN_1(exp_integral_ei, arb_hypgeom_ei)
DEF_CDOUBLE_FUN_1(exp_integral_ei, acb_hypgeom_ei)
DEF_DOUBLE_FUN_1(sin_integral, arb_hypgeom_si)
DEF_CDOUBLE_FUN_1(sin_integral, acb_hypgeom_si)
DEF_DOUBLE_FUN_1(cos_integral, arb_hypgeom_ci)
DEF_CDOUBLE_FUN_1(cos_integral, acb_hypgeom_ci)
DEF_DOUBLE_FUN_1(sinh_integral, arb_hypgeom_shi)
DEF_CDOUBLE_FUN_1(sinh_integral, acb_hypgeom_shi)
DEF_DOUBLE_FUN_1(cosh_integral, arb_hypgeom_chi)
DEF_CDOUBLE_FUN_1(cosh_integral, acb_hypgeom_chi)
DEF_DOUBLE_FUN_1_INT(log_integral, arb_hypgeom_li)
DEF_CDOUBLE_FUN_1_INT(log_integral, acb_hypgeom_li)
DEF_DOUBLE_FUN_2(bessel_j, arb_hypgeom_bessel_j)
DEF_CDOUBLE_FUN_2(bessel_j, acb_hypgeom_bessel_j)
DEF_DOUBLE_FUN_2(bessel_y, arb_hypgeom_bessel_y)
DEF_CDOUBLE_FUN_2(bessel_y, acb_hypgeom_bessel_y)
DEF_DOUBLE_FUN_2(bessel_i, arb_hypgeom_bessel_i)
DEF_CDOUBLE_FUN_2(bessel_i, acb_hypgeom_bessel_i)
DEF_DOUBLE_FUN_2(bessel_k, arb_hypgeom_bessel_k)
DEF_CDOUBLE_FUN_2(bessel_k, acb_hypgeom_bessel_k)
DEF_DOUBLE_FUN_2(bessel_k_scaled, arb_hypgeom_bessel_k_scaled)
DEF_CDOUBLE_FUN_2(bessel_k_scaled, acb_hypgeom_bessel_k_scaled)
static void _arb_hypgeom_airy_ai(arb_t res, const arb_t x, slong prec) { arb_hypgeom_airy(res, NULL, NULL, NULL, x, prec); }
static void _arb_hypgeom_airy_ai_prime(arb_t res, const arb_t x, slong prec) { arb_hypgeom_airy(NULL, res, NULL, NULL, x, prec); }
static void _arb_hypgeom_airy_bi(arb_t res, const arb_t x, slong prec) { arb_hypgeom_airy(NULL, NULL, res, NULL, x, prec); }
static void _arb_hypgeom_airy_bi_prime(arb_t res, const arb_t x, slong prec) { arb_hypgeom_airy(NULL, NULL, NULL, res, x, prec); }
static void _acb_hypgeom_airy_ai(acb_t res, const acb_t x, slong prec) { acb_hypgeom_airy(res, NULL, NULL, NULL, x, prec); }
static void _acb_hypgeom_airy_ai_prime(acb_t res, const acb_t x, slong prec) { acb_hypgeom_airy(NULL, res, NULL, NULL, x, prec); }
static void _acb_hypgeom_airy_bi(acb_t res, const acb_t x, slong prec) { acb_hypgeom_airy(NULL, NULL, res, NULL, x, prec); }
static void _acb_hypgeom_airy_bi_prime(acb_t res, const acb_t x, slong prec) { acb_hypgeom_airy(NULL, NULL, NULL, res, x, prec); }
DEF_DOUBLE_FUN_1(airy_ai, _arb_hypgeom_airy_ai)
DEF_CDOUBLE_FUN_1(airy_ai, _acb_hypgeom_airy_ai)
DEF_DOUBLE_FUN_1(airy_ai_prime, _arb_hypgeom_airy_ai_prime)
DEF_CDOUBLE_FUN_1(airy_ai_prime, _acb_hypgeom_airy_ai_prime)
DEF_DOUBLE_FUN_1(airy_bi, _arb_hypgeom_airy_bi)
DEF_CDOUBLE_FUN_1(airy_bi, _acb_hypgeom_airy_bi)
DEF_DOUBLE_FUN_1(airy_bi_prime, _arb_hypgeom_airy_bi_prime)
DEF_CDOUBLE_FUN_1(airy_bi_prime, _acb_hypgeom_airy_bi_prime)
static void _arb_hypgeom_coulomb_f(arb_t res, const arb_t l, const arb_t eta, const arb_t z, slong prec) { arb_hypgeom_coulomb(res, NULL, l, eta, z, prec); }
static void _arb_hypgeom_coulomb_g(arb_t res, const arb_t l, const arb_t eta, const arb_t z, slong prec) { arb_hypgeom_coulomb(NULL, res, l, eta, z, prec); }
static void _acb_hypgeom_coulomb_f(acb_t res, const acb_t l, const acb_t eta, const acb_t z, slong prec) { acb_hypgeom_coulomb(res, NULL, NULL, NULL, l, eta, z, prec); }
static void _acb_hypgeom_coulomb_g(acb_t res, const acb_t l, const acb_t eta, const acb_t z, slong prec) { acb_hypgeom_coulomb(NULL, res, NULL, NULL, l, eta, z, prec); }
static void _acb_hypgeom_coulomb_hpos(acb_t res, const acb_t l, const acb_t eta, const acb_t z, slong prec) { acb_hypgeom_coulomb(NULL, NULL, res, NULL, l, eta, z, prec); }
static void _acb_hypgeom_coulomb_hneg(acb_t res, const acb_t l, const acb_t eta, const acb_t z, slong prec) { acb_hypgeom_coulomb(NULL, NULL, NULL, res, l, eta, z, prec); }
DEF_DOUBLE_FUN_3(coulomb_f, _arb_hypgeom_coulomb_f)
DEF_CDOUBLE_FUN_3(coulomb_f, _acb_hypgeom_coulomb_f)
DEF_DOUBLE_FUN_3(coulomb_g, _arb_hypgeom_coulomb_g)
DEF_CDOUBLE_FUN_3(coulomb_g, _acb_hypgeom_coulomb_g)
DEF_CDOUBLE_FUN_3(coulomb_hpos, _acb_hypgeom_coulomb_hpos)
DEF_CDOUBLE_FUN_3(coulomb_hneg, _acb_hypgeom_coulomb_hneg)
DEF_DOUBLE_FUN_2(chebyshev_t, arb_hypgeom_chebyshev_t)
DEF_CDOUBLE_FUN_2(chebyshev_t, acb_hypgeom_chebyshev_t)
DEF_DOUBLE_FUN_2(chebyshev_u, arb_hypgeom_chebyshev_u)
DEF_CDOUBLE_FUN_2(chebyshev_u, acb_hypgeom_chebyshev_u)
DEF_DOUBLE_FUN_4(jacobi_p, arb_hypgeom_jacobi_p)
DEF_CDOUBLE_FUN_4(jacobi_p, acb_hypgeom_jacobi_p)
DEF_DOUBLE_FUN_3(gegenbauer_c, arb_hypgeom_gegenbauer_c)
DEF_CDOUBLE_FUN_3(gegenbauer_c, acb_hypgeom_gegenbauer_c)
DEF_DOUBLE_FUN_3(laguerre_l, arb_hypgeom_laguerre_l)
DEF_CDOUBLE_FUN_3(laguerre_l, acb_hypgeom_laguerre_l)
DEF_DOUBLE_FUN_2(hermite_h, arb_hypgeom_hermite_h)
DEF_CDOUBLE_FUN_2(hermite_h, acb_hypgeom_hermite_h)
DEF_DOUBLE_FUN_3_INT(legendre_p, arb_hypgeom_legendre_p)
DEF_CDOUBLE_FUN_3_INT(legendre_p, acb_hypgeom_legendre_p)
DEF_DOUBLE_FUN_3_INT(legendre_q, arb_hypgeom_legendre_q)
DEF_CDOUBLE_FUN_3_INT(legendre_q, acb_hypgeom_legendre_q)
int arb_fpwrap_cdouble_spherical_y(complex_double * res, slong n, slong m, complex_double x1, complex_double x2, int flags)
{
acb_t acb_res, acb_x1, acb_x2;
slong wp;
int status;
acb_init(acb_res);
acb_init(acb_x1);
acb_init(acb_x2);
acb_set_d_d(acb_x1, x1.real, x1.imag);
acb_set_d_d(acb_x2, x2.real, x2.imag);
if (!acb_is_finite(acb_x1) || !acb_is_finite(acb_x2))
{
res->real = D_NAN;
res->imag = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
acb_hypgeom_spherical_y(acb_res, n, m, acb_x1, acb_x2, wp);
CDOUBLE_CHECK_RESULT
}
}
acb_clear(acb_x1);
acb_clear(acb_x2);
acb_clear(acb_res);
return status;
}
DEF_DOUBLE_FUN_2_INT(hypgeom_0f1, arb_hypgeom_0f1)
DEF_CDOUBLE_FUN_2_INT(hypgeom_0f1, acb_hypgeom_0f1)
DEF_DOUBLE_FUN_3_INT(hypgeom_1f1, arb_hypgeom_1f1)
DEF_CDOUBLE_FUN_3_INT(hypgeom_1f1, acb_hypgeom_1f1)
DEF_DOUBLE_FUN_3(hypgeom_u, arb_hypgeom_u)
DEF_CDOUBLE_FUN_3(hypgeom_u, acb_hypgeom_u)
DEF_DOUBLE_FUN_4_INT(hypgeom_2f1, arb_hypgeom_2f1)
DEF_CDOUBLE_FUN_4_INT(hypgeom_2f1, acb_hypgeom_2f1)
int arb_fpwrap_double_hypgeom_pfq(double * res, const double * a, slong p, const double * b, slong q, double z, int regularized, int flags)
{
arb_t arb_res;
arb_ptr t;
slong wp;
slong i;
int status;
arb_init(arb_res);
t = _arb_vec_init(p + q + 1);
for (i = 0; i < p; i++)
arb_set_d(t + i, a[i]);
for (i = 0; i < q; i++)
arb_set_d(t + p + i, b[i]);
arb_set_d(t + p + q, z);
if (!_arb_vec_is_finite(t, p + q + 1))
{
*res = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
arb_hypgeom_pfq(arb_res, t, p, t + p, q, t + p + q, regularized, wp);
DOUBLE_CHECK_RESULT
}
}
_arb_vec_clear(t, p + q + 1);
arb_clear(arb_res);
return status;
}
int arb_fpwrap_cdouble_hypgeom_pfq(complex_double * res, const complex_double * a, slong p, const complex_double * b, slong q, complex_double z, int regularized, int flags)
{
acb_t acb_res;
acb_ptr t;
slong wp;
slong i;
int status;
acb_init(acb_res);
t = _acb_vec_init(p + q + 1);
for (i = 0; i < p; i++)
acb_set_d_d(t + i, a[i].real, a[i].imag);
for (i = 0; i < q; i++)
acb_set_d_d(t + p + i, b[i].real, b[i].imag);
acb_set_d_d(t + p + q, z.real, z.imag);
if (!_acb_vec_is_finite(t, p + q + 1))
{
res->real = D_NAN;
res->imag = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
acb_hypgeom_pfq(acb_res, t, p, t + p, q, t + p + q, regularized, wp);
CDOUBLE_CHECK_RESULT
}
}
_acb_vec_clear(t, p + q + 1);
acb_clear(acb_res);
return status;
}
DEF_DOUBLE_FUN_2(agm, arb_agm)
DEF_CDOUBLE_FUN_2(agm, acb_agm)
DEF_CDOUBLE_FUN_1(elliptic_k, acb_elliptic_k)
DEF_CDOUBLE_FUN_1(elliptic_e, acb_elliptic_e)
DEF_CDOUBLE_FUN_2(elliptic_pi, acb_elliptic_pi)
DEF_CDOUBLE_FUN_2_INT(elliptic_f, acb_elliptic_f)
DEF_CDOUBLE_FUN_2_INT(elliptic_e_inc, acb_elliptic_e_inc)
DEF_CDOUBLE_FUN_3_INT(elliptic_pi_inc, acb_elliptic_pi_inc)
DEF_CDOUBLE_FUN_3_INT(elliptic_rf, acb_elliptic_rf)
DEF_CDOUBLE_FUN_3_INT(elliptic_rg, acb_elliptic_rg)
DEF_CDOUBLE_FUN_4_INT(elliptic_rj, acb_elliptic_rj)
DEF_CDOUBLE_FUN_2(elliptic_p, acb_elliptic_p)
DEF_CDOUBLE_FUN_2(elliptic_p_prime, acb_elliptic_p_prime)
DEF_CDOUBLE_FUN_2(elliptic_inv_p, acb_elliptic_inv_p)
DEF_CDOUBLE_FUN_2(elliptic_zeta, acb_elliptic_zeta)
DEF_CDOUBLE_FUN_2(elliptic_sigma, acb_elliptic_sigma)
static void
_acb_theta1(acb_t res, const acb_t z, const acb_t tau, slong prec)
{
acb_t a, b, c; acb_init(a); acb_init(b); acb_init(c);
acb_modular_theta(res, a, b, c, z, tau, prec);
acb_clear(a); acb_clear(b); acb_clear(c);
}
static void
_acb_theta2(acb_t res, const acb_t z, const acb_t tau, slong prec)
{
acb_t a, b, c; acb_init(a); acb_init(b); acb_init(c);
acb_modular_theta(a, res, b, c, z, tau, prec);
acb_clear(a); acb_clear(b); acb_clear(c);
}
static void
_acb_theta3(acb_t res, const acb_t z, const acb_t tau, slong prec)
{
acb_t a, b, c; acb_init(a); acb_init(b); acb_init(c);
acb_modular_theta(a, b, res, c, z, tau, prec);
acb_clear(a); acb_clear(b); acb_clear(c);
}
static void
_acb_theta4(acb_t res, const acb_t z, const acb_t tau, slong prec)
{
acb_t a, b, c; acb_init(a); acb_init(b); acb_init(c);
acb_modular_theta(a, b, c, res, z, tau, prec);
acb_clear(a); acb_clear(b); acb_clear(c);
}
DEF_CDOUBLE_FUN_2(jacobi_theta_1, _acb_theta1)
DEF_CDOUBLE_FUN_2(jacobi_theta_2, _acb_theta2)
DEF_CDOUBLE_FUN_2(jacobi_theta_3, _acb_theta3)
DEF_CDOUBLE_FUN_2(jacobi_theta_4, _acb_theta4)
DEF_CDOUBLE_FUN_1(dedekind_eta, acb_modular_eta)
DEF_CDOUBLE_FUN_1(modular_j, acb_modular_j)
DEF_CDOUBLE_FUN_1(modular_lambda, acb_modular_lambda)
DEF_CDOUBLE_FUN_1(modular_delta, acb_modular_delta)
DEF_CDOUBLE_FUN_1(dirichlet_eta, acb_dirichlet_eta)
DEF_CDOUBLE_FUN_1(riemann_xi, acb_dirichlet_xi)
static void
_acb_hardy_theta(acb_t res, const acb_t t, slong prec)
{
acb_dirichlet_hardy_theta(res, t, NULL, NULL, 1, prec);
}
static void
_acb_hardy_z(acb_t res, const acb_t t, slong prec)
{
acb_dirichlet_hardy_z(res, t, NULL, NULL, 1, prec);
}
DEF_CDOUBLE_FUN_1(hardy_theta, _acb_hardy_theta)
DEF_CDOUBLE_FUN_1(hardy_z, _acb_hardy_z)
int arb_fpwrap_cdouble_zeta_zero(complex_double * res, ulong n, int flags)
{
fmpz_t t;
acb_t acb_res;
slong wp;
int status;
if (n == 0)
{
res->real = D_NAN;
res->imag = D_NAN;
return FPWRAP_UNABLE;
}
acb_init(acb_res);
fmpz_init(t);
fmpz_set_ui(t, n);
for (wp = WP_INITIAL; ; wp *= 2)
{
acb_dirichlet_zeta_zero(acb_res, t, wp);
CDOUBLE_CHECK_RESULT
}
acb_clear(acb_res);
return status;
}
int arb_fpwrap_double_legendre_root(double * res1, double * res2, ulong n, ulong k, int flags)
{
arb_t arb_res1, arb_res2;
slong wp;
int status;
if (k >= n)
{
*res1 = D_NAN;
*res2 = D_NAN;
return FPWRAP_UNABLE;
}
arb_init(arb_res1);
arb_init(arb_res2);
for (wp = WP_INITIAL; ; wp *= 2)
{
arb_hypgeom_legendre_p_ui_root(arb_res1, arb_res2, n, k, wp);
DOUBLE_CHECK_RESULT2
}
arb_clear(arb_res1);
arb_clear(arb_res2);
return status;
}
int _arb_fpwrap_double_airy_zero(double * res, ulong n, int which, int flags)
{
fmpz_t t;
arb_t arb_res;
slong wp;
int status;
if (n == 0)
{
*res = D_NAN;
return FPWRAP_UNABLE;
}
arb_init(arb_res);
fmpz_init(t);
fmpz_set_ui(t, n);
for (wp = WP_INITIAL; ; wp *= 2)
{
if (which == 0)
arb_hypgeom_airy_zero(arb_res, NULL, NULL, NULL, t, wp);
else if (which == 1)
arb_hypgeom_airy_zero(NULL, arb_res, NULL, NULL, t, wp);
else if (which == 2)
arb_hypgeom_airy_zero(NULL, NULL, arb_res, NULL, t, wp);
else
arb_hypgeom_airy_zero(NULL, NULL, NULL, arb_res, t, wp);
DOUBLE_CHECK_RESULT
}
arb_clear(arb_res);
fmpz_clear(t);
return status;
}
int arb_fpwrap_double_airy_ai_zero(double * res, ulong n, int flags) { return _arb_fpwrap_double_airy_zero(res, n, 0, flags); }
int arb_fpwrap_double_airy_ai_prime_zero(double * res, ulong n, int flags) { return _arb_fpwrap_double_airy_zero(res, n, 1, flags); }
int arb_fpwrap_double_airy_bi_zero(double * res, ulong n, int flags) { return _arb_fpwrap_double_airy_zero(res, n, 2, flags); }
int arb_fpwrap_double_airy_bi_prime_zero(double * res, ulong n, int flags) { return _arb_fpwrap_double_airy_zero(res, n, 3, flags); }
int arb_fpwrap_double_lambertw(double * res, double x, slong branch, int flags)
{
arb_t arb_res, arb_x;
slong wp;
int status;
arb_init(arb_res);
arb_init(arb_x);
arb_set_d(arb_x, x);
if (!arb_is_finite(arb_x) || !(branch == 0 || branch == -1))
{
*res = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
arb_lambertw(arb_res, arb_x, (branch == -1), wp);
DOUBLE_CHECK_RESULT
}
}
arb_clear(arb_x);
arb_clear(arb_res);
return status;
}
int arb_fpwrap_cdouble_lambertw(complex_double * res, complex_double x, slong branch, int flags)
{
fmpz_t t;
acb_t acb_res, acb_x;
slong wp;
int status;
acb_init(acb_res);
acb_init(acb_x);
fmpz_init(t);
acb_set_d_d(acb_x, x.real, x.imag);
fmpz_set_si(t, branch);
if (!acb_is_finite(acb_x))
{
res->real = D_NAN;
res->imag = D_NAN;
status = FPWRAP_UNABLE;
}
else
{
for (wp = WP_INITIAL; ; wp *= 2)
{
acb_lambertw(acb_res, acb_x, t, 0, wp);
CDOUBLE_CHECK_RESULT
}
}
acb_clear(acb_x);
acb_clear(acb_res);
fmpz_clear(t);
return status;
}
/* todo: functions with multiple outputs */
/* todo: elliptic invariants, roots */
/* todo: eisenstein series */
/* todo: dirichlet functions requiring characters */