Arithmetica User Guide
Arithmetica is a Rust crate of exact geometric predicates for f64
input: orient2d, incircle, orient3d and insphere. This
guide is organized by topic; use the left sidebar to move between groups and the right panel to jump within a
page.
Overview
Arithmetica answers the sign questions computational geometry is built
on — which side of a line a point lies on, whether a point is inside a circle
— and returns the exact answer for every finite f64 input,
near-degenerate configurations and extreme magnitudes included. It is a Rust
implementation of Shewchuk’s adaptive-precision predicates, extended so that the
guarantee holds over the whole binary64 range.
The guide is organized into five areas: the numerical model that makes the results exact, the geometric predicates, exact constructions of intersection points, the expansion arithmetic the predicates are built from, and the shared core types and utilities.
The crate is #![no_std], allocates nothing, has no runtime dependencies,
and forbids unsafe code. The predicates and constructions never panic,
whatever the input.
Conventions
A few conventions hold throughout the crate:
- Points are plain arrays:
[f64; 2]in 2D and[f64; 3]in 3D. - Results: every predicate returns
Result<Sign, NonFinite>.SignisPositive,NegativeorZero, and it is the sign of the exact determinant, never an estimate. Zerois an answer, not a failure: it means the configuration is exactly degenerate (collinear, cocircular, coplanar or cospherical). Code that folds it into either of the other two signs has a bug.- Orientation:
orient2disPositivefor a counterclockwise triple, with the y-axis pointing up. The other predicates are defined relative to it; each one’s convention is on its own entry. - Non-finite input: a NaN or infinite coordinate returns
Err(NonFinite). It never produces a sign. - Arithmetic: the proofs assume IEEE 754 binary64 with round-to-nearest-even and no extended precision. Every x86-64 and ARM64 target satisfies this; the x87 FPU in 80-bit mode does not.
- Examples are short Rust programs whose results are shown with
assert_eq!. Every example in this guide is compiled and run against the crate.
Citation
If you use arithmetica in academic work, please cite the software and the two papers whose methods it implements.
Erlick, J. (2026). arithmetica (Version 0.1.0) [Computer software]. https://doi.org/10.5281/zenodo.23307342
- Shewchuk, J. R. (1997). Adaptive precision floating-point arithmetic and fast robust geometric predicates. Discrete & Computational Geometry, 18(3), 305–363. https://doi.org/10.1007/PL00009321
- Bartels, T., Fisikopoulos, V., & Weiser, M. (2023). Fast floating-point filters for robust predicates. BIT Numerical Mathematics, 63, 31. https://doi.org/10.1007/s10543-023-00975-x
Installation
Requirements
- Rust ≥ 1.85, edition 2024 (developed and tested with 1.96)
- No runtime dependencies; works in
#![no_std]crates and without an allocator
From crates.io
cargo add arithmetica
or add it to Cargo.toml directly:
[dependencies]
arithmetica = "0.1"
Cargo features
stage-counters records how many calls each stage of each predicate
answered (see Stage counters). It is off
by default, and with it off the counters compile to nothing.
cargo add arithmetica --features stage-counters
From source
git clone https://github.com/JustinGeoSci/arithmetica.git
cd arithmetica
cargo build
cargo test
API reference documentation for every release is also published on docs.rs.
Quick start
Classify the orientation of three points, test a point against a circle, and see a non-finite coordinate rejected:
use arithmetica::{Sign, incircle, orient2d};
// Counterclockwise, clockwise and collinear triples.
assert_eq!(orient2d([0.0, 0.0], [1.0, 0.0], [0.0, 1.0]), Ok(Sign::Positive));
assert_eq!(orient2d([0.0, 0.0], [0.0, 1.0], [1.0, 0.0]), Ok(Sign::Negative));
assert_eq!(orient2d([0.0, 0.0], [1.0, 1.0], [2.0, 2.0]), Ok(Sign::Zero));
// Is (1, 1) inside the circle through (0, 0), (2, 0) and (0, 2)?
assert_eq!(
incircle([0.0, 0.0], [2.0, 0.0], [0.0, 2.0], [1.0, 1.0]),
Ok(Sign::Positive)
);
// A NaN or infinite coordinate is an error, never a plausible-looking sign.
assert!(orient2d([f64::NAN, 0.0], [1.0, 0.0], [0.0, 1.0]).is_err());
From here, head into a group on the left — for example Geometric predicates for the full function set, or the Numerical model for why every answer is exact.