This directory contains the implementation behind the public scalar API. The main design rule is to preserve exact or symbolic structure for as long as it is cheap and useful, approximate only when a caller asks for numeric precision, and cache approximations/facts that are expensive to rediscover.
lib.rs: public exports and crate-level API surface.problem.rs: domain and arithmetic errors shared by public types.structural.rs: conservative public sign, zero, magnitude, and exactness facts.trace.rsanddispatch_trace: optional instrumentation used by targeted dispatch tracing.serde.rs: serialization for durable expression structure. Transient caches and abort signals are intentionally not serialized.simple.rs: optional expression parser and evaluator behind thesimplefeature.rational/: exact arbitrary-precision rational arithmetic. Seerational/README.md.real/: public symbolic scalar type layered over rational and computable values. Seereal/README.md.computable/: lazy exact-real expression graph and approximation kernels. Seecomputable/README.md.
- Exact rationals stay exact until an API explicitly asks for approximation or conversion to a primitive float.
- Symbolic constants and recognizable forms stay symbolic when doing so avoids precision loss or repeated approximation.
- Approximation is requested by binary precision. More negative precision means more bits after the binary point.
- Approximation may cache intermediate values. Cache hits must not change semantics, structural facts, or later higher-precision approximations.
- Structural facts are conservative. Unknown means "not cheaply proven", not false.
Realequality is structural, not a complete computer-algebra theorem prover.
The implementation should prevent growth at the earliest layer that has enough information:
Rationalkeeps signs separate, recognizes dyadic denominators, canonicalizes zeros, and gives reducers shared-denominator/product-sum paths so repeated GCD work is not forced into every term.Realkeeps exact rational parts and symbolic classes separate, preservingpi,e, roots, logarithms, recognized trig endpoints, and removable small-angle limits until they can simplify, cancel, or provide structural facts.- Product-sum helpers preserve determinant and predicate shapes long enough to reuse exact rational reducers and avoid building avoidable product/add trees.
- Fixed-size vector helpers reuse exact dot-product reducers before square roots so lengths and distances avoid avoidable rational bloat.
- nth-root helpers collapse exact rational perfect roots before falling back to rational-exponent computable forms.
Computableis the fallback for values that need refinement, not the default container for every expression. Kernels reduce arguments, use stable forms near cancellation points, and cache precision-indexed approximations without weakening later higher-precision requests.- Higher layers should pass retained facts into reducers instead of issuing scalar sign or approximation probes inside dense matrix/vector lanes.
Public fallible operations return Problem rather than panicking for ordinary
numeric domain failures:
- divide by zero
- square root of known-negative values
- zero-degree roots, even roots of known-negative values, and unsupported negative-base rational powers
- logarithm of non-positive values
ln_1p/log1pinputs withx <= -1ln_1m/log1minputs withx >= 1logsubexpinputs without a certifiablea > bsqrt1pm1inputs withx < -1, andsqrt1m1inputs withx > 1logitinputs outside0 < p < 1tan_piinputs at tangent poles- certified integer rounding or Euclidean-remainder boundaries that cannot be proved within the bounded exact-real refinement policy
rem_euclid_certifiedwith a non-positive modulus- inverse trig / inverse hyperbolic domain failures
- normal density/CDF inputs outside the supported finite approximation window
- normal upper-tail inputs outside the supported finite approximation window
- normal interval bounds outside the supported finite approximation window, or reversed interval bounds
- normal log-CDF and log-upper-tail inputs outside the supported finite approximation window
- inverse error-function inputs outside their open probability domains
- normal quantile inputs outside the supported probability window
- parametric normal forms with non-positive standard deviation, or whose standardized value/probability is outside the supported standard-normal window
- normal log-hazard and lower-tail inverse Mills inputs outside the supported finite approximation window
- Gaussian derivative forms with a non-integer or negative derivative order, or whose density input is outside the supported finite approximation window
- normal moment forms with a non-integer or negative order, reversed interval bounds, degenerate truncated intervals, or interval bounds outside the supported finite approximation window
- gamma and beta forms with unsupported non-integer/half-integer arguments, or gamma poles at non-positive integers
- regularized beta forms with non-positive or non-integer shape parameters, or
xoutside[0, 1] - regularized gamma forms with non-positive or non-integer/half-integer shape
parameters, or negative
x - chi-square forms with non-positive degrees of freedom or negative
x - invalid primitive float import such as
NaNor infinity
Internal expect calls are reserved for representation invariants that should
already have been proven by construction.
Performance work should follow the same priorities as the implementation:
- defer approximation as long as exact or symbolic structure can answer the question
- reduce symbolic or rational structure before constructing generic computable graphs
- reuse costly approximations and named constants
- avoid unnecessary allocation and cloning on borrowed arithmetic paths
- use inexpensive structural facts before falling back to approximation
- specialize only paths that have stable targeted benchmark evidence
Performance-driven choices should have adjacent comments, especially when the code shape is less direct than the mathematical formula. Existing comments cite papers where an algorithmic principle matters, for example fraction-free elimination and exact-real arithmetic.
Use dispatch tracing to explain a path and Criterion benchmarks to decide whether a change is worth keeping. Trace reductions without Criterion runtime improvements are not enough.
The current benchmark surface mirrors the newer scalar API in four places:
library_perf has focused Criterion groups for stable scalar helpers,
geometry/polynomial helpers, Gaussian/scientific helpers, and Simple parser
exposure; adversarial_library samples tiny residuals, domain edges, tails,
roots, recurrences, and product/polynomial shapes; dispatch_trace has matching
rows for the same groups; and benchmarks.md is regenerated by the benchmark
binaries with the current means and confidence intervals.
Rational: exact storage and arithmetic layer.Real: public symbolic scalar and structural fact layer.Computable: lazy expression graph and numeric approximation layer.