Tutorials

Compute with formal series

Use poly.series to calculate a fixed number of exact coefficients without expanding higher powers. A series retains its order, so a reciprocal, composition, or derivative carries the precision information into the next call.

Expand a reciprocal and an exponential

The reciprocal of \(1-x\) begins \(1+x+x^2+\cdots\). At order six, you know coefficients through \(x^5\) and leave the rest as \(O(x^6)\).

array_toolkit_series.mojo Download
"""Keep a formal truncation order through reciprocals and exponentials."""
from poly import series
from apn_mojo import Rational
from std.testing import assert_equal


def main() raises:
    var denominator = series.asarray([1, -1], order=6)
    var geometric = series.reciprocal(denominator)
    var product = series.multiply(denominator, geometric)
    assert_equal(product[0], Rational(1))
    assert_equal(product[5], Rational(0))
    var exponential = series.exp([0, 1], order=6)
    assert_equal(exponential[5], Rational(1, 120))
    print("Known coefficients:", len(geometric))
    print("Coefficient of x^5:", exponential[5])
    print("Derivative order:", series.derivative(exponential).order())

Run from the repository root pixi run mojo run -I build docs/examples/array_toolkit_series.mojo

Output

Known coefficients: 6
Coefficient of x^5: 1/120
Derivative order: 5

asarray([1, -1], order=6) treats the input as a polynomial and supplies zeros for its missing coefficients below order six. reciprocal returns six ones. The product is \(1+O(x^6)\). For \(\exp(x)\), the coefficient of \(x^5\) is exactly \(1/120\); differentiation reduces the known order from six to five.

Keep the unknown tail visible

A prepared series supports indexing, iteration, and len. Its length is its order, including known trailing zeros. The backing polynomial stays compact; series.coefficients(s) materializes all known coefficients under the work budget. Use series.to_polynomial(s) when you deliberately want to discard the unknown tail and work with the known polynomial part.

Raw coefficient iterables require order=. Operations on a prepared series reuse its order. Two prepared inputs must have equal orders unless you pass an explicit lower order=. series.truncate(s, n) lowers the order, and no operation accepts a request to recover unknown higher coefficients.

This is a formal coefficient calculation. It supplies no analytic error bound for evaluating an infinite series away from zero.

Choose an operation

Function Required input
add, subtract, multiply, negative Compatible exact fields and a common order
divide, reciprocal An invertible divisor constant
compose A zero-constant inner series and a known constant term
derivative Returns order max(0, n-1)
integral Returns order n+1 with zero constant; required divisions must exist
log A known constant equal to one
exp A known constant equal to zero
revert Order at least two, zero constant, and nonzero linear coefficient

Series algorithms use fields. Integer input promotes to QQ; rational, Gaussian rational, and modular inputs retain their inferred fields. Mixed scalar sequences use poly.coefficients, as in the array tutorial. Modular coefficients can mix with raw integer coefficients. A prepared QQ series does not implicitly convert into a prime field. Different moduli raise DOMAIN, including for zero series.

Finite characteristic can prevent the divisions needed by integration, logarithms, and exponentials. A nonzero constant alone does not guarantee that every operation exists at the requested order.

Every calculation accepts max_steps= or a shared Budget. Input collection, promotion, the core algorithm, and result storage consume the same allowance. A failure leaves prepared inputs usable.

See the series API reference for signatures.

For floating-point or ball coefficients, pass context= when constructing the representation and when computing with it. The numerical series and basis example covers both workflows.