# gr_series.h – formal power series over generic rings

We provide two implementations of formal power series:

- `gr_series_mod` - truncated power series \(R[[x]] / x^n\), with exact reresentation of elements.

- `gr_series` - infinite power series \(R[[x]]\), with elements represented as finite truncations with an error term \(O(x^n)\) where n is tracked per-element. Polynomials of small degree can be represented exactly without error term.

It should be noted that these are different algebraic structures. For example, \(\mathbb{Q}[[x]]\) is an integral domain, but \(\mathbb{Q}[[x]] / x^n\) is not. Some operations are admissible for `gr_series` but not for `gr_series_mod`, and vice versa. Note that for `gr_equal()`, \(0 = 0\) is true in both \(R[[x]]\) and \(R[[x]] / x^n\), but \(0 + O(x^n) = 0 + O(x^n)\) (or even \(0 + O(x^n) = 0\)) is unknown in \(R[[x]]\) since we do not know whether the big-O term hides some nonzero term. For a computation where either representation may be used, it is recommended to choose `gr_series_mod` as this will have less overhead.

## Context constructors

void gr_series_mod_ctx_init(gr_ctx_t ctx, gr_ctx_t base_ring, slong prec)

  Initializes ctx to a ring of truncated power series \(R[[x]] / \langle x^n \rangle\) over the given base_ring. Elements have type `gr_poly_t`. It is assumed that all inputs are already truncated to length n, and this invariant is enforced for all outputs.

  The truncation order n of a `gr_series_mod` context is fixed. If \(m \le n\), then elements belonging to a context object for \(R[[x]] / x^m\) can be given as input to a context for \(R[[x]] / x^n\), but not vice versa.

void gr_series_ctx_init(gr_ctx_t ctx, gr_ctx_t base_ring, slong prec)

  Initializes ctx to a ring of power series \(R[[x]]\) over the given base_ring. Elements have type `gr_series_t`.

  Elements are generally inexact, having an error term \(O(x^n)\) where n may be different for each element. The context parameter prec defines the default precision: tails \(c_n x^n + c_{n+1} x^{n+1} + \ldots\) with \(n \ge prec\) will be replaced by the error term \(O(x^n)\).

  The default precision is mutable. Elements can be shared freely between two context objects with the same base ring, even if those context objects have different precision.

## Truncated power series

### Types and macros

GR_SERIES_MOD_ELEM_CTX(ctx)

  Given a `gr_series_mod` context object, accesses the context object of the base ring.

GR_SERIES_MOD_N(ctx)

  Given a `gr_series_mod` context object, accesses the truncation order n.

### Generic methods

Elements of a `gr_series_mod` ring can be manipulated using the standard `gr` interface. The following is a list of implemented functions such that `gr_series_mod_foo` overloads `gr_foo` in the method table for `gr_series_mod`; the user can optionally call `gr_series_mod_foo` directly.

void gr_series_mod_ctx_clear(gr_ctx_t ctx)
int gr_series_mod_ctx_write(gr_stream_t out, gr_ctx_t ctx)
truth_t gr_series_mod_ctx_is_ring(gr_ctx_t ctx)
truth_t gr_series_mod_ctx_is_commutative_ring(gr_ctx_t ctx)
truth_t gr_series_mod_ctx_is_integral_domain(gr_ctx_t ctx)
truth_t gr_series_mod_ctx_is_rational_vector_space(gr_ctx_t ctx)
truth_t gr_series_mod_ctx_is_real_vector_space(gr_ctx_t ctx)
truth_t gr_series_mod_ctx_is_complex_vector_space(gr_ctx_t ctx)
truth_t gr_series_mod_ctx_is_field(gr_ctx_t ctx)
int gr_series_mod_ctx_set_gen_name(gr_ctx_t ctx, const char *s)
int gr_series_mod_ctx_set_gen_names(gr_ctx_t ctx, const char **s)
int gr_series_mod_gens_recursive(gr_vec_t vec, gr_ctx_t ctx)
void gr_series_mod_init(gr_poly_t res, gr_ctx_t ctx)
void gr_series_mod_clear(gr_poly_t res, gr_ctx_t ctx)
void gr_series_mod_swap(gr_poly_t x, gr_poly_t y, gr_ctx_t ctx)
int gr_series_mod_randtest(gr_poly_t res, flint_rand_t state, gr_ctx_t ctx)
int gr_series_mod_write(gr_stream_t out, const gr_poly_t x, gr_ctx_t ctx)
int gr_series_mod_zero(gr_poly_t res, gr_ctx_t ctx)
int gr_series_mod_one(gr_poly_t res, gr_ctx_t ctx)
int gr_series_mod_gen(gr_poly_t res, gr_ctx_t ctx)
int gr_series_mod_set(gr_poly_t res, const gr_poly_t x, gr_ctx_t ctx)
int gr_series_mod_set_other(gr_poly_t res, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx)
void gr_series_mod_set_shallow(gr_poly_t res, const gr_poly_t x, gr_ctx_t ctx)
int gr_series_mod_set_si(gr_poly_t res, slong c, gr_ctx_t ctx)
int gr_series_mod_set_ui(gr_poly_t res, ulong c, gr_ctx_t ctx)
int gr_series_mod_set_fmpz(gr_poly_t res, const fmpz_t c, gr_ctx_t ctx)
int gr_series_mod_set_fmpq(gr_poly_t res, const fmpq_t c, gr_ctx_t ctx)
truth_t gr_series_mod_is_zero(const gr_poly_t x, gr_ctx_t ctx)
truth_t gr_series_mod_is_one(const gr_poly_t x, gr_ctx_t ctx)
truth_t gr_series_mod_equal(const gr_poly_t x, const gr_poly_t y, gr_ctx_t ctx)
int gr_series_mod_neg(gr_poly_t res, const gr_poly_t x, gr_ctx_t ctx)
int gr_series_mod_add(gr_poly_t res, const gr_poly_t x, const gr_poly_t y, gr_ctx_t ctx)
int gr_series_mod_sub(gr_poly_t res, const gr_poly_t x, const gr_poly_t y, gr_ctx_t ctx)
int gr_series_mod_mul(gr_poly_t res, const gr_poly_t x, const gr_poly_t y, gr_ctx_t ctx)
int gr_series_mod_inv(gr_poly_t res, const gr_poly_t x, gr_ctx_t ctx)
int gr_series_mod_div(gr_poly_t res, const gr_poly_t x, const gr_poly_t y, gr_ctx_t ctx)
int gr_series_mod_exp(gr_poly_t res, const gr_poly_t x, gr_ctx_t ctx)
int gr_series_mod_log(gr_poly_t res, const gr_poly_t x, gr_ctx_t ctx)
int gr_series_mod_sqrt(gr_poly_t res, const gr_poly_t x, gr_ctx_t ctx)
int gr_series_mod_rsqrt(gr_poly_t res, const gr_poly_t x, gr_ctx_t ctx)
int gr_series_mod_tan(gr_poly_t res, const gr_poly_t x, gr_ctx_t ctx)
int gr_series_mod_asin(gr_poly_t res, const gr_poly_t x, gr_ctx_t ctx)
int gr_series_mod_acos(gr_poly_t res, const gr_poly_t x, gr_ctx_t ctx)
int gr_series_mod_atan(gr_poly_t res, const gr_poly_t x, gr_ctx_t ctx)
int gr_series_mod_asinh(gr_poly_t res, const gr_poly_t x, gr_ctx_t ctx)
int gr_series_mod_acosh(gr_poly_t res, const gr_poly_t x, gr_ctx_t ctx)
int gr_series_mod_atanh(gr_poly_t res, const gr_poly_t x, gr_ctx_t ctx)

## Power series

### Types and macros

type gr_series_struct
type gr_series_t

  A structure containing a `gr_poly_t` followed by a `slong` representing the exponent in the error term.

type gr_series_vec_struct
type gr_series_vec_t

  Alias for `gr_vec_t` with `gr_series_t` elements, provided for convenience.

GR_SERIES_POLY(x)

  Macro accessing the polynomial part of a `gr_series_t`.

GR_SERIES_ERROR(x)

  Macro accessing the error of a `gr_series_t`.

GR_SERIES_ERR_MAX

  The maximum allowed n in an error term \(O(x^n)\).

GR_SERIES_ERR_EXACT

  A special value of n used to indicate that a series is exact.

GR_SERIES_ELEM_CTX(ctx)

  Given a `gr_series` context object, accesses the context object of the base ring.

GR_SERIES_PREC(ctx)

  Given a `gr_series` context object, accesses the default precision.

### Error term manipulation

slong _gr_series_get_error(const gr_series_t f, gr_ctx_t ctx)

  Return the exponent \(n\) of the error term \(O(x^n)\) of f. If f is exact, returns `GR_SERIES_ERR_EXACT`.

truth_t _gr_series_is_exact(const gr_series_t f, gr_ctx_t ctx)

  Returns whether f is exact as a power series, i.e. lacks error term \(O(x^n)\). This does not recursively check exactness of the underlying elements.

void _gr_series_set_error(gr_series_t f, slong n, gr_ctx_t ctx)

  Add an error term \(O(x^n)\) in-place to f. The exponent n is clamped between 0 and `GR_SERIES_ERR_MAX`. Terms of order higher than or equal to n will be truncated.

void _gr_series_make_exact(gr_series_t f, gr_ctx_t ctx)

  Remove the \(O(x^n)\) error term (if any) from f.

### Generic methods

Elements of a `gr_series` ring can be manipulated using the standard `gr` interface. The following is a list of implemented functions such that `gr_series_foo` overloads `gr_foo` in the method table for `gr_series`; the user can optionally call `gr_series_foo` directly.

void gr_series_ctx_clear(gr_ctx_t ctx)
int gr_series_ctx_write(gr_stream_t out, gr_ctx_t ctx)
truth_t gr_series_ctx_is_ring(gr_ctx_t ctx)
truth_t gr_series_ctx_is_commutative_ring(gr_ctx_t ctx)
truth_t gr_series_ctx_is_integral_domain(gr_ctx_t ctx)
truth_t gr_series_ctx_is_rational_vector_space(gr_ctx_t ctx)
truth_t gr_series_ctx_is_real_vector_space(gr_ctx_t ctx)
truth_t gr_series_ctx_is_complex_vector_space(gr_ctx_t ctx)
int gr_series_ctx_set_gen_name(gr_ctx_t ctx, const char *s)
int gr_series_ctx_set_gen_names(gr_ctx_t ctx, const char **s)
void gr_series_init(gr_series_t res, gr_ctx_t ctx)
void gr_series_clear(gr_series_t res, gr_ctx_t ctx)
void gr_series_swap(gr_series_t x, gr_series_t y, gr_ctx_t ctx)
void gr_series_set_shallow(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_randtest(gr_series_t res, flint_rand_t state, gr_ctx_t ctx)
int gr_series_write(gr_stream_t out, const gr_series_t x, gr_ctx_t ctx)
int gr_series_zero(gr_series_t res, gr_ctx_t ctx)
int gr_series_one(gr_series_t res, gr_ctx_t ctx)
int gr_series_set(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_gen(gr_series_t res, gr_ctx_t ctx)
int gr_series_gens_recursive(gr_vec_t vec, gr_ctx_t ctx)
int gr_series_neg(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_set_gr_poly(gr_series_t res, const gr_poly_t x, gr_ctx_t ctx)
int gr_series_set_scalar(gr_series_t res, gr_srcptr x, gr_ctx_t ctx)
int gr_series_set_si(gr_series_t res, slong c, gr_ctx_t ctx)
int gr_series_set_ui(gr_series_t res, ulong c, gr_ctx_t ctx)
int gr_series_set_fmpz(gr_series_t res, const fmpz_t c, gr_ctx_t ctx)
int gr_series_set_fmpq(gr_series_t res, const fmpq_t c, gr_ctx_t ctx)
int gr_series_set_other(gr_series_t res, gr_srcptr x, gr_ctx_t x_ctx, gr_ctx_t ctx)
truth_t gr_series_is_zero(const gr_series_t x, gr_ctx_t ctx)
truth_t gr_series_is_one(const gr_series_t x, gr_ctx_t ctx)
truth_t gr_series_coeff_is_zero(const gr_series_t x, slong i, gr_ctx_t ctx)
truth_t gr_series_equal(const gr_series_t x, const gr_series_t y, gr_ctx_t ctx)
int gr_series_add(gr_series_t res, const gr_series_t x, const gr_series_t y, gr_ctx_t ctx)
int gr_series_sub(gr_series_t res, const gr_series_t x, const gr_series_t y, gr_ctx_t ctx)
int gr_series_mul(gr_series_t res, const gr_series_t x, const gr_series_t y, gr_ctx_t ctx)
int gr_series_inv(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_div(gr_series_t res, const gr_series_t x, const gr_series_t y, gr_ctx_t ctx)
int gr_series_divexact(gr_series_t res, const gr_series_t x, const gr_series_t y, gr_ctx_t ctx)
int gr_series_sqrt(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_rsqrt(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_exp(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_log(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_tan(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_asin(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_acos(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_atan(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_asinh(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_acosh(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_atanh(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_gamma(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_rgamma(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_lgamma(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_digamma(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_erf(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_erfc(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_erfi(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_exp_integral_ei(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_cos_integral(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_cosh_integral(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_sin_integral(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_sinh_integral(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_fresnel(gr_series_t res1, gr_series_t res2, const gr_series_t x, int normalized, gr_ctx_t ctx)
int gr_series_fresnel_s(gr_series_t res, const gr_series_t x, int normalized, gr_ctx_t ctx)
int gr_series_fresnel_c(gr_series_t res, const gr_series_t x, int normalized, gr_ctx_t ctx)
int gr_series_airy(gr_series_t res1, gr_series_t res2, gr_series_t res3, gr_series_t res4, const gr_series_t x, gr_ctx_t ctx)
int gr_series_airy_ai(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_airy_ai_prime(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_airy_bi(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_airy_bi_prime(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_log_integral(gr_series_t res, const gr_series_t x, int offset, gr_ctx_t ctx)
int gr_series_gamma_upper(gr_series_t res, const gr_series_t s, const gr_series_t x, int regularized, gr_ctx_t ctx)
int gr_series_gamma_lower(gr_series_t res, const gr_series_t s, const gr_series_t x, int regularized, gr_ctx_t ctx)
int gr_series_beta_lower(gr_series_t res, const gr_series_t a, const gr_series_t b, const gr_series_t x, int regularized, gr_ctx_t ctx)
int gr_series_polylog(gr_series_t res, const gr_series_t s, const gr_series_t z, gr_ctx_t ctx)
int gr_series_hurwitz_zeta(gr_series_t res, const gr_series_t s, const gr_series_t z, gr_ctx_t ctx)
int gr_series_dirichlet_l(gr_series_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const gr_series_t x, gr_ctx_t ctx)
int gr_series_dirichlet_hardy_theta(gr_series_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const gr_series_t x, gr_ctx_t ctx)
int gr_series_dirichlet_hardy_z(gr_series_t res, const dirichlet_group_t G, const dirichlet_char_t chi, const gr_series_t x, gr_ctx_t ctx)
int gr_series_jacobi_theta(gr_series_t res1, gr_series_t res2, gr_series_t res3, gr_series_t res4, const gr_series_t x, const gr_series_t tau, gr_ctx_t ctx)
int gr_series_jacobi_theta_1(gr_series_t res, const gr_series_t x, const gr_series_t tau, gr_ctx_t ctx)
int gr_series_jacobi_theta_2(gr_series_t res, const gr_series_t x, const gr_series_t tau, gr_ctx_t ctx)
int gr_series_jacobi_theta_3(gr_series_t res, const gr_series_t x, const gr_series_t tau, gr_ctx_t ctx)
int gr_series_jacobi_theta_4(gr_series_t res, const gr_series_t x, const gr_series_t tau, gr_ctx_t ctx)
int gr_series_agm1(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_elliptic_k(gr_series_t res, const gr_series_t x, gr_ctx_t ctx)
int gr_series_weierstrass_p(gr_series_t res, const gr_series_t x, const gr_series_t tau, gr_ctx_t ctx)
int gr_series_hypgeom_pfq(gr_series_t res, const gr_series_vec_t a, const gr_series_vec_t b, const gr_series_t x, int regularized, gr_ctx_t ctx)