Skip to main content

prism_numerics/
lib.rs

1//! Prism standard-library numerics sub-crate.
2//!
3//! `prism-numerics` realizes the numerics Layer-3 of the standard
4//! library named in [Wiki ADR-031][09-adr-031]: it declares the
5//! arithmetic-domain axis traits (`BigIntAxis`, `FixedPointAxis`,
6//! `FieldAxis`, `RingAxis`) through the [`axis!`][09-adr-030] SDK
7//! macro and supplies parametric reference impls plus matching
8//! ConstrainedTypeShape carriers per the wiki's ADR-031 roster.
9//!
10//! ## Scope
11//!
12//! Every axis kernel takes `(input: &[u8], out: &mut [u8])` per
13//! ADR-030's signature contract. Axis impls are generic in their
14//! natural axis (byte-width, Q-format split) so applications can
15//! instantiate the impl their model needs without re-rolling the
16//! kernel body.
17//!
18//! - **`BigIntAxis`** — `(a + b) / (a - b) / (a * b) mod 2^(8*N)`.
19//!   Parametric: [`BigIntModularNumeric<BYTES>`] with `BYTES` in
20//!   `[1, MAX_BIG_INT_BYTES]`. Aliases: [`BigInt64Numeric`],
21//!   [`BigInt128Numeric`], [`BigInt256Numeric`], [`BigInt512Numeric`].
22//!   Shape: [`BigIntShape<BYTES>`].
23//! - **`FixedPointAxis`** — Q-format arithmetic on a 64-bit container.
24//!   Parametric: [`FixedPointQNumeric<INT_BITS, FRAC_BITS>`].
25//!   Aliases: [`FixedPointQ16_16Numeric`], [`FixedPointQ32_32Numeric`],
26//!   [`FixedPointQ1_31Numeric`], [`FixedPointQ48_16Numeric`].
27//!   Shape: [`FixedPointShape<I, F>`].
28//! - **`FieldAxis`** — prime-field arithmetic. The reference impl
29//!   [`PrimeFieldNumericSecp256k1`] fixes the modulus at
30//!   `p = 2^256 - 2^32 - 977`; alternative primes are operational
31//!   policy per ADR-031. Shape: [`FieldElementShape<BYTES>`].
32//! - **`RingAxis`** — finite-ring arithmetic. Parametric:
33//!   [`Gf2NumericAxisN<BYTES>`] for GF(2) over `N` bytes (bitwise
34//!   XOR / AND). Aliases: [`Gf2NumericAxis`], [`Gf2NumericAxis128`],
35//!   [`Gf2NumericAxis512`]. Shape: [`Gf2RingShape<BYTES>`].
36//!
37//! ## ConstrainedTypeShape declarations
38//!
39//! Per ADR-031's shape-declaration commitment (`BigInt<MaxBits>`,
40//! `FixedPoint<I, F>`, `FieldElement<P>`, ...), each axis has a
41//! matching `ConstrainedTypeShape` carrier so downstream
42//! `prism_model!` invocations can use the shape as `Input` / `Output`
43//! through the SDK macros. Every shape is `GroundedShape +
44//! IntoBindingValue`-bound for use as a model `Output` per ADR-027.
45//! Per ADR-017's closure rule, shape identity flows through
46//! `(SITE_COUNT, CONSTRAINTS)` — distinct parametric instantiations
47//! with the same site count content-address identically.
48//!
49//! ## Closure under uor-foundation (ADR-013)
50//!
51//! Every axis trait has `::uor_foundation::pipeline::AxisExtension` as
52//! a supertrait (enforced by `axis!`). Parametric axis impls
53//! hand-write their `AxisExtension` impl since the `axis!`-emitted
54//! companion macro takes `:ident` and cannot apply to generic types
55//! (the hand-written impls replicate the companion macro's dispatch
56//! arms verbatim).
57//!
58//! ## See also
59//!
60//! - [Wiki: 09 Architecture Decisions § ADR-027 — `output_shape!` SDK macro][09-adr-027]
61//! - [Wiki: 09 Architecture Decisions § ADR-030 — `axis!` SDK macro][09-adr-030]
62//! - [Wiki: 09 Architecture Decisions § ADR-031 — `prism` is the standard library][09-adr-031]
63//! - [Wiki: 12 Glossary § Numerics][12-glossary]
64//!
65//! [09-adr-027]: https://github.com/UOR-Foundation/UOR-Framework/wiki/09-Architecture-Decisions
66//! [09-adr-030]: https://github.com/UOR-Foundation/UOR-Framework/wiki/09-Architecture-Decisions
67//! [09-adr-031]: https://github.com/UOR-Foundation/UOR-Framework/wiki/09-Architecture-Decisions
68//! [12-glossary]: https://github.com/UOR-Foundation/UOR-Framework/wiki/12-Glossary
69
70#![no_std]
71#![cfg_attr(docsrs, feature(doc_cfg))]
72
73use uor_foundation::enforcement::ShapeViolation;
74
75pub mod bigint;
76pub mod field;
77pub mod fixed_point;
78pub mod polynomial;
79pub mod ring;
80pub mod verbs;
81
82pub use bigint::{
83    BigInt128Numeric, BigInt256Numeric, BigInt512Numeric, BigInt64Numeric, BigIntAxis,
84    BigIntModularNumeric, BigIntShape, MAX_BIG_INT_BYTES,
85};
86pub use field::{FieldAxis, FieldElementShape, PrimeFieldNumericSecp256k1};
87pub use fixed_point::{
88    FixedPointAxis, FixedPointQ16_16Numeric, FixedPointQ1_31Numeric, FixedPointQ32_32Numeric,
89    FixedPointQ48_16Numeric, FixedPointQNumeric, FixedPointShape,
90};
91pub use polynomial::{Polynomial15Mod256, Polynomial7Mod256, PolynomialShape};
92pub use ring::{
93    Gf2NumericAxis, Gf2NumericAxis128, Gf2NumericAxis512, Gf2NumericAxisN, Gf2RingShape, RingAxis,
94    MAX_GF2_BYTES,
95};
96
97/// Wiki ADR-031 standard-library version banner.
98pub const STANDARD_LIBRARY_VERSION: &str = env!("CARGO_PKG_VERSION");
99
100fn arity_violation(constraint: &'static str) -> ShapeViolation {
101    ShapeViolation {
102        shape_iri: "https://uor.foundation/axis/NumericAxisShape",
103        constraint_iri: constraint,
104        property_iri: "https://uor.foundation/axis/inputBytes",
105        expected_range: "https://uor.foundation/axis/NumericInputArity",
106        min_count: 0,
107        max_count: 0,
108        kind: uor_foundation::ViolationKind::ValueCheck,
109    }
110}
111
112pub(crate) fn split_pair(
113    input: &[u8],
114    operand_bytes: usize,
115) -> Result<(&[u8], &[u8]), ShapeViolation> {
116    if input.len() != 2 * operand_bytes {
117        return Err(arity_violation(
118            "https://uor.foundation/axis/NumericAxisShape/operandPair",
119        ));
120    }
121    Ok((&input[..operand_bytes], &input[operand_bytes..]))
122}
123
124pub(crate) fn check_output(out: &[u8], bytes: usize) -> Result<(), ShapeViolation> {
125    if out.len() < bytes {
126        return Err(arity_violation(
127            "https://uor.foundation/axis/NumericAxisShape/outputBuffer",
128        ));
129    }
130    Ok(())
131}