Skip to content

timschmidt/hyperlimit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

hyperlimit Hyper, a clever mathematician

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.

Relationship to Other Crates

  • hyperreal supplies exact/symbolic scalar facts and bounded sign refinement through hyperreal::Real.
  • hyperlattice supplies Scalar<B> values for vector and matrix code and forwards backend-neutral scalar facts to hyperlimit.
  • hyperlimit owns predicate policy, escalation order, fallback selection, and result provenance.

hyperlimit does not own scalar expression internals or linear algebra types.

Current State

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> and Point3<S>
  • orient2d, orient3d
  • incircle2d, insphere3d
  • classify_point_line
  • Plane3, classify_point_plane, classify_point_oriented_plane
  • batch APIs, with optional Rayon parallel variants
  • PredicateOutcome<T> with certainty and deciding stage
  • PredicatePolicy for strict, filtered, refined, robust, and approximate behavior
  • scalar traits for structural facts, finite f64 filters, borrowed arithmetic, and bounded sign refinement
  • optional adapters for hyperreal, hyperlattice, inari, robust, and geogram_predicates

Strict policies do not return approximate topology. Approximate signs are available only when the policy explicitly allows them.

Installation

[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"]
}

Quick Start

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)
);

Outcomes and Policy

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:

  • Exact
  • Filtered
  • RobustFloat
  • Approximate

Stages:

  • Structural
  • Filter
  • Exact
  • Refined
  • RobustFallback
  • Undecided

The shared sign resolver attempts:

  1. scalar structural sign
  2. determinant term filters and conservative numeric filters
  3. exact scalar or exact predicate hooks
  4. bounded scalar sign refinement
  5. robust backend fallback
  6. approximate sign, only when policy allows it
  7. 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"]
Loading

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:?}");

Scalar Model

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.

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 interval

When 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.

Module Map

  • scalar: scalar traits and fact types
  • predicate: outcome, certainty, policy, and sign types
  • filter: conservative determinant filters
  • resolve: shared internal sign-resolution pipeline
  • orient: points and orientation/circle/sphere predicates
  • plane: explicit and oriented plane classification
  • classify: line and plane side enums
  • batch: sequential and optional parallel batch APIs
  • backend: optional backend adapters
  • error: crate-local error/result types

Common public types and functions are re-exported from the crate root.

Benchmarks and Development

Run checks:

cargo test
cargo test --no-default-features
cargo test --features robust
cargo test --features hyperreal
cargo test --features hyperlattice

Run the broad feature set:

cargo test --features geogram,robust,hyperreal,hyperlattice,parallel
RUSTFLAGS='-Ctarget-cpu=haswell' cargo test --features geogram,robust,hyperreal,hyperlattice,interval,parallel

Run benchmarks:

cargo bench --bench predicates

The generated benchmark summary is in benchmarks.md.

Run dispatch tracing separately:

cargo bench --bench predicates --features dispatch-trace,hyperlattice -- --write-dispatch-trace-md

The generated trace summary is in dispatch_trace.md.

Render predicate demo plots:

cargo run --example predicate_plots -- --out doc/predicate-plots --size 512

See plots.md for the plot gallery.

License

MIT OR Apache-2.0.

About

Robust geometry predicates with structural scalar awareness and decision tracing.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages