Skip to main content

Crate fgf

Crate fgf 

Source
Expand description

[!WARNING] This library was made with the help of AI. Audit the code yourself, or with your own agent before using.

[!WARNING] fgf is variable-time throughout and guarantees no constant-time operation. Security applications are not a supported use: any handling of secret field elements, coefficients, or buffers must be audited separately.

§fgf — Faster Galois Fields

fgf provides finite-field elements and high-throughput operations over packed buffers. It targets the arithmetic underneath erasure coding, proof systems, and other workloads that repeatedly scale, combine, or reconstruct rows.

Main propertyWhat it provides
Checked public APISafe operations validate element widths, slice lengths, coefficient counts, and row geometry before dispatch.
Runtime SIMDOne process-wide selection chooses GFNI, AVX2, SSSE3/SSE4.2, NEON, Wasm SIMD, or the portable fallback.
Broad field setBinary polynomial fields, binary towers, canonical Fan–Paar towers, Mersenne31, Goldilocks, QM31, and bit-packed GF(2).
Packed operationsSingle-row AXPY, scatter, gather, matrix, overwrite, elementwise, and bit-range kernels.
Reusable preparationPrepared coefficients remove repeated table construction while keeping the steady-state operation allocation-free.
Const scalar arithmeticConcrete element operations are const, allowing coefficients and coding matrices to be built at compile time.
Stable representationFixed-width, little-endian encodings do not require aligned buffers.

fgf is an arithmetic library, not a codec. It does not construct coding matrices, own shards, invert matrices, or implement a recovery protocol.

§Installation

The minimum supported Rust version is 1.93.

[dependencies]
fgf = "1.2.2"

For the portable no_std surface without allocation:

[dependencies]
fgf = { version = "1.2.2", default-features = false }

§Quick start

Scalar elements expose inherent const arithmetic:

use fgf::gf16;

const A: gf16::Elem = gf16::Elem::from_raw(0x1234);
const B: gf16::Elem = gf16::Elem::from_raw(0x0108);
const PRODUCT: gf16::Elem = A.mul(B);

assert_eq!(PRODUCT.div(B), A);

Packed operations use the field marker as their generic parameter. Buffers contain consecutive little-endian elements and may be unaligned.

use fgf::{Gf8B, gf8b, ops};

let src = [0x01u8, 0x02, 0x03, 0x04];
let mut dst = [0u8; 4];

ops::mul_add::<Gf8B>(&mut dst, gf8b::Elem::from_raw(0x03), &src);
assert_eq!(dst, [0x03, 0x06, 0x05, 0x0c]);

§Supported fields

FieldMarker and elementConstructionAccelerated backends
GF(2^8)Gf8B, gf8b::ElemAES polynomial 0x11Bx86 GFNI
GF(2^8)Gf8D, gf8d::Elempolynomial 0x11Dx86 GFNI affine; x86, AArch64, and Wasm shuffle
GF(2^16)Gf16, gf16::Elemquadratic tower over Gf8Bx86 GFNI and shuffle
GF(2^32)Gf32, gf32::Elemquadratic tower over Gf16x86 GFNI
GF(2^64)Gf64, gf64::Elemquadratic tower over Gf32x86 GFNI
Fan–Paar GF(2^8)FanPaar8, fan_paar::fp8::Elemcanonical recursive towerportable
Fan–Paar GF(2^16)FanPaar16, fan_paar::fp16::Elemcanonical recursive towerx86 AVX2 and SSSE3
Fan–Paar GF(2^32)FanPaar32, fan_paar::fp32::Elemcanonical recursive towerx86 AVX2
Fan–Paar GF(2^64)FanPaar64, fan_paar::fp64::Elemcanonical recursive towerx86 AVX2
GF(2^31 − 1)Mersenne31, mersenne31::ElemMersenne prime in u32 lanesx86 AVX2 and SSE4.2
GF(2^64 − 2^32 + 1)Goldilocks, goldilocks::ElemGoldilocks prime in u64 lanesx86 AVX2 and SSE4.2
GF((2^31 − 1)²)QuadMersenne31, quad_mersenne31::Elemi² = −1 over Mersenne31x86 AVX2
GF(2)Gf2, gf2::Elemone element per bitdispatched XOR; portable word kernels

All element families support arithmetic operators including unary negation, assignment operators, Sum, Product, ordering, formatting, and named raw conversions. In characteristic two negation is the identity. Import fgf::field::Elem when generic code needs the trait methods.

By convention, inversion and division are total: inv(0) == 0 and x / 0 == 0.

§Packed operations

OperationContractTypical use
add_assigndst += srcparity or modular row addition
add_assign_rowsrow-shaped dst += srcbatched row addition
add_gather_offsetsadd selected rows from one regioncompact back-substitution
mul_adddst += coefficient × srcfinite-field AXPY
mul_intodst = coefficient × srcoverwrite scaling
mul_assigndst *= coefficientin-place scaling
mul_add_scatterone source accumulates into many rowssystematic encoding
mul_add_gathermany sources accumulate into one rowreconstruction
mul_into_gathermany sources overwrite one rowfresh recovered symbol
mul_add_matrixmany sources accumulate into many rowsmatrix application
mul_into_matrixmany sources overwrite many rowsfresh encoded rows
mul_add_matrix_atmany sources accumulate into offset rowsin-place reconstruction
mul_elementwisedst[i] = a[i] × b[i]pointwise products

The _with forms consume prepared coefficients. Preparation does not weaken validation: prepared and one-shot operations enforce the same public geometry.

use fgf::{Gf16, gf16, ops};

let coeff = ops::Coeff::<Gf16>::new(gf16::Elem::from_raw(0x0108));
let src = 0x1234u16.to_le_bytes();
let mut dst = [0u8; 2];

for _ in 0..3 {
    ops::mul_add_with::<Gf16>(&mut dst, &coeff, &src);
}

let once = gf16::Elem::from_raw(0x1234).mul(gf16::Elem::from_raw(0x0108));
assert_eq!(dst, once.to_bytes());

Coeff<F> prepares one coefficient without allocation. With alloc, CoeffVec<F> and CoeffMatrix<F> own reusable prepared collections; a single entry borrows as CoeffRef<'_, F>, which the single-coefficient _with operations accept directly. Prepared values are process-backend-specific and should be rebuilt rather than serialized.

ops::pack, ops::unpack, and ops::pack_to_vec convert between typed elements and packed byte buffers.

§Bit-packed GF(2)

The bits module stores one GF(2) element per bit, least-significant bit first. Operations that depend on the logical element count take it explicitly.

use fgf::bits;

let mut row = [0u8; 1];
bits::set_range(&mut row, 7, 0, 7);
bits::clear_range(&mut row, 7, 1, 3);

assert_eq!(row[0], 0b0111_1001);
assert_eq!(bits::weight(&row, 7), 5);

Range operations leave padding bits untouched. Whole-buffer operations process the complete supplied slices.

§Features

FeatureEffect
defaultenables std and runtime-dispatched simd
allocprepared coefficient collections and pack_to_vec
stdruntime support and lazily initialized shared tables; implies alloc
simdruntime-dispatched architecture kernels; implies std
internalsre-export-only facade of direct kernel and table surfaces

Nothing behind internals is a compatibility promise; the facade groups the implementation modules under fgf::internals and may change shape in any release. Normal users should use ops, which handles backend selection and capability proofs internally.

§Platforms and backends

BackendTarget
v3_gfni_cryptox86/x86_64 with AVX2 and GFNI
v3x86/x86_64 AVX2 shuffle kernels
v2x86/x86_64 SSSE3/SSE4.2 kernels
neon_aesAArch64 NEON with AES/PMULL capability
neonAArch64 NEON shuffle kernels
wasm128WebAssembly simd128
scalarportable fallback

backend() reports the process-wide selection. backend_for::<F>() reports the backend implemented by a particular field. SIMD_BACKEND may request a weaker backend at process startup; unsupported upgrades are ignored.

§Frozen encodings

These are the wire conventions a consumer above this crate depends on. Each is stated in full by the module that owns it.

SurfaceConvention
every fieldfixed-width little-endian element encoding of Field::BYTES, packed without alignment or padding
gf8breduction polynomial 0x11B, generator 0x03
gf8dreduction polynomial 0x11D, generator 0x02, the Reed-Solomon interop field
field::towercomponent order [a, b], constant component first, over Gf8B
fan_paarcanonical Wiedemann tower basis, a different basis from field::tower and not interoperable with it
bitsone GF(2) element per bit, LSB-first within each byte, padding bits caller-owned
prime fieldscanonical lanes on packed buffer boundaries

§Safety and scope

The stable API is safe, but the implementation is variable-time. Table lookups, cache behavior, and data-dependent work make fgf unsuitable for secret field elements or coefficients.

Packed prime-field operations expect canonical input lanes and preserve canonical output. Scalar prime-field operations accept any raw lane and reduce arithmetic results canonically.

§Performance

BENCHMARKS.md records pinned measurements for the public operation shapes on multiple x86 hosts. The benchmark targets are:

cargo bench --features internals --bench kernels
cargo bench --features internals --bench compare

§Building

cargo build
cargo build --no-default-features
cargo test --all-features

§License

MIT — see LICENSE.

Re-exports§

pub use field::FanPaar8;
pub use field::FanPaar16;
pub use field::FanPaar32;
pub use field::FanPaar64;
pub use field::Field;
pub use field::Gf2;
pub use field::Gf8B;
pub use field::Gf8D;
pub use field::Gf16;
pub use field::Gf32;
pub use field::Gf64;
pub use field::Goldilocks;
pub use field::Mersenne31;
pub use field::QuadMersenne31;
pub use field::fan_paar;
pub use field::gf2;
pub use field::gf8b;
pub use field::gf8d;
pub use field::gf16;
pub use field::gf32;
pub use field::gf64;
pub use field::goldilocks;
pub use field::mersenne31;
pub use field::quad_mersenne31;
pub use kernel::FGF_TIERS;
pub use kernel::FieldKernels;
pub use kernel::KernelBackend;
pub use kernel::backend;
pub use kernel::backend_for;
pub use kernel::has_vector_elementwise;

Modules§

bits
Bit-packed GF(2) buffers: one element per bit.
field
Field definitions and the scalar algebra contract.
kernel
Vector kernels and backend selection.
ops
The public vector operation surface.

Structs§

ParseBackendError
Error returned when a Backend name is not recognized.

Enums§

Backend
The SIMD capability ladder, one variant per archmage tier the ecosystem has kernels for.