Skip to content

Releases: nanithefkuc/fgf

fgf 3.0.1

Choose a tag to compare

@nanithefkuc nanithefkuc released this 20 Oct 02:09
94b6ff4

3.0.1 is the first supported v3 release. The 3.0.0 published before it went
out by accident and was yanked; 3.0.1 is not API-compatible with that artifact
(see the 3.0.0 entry), and code locked to it must migrate. The supported
upgrade path is from 2.x: follow
Migrating from 2.x
and the breaking entries below.

Added

  • The canonical generic field family FiniteField<const P: u64, const N: u32, R: FiniteFieldRepr<P, N> = Residue> with the Residue presentation at
    degree one over every u64 prime. Each row exposes the full scalar and
    const element surface (from_raw, checked from_residue, to_residue,
    arithmetic, pow, canonical),
    total arithmetic under the crate-wide conventions (inv(0) == 0,
    x / 0 == 0, 0^0 == 1, with the explicit inverse-zero branch at
    P = 2), a little-endian wire lane sized to the characteristic —
    characteristic two uses an eight-byte lane, and an odd characteristic
    uses one, two, four, or eight bytes as its residues fit within 2^8,
    2^16, 2^32, and u64 — with FieldBuffer::decode/encode as the
    byte API of these rows, the checked packed
    operation surface with prepared coefficients, and vector routing on
    capable x86-64 hosts — AVX2 single-row kernels, AVX-512 under simd512 —
    with Scalar routing elsewhere. Broadcast add/sub take the modular path
    for every characteristic, so packed lanes stay canonical at P = 2.
    Values live in
    field::finite_field, re-exported at the root.
  • Sealed PrimeField marker for degree-one fields, the validated const
    integer reductions field::prime::reduce and reduce_wide, RangeError
    for out-of-range conversions, and the PrimeIdentity characteristic
    facts BITS, TWO_ADICITY, and RESIDUE_MOD_8.
  • just compile-fail compiles the negative consumer snippets under
    tests/compile_fail/ on the crate MSRV, each required to fail with its
    declared crate panic fragment, or simply to be rejected for trait-bound
    and privacy cases, and just msrv-accept runs
    those snippets plus the tests/consumers.rs compile-and-run matrix on
    the MSRV toolchain.
  • Wiki source guides cover the generic type model, field presentations,
    embeddings, custom towers and scalar fields, packed workflows, preparation,
    prime and bit-packed arithmetic, deployment, and migration from 2.x.
    wiki/Home.md and the sidebar organize the reader paths.
  • Sealed presentations MersenneFold (label mersenne-fold) and
    GoldilocksFold (label goldilocks-fold), re-exported at the root. Both
    rows implement PrimeField and gain const from_residue(u64) -> Result<Self, RangeError> and to_residue(self) -> Option<u64>. The
    default Residue row at either modulus remains a distinct type with its
    own lane width; values move between the two by residue conversion.
  • The binary degree-one rows FiniteField<2, 1, R> implement PrimeField
    and gain const from_residue(u64) -> Result<Self, RangeError> and
    to_residue(self) -> Option<u64>; they stay distinct from
    FiniteField<2, 1, Residue>, which stores a u64 residue.
  • just external-check type-checks every package under external/
    against the working copy.
  • The generic extension presentation FiniteField<P, N, Extension<S, D>>
    with data-only ExtensionSpec providers, the sealed storage family
    (Components, Packed, PackedPadded), the opaque const-constructible
    Relation, generic arithmetic under the crate-wide total conventions,
    component bytes and the checked packed surface with Scalar routing,
    ExtensionField component conversions, and BinaryField on
    characteristic-two rows over binary bases. The surface lives in
    field::extension, re-exported at the root. EmbeddingError gains the
    NoCanonicalMap variant for dividing degrees with no canonical map.
  • ComplexMersenne31, the ExtensionSpec<2> of QuadMersenne31:
    Mersenne31 extended by t^2 + 1 with Components storage,
    re-exported at the root.
  • An extension row whose base presentation, relation, and storage equal a
    shipped instance's runs that instance's specialized scalar arithmetic and
    reaches its kernel arms; every other extension row runs the generic body
    and reports Scalar.
  • FieldElem::from_residue/to_residue and from_index/to_index on
    every row: the prime-subfield value and the presentation index share one
    generic body over the crate-private row hooks, and the inherent const
    residue constructors check through the same bound.
  • The characteristic-independent relation surface in field::embedding,
    re-exported at the root: Embedding<S, T> over every pair of rows of
    equal characteristic whose degrees divide, with from_images,
    to_images, generator_count, generator, then, and
    Isomorphism<S, T> with apply, a total unapply,
    inverse, and composition; and the NoCanonicalMap and InvalidImages
    variants of EmbeddingError. Maps come from structural inclusions, the
    frozen binary ladder, or validated caller images; every pre-cutover
    binary result is unchanged.
  • Wiki reference for operation suffixes, destination behavior, prepared state,
    row addressing, and allocation.
  • One-time field migration verification is recorded in
    Issue #41, rather than a
    permanent expanded regression corpus.
  • Behavioral regressions cover irreducible and reducible extension relations,
    relation-field arithmetic, ordered-basis subfield embeddings, rejected
    restrictions and degree mismatches, and quadratic prime identity predicates.
  • Raw kernel dispatch is unreachable outside the crate: every FieldKernels
    kernel entry takes the crate-private RawDispatch proof argument, so code
    holding an F: FieldKernels bound — including under internals — cannot
    call the raw entries. The negative consumer snippet
    tests/compile_fail/raw_dispatch_without_proof.rs pins the rejection.
  • Three examples join the educational set, each running against the library
    with std and alloc disabled: custom_extensions defines a custom
    ExtensionSpec field, basis_maps moves values through Embedding
    between basis presentations, and packed_no_alloc runs packed row
    operations without an allocator. just examples-portable runs them in
    that configuration.
  • just release-accept runs the crate-specific release acceptance, separate
    from the shared pull-request gate just validate. Its pieces also stand
    alone: just test-gather-validation-32 runs the gather validation as a
    release i686 build with overflow checks disabled — the configuration the
    gather fix below required — and CI runs it as its own job;
    just benchmark-check validates portable benchmark fixtures and compares
    their inventory with compiler-derived public API declarations;
    just benchmark-check-native validates the GF16 presentation comparisons
    and existing native geometries on capable hosts. just isa-accept EXPECTED
    requires the requested process backend and positive execution evidence
    before running the full tier matrix. Native release acceptance uses
    dedicated Willow Cove (v4x) and Golden Cove (v3_gfni_crypto) hosts.
  • The surfaces benchmark artifact measures the public API end to end:
    scalar arithmetic, packed single-row and multi-row operations, prepared
    coefficient forms, and Embedding/Isomorphism maps, over representative
    fields including the AES byte field, the Rijndael sixteen tower, and the
    MersenneFold/GoldilocksFold prime rows. --inventory prints every
    registered measurement without timing, --check runs each fixture's
    correctness check once, and --smoke shortens repetition without
    dropping cases. Each timed record names its public callable paths, exact
    registered field label, scope, logical byte numerator, lane and
    source/destination counts, and the resolved backend; a byte-XOR control
    identifies itself with control and phase fields, and zero-work APIs
    report latency instead of throughput.
  • The native GF16 comparison gains --presentations, a separate output mode
    beside the legacy format so existing parsing is unchanged. It covers
    representative shipped Rijndael and Fan-Paar fields, custom RS-rooted
    fields, normal and Cantor bases, and competitor-matched fields, with
    duplicate fgf control arms, interleaved arms and fixed/cycling
    coefficients, and every map and fixture validated outside timing;
    --presentations --check validates every new geometry without timing,
    and --presentations --smoke shortens the sampling budget without
    dropping a registered case. Both output modes open with a
    BENCHMARK_MODE banner (full, smoke, or check), and each
    GF16_SURFACE record carries its sample count and calibrated batch size
    as samples and batch_reps. Presentation conversions run public scalar
    caller loops.
  • The capture family surfaces records the artifact and the GF16
    --presentations mode for current v3 in five rounds per host, published
    in the v3 record (benchmarks/v3/public-api.md, benchmarks/v3/maps.md,
    and the GF16 presentation panels). No released-v2 counterpart is
    fabricated for the new public APIs.

Changed

  • Breaking: generic residue rows size their byte lane to the
    characteristic instead of always storing eight bytes: characteristic
    two keeps an eight-byte lane, and an odd characteristic uses one, two,
    four, or eight bytes as its residues fit within 2^8, 2^16, 2^32,
    and u64 — for example FiniteField<7, 1> moves one byte per element
    and FiniteField<1_000_000_007, 1> moves four. FieldBuffer::decode
    and encode are the byte API of these rows. Migration: the inherent
    fixed-array from_bytes/to_bytes are absent for these rows (every
    characteristic, P = 2 included), and no const byte form exists for
    them — size buffers from `FieldBuffer::B...
Read more

fgf 3.0.0-rc.1

fgf 3.0.0-rc.1 Pre-release
Pre-release

Choose a tag to compare

@nanithefkuc nanithefkuc released this 07 Oct 12:46
fce68bc

Added

  • Version-independent benchmark labels and separate absolute benchmarks/v2/
    and benchmarks/v3/ records, with matched speed factors under
    benchmarks/comparison/. Released v2.1.0 replaces the generic-API baseline.
  • Reproducible benchmark-only v2 preparation, paired host campaigns, and a
    fail-closed publisher with a raw-record cell evidence index.
  • Custom RS-rooted gf16d one-shot, prepared, and scalar measurements, with
    no fabricated released-v2 counterpart.
  • Explicit binary embeddings: Embedding<S, T> prepares the canonical
    inclusion of one binary field into another whose degree is a multiple of
    it, for every supported presentation — polynomial, ordered-basis, and
    tower, custom TowerSpec instances included. One frozen reference per
    degree (Polynomial<3>, Polynomial<0x7>, Polynomial<0x13>, the AES
    field, and the Rijndael towers Binary<16, Tower<Rijndael16>>,
    Binary<32, Tower<Rijndael32>>, and Binary<64, Tower<Rijndael64>>) fixes the
    consecutive inclusions: the identity into degree two, smallest-raw-root
    inclusions below the AES field, and low-component inclusions above it.
    new returns EmbeddingError::IncompatibleDegree when the source degree
    does not divide the target degree. embed, contains, restrict,
    frobenius, trace, and norm apply the prepared column arrays without
    allocating; equal presentation descriptions embed identically, and
    Embedding<Binary<1, Polynomial<3>>, T> supplies the absolute trace and norm.
  • Recursive quadratic towers through degree 64. One open TowerSpec
    supplies Base, LINEAR_COEFFICIENT, CONSTANT_COEFFICIENT, and NAME
    for every quadratic tower at degrees 2, 4, 8, 16, 32, and 64 over a
    supported base of half the degree; TowerGeneratorSpec optionally pins a
    multiplicative generator checked to full order against the complete prime
    factors of 2^N - 1 at each degree. Shipped specs root at the AES field
    (Rijndael16, Rijndael32, Rijndael64) or nest from GF(2) through the
    Wiedemann relation (FanPaar2 through FanPaar64, the degree-two and
    degree-four levels joining the ladder). Custom specs validate through the
    field description: the base first, excess coefficient bits, A != 0, and
    absolute trace(B/A^2) == 1 for the relation t^2 + A*t + B = 0.
  • Custom tower bulk operations: one dispatch implementation per degree
    serves every representation, routing pinned Rijndael and Fan-Paar
    descriptions to their vector kernels and every other tower to the typed
    scalar fallback with backend_for reporting Scalar; degree-eight
    towers join the single degree-eight dispatch. Towers at degrees 8, 16,
    32, and 64 implement FieldBuffer.
  • Ordered-basis byte presentations: Normal<P, E> wraps a polynomial
    element into its conjugate basis (bit i selects E^(2^i); one is all
    bits set) and Cantor<P, SEED> builds the chain c_(N-1) = SEED,
    c_i = c_(i+1)^2 + c_(i+1) (bit i selects c_i; validity asserts
    c_0 == ONE), at degrees 2, 4, and 8. Basis rank and inverse columns are
    checked by bounded enumeration; generators are the transported polynomial
    generators, verified to full order. Polynomial presentations extend to
    degrees two (Polynomial<0x7>) and four (Polynomial<0x13>,
    Polynomial<0x19>, Polynomial<0x1F>); degrees 1, 2, and 4 are
    scalar-only. Basis bulk operations run the typed scalar fallback;
    polynomial arithmetic never touches basis coordinates.
  • Open scalar field definitions. Field is implementable downstream;
    PrimeCharacteristic<P> supplies a checked prime identity at any u64
    prime through deterministic Miller-Rabin, and the central validation
    block — reached from every generic construction — checks the
    characteristic identity, a positive degree, ORDER == CHARACTERISTIC^DEGREE with overflow checking, and the binary degree cap
    of 64. Binary fields convert through BinaryField::to_coordinates and
    from_coordinates, which reject excess bits above the degree through
    CoordinateError.
  • just cross-check compiles the AArch64 and Wasm library paths, including
    the explicit Wasm SIMD configuration, and just bench-build NAME builds a
    portable benchmark artifact without running it.
  • just bench-gf16-comp runs an interleaved native GF(2^16) field
    comparison against GF-Complete, reed-solomon-erasure,
    reed-solomon-simd, and Leopard-RS 1.x; the harness validates basis maps
    and region outputs against independent arithmetic, includes
    duplicate-operation controls, and reports unavailable primitives
    separately. bench-gf-comp includes the same harness in its shuffled
    rounds.
  • The benchmark record is split by field family. BENCHMARKS.md indexes
    the pages under benchmarks/ and holds the hosts, shared method, number
    format, and reproduction commands; each page carries its own setup,
    self-timings, and competitor tables. Every value in a table has the same
    digit count, so paired Tiger Lake / Golden Cove cells line up down each
    column.

Changed

  • Breaking: fields have no public type aliases; Binary<N, R> is the
    only spelling. Gf1, Gf16, Gf32, Gf64, and FanPaar2 through
    FanPaar64 (the field aliases) are not provided: replace each with its
    canonical type — Binary<1, Polynomial<3>>,
    Binary<16, Tower<Rijndael16>>, Binary<32, Tower<Rijndael32>>,
    Binary<64, Tower<Rijndael64>>, and Binary<N, Tower<FanPaarN>> — or
    declare a local alias such as
    type Gf2P16 = Binary<16, Tower<Rijndael16>>;. The Fan-Paar spec markers
    are named like Rijndael16: FanPaar2Spec through FanPaar64Spec become
    FanPaar2 through FanPaar64, so Fan-Paar GF(2^16) is
    Binary<16, Tower<FanPaar16>>.
  • Breaking: Binary<N, R> replaces Gf<N, R> and explicitly names
    characteristic-two fields; BinaryField remains the capability trait.
    Polynomial<P> replaces Poly<P>, and RS replaces REED_SOLOMON
    for the unchanged 0x11D polynomial convention. The Gf8<R> transition
    alias is removed: replace it with Binary<8, R>, including associated
    item paths such as Binary::<8, Polynomial<AES>>::ORDER. For example,
    Elem<Gf8<Poly<REED_SOLOMON>>> becomes
    Elem<Binary<8, Polynomial<RS>>>. No compatibility aliases remain.
  • Breaking: TowerSpec::LINEAR_COEFFICIENT and
    TowerSpec::CONSTANT_COEFFICIENT replace TowerSpec::A and
    TowerSpec::B. Rename the associated constants in custom specs and their
    qualified uses; values remain raw coordinates in Base for the relation
    t^2 + A*t + B = 0. TowerSpec and TowerGeneratorSpec remain separate:
    arithmetic requires no selected generator. Field arithmetic, wire bytes,
    selected generators, and backend routing are unchanged.
  • The canonical $GF(2)$ benchmark label is gf1, denoting extension degree.
    Its pages move from gf2.md to gf1.md in the v2, v3, and comparison
    directories; the released-v2 API mapping remains Gf2.
  • Breaking: one element wrapper, Elem<F>, replaces every concrete
    element path. mersenne31::Elem, goldilocks::Elem,
    quad_mersenne31::Elem, the binary Elem<N, R> spelling, the
    gf16/gf32/gf64 and Fan-Paar element structs, and gf2::Elem are
    removed, as are the module GENERATOR constants (Elem::<F>::GENERATOR
    replaces them all). Gf2 becomes Binary<1, Polynomial<3>>, and
    bits::dot_product returns Elem<Binary<1, Polynomial<3>>>. Migrate
    gf2::Elem to Elem<Binary<1, Polynomial<3>>>, mersenne31::Elem to
    Elem<Mersenne31>, gf16::Elem to Elem<Binary<16, Tower<Rijndael16>>>,
    fan_paar::fp16::Elem to Elem<Binary<16, Tower<FanPaar16>>>, and the
    binary Elem<8, Poly<POLY>> to Elem<Binary<8, Polynomial<POLY>>>;
    spell elements of the wider towers and the prime families the same way.
    Inherent const arithmetic sits on the Elem<F> types; ZERO, ONE,
    GENERATOR, and to_raw are the generic items and are not redeclared
    per family. Debug
    for every element is the generic NAME(raw) format; family Display
    formats are unchanged. The scalar-arithmetic trait field::Elem is
    renamed FieldElem (re-exported as fgf::FieldElem): replace
    use fgf::field::Elem; trait imports with use fgf::field::FieldElem;.
    Wire bytes, generators, and relations are unchanged.
  • Breaking: Field is split into three contracts. Field keeps scalar
    algebra and metadata (Raw, Characteristic, NAME, DEGREE, ORDER,
    ZERO_RAW, ONE_RAW, VALID, raw arithmetic); FieldBuffer carries the
    byte encoding (BYTES, STORAGE_BITS, decode, encode), implemented
    by binary degrees 8/16/32/64 and the prime families; HasGenerator
    carries the selected generator (GENERATOR_RAW). Field::Elem,
    Field::BITS, Field::CHARACTERISTIC, Field::GENERATOR, and
    Field::elem_count are removed. Generic code reads the characteristic as
    <F::Characteristic as PrimeIdentity>::CHARACTERISTIC, the storage width
    as FieldBuffer::STORAGE_BITS, and the generator as
    Elem::<F>::GENERATOR under a HasGenerator bound. FieldKernels and
    every ops operation — pack, unpack, and pack_to_vec included —
    bound on FieldBuffer and take Elem<F>. FieldElem is sealed and
    implemented only by the blanket impl<F: Field> FieldElem for Elem<F>;
    downstream custom fields implement the new Field contract and receive
    the trait. The trait exponent is u128 (pow(u128)), the inherent
    const pow on every family takes u128, and QuadMersenne31::pow_u128
    is removed in its favour.
  • Breaking: prime from_raw canonicalizes and to_raw returns
    canonical storage. In 2.x, from_raw and decode retained the
    unreduced lane and to_raw exposed the stored bits; every safely
    constructed element now holds canonical coordinates, so comparison,
    hashing, and packing see the reduced lane. Packed prime operations accept
    every lane bit pattern a decode accepts and emi...
Read more

fgf 2.1.0

Choose a tag to compare

@nanithefkuc nanithefkuc released this 02 Oct 02:41

Added

  • Self-contained, runnable examples cover scalar arithmetic across every field,
    parity-shard encoding and erasure recovery, streaming GF(2^16) parity updates,
    bit-packed Hamming syndromes, extension-field embeddings and trace/norm, and
    canonical prime-field evaluation-vector arithmetic.
  • just example NAME [ARGS] and just examples [ARGS] run one tutorial or the
    complete educational set, including portable builds with alloc.
  • QuadMersenne31 dispatches V4x under simd512: mul_into, mul_add,
    and mul_elementwise run AVX-512 kernels, and backend_for::<QuadMersenne31>()
    reports v4x on those hosts. The remaining operations run the AVX2 kernels.

Changed

  • BENCHMARKS.md presents a complete Tiger Lake / Golden Cove snapshot of
    public API and interleaved competitor timings. Measurement history and
    dispatch-threshold experiments are excluded from the public tables.
  • Prime-field vector multiplication is faster. Mersenne31 AVX2 and AVX-512
    multiplies skip re-folding canonical operands, and the AVX-512 product uses a
    masked recombination; QuadMersenne31 AVX2 complex products defer reduction
    until four partial products are summed. Goldilocks AVX2 addition and
    subtraction use fewer compare steps. Outputs remain canonical, and the
    raw-destination guarantees of add_assign_scalar and sub_assign_scalar
    are unchanged. See BENCHMARKS.md.
  • bench-m31-comp runs only the five-round public snapshot campaign;
    the prime_ntt threshold investigation remains a separate benchmark.
  • The AVX-512 GF(2^8) matrix kernels (Gf8D and Gf8B, contiguous,
    scattered-row, provider, and prepared forms) use direct coefficient reads
    for short rows and resolve each row group's coefficients into map words
    once per chunk of terms for longer rows, folding terms in pairs. Results
    are unchanged.
  • The GFNI and AVX-512 byte-field matrix kernels, contiguous and
    scattered-row, process long rows in column blocks when the destination
    spans more than one row group, so each source block is reused from cache
    across every row group instead of being re-read from memory per group.
    Results are unchanged.
  • The GFNI byte-field matrix kernels prefetch each source ahead of the tile
    loop on long rows whose terms fit in one resolve chunk, and run the column
    blocks above only for larger term counts. Results are unchanged.
  • The GFNI byte-field matrix kernels (Gf8D and Gf8B, contiguous,
    scattered-row, provider, and prepared forms) split the destination rows
    into the fewest width-balanced row groups of up to six rows, or four with
    one or two terms, instead of fixed groups of four, two, and one, so the
    sources are streamed once per group and fewer groups run. Overwrite seeds
    multi-row groups from the first product rather than from zero. Results are
    unchanged. BENCHMARKS.md is refreshed on both hosts for this change.
  • The GFNI byte-field matrix kernels run a three-row group with three
    32-byte lanes per row, folding terms two at a time, when its terms number
    from six through one resolve chunk and its rows are cache-resident; other
    three-row groups keep two lanes. This covers three-destination calls and
    the trailing group of seven-destination calls, contiguous and
    scattered-row. Results are unchanged.

Fixed

  • The Plonky3 competitor harness aligns packed quadratic-extension fixtures
    for native AVX-512 builds and reports the actual packing widths.
  • CI coverage uses just cover, including the portable feature run, and
    exports LCOV through just cover-lcov with the same exclusion set. The
    AVX-512-only QuadMersenne31 kernel is excluded on incapable coverage
    runners; the AVX2 kernel and mixed-ISA dispatch remain included.
  • NEON and Wasm row-geometry checks compile only on their consumer targets,
    rather than appearing as unreachable x86 coverage obligations.
  • The GFNI and AVX-512 GF(2^8) matrix kernels over a generic Matrix
    provider check the length of each source slice they stage, so a provider
    that returns a shorter slice than the one the entry validated panics
    instead of reading out of bounds.

fgf 1.0.0

Choose a tag to compare

@nanithefkuc nanithefkuc released this 14 Sep 22:45
e2c4e18

First stable release. The public API — fields, ops, bits, backend reporting, and every stable byte encoding — is now under semantic versioning; the internals feature stays explicitly unstable. MSRV is Rust 1.93. See CHANGELOG.md for the full entry.