renew_fixed/lib.rs
1//! Fixed-point arithmetic, for simulation code whose output has to reproduce
2//! bit-for-bit on every target.
3//!
4//! # Why this crate exists
5//!
6//! Rust guarantees IEEE 754 semantics for `f32` and `f64` *operators*, and
7//! that guarantee stops at the operators: `sin`, `cos` and their siblings are
8//! the platform's maths library, and are permitted to differ between targets.
9//! A simulation that calls them has no cross-target claim to make.
10//!
11//! Integer arithmetic is bit-identical everywhere, with nothing to police.
12//! That is the whole argument.
13//!
14//! # Contract
15//!
16//! - **Q47.16 in an `i64`.** 16 fractional bits: a resolution of 2⁻¹⁶, and a
17//! range of ±2⁴⁷. See [`Fixed`] for why those numbers and not others.
18//! - **No `f32` or `f64` in any signature this crate exposes.** Converting to
19//! a float is a presentation concern, and the conversion is written at the
20//! boundary that needs it rather than offered here. It cannot be centralised
21//! in the maths crate: that crate is core and this one is optional, so the
22//! core-closure rule refuses the edge outright. Nor is centralising it worth
23//! much — each boundary carries its own precision-loss exemption with its own
24//! reason, and one shared helper would flatten those into a single reason
25//! that fits none of them. What stops a simulation from converting is not
26//! this contract but the float-arithmetic denial it already builds under.
27//! - **Every operation is deterministic and target-independent.** No operation
28//! here consults a clock, an allocator, an environment variable, or anything
29//! whose value could differ between two machines running the same build.
30//! - **Overflow saturates, in every build profile, and is counted.** Never
31//! wraps, never differs between debug and release. See [`Fixed::saturations`].
32
33// This crate is arithmetic; it does not print. And it is the crate simulation
34// arithmetic is written in, so a float operator here would defeat its only
35// purpose — denied rather than left to review, and there is no `allow` below.
36#![deny(clippy::print_stdout, clippy::print_stderr, clippy::float_arithmetic)]
37
38mod angle;
39mod saturation;
40mod scalar;
41mod vector;
42mod wide;
43
44pub use angle::Angle;
45pub use saturation::{Saturations, saturations};
46pub use scalar::Fixed;
47pub use vector::{Vec2, Vec3};
48pub use wide::Wide;