mirror of
https://github.com/vale981/arb
synced 2025-03-06 09:51:39 -05:00
337 lines
13 KiB
ReStructuredText
337 lines
13 KiB
ReStructuredText
**fmpz_holonomic.h** -- holonomic sequences and functions
|
|
===============================================================================
|
|
|
|
This module provides support for holonomic sequences and functions,
|
|
which are represented via annihilating operators
|
|
`A = \sum_{i=0}^r a_i D^i` where `a_i \in \mathbb{Z}[x]`.
|
|
|
|
Depending on context, `D` is one of the following:
|
|
|
|
A forward shift operator `D f(x) = f(x+1)`, making `A` a difference operator
|
|
which defines a family of sequences `c(x)` satisfying the difference equation
|
|
|
|
.. math ::
|
|
|
|
a_0(x) c(x) + a_1(x) c(x+1) + \ldots + a_r(x) c(x+r) = 0.
|
|
|
|
A differential operator `D f(x) = f'(x)`, making `A` a differential operator
|
|
which defines a family of functions `f(x)` satisfying the differential
|
|
equation
|
|
|
|
.. math ::
|
|
|
|
a_0(x) f(x) + a_1(x) f'(x) + \ldots + a_r(x) f^{(r)}(x) = 0.
|
|
|
|
A specific sequence of function is defined by fixing `r` initial values
|
|
(derivatives), where `r` is called the *order* of the operator `A`.
|
|
|
|
|
|
Types, macros and constants
|
|
-------------------------------------------------------------------------------
|
|
|
|
.. type:: fmpz_holonomic_struct
|
|
|
|
.. type:: fmpz_holonomic_t
|
|
|
|
Represents a holonomic difference or differential operator as
|
|
a sequence of coefficients of type *fmpz_poly_struct*.
|
|
|
|
An *fmpz_holonomic_t* is defined as an array of length one of type
|
|
*fmpz_holonomic_t*, permitting an *fmpz_holonomic_t* to
|
|
be passed by reference.
|
|
|
|
|
|
Memory management
|
|
-------------------------------------------------------------------------------
|
|
|
|
.. function:: void fmpz_holonomic_init(fmpz_holonomic_t op)
|
|
|
|
Initializes *op* for use, setting it to the zero operator (note that
|
|
this is not a valid operator for input to most functions).
|
|
|
|
|
|
.. function:: void fmpz_holonomic_clear(fmpz_holonomic_t op)
|
|
|
|
Clears *op*, deallocating all coefficients and the coefficient array.
|
|
|
|
|
|
.. function:: void fmpz_holonomic_fit_length(fmpz_holonomic_t op, long len)
|
|
|
|
Makes sure that the coefficient array of the operator contains at
|
|
least *len* initialized polynomials.
|
|
|
|
|
|
.. function:: void _fmpz_holonomic_set_length(fmpz_holonomic_t op, long len)
|
|
|
|
Directly changes the length of the operator, without allocating or
|
|
deallocating coefficients. The value shold not exceed the allocation length.
|
|
|
|
|
|
Basic operations
|
|
-------------------------------------------------------------------------------
|
|
|
|
.. function:: void fmpz_holonomic_set(fmpz_holonomic_t rop, const fmpz_holonomic_t op)
|
|
|
|
Sets `op` to a copy of `op`.
|
|
|
|
.. function:: void fmpz_holonomic_one(fmpz_holonomic_t op)
|
|
|
|
Sets *op* to the constant operator 1. As a differential operator, this
|
|
annihilates the zero function. As a difference operator, it annihilates
|
|
the zero sequence.
|
|
|
|
.. function:: void fmpz_holonomic_randtest(fmpz_holonomic_t op, flint_rand_t state, long r, long d, long b)
|
|
|
|
Sets *op* to a random nonzero operator of order at most *r*, degree
|
|
at most *d*, and with coefficients at most *b* bits in size. The operator
|
|
is guaranteed to have a nonzero leading coefficient, but otherwise
|
|
will not be normalised.
|
|
|
|
Properties
|
|
-------------------------------------------------------------------------------
|
|
|
|
.. function:: long fmpz_holonomic_order(const fmpz_holonomic_t op)
|
|
|
|
Returns the order *r* of *op*.
|
|
|
|
.. function:: long fmpz_holonomic_degree(const fmpz_holonomic_t op)
|
|
|
|
Returns the degree *d* of *op*, defined as the highest degree of
|
|
all its coefficients.
|
|
|
|
.. function:: int fmpz_holonomic_seq_is_constant(const fmpz_holonomic_t op)
|
|
|
|
Returns nonzero if *op* is zero-order, i.e. annihilates constant
|
|
sequences.
|
|
|
|
.. function:: int fmpz_holonomic_seq_is_cfinite(const fmpz_holonomic_t op)
|
|
|
|
Returns nonzero if *op* has constant coefficients, i.e. annihilates
|
|
C-finite sequences.
|
|
|
|
.. function:: int fmpz_holonomic_seq_is_hypgeom(const fmpz_holonomic_t op)
|
|
|
|
Return nonzero if *op* is first-order, i.e. annihilates hypergeometric
|
|
sequences.
|
|
|
|
Input and output
|
|
-------------------------------------------------------------------------------
|
|
|
|
.. function:: void fmpz_holonomic_print(const fmpz_holonomic_t op, const char * x, const char * d)
|
|
|
|
Prints a pretty representation of *op*, using the string *x* for the
|
|
variable of the coefficient polynomials, and using the string *d* for
|
|
the differential or difference operator.
|
|
|
|
|
|
Normalisation
|
|
-------------------------------------------------------------------------------
|
|
|
|
.. function:: void fmpz_holonomic_normalise_leading(fmpz_holonomic_t op)
|
|
|
|
Normalises *op* by removing leading zero coefficients.
|
|
|
|
.. function:: void fmpz_holonomic_normalise_sign(fmpz_holonomic_t op)
|
|
|
|
Normalises *op* by making the leading coefficient of the leading
|
|
polynomial positive.
|
|
|
|
.. function:: void fmpz_holonomic_normalise_content(fmpz_holonomic_t op)
|
|
|
|
Normalises *op* by dividing out the content, i.e. the greatest common
|
|
divisor, of all the coefficients.
|
|
|
|
.. function:: void fmpz_holonomic_seq_normalise_trailing(fmpz_holonomic_t op)
|
|
|
|
Normalises *op* as a difference operator by removing trailing
|
|
zero coefficients. This requires shifting the higher-order coefficients
|
|
to compensate.
|
|
|
|
.. function:: void fmpz_holonomic_seq_normalise(fmpz_holonomic_t op)
|
|
|
|
Normalises *op* as a difference operator by removing leading and trailing
|
|
zero coefficients, removing the content, and making the leading
|
|
polynomial positive.
|
|
|
|
|
|
Shifting
|
|
-------------------------------------------------------------------------------
|
|
|
|
.. function:: void fmpz_holonomic_shift_fmpz(fmpz_holonomic_t res, const fmpz_holonomic_t op, const fmpz_t s)
|
|
|
|
.. function:: void fmpz_holonomic_shift_fmpq(fmpz_holonomic_t res, const fmpz_holonomic_t op, const fmpq_t s)
|
|
|
|
.. function:: void fmpz_holonomic_shift_si(fmpz_holonomic_t res, const fmpz_holonomic_t op, long s)
|
|
|
|
Given an operator *op* annihilating a function or sequence `f(x)`,
|
|
sets *res* to an annihilator of the shifted function
|
|
or sequence `f(x+s)`.
|
|
|
|
|
|
Special sequences
|
|
-------------------------------------------------------------------------------
|
|
|
|
.. function:: void fmpz_holonomic_seq_set_const(fmpz_holonomic_t op)
|
|
|
|
Sets *op* to an annihilator of the constant sequence `c, c, c, \ldots`
|
|
where `c` is arbitrary.
|
|
|
|
.. function:: void fmpz_holonomic_seq_set_fmpz_pow(fmpz_holonomic_t op, const fmpz_t c)
|
|
|
|
.. function:: void fmpz_holonomic_seq_set_fmpq_pow(fmpz_holonomic_t op, const fmpq_t c)
|
|
|
|
Sets *op* to an annihilator of the sequence `c, c^2, c^3, \ldots`.
|
|
|
|
.. function:: void fmpz_holonomic_seq_set_factorial(fmpz_holonomic_t op)
|
|
|
|
Sets *op* to an annihilator of the sequence of factorials `n!`.
|
|
|
|
.. function:: void fmpz_holonomic_seq_set_harmonic(fmpz_holonomic_t op)
|
|
|
|
Sets *op* to an annihilator of the sequence of harmonic numbers
|
|
`H_n = 1 + 1/2 + 1/3 + \ldots + 1/n`.
|
|
|
|
.. function:: void fmpz_holonomic_seq_set_fibonacci(fmpz_holonomic_t op)
|
|
|
|
Sets *op* to an annihilator of the sequence of Fibonacci numbers `F_n`.
|
|
|
|
|
|
Special functions
|
|
-------------------------------------------------------------------------------
|
|
|
|
.. function:: void fmpz_holonomic_fun_set_pow_fmpq(fmpz_holonomic_t op, const fmpq_t c)
|
|
|
|
.. function:: void fmpz_holonomic_fun_set_pow_fmpz(fmpz_holonomic_t op, const fmpz_t c)
|
|
|
|
Sets *op* to a differential operator annihilating the power function `x^c`.
|
|
|
|
.. function:: void fmpz_holonomic_fun_set_exp(fmpz_holonomic_t op)
|
|
|
|
Sets *op* to a differential operator annihilating the exponential function `e^x`.
|
|
|
|
.. function:: void fmpz_holonomic_fun_set_sin_cos(fmpz_holonomic_t op)
|
|
|
|
Sets *op* to a differential operator annihilating the sine
|
|
and cosine functions `\sin(x)` and `\cos(x)`.
|
|
|
|
.. function:: void fmpz_holonomic_fun_set_log(fmpz_holonomic_t op)
|
|
|
|
Sets *op* to a differential operator annihilating the
|
|
natural logarithm `\log(x)`.
|
|
|
|
.. function:: void fmpz_holonomic_fun_set_atan(fmpz_holonomic_t op)
|
|
|
|
Sets *op* to a differential operator annihilating the
|
|
inverse tangent function `\operatorname{atan}(x)`.
|
|
|
|
.. function:: void fmpz_holonomic_fun_set_asin_acos(fmpz_holonomic_t op)
|
|
|
|
Sets *op* to a differential operator annihilating the inverse
|
|
sine and cosine functions `\operatorname{asin}(x)` and `\operatorname{acos}(x)`.
|
|
|
|
.. function:: void fmpz_holonomic_fun_set_erf(fmpz_holonomic_t op)
|
|
|
|
Sets *op* to a differential operator annihilating the error function `\operatorname{erf}(x)`.
|
|
|
|
|
|
Sequence transformations
|
|
-------------------------------------------------------------------------------
|
|
|
|
.. function:: void fmpz_holonomic_seq_mul(fmpz_holonomic_t res, const fmpz_holonomic_t op1, const fmpz_holonomic_t op2)
|
|
|
|
Given annihilators *op1* and *op2* of sequences `a_0, a_1, \ldots` and
|
|
`b_0, b_1, \ldots`, sets *res* to an annihilator of the sequence
|
|
`a_0 b_0, a_1 b_1, \ldots`.
|
|
This function currently requires *op1* and *op2* to be hypergeometric
|
|
(i.e. of order 1).
|
|
|
|
.. function:: void fmpz_holonomic_seq_pow_si(fmpz_holonomic_t res, const fmpz_holonomic_t op, long e)
|
|
|
|
Given an annihilator *op* of the sequence `c_0, c_1, c_2, \ldots`, outputs
|
|
an annihilator of the sequence `c_0^e, c_1^e, c_2^e, \ldots`.
|
|
This function currently requires *op* to be hypergeometric
|
|
(i.e. of order 1).
|
|
|
|
.. function:: void fmpz_holonomic_seq_reverse(fmpz_holonomic_t res, const fmpz_holonomic_t op)
|
|
|
|
Given an annihilator *op* of the sequence `c(n)`, sets *res* to an
|
|
annihilator of the sequence `c(-n)`.
|
|
|
|
.. function:: void fmpz_holonomic_seq_section(fmpz_holonomic_t res, const fmpz_holonomic_t op, long m)
|
|
|
|
Given an annihilator *op* of the sequence `c(n)` and an integer constant *m*,
|
|
sets *res* to an annihilator of the sequence `c(mn)`.
|
|
The constant *m* can be zero or negative.
|
|
|
|
|
|
Taylor series
|
|
-------------------------------------------------------------------------------
|
|
|
|
.. function:: void fmpz_holonomic_get_series(fmpz_holonomic_t re, const fmpz_holonomic_t de)
|
|
|
|
Given a differential operator *de* annihilating some function `f(x)`,
|
|
sets *re* to a difference operator annihilating the coefficients `c_k`
|
|
in the Taylor series at `x = 0`,
|
|
|
|
.. math ::
|
|
|
|
f(x) = \sum_{k=0}^{\infty} c_k x^k.
|
|
|
|
|
|
Sequence evaluation
|
|
-------------------------------------------------------------------------------
|
|
|
|
.. function:: void fmpz_holonomic_forward_fmpz_mat(fmpz_mat_t M, fmpz_t Q, const fmpz_holonomic_t op, long start, long n)
|
|
|
|
Let *op* be an operator of order *r* annihilating a sequence `c(k)`.
|
|
This function computes an *r* by *r* integer matrix `M` and a
|
|
denominator `Q` such that, for any initial values
|
|
`c(s), c(s+1), \ldots, c(s+r-1)` where `s` is given by *start*,
|
|
|
|
.. math ::
|
|
|
|
Q \, \begin{pmatrix} c(s+n) \\ c(s+n+1) \\ \vdots \\ c(s+n+r-1) \end{pmatrix}
|
|
=
|
|
M \, \begin{pmatrix} c(s) \\ c(s+1) \\ \vdots \\ c(s+r-1) \end{pmatrix}.
|
|
|
|
The output is computed by multiplying together successive companion
|
|
matrices, using binary splitting to balance the sizes of the subproducts.
|
|
|
|
Some special cases are handled more efficiently. In particular,
|
|
if *op* has constant coefficients, matrix exponentiation is used.
|
|
|
|
In general, no attempt is made to divide out content from `M` and `Q`.
|
|
If `Q` is zero, the leading coefficient of *op* has a root somewhere
|
|
among the evaluation points, making the sequence undefined from
|
|
that point onward.
|
|
|
|
It is assumed that *start + n* does not overflow a long (to start
|
|
from a larger initial value, one can shift the operator).
|
|
|
|
.. function:: void fmpz_holonomic_forward_fmprb_mat(fmprb_mat_t M, fmprb_t Q, const fmpz_holonomic_t op, long start, long n, long prec)
|
|
|
|
Equivalent to the *fmpz_mat* version, but truncates large entries.
|
|
|
|
.. function:: void fmpz_holonomic_forward_nmod_mat(nmod_mat_t M, mp_limb_t * Q, const fmpz_holonomic_t op, ulong start, ulong n)
|
|
|
|
Computes a forward matrix modulo the word-size modulus of *M*. This
|
|
function implements a sublinear algorithm: letting `m = \lfloor \sqrt n \rfloor`,
|
|
we multiply together `m` shifted companion matrices, evaluate
|
|
them at the points `0, m, 2m, \ldots, m(m-1)` using fast multipoint
|
|
evaluation, and finally multiply together the evaluated matrices.
|
|
This implementation is not intended to be optimal for small *n*.
|
|
|
|
.. function:: void fmpz_holonomic_get_nth_fmpz(fmpz_t res, const fmpz_holonomic_t op, const fmpz * initial, long n0, long n)
|
|
|
|
.. function:: void fmpz_holonomic_get_nth_fmpq(fmpq_t res, const fmpz_holonomic_t op, const fmpq * initial, long n0, long n)
|
|
|
|
.. function:: mp_limb_t fmpz_holonomic_get_nth_nmod(const fmpz_holonomic_t op, mp_srcptr initial, ulong n0, ulong n, nmod_t mod)
|
|
|
|
Computes element `c(n)` in the sequence annihilated by the
|
|
difference operator *op*, given the
|
|
initial values `c(n_0), c(n_1), \ldots, c(n_0+r-1)` where
|
|
`r` is the order of *op*. This is done by computing a forward
|
|
matrix, and is not optimal for small *n*.
|
|
The *fmpz* version assumes that the result is actually an integer.
|
|
|
|
|