Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions libs/math/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Crypto3.Math

Matrix and polynomial arithmetic, evaluation domains, and Fast Fourier
Transform algorithms for the Crypto3 suite.
Matrix and polynomial arithmetic, evaluation domains, exact geometric-domain
Lagrange weights, Fast Fourier Transform algorithms, finite-field polynomial
factorization, and polynomial recovery primitives for the Crypto3 suite.

This header-only component is maintained as part of the Crypto3 monorepo. See
the [root build instructions](../../README.md#clone-and-build) to configure the
Expand Down
118 changes: 116 additions & 2 deletions libs/math/docs/concepts.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,117 @@
# Concepts # {#fft_concepts}
# C++ concepts {#fft_concepts}

@tableofcontents
@tableofcontents

This page lists the C++20 concepts exposed by Crypto3.Math. A concept is a compile-time predicate used to constrain a
template argument. It describes the interface an argument must provide; it does not construct an object or generate
runtime code.

Crypto3.Math currently exposes concepts for matrix and vector expressions, polynomial representations, and polynomial
multiplication backends. Concepts declared in a `detail` namespace are implementation constraints and are summarized
separately at the end of this page.

## Matrix and vector concepts

The matrix concepts are declared in:

<nil/crypto3/math/matrix/concepts.hpp>

### Readable expressions

`VectorExpression<T>` describes a readable vector-like expression. The type must provide `value_type`, `size_type`,
`size()`, and indexed access through `value(i)`.

`MatrixExpression<T>` describes a readable matrix-like expression. The type must provide `value_type`, `size_type`,
indexed access through `value(row, column)`, and dimensions through either:

* `rows()` and `columns()`; or
* `size1()` and `size2()`.

The free `rows(expression)` and `columns(expression)` functions provide one interface for both dimension naming
conventions.

Expression concepts are deliberately weak. In particular, an expression-template result may be readable without
owning storage or permitting mutation.

### Writable backends

`VectorBackend<T>` extends `VectorExpression<T>`. It additionally requires a semiregular type and writable indexed
access through `value(i)`.

`MatrixBackend<T>` similarly extends `MatrixExpression<T>` with semiregular value semantics and writable access
through `value(row, column)`.

The resizable variants add their corresponding resize operation:

| Concept | Additional operation |
|---|---|
| `ResizableVectorBackend<T>` | `value.resize(size)` |
| `ResizableMatrixBackend<T>` | `value.resize(rows, columns)` |

Algorithms that only read their operands should accept expression types. Algorithms that create or overwrite results
use backend or resizable-backend constraints as appropriate.

## Polynomial representation concepts

The polynomial representation concepts are declared in:

<nil/crypto3/math/polynomial/concepts.hpp>

Both concepts require `value_type`, `size_type`, `size()`, `degree()`, indexed read access, and a representation tag.
They accept const and reference-qualified types.

### CoefficientPolynomial

`CoefficientPolynomial<T>` identifies a polynomial stored as coefficients in ascending degree order:

[a0, a1, ..., an] represents a0 + a1 X + ... + an X^n.

Its `representation_type` must be `coefficient_representation`. Crypto3's `polynomial`, `polynomial_view`, and
`polymorphic_polynomial` satisfy this concept.

```cpp
template<nil::crypto3::math::CoefficientPolynomial Polynomial>
void consume_coefficients(const Polynomial &polynomial);
```

### EvaluationPolynomial

`EvaluationPolynomial<T>` identifies a polynomial stored as evaluations over a domain. Indexed entries are samples,
not coefficients, and the logical degree may differ from `size() - 1`.

Its `representation_type` must be `evaluation_representation`. Crypto3's `polynomial_dfs`, `polynomial_dfs_view`, and
`polymorphic_polynomial_dfs` satisfy this concept.

```cpp
template<nil::crypto3::math::EvaluationPolynomial Polynomial>
void consume_evaluations(const Polynomial &polynomial);
```

The representation tag prevents a coefficient algorithm from accidentally accepting an evaluation polynomial merely
because both types provide similar container operations. A bare `std::vector` satisfies neither concept because it
does not identify what its entries represent.

These concepts describe readable representation only. They do not require field-valued entries, mutability,
canonical storage, arithmetic operators, or alias-safe operations.

## PolynomialBackend

The polynomial multiplication backend concept is declared in:

<nil/crypto3/math/polynomial/polynomial_backend.hpp>

`polynomial_arithmetic::PolynomialBackend<Backend>` requires an associated `polynomial_type` that satisfies
`CoefficientPolynomial` and three operations:

```cpp
backend.multiply(output, left, right);
backend.square(output, input);
backend.multiply_low(output, left, right, coefficient_count);
```

The operations produce canonical coefficient polynomials and permit output to alias an input. `multiply_low` computes
the product modulo `X^coefficient_count`.

Backend operations receive a mutable backend object so implementations can reuse plans and scratch storage. The
[polynomial arithmetic infrastructure](@ref math_polynomial_arithmetic) documents the supplied schoolbook and
mixed-radix backends and the `polynomial_context` that owns them.
97 changes: 97 additions & 0 deletions libs/math/docs/geometric_lagrange.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Exact geometric-domain Lagrange weights {#math_geometric_lagrange}

@tableofcontents

`geometric_sequence_domain<FieldType, ValueType>` represents the exact-size domain

x_i = r^i, 0 <= i < m,

where `r` is the field's configured geometric generator. The domain provides a linear-time field-element API for
evaluating every Lagrange basis polynomial at an arbitrary point.

The relevant headers are:

| Facility | Header |
|---|---|
| Montgomery batch inversion | `<nil/crypto3/math/algorithms/batch_inverse.hpp>` |
| Evaluation-domain interface | `<nil/crypto3/math/domains/evaluation_domain.hpp>` |
| Exact geometric domain | `<nil/crypto3/math/domains/geometric_sequence_domain.hpp>` |

## Domain precomputation

Construction requires `m > 1`, a nonzero geometric generator, and distinct points `1, r, ..., r^(m-1)`. It rejects a
size that would repeat a point.

For the Lagrange path, the constructor precomputes:

* every domain point `x_i`;
* the barycentric weights `w_i = 1 / Z'(x_i)`; and
* the coefficients of the vanishing polynomial

Z(X) = product(X - x_i, i = 0 .. m - 1).

For general points, constructing every `w_i` from pairwise differences would take quadratic work. Geometric points
instead satisfy the recurrence

w_0 = product((1 - x_j)^-1, j = 1 .. m - 1),
w_i = -w_(i-1) * x_(m-1-i)^-1 * (1 - x_(m-i)) / (1 - x_i).

All required inverses of `1 - r^i`, together with `r^-1`, are obtained through one Montgomery batch inversion. For
`m` nonzero inputs, `batch_inverse_nonzero` performs one field inversion and exactly `3 * (m - 1)` field
multiplications.

Writing

Z(X) = sum(c_j * X^(m-j), j = 0 .. m), c_0 = 1,

the vanishing-polynomial coefficients use the recurrence

c_j = -c_(j-1) * r^(j-1) * (1 - r^(m-j+1)) / (1 - r^j).

If `r` has exact order `m`, the final denominator vanishes and the implementation uses the resulting special case
`Z(X) = X^m - 1`.

Construction therefore takes `O(m)` field operations, one field inversion, and `O(m)` stored field elements.

## Evaluating all weights

The combined overload returns both the weights and `Z(t)` without repeating the product:

```cpp
#include <nil/crypto3/math/domains/geometric_sequence_domain.hpp>

namespace math = nil::crypto3::math;

math::geometric_sequence_domain<field_type> domain(domain_size);

value_type vanishing_at_t;
const std::vector<value_type> weights =
domain.evaluate_all_lagrange_polynomials(t, vanishing_at_t);
```

Away from the domain, it uses the barycentric formula

L_i(t) = Z(t) * w_i / (t - x_i).

The implementation forms all denominators `t - x_i`, computes `Z(t)` as their product, and batch-inverts the
denominators with one field inversion. If `t = x_i`, it instead returns the corresponding unit vector and sets
`Z(t) = 0` without attempting an inversion.

For evaluations `f(x_i)`, the returned weights satisfy

f(t) = sum(f(x_i) * L_i(t), i = 0 .. m - 1)

for every polynomial of degree below `m`. The weights belong to `FieldType::value_type`; they may also scale values in
a compatible extension field.

## Rough current costs

| Operation | Rough current cost |
|---|---|
| Construct a size-`m` domain | `O(m)` field operations and one inversion |
| Evaluate all weights at one off-domain point | `O(m)` field operations and one inversion |
| Evaluate at a domain point | `O(m)` work and no inversion |
| Evaluate all weights at `k` independent points | `O(k * m)` field operations and at most `k` inversions |

Returning `m` weights already requires linear output work. All scratch storage used by an evaluation is local, while
the domain precomputation is immutable, so concurrent weight evaluations on one domain do not share mutable scratch.
14 changes: 13 additions & 1 deletion libs/math/docs/index.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
# Crypto3.Math {#fft_index}

@subpage fft_introduction @subpage fft_manual @subpage fft_concepts
@subpage fft_introduction

@subpage fft_manual

@subpage fft_concepts

@subpage math_geometric_lagrange

@subpage math_polynomial_arithmetic

@subpage math_polynomial_factorization

@subpage math_polynomial_recovery
15 changes: 11 additions & 4 deletions libs/math/docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@

@tableofcontents

Crypto3.Math extends the Crypto3 algebra library and provides Fast Fourier Transform
evaluation algorithms implemented in way C++ standard library implies: concepts, algorithms, predictable behavior,
latest standard features support and clean architecture without compromising security and performance.
Crypto3.Math extends the Crypto3 algebra library with polynomial and matrix arithmetic, evaluation domains, FFTs over
finite fields, polynomial factorization, and quotient-field recovery algorithms. Its interfaces use modern C++
concepts, generic algorithms, explicit arithmetic contexts, and interchangeable multiplication backends.

Crypto3.Math consists of several parts to review:

* [Manual](@ref fft_manual).
* [Concepts](@ref fft_concepts).
* [Exact geometric-domain Lagrange weights](@ref math_geometric_lagrange).
* [Polynomial arithmetic infrastructure](@ref math_polynomial_arithmetic).
* [Polynomial factorization](@ref math_polynomial_factorization).
* [Polynomial recovery](@ref math_polynomial_recovery).

## Background
## FFT background

There is currently a variety of algorithms for computing the Fast Fourier Transform (FFT) over the field of complex
numbers. For this situation, there exists many libraries, such as [FFTW](http://www.fftw.org/), that have been
Expand Down Expand Up @@ -84,6 +88,9 @@ conversion algorithm between the monomial and the Newton bases. The domain takes
Newton evaluation and interpolation by choosing sample points that form a geometric progression, _a\_n = r^(n-1)_, see
\[BS05\].

The field-element path also provides [exact geometric-domain Lagrange weights](@ref math_geometric_lagrange) with
linear domain precomputation and linear work per evaluation point.

## Dependencies ## {#fft_dependencies}

Internal dependencies:
Expand Down
19 changes: 18 additions & 1 deletion libs/math/docs/manual.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
# Manual # {#fft_manual}

@tableofcontents
@tableofcontents

Crypto3.Math provides coefficient-form and evaluation-form polynomials, evaluation domains, FFT algorithms, and
backend-aware polynomial arithmetic. The higher-level polynomial algorithms share a
`polynomial_arithmetic::polynomial_context<Backend>`. Reusing a context lets its multiplication backend retain plans,
configuration, and scratch storage across an operation.

The following pages describe the optimized domain and polynomial facilities:

* [Exact geometric-domain Lagrange weights](@ref math_geometric_lagrange) covers exact-size geometric points,
barycentric precomputation, batch inversion, vanishing polynomials, and linear-time weight evaluation.
* [Polynomial arithmetic infrastructure](@ref math_polynomial_arithmetic) describes multiplication backends,
reusable contexts, division, GCD, quotient-ring arithmetic, modular composition, and Frobenius maps shared by the
higher-level algorithms.
* [Polynomial factorization](@ref math_polynomial_factorization) covers square-free, distinct-degree, equal-degree,
complete, and staged factorization.
* [Polynomial recovery](@ref math_polynomial_recovery) covers square testing and square roots in polynomial quotient
fields, bounded rational reconstruction, and the relation between these operations and polynomial norms.
Loading
Loading