primitives.polynomial#

Abstract polynomial operations.

This module provides protocol-level polynomial operations without exposing implementation details like NTT/INTT. The protocol layer should use these abstractions rather than directly invoking NTT primitives.

Protocol Invariant: If you can change an implementation detail without changing the resulting proof bytes, that detail does NOT belong in the protocol specification.

Functions#

to_coefficients(→ numpy.ndarray)

Convert polynomial from evaluation form to coefficient form.

to_evaluations(→ numpy.ndarray)

Convert polynomial from coefficient form to evaluation form.

extend_to_domain(→ numpy.ndarray)

Extend polynomial from smaller domain to larger domain (Low-Degree Extension).

to_coefficients_cubic(→ list[primitives.field.FF3])

Convert cubic extension field elements from evaluation to coefficient form.

Module Contents#

primitives.polynomial.to_coefficients(evaluations: numpy.ndarray, domain_size: int, n_cols: int = 1) numpy.ndarray[source]#

Convert polynomial from evaluation form to coefficient form.

This is the protocol-level abstraction for interpolation. The fact that we use NTT/INTT internally is an implementation detail - the protocol only cares that we can convert between representations.

Args:

evaluations: Polynomial values at domain points (shape: (domain_size, n_cols) or flat) domain_size: Size of evaluation domain (must be power of 2) n_cols: Number of columns (for batched operations)

Returns:

Polynomial coefficients in same shape as input

primitives.polynomial.to_evaluations(coefficients: numpy.ndarray, domain_size: int, n_cols: int = 1) numpy.ndarray[source]#

Convert polynomial from coefficient form to evaluation form.

This is the protocol-level abstraction for evaluation. The fact that we use NTT internally is an implementation detail.

Args:

coefficients: Polynomial coefficients (shape: (domain_size, n_cols) or flat) domain_size: Size of evaluation domain (must be power of 2) n_cols: Number of columns (for batched operations)

Returns:

Polynomial evaluations in same shape as input

primitives.polynomial.extend_to_domain(evaluations: numpy.ndarray, original_size: int, extended_size: int, n_cols: int = 1) numpy.ndarray[source]#

Extend polynomial from smaller domain to larger domain (Low-Degree Extension).

This is the protocol-level operation for LDE. Implementation uses: 1. Convert to coefficients (INTT) 2. Zero-pad 3. Convert back to evaluations (NTT on larger domain)

But the protocol doesn’t need to know these steps.

Args:

evaluations: Values on original domain original_size: Original domain size extended_size: Target extended domain size n_cols: Number of columns

Returns:

Values on extended domain

primitives.polynomial.to_coefficients_cubic(values: list[primitives.field.FF3], n: int) list[primitives.field.FF3][source]#

Convert cubic extension field elements from evaluation to coefficient form.

For FF3 polynomials, we apply the transform component-wise over the base field. This is a protocol operation because it’s about converting polynomial representations, not about how we implement the transform.

Args:

values: List of FF3 evaluations n: Domain size

Returns:

List of FF3 coefficients