#ifndef LIBBF_H
#define LIBBF_H
#include <stddef.h>
#include <stdint.h>
#if defined(__SIZEOF_INT128__) && (INTPTR_MAX >= INT64_MAX)
#define LIMB_LOG2_BITS 6
#else
#define LIMB_LOG2_BITS 5
#endif
#define LIMB_BITS (1 << LIMB_LOG2_BITS)
#if LIMB_BITS == 64
typedef
__int128 int128_t;
typedef
unsigned __int128 uint128_t;
typedef
int64_t slimb_t;
typedef
uint64_t limb_t;
typedef
uint128_t dlimb_t;
#define BF_RAW_EXP_MIN INT64_MIN
#define BF_RAW_EXP_MAX INT64_MAX
#define LIMB_DIGITS 19
#define BF_DEC_BASE UINT64_C(10000000000000000000)
#else
typedef
int32_t slimb_t;
typedef
uint32_t limb_t;
typedef
uint64_t dlimb_t;
#define BF_RAW_EXP_MIN INT32_MIN
#define BF_RAW_EXP_MAX INT32_MAX
#define LIMB_DIGITS 9
#define BF_DEC_BASE 1000000000U
#endif
#define BF_EXP_BITS_MIN 3
#define BF_EXP_BITS_MAX (LIMB_BITS - 3)
#define BF_EXT_EXP_BITS_MAX (BF_EXP_BITS_MAX + 1)
#define BF_PREC_MIN 2
#define BF_PREC_MAX (((limb_t)1 << (LIMB_BITS - 2)) - 2)
#define BF_PREC_INF (BF_PREC_MAX + 1) /* infinite precision */
#if LIMB_BITS == 64
#define BF_CHKSUM_MOD (UINT64_C(975620677) * UINT64_C(9795002197))
#else
#define BF_CHKSUM_MOD 975620677U
#endif
#define BF_EXP_ZERO BF_RAW_EXP_MIN
#define BF_EXP_INF (BF_RAW_EXP_MAX - 1)
#define BF_EXP_NAN BF_RAW_EXP_MAX
typedef
struct
{
struct
bf_context_t *ctx;
int
sign;
slimb_t expn;
limb_t len;
limb_t *tab;
} bf_t;
typedef
struct
{
struct
bf_context_t *ctx;
int
sign;
slimb_t expn;
limb_t len;
limb_t *tab;
} bfdec_t;
typedef
enum
{
BF_RNDN,
BF_RNDZ,
BF_RNDD,
BF_RNDU,
BF_RNDNA,
BF_RNDA,
BF_RNDF,
} bf_rnd_t;
#define BF_FLAG_SUBNORMAL (1 << 3)
#define BF_FLAG_RADPNT_PREC (1 << 4)
#define BF_RND_MASK 0x7
#define BF_EXP_BITS_SHIFT 5
#define BF_EXP_BITS_MASK 0x3f
#define BF_FLAG_EXT_EXP (BF_EXP_BITS_MASK << BF_EXP_BITS_SHIFT)
typedef
uint32_t bf_flags_t;
typedef
void
*bf_realloc_func_t(
void
*opaque,
void
*ptr,
size_t
size);
typedef
struct
{
bf_t val;
limb_t prec;
} BFConstCache;
typedef
struct
bf_context_t {
void
*realloc_opaque;
bf_realloc_func_t *realloc_func;
BFConstCache log2_cache;
BFConstCache pi_cache;
struct
BFNTTState *ntt_state;
} bf_context_t;
static
inline
int
bf_get_exp_bits(bf_flags_t flags)
{
int
e;
e = (flags >> BF_EXP_BITS_SHIFT) & BF_EXP_BITS_MASK;
if
(e == BF_EXP_BITS_MASK)
return
BF_EXP_BITS_MAX + 1;
else
return
BF_EXP_BITS_MAX - e;
}
static
inline
bf_flags_t bf_set_exp_bits(
int
n)
{
return
((BF_EXP_BITS_MAX - n) & BF_EXP_BITS_MASK) << BF_EXP_BITS_SHIFT;
}
#define BF_ST_INVALID_OP (1 << 0)
#define BF_ST_DIVIDE_ZERO (1 << 1)
#define BF_ST_OVERFLOW (1 << 2)
#define BF_ST_UNDERFLOW (1 << 3)
#define BF_ST_INEXACT (1 << 4)
#define BF_ST_MEM_ERROR (1 << 5)
#define BF_RADIX_MAX 36 /* maximum radix for bf_atof() and bf_ftoa() */
static
inline
slimb_t bf_max(slimb_t a, slimb_t b)
{
if
(a > b)
return
a;
else
return
b;
}
static
inline
slimb_t bf_min(slimb_t a, slimb_t b)
{
if
(a < b)
return
a;
else
return
b;
}
void
bf_context_init(bf_context_t *s, bf_realloc_func_t *realloc_func,
void
*realloc_opaque);
void
bf_context_end(bf_context_t *s);
void
bf_clear_cache(bf_context_t *s);
static
inline
void
*bf_realloc(bf_context_t *s,
void
*ptr,
size_t
size)
{
return
s->realloc_func(s->realloc_opaque, ptr, size);
}
static
inline
void
*bf_malloc(bf_context_t *s,
size_t
size)
{
return
bf_realloc(s, NULL, size);
}
static
inline
void
bf_free(bf_context_t *s,
void
*ptr)
{
if
(ptr)
bf_realloc(s, ptr, 0);
}
void
bf_init(bf_context_t *s, bf_t *r);
static
inline
void
bf_delete(bf_t *r)
{
bf_context_t *s = r->ctx;
if
(s && r->tab) {
bf_realloc(s, r->tab, 0);
}
}
static
inline
void
bf_neg(bf_t *r)
{
r->sign ^= 1;
}
static
inline
int
bf_is_finite(
const
bf_t *a)
{
return
(a->expn < BF_EXP_INF);
}
static
inline
int
bf_is_nan(
const
bf_t *a)
{
return
(a->expn == BF_EXP_NAN);
}
static
inline
int
bf_is_zero(
const
bf_t *a)
{
return
(a->expn == BF_EXP_ZERO);
}
static
inline
void
bf_memcpy(bf_t *r,
const
bf_t *a)
{
*r = *a;
}
int
bf_set_ui(bf_t *r, uint64_t a);
int
bf_set_si(bf_t *r, int64_t a);
void
bf_set_nan(bf_t *r);
void
bf_set_zero(bf_t *r,
int
is_neg);
void
bf_set_inf(bf_t *r,
int
is_neg);
int
bf_set(bf_t *r,
const
bf_t *a);
void
bf_move(bf_t *r, bf_t *a);
int
bf_get_float64(
const
bf_t *a,
double
*pres, bf_rnd_t rnd_mode);
int
bf_set_float64(bf_t *a,
double
d);
int
bf_cmpu(
const
bf_t *a,
const
bf_t *b);
int
bf_cmp_full(
const
bf_t *a,
const
bf_t *b);
int
bf_cmp(
const
bf_t *a,
const
bf_t *b);
static
inline
int
bf_cmp_eq(
const
bf_t *a,
const
bf_t *b)
{
return
bf_cmp(a, b) == 0;
}
static
inline
int
bf_cmp_le(
const
bf_t *a,
const
bf_t *b)
{
return
bf_cmp(a, b) <= 0;
}
static
inline
int
bf_cmp_lt(
const
bf_t *a,
const
bf_t *b)
{
return
bf_cmp(a, b) < 0;
}
int
bf_add(bf_t *r,
const
bf_t *a,
const
bf_t *b, limb_t prec, bf_flags_t flags);
int
bf_sub(bf_t *r,
const
bf_t *a,
const
bf_t *b, limb_t prec, bf_flags_t flags);
int
bf_add_si(bf_t *r,
const
bf_t *a, int64_t b1, limb_t prec, bf_flags_t flags);
int
bf_mul(bf_t *r,
const
bf_t *a,
const
bf_t *b, limb_t prec, bf_flags_t flags);
int
bf_mul_ui(bf_t *r,
const
bf_t *a, uint64_t b1, limb_t prec, bf_flags_t flags);
int
bf_mul_si(bf_t *r,
const
bf_t *a, int64_t b1, limb_t prec,
bf_flags_t flags);
int
bf_mul_2exp(bf_t *r, slimb_t e, limb_t prec, bf_flags_t flags);
int
bf_div(bf_t *r,
const
bf_t *a,
const
bf_t *b, limb_t prec, bf_flags_t flags);
#define BF_DIVREM_EUCLIDIAN BF_RNDF
int
bf_divrem(bf_t *q, bf_t *r,
const
bf_t *a,
const
bf_t *b,
limb_t prec, bf_flags_t flags,
int
rnd_mode);
int
bf_rem(bf_t *r,
const
bf_t *a,
const
bf_t *b, limb_t prec,
bf_flags_t flags,
int
rnd_mode);
int
bf_remquo(slimb_t *pq, bf_t *r,
const
bf_t *a,
const
bf_t *b, limb_t prec,
bf_flags_t flags,
int
rnd_mode);
int
bf_rint(bf_t *r,
int
rnd_mode);
int
bf_round(bf_t *r, limb_t prec, bf_flags_t flags);
int
bf_sqrtrem(bf_t *r, bf_t *rem1,
const
bf_t *a);
int
bf_sqrt(bf_t *r,
const
bf_t *a, limb_t prec, bf_flags_t flags);
slimb_t bf_get_exp_min(
const
bf_t *a);
int
bf_logic_or(bf_t *r,
const
bf_t *a,
const
bf_t *b);
int
bf_logic_xor(bf_t *r,
const
bf_t *a,
const
bf_t *b);
int
bf_logic_and(bf_t *r,
const
bf_t *a,
const
bf_t *b);
#define BF_ATOF_NO_HEX (1 << 16)
#define BF_ATOF_BIN_OCT (1 << 17)
#define BF_ATOF_NO_NAN_INF (1 << 18)
#define BF_ATOF_EXPONENT (1 << 19)
int
bf_atof(bf_t *a,
const
char
*str,
const
char
**pnext,
int
radix,
limb_t prec, bf_flags_t flags);
int
bf_atof2(bf_t *r, slimb_t *pexponent,
const
char
*str,
const
char
**pnext,
int
radix,
limb_t prec, bf_flags_t flags);
int
bf_mul_pow_radix(bf_t *r,
const
bf_t *T, limb_t radix,
slimb_t expn, limb_t prec, bf_flags_t flags);
#define BF_FTOA_FORMAT_MASK (3 << 16)
#define BF_FTOA_FORMAT_FIXED (0 << 16)
#define BF_FTOA_FORMAT_FRAC (1 << 16)
#define BF_FTOA_FORMAT_FREE (2 << 16)
#define BF_FTOA_FORMAT_FREE_MIN (3 << 16)
#define BF_FTOA_FORCE_EXP (1 << 20)
#define BF_FTOA_ADD_PREFIX (1 << 21)
#define BF_FTOA_JS_QUIRKS (1 << 22)
char
*bf_ftoa(
size_t
*plen,
const
bf_t *a,
int
radix, limb_t prec,
bf_flags_t flags);
#define BF_GET_INT_MOD (1 << 0)
int
bf_get_int32(
int
*pres,
const
bf_t *a,
int
flags);
int
bf_get_int64(int64_t *pres,
const
bf_t *a,
int
flags);
int
bf_get_uint64(uint64_t *pres,
const
bf_t *a);
void
mp_print_str(
const
char
*str,
const
limb_t *tab, limb_t n);
void
bf_print_str(
const
char
*str,
const
bf_t *a);
int
bf_resize(bf_t *r, limb_t len);
int
bf_get_fft_size(
int
*pdpl,
int
*pnb_mods, limb_t len);
int
bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags);
int
bf_can_round(
const
bf_t *a, slimb_t prec, bf_rnd_t rnd_mode, slimb_t k);
slimb_t bf_mul_log2_radix(slimb_t a1, unsigned
int
radix,
int
is_inv,
int
is_ceil1);
int
mp_mul(bf_context_t *s, limb_t *result,
const
limb_t *op1, limb_t op1_size,
const
limb_t *op2, limb_t op2_size);
limb_t mp_add(limb_t *res,
const
limb_t *op1,
const
limb_t *op2,
limb_t n, limb_t carry);
limb_t mp_add_ui(limb_t *tab, limb_t b,
size_t
n);
int
mp_sqrtrem(bf_context_t *s, limb_t *tabs, limb_t *taba, limb_t n);
int
mp_recip(bf_context_t *s, limb_t *tabr,
const
limb_t *taba, limb_t n);
limb_t bf_isqrt(limb_t a);
int
bf_const_log2(bf_t *T, limb_t prec, bf_flags_t flags);
int
bf_const_pi(bf_t *T, limb_t prec, bf_flags_t flags);
int
bf_exp(bf_t *r,
const
bf_t *a, limb_t prec, bf_flags_t flags);
int
bf_log(bf_t *r,
const
bf_t *a, limb_t prec, bf_flags_t flags);
#define BF_POW_JS_QUIRKS (1 << 16) /* (+/-1)^(+/-Inf) = NaN, 1^NaN = NaN */
int
bf_pow(bf_t *r,
const
bf_t *x,
const
bf_t *y, limb_t prec, bf_flags_t flags);
int
bf_cos(bf_t *r,
const
bf_t *a, limb_t prec, bf_flags_t flags);
int
bf_sin(bf_t *r,
const
bf_t *a, limb_t prec, bf_flags_t flags);
int
bf_tan(bf_t *r,
const
bf_t *a, limb_t prec, bf_flags_t flags);
int
bf_atan(bf_t *r,
const
bf_t *a, limb_t prec, bf_flags_t flags);
int
bf_atan2(bf_t *r,
const
bf_t *y,
const
bf_t *x,
limb_t prec, bf_flags_t flags);
int
bf_asin(bf_t *r,
const
bf_t *a, limb_t prec, bf_flags_t flags);
int
bf_acos(bf_t *r,
const
bf_t *a, limb_t prec, bf_flags_t flags);
static
inline
void
bfdec_init(bf_context_t *s, bfdec_t *r)
{
bf_init(s, (bf_t *)r);
}
static
inline
void
bfdec_delete(bfdec_t *r)
{
bf_delete((bf_t *)r);
}
static
inline
void
bfdec_neg(bfdec_t *r)
{
r->sign ^= 1;
}
static
inline
int
bfdec_is_finite(
const
bfdec_t *a)
{
return
(a->expn < BF_EXP_INF);
}
static
inline
int
bfdec_is_nan(
const
bfdec_t *a)
{
return
(a->expn == BF_EXP_NAN);
}
static
inline
int
bfdec_is_zero(
const
bfdec_t *a)
{
return
(a->expn == BF_EXP_ZERO);
}
static
inline
void
bfdec_memcpy(bfdec_t *r,
const
bfdec_t *a)
{
bf_memcpy((bf_t *)r, (
const
bf_t *)a);
}
int
bfdec_set_ui(bfdec_t *r, uint64_t a);
int
bfdec_set_si(bfdec_t *r, int64_t a);
static
inline
void
bfdec_set_nan(bfdec_t *r)
{
bf_set_nan((bf_t *)r);
}
static
inline
void
bfdec_set_zero(bfdec_t *r,
int
is_neg)
{
bf_set_zero((bf_t *)r, is_neg);
}
static
inline
void
bfdec_set_inf(bfdec_t *r,
int
is_neg)
{
bf_set_inf((bf_t *)r, is_neg);
}
static
inline
int
bfdec_set(bfdec_t *r,
const
bfdec_t *a)
{
return
bf_set((bf_t *)r, (bf_t *)a);
}
static
inline
void
bfdec_move(bfdec_t *r, bfdec_t *a)
{
bf_move((bf_t *)r, (bf_t *)a);
}
static
inline
int
bfdec_cmpu(
const
bfdec_t *a,
const
bfdec_t *b)
{
return
bf_cmpu((
const
bf_t *)a, (
const
bf_t *)b);
}
static
inline
int
bfdec_cmp_full(
const
bfdec_t *a,
const
bfdec_t *b)
{
return
bf_cmp_full((
const
bf_t *)a, (
const
bf_t *)b);
}
static
inline
int
bfdec_cmp(
const
bfdec_t *a,
const
bfdec_t *b)
{
return
bf_cmp((
const
bf_t *)a, (
const
bf_t *)b);
}
static
inline
int
bfdec_cmp_eq(
const
bfdec_t *a,
const
bfdec_t *b)
{
return
bfdec_cmp(a, b) == 0;
}
static
inline
int
bfdec_cmp_le(
const
bfdec_t *a,
const
bfdec_t *b)
{
return
bfdec_cmp(a, b) <= 0;
}
static
inline
int
bfdec_cmp_lt(
const
bfdec_t *a,
const
bfdec_t *b)
{
return
bfdec_cmp(a, b) < 0;
}
int
bfdec_add(bfdec_t *r,
const
bfdec_t *a,
const
bfdec_t *b, limb_t prec,
bf_flags_t flags);
int
bfdec_sub(bfdec_t *r,
const
bfdec_t *a,
const
bfdec_t *b, limb_t prec,
bf_flags_t flags);
int
bfdec_add_si(bfdec_t *r,
const
bfdec_t *a, int64_t b1, limb_t prec,
bf_flags_t flags);
int
bfdec_mul(bfdec_t *r,
const
bfdec_t *a,
const
bfdec_t *b, limb_t prec,
bf_flags_t flags);
int
bfdec_mul_si(bfdec_t *r,
const
bfdec_t *a, int64_t b1, limb_t prec,
bf_flags_t flags);
int
bfdec_div(bfdec_t *r,
const
bfdec_t *a,
const
bfdec_t *b, limb_t prec,
bf_flags_t flags);
int
bfdec_divrem(bfdec_t *q, bfdec_t *r,
const
bfdec_t *a,
const
bfdec_t *b,
limb_t prec, bf_flags_t flags,
int
rnd_mode);
int
bfdec_rem(bfdec_t *r,
const
bfdec_t *a,
const
bfdec_t *b, limb_t prec,
bf_flags_t flags,
int
rnd_mode);
int
bfdec_rint(bfdec_t *r,
int
rnd_mode);
int
bfdec_sqrt(bfdec_t *r,
const
bfdec_t *a, limb_t prec, bf_flags_t flags);
int
bfdec_round(bfdec_t *r, limb_t prec, bf_flags_t flags);
int
bfdec_get_int32(
int
*pres,
const
bfdec_t *a);
int
bfdec_pow_ui(bfdec_t *r,
const
bfdec_t *a, limb_t b);
char
*bfdec_ftoa(
size_t
*plen,
const
bfdec_t *a, limb_t prec, bf_flags_t flags);
int
bfdec_atof(bfdec_t *r,
const
char
*str,
const
char
**pnext,
limb_t prec, bf_flags_t flags);
extern
const
limb_t mp_pow_dec[LIMB_DIGITS + 1];
void
bfdec_print_str(
const
char
*str,
const
bfdec_t *a);
static
inline
int
bfdec_resize(bfdec_t *r, limb_t len)
{
return
bf_resize((bf_t *)r, len);
}
int
bfdec_normalize_and_round(bfdec_t *r, limb_t prec1, bf_flags_t flags);
#endif /* LIBBF_H */