hyperreal 0.10.1

Exact rational and computable real arithmetic in Rust
Documentation
# Hyperreal

Hyperreal is a Rust library for exact rational arithmetic and computable real arithmetic. It started from Hans Boehm's "Towards an API for the Real Numbers" model and has since grown into a more performance-focused Rust implementation with symbolic tracking, exact shortcuts, structural inspection APIs, borrowed arithmetic support, and a benchmark suite for the hot numerical paths.

## What it provides

- `Rational`
  - arbitrary-precision rational values
  - exact arithmetic
  - conversions to and from integers and IEEE-754 floats
- `Computable`
  - lazy real-number evaluation to requested precision
  - transcendental functions such as `exp`, `ln`, `sqrt`, `sin`, `cos`, and `tan`
  - caching, structural simplification, and targeted argument reduction
  - conservative structural facts through `structural_facts`
  - bounded sign refinement through `sign_until`
- `Real`
  - a higher-level real type that combines exact rational structure with computable irrational parts
  - symbolic handling for common classes such as square roots, logarithms, exponentials, and rational multiples of `pi`
  - public exact-rational access through `exact_rational`
  - conservative sign, zero, exactness, and magnitude facts through `structural_facts`
  - borrowed finite `f64` approximation through `to_f64_approx`
- Structural fact types
  - `RealSign`
  - `ZeroKnowledge`
  - `MagnitudeBits`
  - `RealStructuralFacts`
- `Simple`
  - a small Lisp-like expression parser and evaluator for interactive use
  - enabled by the default `simple` Cargo feature

## Current state

The project is no longer just a straight Java port. The current codebase includes:

- direct and benchmarked transcendental fast paths
- exact and symbolic trig/log shortcuts
- borrowed `Rational` and `Real` arithmetic APIs
- public structural inspection for robust downstream filtering and predicates
- bounded sign refinement that stops at the requested precision floor
- owned exact-rational access that does not expose internal representation
- Criterion benchmark suites for:
  - library-level behavior
  - numerical kernels
  - borrowed-vs-owned arithmetic
  - float conversion
- internal separation between public exact facts and planner-only evaluator facts

The evaluator refactor plan lives in [`evaluator-refactor.md`](./evaluator-refactor.md).

## Installation

```toml
[dependencies]
hyperreal = "0.10.1"
```

To build only the numeric library without the `Simple` expression parser:

```toml
[dependencies]
hyperreal = { version = "0.10.1", default-features = false }
```

Cargo features:

- `simple` (default): builds and exports `Simple` and the package calculator binary.

## Examples

### Exact rationals

```rust
use hyperreal::Rational;

let a = Rational::fraction(7, 8).unwrap();
let b = Rational::fraction(9, 10).unwrap();
let c = a + b;

assert_eq!(c, Rational::fraction(79, 40).unwrap());
```

### Real arithmetic

```rust
use hyperreal::{Rational, Real};

let x = Real::new(Rational::new(2)).sqrt().unwrap();
let y = Real::new(Rational::new(3)).sqrt().unwrap();
let z = x * y;

let approx: f64 = z.into();
assert!(approx > 2.44 && approx < 2.45);
```

### Computable values

```rust
use hyperreal::{Computable, Rational};

let x = Computable::rational(Rational::fraction(7, 5).unwrap()).sin();
let approx = x.approx(-40);

assert_ne!(approx, 0.into());
```

### Structural inspection

```rust
use hyperreal::{Rational, Real, RealSign, ZeroKnowledge};

let value = Real::new(Rational::new(2)).sqrt().unwrap();
let facts = value.structural_facts();

assert_eq!(facts.sign, Some(RealSign::Positive));
assert_eq!(facts.zero, ZeroKnowledge::NonZero);
assert!(!facts.exact_rational);

let sign = value.refine_sign_until(-64);
assert_eq!(sign, Some(RealSign::Positive));
```

Structural facts are conservative. A missing sign or magnitude means the value was not proven by cheap structural inspection; it does not imply the fact is false. Bounded sign refinement may populate approximation caches, but it terminates at or before the requested precision floor.

### Simple expressions

```rust
use hyperreal::Simple;

let expr: Simple = "(* (+ pi pi) (sin (/ 1 5)))".parse().unwrap();
let value = expr.evaluate(&Default::default()).unwrap();

let _: f64 = value.into();
```

## Simple expression language

`Simple` is enabled by the default `simple` feature and uses a Lisp-like syntax:

- arithmetic: `+`, `-`, `*`, `/`
- roots and powers: `sqrt`, `pow`, `^`
- logs and exponentials: `ln`, `log10`, `exp`, `e`
- trig: `sin`, `cos`, `tan`, `asin`, `acos`, `atan`
- inverse hyperbolic: `asinh`, `acosh`, `atanh`

Examples:

```text
(+ 1 2 3 4)
(* (+ pi pi) (sin (/ 1 5)))
(pow (+ 3/2 4/7) 9/2)
(sqrt 9)
```

Numeric literals may be:

- integers: `42`
- decimals: `2.75`
- fractions: `11/7`

Built-in names include `pi` and `e`.

## Conversions

Hyperreal supports Rust conversion traits where they make sense:

- integer types -> `Rational` / `Real`
- `f32` / `f64` -> `Rational` / `Real` via exact IEEE-754 decoding
- `Real` -> `f32` / `f64` via nearest representable floating-point value
- `Real::to_f64_approx()` for a borrowed, finite-only approximation useful for filtering

Float conversions from IEEE-754 values are fallible on `NaN` and infinities. `Real::to_f64_approx()` returns `None` when no finite `f64` approximation can be produced, including overflow to infinity; values too small for `f64` may underflow to `Some(0.0)`.

## Serialization

The crate includes `serde` support. `Computable` serializes its expression structure, but not transient runtime state such as approximation caches or abort signals.

## Performance

Performance is now an explicit project goal.

Current work in the tree includes:

- specialized transcendental kernels
- faster large-argument reduction for trig and `exp`
- exact rational and symbolic shortcuts
- structural fact and bounded sign-refinement shortcuts
- borrowed arithmetic improvements
- benchmark-guided evaluator refactoring

Benchmark targets:

- `cargo bench --bench library_perf`
- `cargo bench --bench numerical_micro`
- `cargo bench --bench borrowed_ops`
- `cargo bench --bench float_convert`

## Notes

- Some computations are intentionally lazy and may run for a long time if you request difficult values at high precision.
- `Real::abort` can be used to attach an external stop signal to long-running evaluation.
- Public structural APIs expose conservative numeric facts without exposing private evaluator internals.
- Planner-only evaluator facts remain private; downstream crates should use `structural_facts`, `exact_rational`, `refine_sign_until`, and `sign_until`.