Real is the public symbolic scalar. It combines an exact rational scale, a
compact symbolic class, an optional lazy computable certificate, and a lock-free
primitive-approximation cache. An optional abort signal lives on the computable
payload so it is not represented twice.
+-----------------------------------------------------------------------+
| Real |
| |
| rational: Rational |
| + exact signed scale |
| + zero is represented here |
| + multiplies every nonzero symbolic/computable class |
| |
| class: Class |
| + One exact rational only |
| + Pi, PiPow, PiInv pi-family certificates |
| + Exp, PiExp, ConstProduct e/pi product certificates |
| + Sqrt, PiSqrt, ...Sqrt factored square-root certificates |
| + Ln, LnAffine, LnProduct logarithm certificates |
| + Log10 base-10 logarithm certificate |
| + SinPi, TanPi rational trig certificates |
| + Irrational opaque computable value |
| |
| computable: Option<Computable> |
| + lazy approximation graph |
| + shared constants and cached approximations live inside Computable |
| + absent only when the rational/class certificate is sufficient |
| + optional abort hook lives on the Computable payload |
| + attaching one materializes that payload when it was absent |
+-----------------------------------------------------------------------+
The Class value is a certificate, not the entire number. The mathematical
value is rational * class_value, with Computable available when numeric
approximation is required.
mod.rs: public export and semantic module split.arithmetic.rs: representation, symbolic classes, constructors, simplification, arithmetic, elementary functions, display, and most tests.constructors.rs: public constructor grouping.facts.rs: structural fact API grouping.approximation.rs: approximation-facing API grouping.linear_combination.rs: exact linear combination and product-sum helpers.convert.rs: primitive and rational conversions.tests.rs: semantic and regression tests.
Most implementation still lives in arithmetic.rs because private fields and
hot simplification paths are tightly coupled. Avoid moving code just for file
shape unless benchmarks show no cost.
Real::new(Rational)creates exact rational values.- named constants such as
pi,e, andtauuse cached/shared construction. - arithmetic preserves recognizable symbolic structure where benchmarks justify it.
- fallible methods return
Problemfor known domain errors. ln_1p/log1p,ln_1m/log1m, andexpm1preserve small-residual intent instead of forcing users to spellln(1+x),ln(1-x), orexp(x)-1as cancellation-prone generic arithmetic;softplus,logaddexp,logsubexp,logit, andsigmoidare stable public compositions built on those primitives.sin_pi,cos_pi, andtan_piexpose rational-turn trig directly; exact rational inputs reuse the sameSinPi/TanPicertificates and exact small-denominator tables that ordinary trig reaches throughpiproducts.sinc,sinc_pi, andcoscpreserve removable small-angle limits at zero instead of requiring users to spell them as division-heavy generic arithmetic.sqrt1pm1,sqrt1m1, andhypot_minuspreserve common square-root cancellation patterns used by offsets, normalized vectors, and curvature calculations.mul_add,sum_products, anddiff_of_productsexpose common product-sum forms directly, reusing exact-rational product reducers and omitting known-zero product lanes.eval_polyandeval_rational_polypreserve Horner and rational-polynomial evaluation structure instead of requiring callers to expand polynomial arithmetic by hand. Bernstein and de Casteljau operations carry curve-basis semantics and live in higher geometry crates.hypot2andhypot3reuse the exact dot-product reducers before square roots, so rational lengths such as 3-4-5 stay exact and symbolic zero axes reduce throughabs.cbrt,root_n, andpow_rationalpreserve exact rational perfect roots; non-perfect positive roots fall back to rational-exponent computable forms, and negative odd roots are handled by symmetry.floor_certified,ceil_certified,round_certified,trunc_certified,fract_certified, andrem_euclid_certifiedexpose discontinuous integer decisions only when exact rational shortcuts or bounded exact-real comparison can certify the relevant boundary.erf,erfc,erfcx,dnorm,pnorm,normal_sf,pnorm_upper,normal_interval,pnorm_diff,log_pnorm,log_normal_sf,log_dnorm,erfinv,erfcinv,qnorm, andqnorm_upperexpose computable Gaussian helpers;dnorm/pnorm/normal_sf, log tails, and interval bounds are bounded to finite inputs withabs(x) <= 10, normal intervals requirelo <= hi,log_dnormuses the analytic-x^2/2 - ln(2*pi)/2form,erfinv/erfcinvuse open domains, and quantiles are bounded to probabilities strictly betweenpnorm(-10)andpnorm(10).- parametric normal helpers (
normal_pdf,normal_cdf,normal_survival,normal_quantile) requiresigma > 0, standardize exactly before entering the standard-normal helper, and inherit the same standard-normal resource windows. - Mills and hazard helpers use the standard upper-tail convention for
normal_mills = normal_sf / dnormandnormal_hazard = dnorm / normal_sf;normal_millsis built through the stablesqrt(pi/2) * erfcx(x/sqrt(2))identity, whilenormal_inverse_millsis the lower-taildnorm / pnormconvention and inherits the normal CDF window. hermite_probabilists,dnorm_derivative, andgaussian_derivativekeep the probabilists' Hermite polynomial recurrence exact; only the shared normal density factor enters the computable approximation layer.standard_normal_momentuses exact double-factorial closed forms, whilenormal_interval_moment,truncated_normal_mean, andtruncated_normal_variancereusenormal_intervalplus boundary density recurrence terms.gamma,lgamma,beta,ln_beta/lbeta,regularized_beta, andregularized_beta_qprovide exact integer/half-integer gamma and finite positive-integer beta forms for scientific scalar workloads without moving root-solving policy into the scalar layer.regularized_gamma_pandregularized_gamma_qsupport exact positive integer and half-integer shape parameters withx >= 0, using finite recurrences over existingerf/erfc,exp,sqrt, and exact factorial coefficients;chi_square_cdfandchi_square_sfwrap those forms asP(k/2, x/2)andQ(k/2, x/2)for positive integer degrees of freedom.- benchmark coverage for these public helpers lives in
library_perfunder stable scalar, geometry/polynomial, normal/scientific, andSimplesurface groups; adversarial and dispatch-trace rows cover tiny residuals, domain boundaries, normal tails, finite gamma/beta recurrences, and exact product/polynomial shapes. - structural queries return conservative facts and should not force expensive approximation when representation facts are enough.
- borrowed arithmetic should avoid unnecessary expression cloning.
- conversion to primitive floats approximates; conversion from finite primitive floats is exact.
Real should prefer this order:
- answer from exact rational structure
- answer from symbolic class facts
- simplify symbolically into a smaller exact/certified form
- construct or reuse a
Computable - approximate only at requested precision
This is why many methods contain special cases for exact rationals, dyadics, pi/e products, square roots, logarithms, and rational trig endpoints.
Real delays expansion by keeping scale, symbolic class, and computable
fallback separate:
- exact rational and dyadic values stay accessible for reducers and primitive conversions
- symbolic constants and factored forms are preserved so later operations can cancel, classify, or answer sign/domain questions structurally
- endpoint, identity, inverse, and small-argument rewrites shrink expressions before a generic computable graph is built
- borrowed arithmetic should reuse existing structure rather than cloning graph nodes solely to ask scalar questions
- bounded sign and magnitude refinement is used only when retained facts cannot decide a branch
Errors are semantic domain failures, not "could not prove cheaply" failures. For example, a known-negative square root fails. A value whose sign is not cheaply known may move to a computable path or bounded refinement path instead of immediately failing, depending on the method.
Performance-sensitive code should document why a non-obvious representation is kept. Typical reasons:
- preserving exact rational access for matrix/vector kernels
- keeping
pi,e, andsqrtfactors separate so later operations cancel them before approximation - using cached computable constants rather than rebuilding kernels
- avoiding generic computable graphs for exact endpoints
- keeping direct expression shapes when Criterion shows they inline better