luna-poly

luna-poly provides canonical polynomial types for MoonBit: dense univariate polynomials, multivariate polynomials as sorted term arrays or ordered maps, and polynomials over named variables with evaluation, partial evaluation and substitution. Every type comes in an immutable flavour, where polynomials are values, and a mutable flavour, where explicitly named methods update a container in place. This manual describes version 0.2.0.

What you get

  • Canonical forms. Every representation removes zero terms and keeps one normal form, so == is equality of polynomials.
  • A shared monomial model. Exponent vectors without a fixed number of variables, ordered by a graded monomial order.
  • Algorithms with stated costs. Schoolbook and Karatsuba multiplication, Horner evaluation, composition, formal derivatives, binary powers, and simultaneous substitution as a ring homomorphism.
  • Generic code. Small capability traits, operation records, and the algebra traits of luna-generic re-exported by both facades.
  • Named variables through variable contexts, bridged to type_theory names.
  • Checked variants of every partial operation, returning None instead of aborting.

Packages

PackageRolePages
coreexponent vectors, variables and contexts, shapes, capability traits, operation recordsAPI · tutorial · design
immutfacade of the immutable layerAPI · tutorial · design
immut/denseimmutable dense univariate DensePolynomialAPI · tutorial · design
immut/termimmutable sorted-term TermPolynomialAPI · tutorial · design
immut/sparseimmutable ordered-map SparsePolynomialAPI · tutorial · design
immut/contextimmutable named-variable ContextPolynomial and substitutionAPI · tutorial · design
mutablefacade of the mutable layerAPI · tutorial · design
mutable/densemutable DensePolynomialAPI · tutorial · design
mutable/termmutable TermPolynomialAPI · tutorial · design
mutable/sparsemutable SparsePolynomialAPI · tutorial · design
mutable/contextmutable ContextPolynomialAPI · tutorial · design
internalmodule-private helpers (natural powers)API · tutorial · design
consistencytest-only package checking that layers and representations agreeAPI · tutorial · design

The architecture guide shows how the packages depend on each other.

Reading paths

New to the library. Read the immut tutorial, then the tutorial of the representation you need: dense for one variable, term or sparse for several, context for named variables and substitution.

Using it in an application. Keep the immut API and the per-representation API pages at hand; they state every precondition, failure case and cost. Read the mutable tutorial when profiling shows that intermediate values matter.

Writing generic code or a new representation. Read the core tutorial and the core design, which derives the monomial order and explains the capability traits and operation records.

Contributing. Read the architecture guide, the design pages of the packages you touch, the consistency page, and the contributing guide.

Requirements and installation

luna-poly needs the MoonBit toolchain with moonc 0.10 or later. Add it to a module with

moon add Luna-Flow/luna-poly@0.2.0

and import a facade in moon.pkg:

import {
  "Luna-Flow/luna-poly/immut",
}

It depends on Luna-Flow/luna-generic, Luna-Flow/arithmetic and Luna-Flow/type_theory, which moon installs automatically.

A first example

test "first example" {
  let p = @immut.DensePolynomial::from_coefficients([1, 2, 3])
  inspect(p.pow(2).eval(2), content="289")

  let ctx = @immut.VariableContext::from_names(["x", "y"])
  let x = ctx.require_variable("x")
  let y = ctx.require_variable("y")
  let q = @immut.ContextPolynomial::from_named_terms_as_sparse(ctx, [
    ([(x, 2U)], 1),
    ([(x, 1U), (y, 1U)], 3),
    ([], 4),
  ])
  inspect(q.eval_named([(x, 2), (y, 5)]), content="38")
  inspect(q.eval_partial([(x, 2)]), content="8 + 6 * y")
}

Version 0.2.0 layout

Version 0.2.0 replaced the former single root package by core, the implementation packages and the two facades. Import Luna-Flow/luna-poly/immut or Luna-Flow/luna-poly/mutable explicitly; code written for the old root package does not compile unchanged.