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}