hyperreal 0.11.0

Exact rational and computable real arithmetic in Rust
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
<h1>
  hyperreal
  <img src="./doc/hyper.png" alt="Hyper, a clever math thief" width="144" align="right">
</h1>

`hyperreal` provides exact rational arithmetic, symbolic real values, and lazy
computable real approximation.

It is useful when code needs more information than an `f64` can provide:
structural sign facts, exact zero/nonzero knowledge, exact rational access,
bounded sign refinement, and recognizable forms such as `pi`, `e`, square
roots, logarithms, and rational trig constants.

## Numeric Model

`hyperreal` is built around three layers that deliberately keep exact and
symbolic information available before approximation:

- [`Rational`]src/rational/README.md: is the exact arithmetic base. It stores arbitrary-precision
  numerator/denominator values and performs exact reduction, dyadic detection,
  square extraction, shared-denominator dot products, and exact IEEE-754 import.
- [`Computable`]src/computable/README.md: is the lazy approximation layer. It represents exact-real
  expression graphs such as sums, products, inverses, roots, logs, trig kernels,
  and shared constants. It approximates only when a caller asks for a binary
  precision, then caches the result and conservative sign/magnitude facts.
- [`Real`]src/real/README.md: is the public symbolic scalar. It stores an exact rational scale plus a
  compact symbolic class and, when needed, a `Computable` certificate. Common
  classes include exact one, powers/products of `pi` and `e`, selected square
  roots, logarithms, trig forms, and factored constant products.
- `RealStructuralFacts`: conservative public facts about sign, zero status,
  magnitude, and exact-rational state.
- `Simple`: a small Lisp-like expression parser, enabled by the optional
  `simple` feature.

## Relationship to Other Crates

- `realistic_blas` uses `hyperreal::Real` as its default exact/symbolic scalar
  backend. It forwards `hyperreal` structural facts through its `Scalar` type
  and adds vector, matrix, transform, and retained-geometry facts around them.
- `liminal` can consume `hyperreal::Real` directly, using structural facts,
  finite `f64` approximations, and bounded sign refinement before robust
  fallback.
- `hypersolve` is the experimental solver layer. Its current direction is to
  evaluate constraints through symbolic references to variables, reuse
  reductions across iterations, and route repeated residual and geometry
  kernels through `hyperreal` and `realistic_blas` instead of rebuilding scalar
  expressions from scratch.

`hyperreal` owns scalar representation and approximation. It does not own vector
or matrix algebra, and it does not decide geometry topology. The stack is
layered intentionally: scalar facts live here, object-level facts live in
`realistic_blas`/geometry layers, and decision procedures live above them.

## Problems This Stack Targets

`hyperreal` and the surrounding stack are aimed at problems where ordinary
floating-point arithmetic is fast but loses too much information too early.
The target workloads tend to have many cheap structural decisions, a smaller
number of expensive exact or high-precision decisions, and repeated kernels
where cached structure can be reused.

Representative problem families include:

- robust geometric predicates such as orientation, sidedness, intersection, and
  clearance tests
- CAD-style geometric constraint solving, where many residuals share variables,
  transforms, and symbolic subexpressions
- PCB routing and autorouting constraints, where exact topology and clearance
  decisions matter before approximate coordinates are useful
- toolpath planning and manufacturing geometry, where small sign or ordering
  errors can change topology
- matrix/vector transform stacks with many affine, diagonal, triangular,
  homogeneous, point, or direction-specialized cases
- exact-rational or symbolic scalar workloads that should remain exact until a
  caller explicitly asks for digits

The implementation strategy is intentionally thin:

- Preserve exact rational, dyadic, symbolic, sign, zero, magnitude, and
  approximation-cache facts at the scalar layer.
- Carry inexpensive object facts at higher layers, such as known point/direction
  `w`, affine form, diagonal or triangular matrix structure, retained transform
  facts, shared determinant/cofactor work, and known coordinate zeros.
- Reduce symbolically before approximating. Common forms such as exact
  rationals, `pi`, `e`, roots, logarithms, and selected trig constants should
  simplify or classify without entering a generic approximation kernel.
- Defer approximation until a decision or output precision requires it, then
  cache the result and any conservative sign or magnitude information.
- Prefer deterministic fast paths guarded by cheap facts over speculative
  probing inside dense loops.
- Keep similar functions flat: a fast path should improve the family it targets
  without making neighboring functions erratic.

## Current State

The crate is active, benchmark-driven, and no longer just a direct port of
computable real ideas. Current implementation work includes:

- exact rational and dyadic fast paths
- dedicated identity constructors for common exact ones and zeros
- cached internal constants for `pi`, `tau`, `e`, common square roots, and
  common logarithms
- symbolic classes for selected `pi`, `e`, `sqrt`, `ln`, `sin(pi*q)`, and
  `tan(pi*q)` forms
- exact trig, inverse-trig, logarithm, exponential, and inverse-hyperbolic
  shortcuts where the input structure is recognizable
- argument reduction and prescaled kernels for transcendental approximation
- structural sign, zero, nonzero, magnitude, and exact-rational queries
- bounded sign refinement through `sign_until` and `refine_sign_until`
- cached approximation and structural-fact propagation through computable nodes
- borrowed arithmetic paths for `Rational` and `Real`
- shared-denominator and signed-product-sum hooks used by matrix/vector callers
  to delay rational canonicalization
- `serde` support for expression structure, excluding transient caches and abort
  signals
- dispatch tracing and targeted benchmark suites for scalar, approximation,
  symbolic, adversarial, and stack-facing regressions
- source-level READMEs for `Rational`, `Real`, and `Computable`, plus
  `structural_facts.txt` for planned and implemented fact propagation

## Installation

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

With the `Simple` parser and calculator binary:

```toml
[dependencies]
hyperreal = { version = "0.10.6", features = ["simple"] }
```

Feature flags:

| Feature | Default | Purpose |
| --- | --- | --- |
| `simple` | no | Enables `Simple` and the package calculator binary. |

## Examples

### Exact Rationals

`Rational` is the exact base layer. It is useful for imported measurements,
test fixtures, small coefficients, and any value that should not become binary
floating-point noise before the rest of the stack sees it.

```rust
use hyperreal::Rational;
use std::convert::TryFrom;

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

assert_eq!(a + b, Rational::fraction(79, 40).unwrap());

// Finite floats import by exact IEEE-754 decoding, not by decimal rounding.
let half = Rational::try_from(0.5_f64).unwrap();
assert_eq!(half, Rational::fraction(1, 2).unwrap());

// Decimal and fraction strings parse into exact rationals.
let decimal: Rational = "12.125".parse().unwrap();
let fraction: Rational = "97/8".parse().unwrap();
assert_eq!(decimal, fraction);
```

### Symbolic Reals

`Real` keeps a rational scale plus a symbolic/computable class. That lets common
forms simplify or expose facts before approximation is needed.

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

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

let half = Real::new(Rational::fraction(1, 2).unwrap());
let angle = half * Real::pi();
let cosine = angle.cos().unwrap();

// Recognizable symbolic/trig forms can answer facts without a full equality
// proof or high-precision decimal expansion.
let facts = cosine.structural_facts();
assert_eq!(facts.zero, ZeroKnowledge::Zero);
assert_eq!(cosine.refine_sign_until(-32), Some(RealSign::Zero));
```

### Computable Approximation

`Computable` is the lazy approximation layer. It stores an expression graph and
only computes a scaled integer approximation when a precision is requested.

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

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

assert_ne!(scaled, 0.into());

// Sign refinement asks for only enough precision to decide the sign down to a
// requested floor. The result may be `None` for unresolved or truly difficult
// cases, so callers can decide whether to refine further or use a fallback.
let near_pi = Computable::pi().add(Computable::rational(
    Rational::fraction(-22, 7).unwrap(),
));
assert_eq!(near_pi.sign_until(-8), Some(RealSign::Positive));
```

### Structural Facts

Structural facts are conservative certificates. They are designed for filters,
predicates, and higher-level kernels that want to avoid approximation unless a
decision actually requires it.

```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);
assert_eq!(value.refine_sign_until(-64), Some(RealSign::Positive));

let exact = Real::new(Rational::fraction(9, 18).unwrap());
let exact_facts = exact.structural_facts();

assert_eq!(exact.exact_rational(), Some(Rational::fraction(1, 2).unwrap()));
assert_eq!(exact_facts.sign, Some(RealSign::Positive));
assert_eq!(exact_facts.zero, ZeroKnowledge::NonZero);
assert!(exact_facts.exact_rational);
```

Facts are conservative. Missing sign or magnitude information means the fact
was not proven cheaply.

### Stack-Facing Filters

The surrounding geometry stack uses `hyperreal` values as scalar certificates:
try cheap structural facts first, use finite approximation when that is enough,
and only then request bounded refinement.

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

fn classify_positive(value: &Real) -> Option<bool> {
    if let Some(sign) = value.structural_facts().sign {
        return Some(sign == RealSign::Positive);
    }

    if let Some(approx) = value.to_f64_approx() {
        if approx > 1e-12 {
            return Some(true);
        }
        if approx < -1e-12 {
            return Some(false);
        }
    }

    value
        .refine_sign_until(-80)
        .map(|sign| sign == RealSign::Positive)
}

let offset = Real::pi() - Real::new(Rational::fraction(22, 7).unwrap());
assert_eq!(classify_positive(&offset), Some(true));
```

This pattern is the intended handoff to `realistic_blas` and `liminal`: cheap
facts route the common case, approximation is delayed until useful, and bounded
refinement remains available for hard predicate boundaries.

### Simple Expressions

Requires the `simple` feature.

```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` supports arithmetic, roots, powers, logs, exponentials, trig, inverse
trig, inverse hyperbolic functions, integers, decimals, fractions, `pi`, and
`e`.

It can also be useful for small configuration- or test-facing formulas:

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

let expr: Simple = "(sqrt (/ 49 64))".parse().unwrap();
let value = expr.evaluate(&Default::default()).unwrap();

assert_eq!(value.exact_rational(), Some(Rational::fraction(7, 8).unwrap()));
```

## Conversions

Supported conversions include:

- integer types to `Rational` and `Real`
- finite `f32`/`f64` to `Rational` and `Real` by exact IEEE-754 decoding
- `Real` to `f32`/`f64` by approximation
- `Real::to_f64_approx()` for borrowed finite approximation used by filters

Float import rejects `NaN` and infinities. `to_f64_approx()` returns `None`
when no finite `f64` approximation can be produced.

Finite decimal and fraction strings parse losslessly through `Rational`; the
parser also accepts leading `+` signs and digit separators where the rational
parser supports them. Scientific notation is not a supported exact text format.
`-0.0` imports as exact rational zero, so IEEE signed-zero information is not
preserved.

`PartialEq` on `Real` is structural, not a full computer-algebra equality
proof. Two expressions may print/debug similarly and approximate identically
while still comparing unequal if they were built through different computable
expression histories. Use structural facts, exact-rational extraction, or
explicit approximation/refinement when semantic equivalence rather than
representation identity is the question.

## Performance Notes

Performance shortcuts are intentionally documented next to the code that uses
them. The main techniques are:

- keep exact rational and dyadic values outside generic computable graphs
- build identity values through dedicated constructors and clone cached named
  constants instead of rebuilding them
- preserve lightweight symbolic classes only where benchmarks show value
- reduce trig and exponential arguments before entering series kernels
- use endpoint and tiny-argument transforms for inverse trig and inverse
  hyperbolic functions
- answer structural queries from certificates before refining approximations
- use borrowed arithmetic to reduce expression-graph cloning in callers such as
  `realistic_blas` and `liminal`

Benchmark suites:

```sh
cargo bench --bench library_perf
cargo bench --bench numerical_micro
cargo bench --bench borrowed_ops
cargo bench --bench float_convert
cargo bench --bench scalar_micro
cargo bench --bench adversarial_transcendentals
```

The generated benchmark summary is in [`benchmarks.md`](./benchmarks.md).
Hand-maintained profiling anchors and regression goals for the `Rational`,
`Real`, and `Computable` paths are in [`PERFORMANCE.md`](./PERFORMANCE.md).

Run dispatch tracing separately:

```sh
cargo bench --bench dispatch_trace --features dispatch-trace
```

The generated trace summary is in [`dispatch_trace.md`](./dispatch_trace.md).

## Development

Common checks:

```sh
cargo fmt --check
cargo test
cargo bench --bench numerical_micro
```

When adding a shortcut, add a focused correctness test and a benchmark row for
the smallest affected surface. Keep the shortcut only if it improves the target
without regressing broader `realistic_blas` or `liminal` benchmarks.

## Provenance and Acknowledgements

`hyperreal` descends from the
[`realistic`](https://github.com/tialaramex/realistic/) project and continues
that project's interest in practical computable real arithmetic.

Special thanks to [siefkenj](https://github.com/siefkenj), whose contributions
improved realistic and hyperreal.

## References

These are the papers and books which contribute ideas or methods to this crate.
They are listed here in MLA style for easy citation.

- Bareiss, Erwin H. "[Sylvester's Identity and Multistep Integer-Preserving
  Gaussian Elimination](https://www.ams.org/mcom/1968-22-103/S0025-5718-1968-0226829-0/)."
  *Mathematics of Computation*, vol. 22, no. 103, 1968, pp. 565-578.
  American Mathematical Society, https://doi.org/10.1090/S0025-5718-1968-0226829-0.
- Boehm, Hans-Juergen, Robert Cartwright, Mark Riggle, and Michael J.
  O'Donnell. "[Exact Real Arithmetic: A Case Study in Higher Order
  Programming](https://doi.org/10.1145/319838.319860)." *Proceedings of the
  1986 ACM Conference on LISP and Functional Programming*, ACM, 1986,
  pp. 162-173.
- Boehm, Hans-J. "[Towards an API for the Real
  Numbers](https://doi.org/10.1145/3385412.3386037)." *Proceedings of the
  41st ACM SIGPLAN International Conference on Programming Language Design and
  Implementation*, ACM, 2020, pp. 562-576.
- Brent, Richard P. "[Fast Multiple-Precision Evaluation of Elementary
  Functions](https://doi.org/10.1145/321941.321944)." *Journal of the ACM*,
  vol. 23, no. 2, 1976, pp. 242-251.
- Brent, Richard P., and Paul Zimmermann.
  "[Modern Computer Arithmetic]https://doi.org/10.1017/CBO9780511921698."
  Cambridge University Press, 2010.
- Middeke, Johannes, David J. Jeffrey, and Christoph Koutschan.
  "[Common Factors in Fraction-Free Matrix
  Decompositions](https://doi.org/10.1007/s11786-020-00495-9)."
  *Mathematics in Computer Science*, vol. 15, 2021, pp. 589-608.
- Payne, Mary H., and Robert N. Hanek.
  "[Radian Reduction for Trigonometric
  Functions](https://doi.org/10.1145/1057600.1057602)." *ACM SIGNUM
  Newsletter*, vol. 18, no. 1, 1983, pp. 19-24.
- Shewchuk, Jonathan Richard. "[Adaptive Precision Floating-Point Arithmetic
  and Fast Robust Geometric
  Predicates](https://doi.org/10.1007/PL00009321)." *Discrete &
  Computational Geometry*, vol. 18, no. 3, 1997, pp. 305-363.
- Smith, Luke, and Joan Powell. "[An Alternative Method to Gauss-Jordan
  Elimination: Minimizing Fraction
  Arithmetic](https://doi.org/10.63301/tme.v20i2.1957)." *The Mathematics
  Educator*, vol. 20, no. 2, 2011, pp. 44-50.
- Yap, Chee-Keng. "[Towards Exact Geometric
  Computation](https://doi.org/10.1016/0925-7721(95)00040-2)." *Computational
  Geometry*, vol. 7, nos. 1-2, 1997, pp. 3-23.

## License

(C) https://github.com/timschmidt Apache-2.0 / MIT

(C) https://github.com/tialaramex/realistic/ Apache-2.0

(C) https://github.com/siefkenj Apache-2.0