hyperlimit provides geometry predicates that report both the result and how
the result was decided.
It implements 2D/3D orientation, in-circle, in-sphere, line classification, and plane classification over scalar types that can expose structural facts. The resolver tries cheap scalar and determinant facts before exact arithmetic, bounded refinement, or robust fallback.
hyperrealsupplies exact/symbolic scalar facts and bounded sign refinement throughhyperreal::Real.hyperlatticesuppliesScalar<B>values for vector and matrix code and forwards backend-neutral scalar facts tohyperlimit.hyperlimitowns predicate policy, escalation order, fallback selection, and result provenance.
hyperlimit does not own scalar expression internals or linear algebra types.
Version 0.1.3 is an early, documented predicate crate with a small public API.
It is not a mesh, polygon, BSP, CSG, or intersection library.
Implemented:
Point2<S>andPoint3<S>orient2d,orient3dincircle2d,insphere3dclassify_point_linePlane3,classify_point_plane,classify_point_oriented_plane- batch APIs, with optional Rayon parallel variants
PredicateOutcome<T>with certainty and deciding stagePredicatePolicyfor strict, filtered, refined, robust, and approximate behavior- scalar traits for structural facts, finite
f64filters, borrowed arithmetic, and bounded sign refinement - optional adapters for
hyperreal,hyperlattice,inari,robust, andgeogram_predicates
Strict policies do not return approximate topology. Approximate signs are available only when the policy explicitly allows them.
[dependencies]
hyperlimit = "0.1.3"From sibling checkouts:
[dependencies]
hyperlimit = { path = "../hyperlimit" }Enable only the backends you need:
[dependencies]
hyperlimit = {
version = "0.1.3",
features = ["hyperreal", "robust"]
}use hyperlimit::{Point2, Sign, orient2d};
let a = Point2::new(0.0_f64, 0.0);
let b = Point2::new(1.0_f64, 0.0);
let c = Point2::new(0.0_f64, 1.0);
let outcome = orient2d(&a, &b, &c);
assert_eq!(outcome.value(), Some(Sign::Positive));Line-side classification maps orientation signs into geometry names:
use hyperlimit::{LineSide, Point2, classify_point_line};
let from = Point2::new(0.0_f64, 0.0);
let to = Point2::new(1.0_f64, 0.0);
let point = Point2::new(0.0_f64, 1.0);
assert_eq!(
classify_point_line(&from, &to, &point).value(),
Some(LineSide::Left)
);Plane classification works with explicit plane equations:
use hyperlimit::{Plane3, PlaneSide, Point3, classify_point_plane};
let plane = Plane3::new(Point3::new(0.0_f64, 0.0, 1.0), -2.0);
let point = Point3::new(0.0_f64, 0.0, 3.0);
assert_eq!(
classify_point_plane(&point, &plane).value(),
Some(PlaneSide::Above)
);Predicates return PredicateOutcome<T>:
use hyperlimit::{Point2, PredicateOutcome, orient2d};
let a = Point2::new(0.0_f64, 0.0);
let b = Point2::new(1.0_f64, 0.0);
let c = Point2::new(0.0_f64, 1.0);
match orient2d(&a, &b, &c) {
PredicateOutcome::Decided { value, certainty, stage } => {
println!("{value:?} from {certainty:?} at {stage:?}");
}
PredicateOutcome::Unknown { needed, stage } => {
println!("unknown at {stage:?}; needs {needed:?}");
}
}Certainty values:
ExactFilteredRobustFloatApproximate
Stages:
StructuralFilterExactRefinedRobustFallbackUndecided
The shared sign resolver attempts:
- scalar structural sign
- determinant term filters and conservative numeric filters
- exact scalar or exact predicate hooks
- bounded scalar sign refinement
- robust backend fallback
- approximate sign, only when policy allows it
Unknown
The same escalation path as a flow:
flowchart TD
Predicate["Predicate call\norient, incircle, plane side"] --> Structural["Structural scalar facts\nsign, zero, nonzero, bounds"]
Structural -->|decided| ExactOutcome["PredicateOutcome\nExact"]
Structural -->|unknown| Filter["Determinant filters\nand conservative envelopes"]
Filter -->|decided| FilteredOutcome["PredicateOutcome\nFiltered"]
Filter -->|uncertain| ExactHook["Exact scalar or\nexact predicate hook"]
ExactHook -->|decided| ExactOutcome
ExactHook -->|unavailable or unknown| Refine["Bounded sign refinement"]
Refine -->|decided| RefinedOutcome["PredicateOutcome\nExact or Refined"]
Refine -->|still unknown| Robust["Robust backend fallback\nrobust or geogram"]
Robust -->|decided| RobustOutcome["PredicateOutcome\nRobustFloat"]
Robust -->|unavailable or disagrees| ApproxGate{"Policy allows\napproximate topology?"}
ApproxGate -->|yes| Approx["Approximate sign"]
Approx --> ApproxOutcome["PredicateOutcome\nApproximate"]
ApproxGate -->|no| Unknown["PredicateOutcome::Unknown"]
Use policy-specific functions when the default strict behavior is not desired:
use hyperlimit::{Point2, PredicatePolicy, orient::orient2d_with_policy};
let a = Point2::new(0.0_f64, 0.0);
let b = Point2::new(1.0_f64, 1.0);
let c = Point2::new(2.0_f64, 2.0);
let outcome = orient2d_with_policy(&a, &b, &c, PredicatePolicy::APPROXIMATE);
println!("{outcome:?}");StructuralScalar can expose:
- known sign
- exact zero status
- provable nonzero status
- exact/rational state
- magnitude bounds
- bounded sign refinement
PredicateScalar adds arithmetic and finite f64 conversion for filters and
fallbacks. BorrowedPredicateScalar adds borrowed add_ref, sub_ref, and
mul_ref operations so richer scalar backends avoid cloning every determinant
term.
Primitive f32 and f64 implement the scalar traits without optional features.
| Feature | Purpose |
|---|---|
std |
Default feature. No special public API is attached to it currently. |
parallel |
Rayon-backed batch predicate variants. |
hyperreal |
Implements predicate scalar traits for hyperreal::Real. |
hyperlattice |
Implements predicate scalar traits for hyperlattice::Scalar<B>. |
interval |
Implements predicate scalar traits for inari::Interval. |
robust |
Robust fallback through the robust crate for finite f64-convertible inputs. |
geogram |
Robust fallback through the Rust-port geogram_predicates branch. |
Interval values expose finite f64 fallback only for singleton finite
intervals. This avoids treating interval midpoints as exact geometry.
inari 2 requires Haswell-class SIMD on x86-64:
RUSTFLAGS='-Ctarget-cpu=haswell' cargo test --features intervalWhen both geogram and robust are enabled, fallback dispatch prefers Geogram.
For Geogram in-circle and in-sphere fallback, both symbolic-perturbation
polarities are checked and disagreement is reported as zero.
scalar: scalar traits and fact typespredicate: outcome, certainty, policy, and sign typesfilter: conservative determinant filtersresolve: shared internal sign-resolution pipelineorient: points and orientation/circle/sphere predicatesplane: explicit and oriented plane classificationclassify: line and plane side enumsbatch: sequential and optional parallel batch APIsbackend: optional backend adapterserror: crate-local error/result types
Common public types and functions are re-exported from the crate root.
Run checks:
cargo test
cargo test --no-default-features
cargo test --features robust
cargo test --features hyperreal
cargo test --features hyperlatticeRun the broad feature set:
cargo test --features geogram,robust,hyperreal,hyperlattice,parallel
RUSTFLAGS='-Ctarget-cpu=haswell' cargo test --features geogram,robust,hyperreal,hyperlattice,interval,parallelRun benchmarks:
cargo bench --bench predicatesThe generated benchmark summary is in benchmarks.md.
Run dispatch tracing separately:
cargo bench --bench predicates --features dispatch-trace,hyperlattice -- --write-dispatch-trace-mdThe generated trace summary is in dispatch_trace.md.
Render predicate demo plots:
cargo run --example predicate_plots -- --out doc/predicate-plots --size 512See plots.md for the plot gallery.
MIT OR Apache-2.0.
