Skip to main content

logicaffeine_base/
tower.rs

1//! The exact real types in a program's value model: real algebraic numbers, computable reals, the
2//! program's infinitesimal and the hyperreals it generates, infinite integers, ordinals, and the
3//! values a supertask leaves.
4//!
5//! Each type lives in its own module of this crate; this module decides how they mix with the
6//! numeric tower and with each other, once, for every value model that holds them. A value model
7//! (the interpreter's runtime value, a compiled program's value) implements [`TowerValue`]: how to
8//! see one of its values as an exact type or a standard number, and how to build one. Everything
9//! here is generic over it, so every tier computes, compares and prints these values identically.
10//!
11//! - an integer, rational or float operand is lifted exactly (a float is the dyadic rational it
12//!   denotes, never a rounding of the other side) into the exact type it meets;
13//! - real algebraic numbers sit below computable reals; the hyperreals are generated by the
14//!   infinitesimal over the algebraic numbers, exactly as rational functions of `dt`; a value a flow
15//!   leaves, or a computable transcendental meeting the infinitesimal, is a germ — known by its
16//!   series in `dt` with exact coefficients, compared by the sign of its first nonzero one;
17//! - an infinite integer meets a standard integer as an infinite integer (`+ − ×`, floor division
18//!   and remainder keep integer meaning) and anything fractional as a hyperreal;
19//! - a value that depends on the residue of `1/dt` lifts every operation branch by branch, and a
20//!   comparison of infinite integers can itself depend on that residue;
21//! - an ordinal meets only ordinals and naturals.
22//!
23//! Every result is held in its smallest exact form — a hyperreal with no infinitesimal part is
24//! its standard value, a hyperreal that is an integer for every admitted `⌈1/dt⌉` is that infinite
25//! integer, an algebraic number that is rational is a rational — so a value has one representation
26//! whatever route produced it, exactly as the tower downsizes `BigInt` to `Int`.
27
28use std::cell::RefCell;
29use std::cmp::Ordering;
30use std::sync::Arc;
31
32use crate::algebraic::{negative_root, Algebraic};
33use crate::exact_codec::ExactCodec;
34use crate::exact_real::{ExactReal, DEFAULT_BUDGET};
35use crate::germ::Germ;
36use crate::hypernatural::Hypernatural;
37use crate::hyperreal::Hyperreal;
38use crate::limit_value::{Converging, Depends, LimitRule, ResidueError, ResidueType};
39use crate::multi::Multi;
40use crate::nested::NestedGerm;
41use crate::number::Number;
42use crate::numeric::{BigInt, Rational};
43use crate::ordered_field::{OrderedField, PolyOver};
44use crate::ordinal::Ordinal;
45use crate::poly::Poly;
46use crate::puiseux::{Closed, Puiseux};
47
48/// An infinitesimal of the program: the name it was declared under, what is known about the
49/// residues of its reciprocal, the infinite natural `⌈1/dt⌉`, and where it stands among the others.
50///
51/// `dx` declared much smaller than `dt` is smaller than every positive number made from `dt`, so the
52/// two are ordered as levels: every value of `dx` with coefficients made from `dt` has the sign of
53/// its lowest-order coefficient in `dx`. A declaration names at most one infinitesimal it is much
54/// smaller than and one it is much larger than, and the order of any two is what those statements
55/// give by transitivity ([`Scale::order`]); two the declarations do not order are never combined.
56#[derive(Debug, PartialEq, Eq, Hash)]
57pub struct Scale {
58    pub name: String,
59    pub residues: ResidueType,
60    /// The infinitesimal this one was declared much smaller than.
61    pub much_smaller_than: Option<Arc<Scale>>,
62    /// The infinitesimal this one was declared much larger than.
63    pub much_larger_than: Option<Arc<Scale>>,
64    /// The declared infinitesimal this is, read on one residue class of its reciprocal: the
65    /// engine's copy for a class keeps the declaration it refines, and is that infinitesimal.
66    pub refines: Option<Arc<Scale>>,
67}
68
69impl Scale {
70    /// An infinitesimal declared on its own.
71    pub fn new(name: &str, residues: ResidueType) -> Scale {
72        Scale {
73            name: name.to_string(),
74            residues,
75            much_smaller_than: None,
76            much_larger_than: None,
77            refines: None,
78        }
79    }
80
81    /// An infinitesimal declared much smaller than `larger` and much larger than `smaller`, each
82    /// when given; refused when the bounds are not already ordered, smaller below larger, or when it
83    /// would share a name with an infinitesimal it is ordered with.
84    pub fn ordered(
85        name: &str,
86        residues: ResidueType,
87        larger: Option<Arc<Scale>>,
88        smaller: Option<Arc<Scale>>,
89    ) -> Result<Scale, String> {
90        if let (Some(l), Some(s)) = (&larger, &smaller) {
91            match s.order(l) {
92                Some(Ordering::Less) => {}
93                Some(Ordering::Equal) => {
94                    return Err(format!("{name} cannot be both much smaller and much larger than {}", l.name))
95                }
96                Some(Ordering::Greater) => {
97                    return Err(format!(
98                        "{name} is declared much smaller than {} and much larger than {}, but {} is much larger than {}",
99                        l.name, s.name, s.name, l.name
100                    ))
101                }
102                None => {
103                    return Err(format!(
104                        "{name} is declared much smaller than {} and much larger than {}, but the program does not state that {} is much smaller than {}",
105                        l.name, s.name, s.name, l.name
106                    ))
107                }
108            }
109        }
110        let related = larger
111            .iter()
112            .flat_map(|l| l.larger_chain())
113            .chain(smaller.iter().flat_map(|s| s.smaller_chain()));
114        if let Some(clash) = related.into_iter().find(|s| s.name == name) {
115            return Err(format!(
116                "{name} is ordered with the infinitesimal {}, so it needs a name of its own",
117                clash.name
118            ));
119        }
120        Ok(Scale {
121            name: name.to_string(),
122            residues,
123            much_smaller_than: larger,
124            much_larger_than: smaller,
125            refines: None,
126        })
127    }
128
129    /// The same infinitesimal on a narrower residue type of its reciprocal.
130    pub fn with_residues(self: &Arc<Scale>, residues: ResidueType) -> Scale {
131        Scale {
132            name: self.name.clone(),
133            residues,
134            much_smaller_than: self.much_smaller_than.clone(),
135            much_larger_than: self.much_larger_than.clone(),
136            refines: Some(self.declaration_arc()),
137        }
138    }
139
140    fn declaration_arc(self: &Arc<Scale>) -> Arc<Scale> {
141        match &self.refines {
142            Some(d) => d.clone(),
143            None => self.clone(),
144        }
145    }
146
147    /// The declaration this infinitesimal is: itself, or the one a residue class's copy refines.
148    fn declaration(&self) -> &Scale {
149        self.refines.as_deref().unwrap_or(self)
150    }
151
152    /// Whether the two are one infinitesimal: one declaration, whatever residue class either is read on.
153    pub fn same_infinitesimal(&self, o: &Scale) -> bool {
154        std::ptr::eq(self.declaration(), o.declaration()) || self.declaration() == o.declaration()
155    }
156
157    /// This infinitesimal and each it was declared much smaller than, in turn.
158    fn larger_chain(&self) -> Vec<&Scale> {
159        let mut out = vec![self];
160        let mut at = self;
161        while let Some(next) = at.much_smaller_than.as_deref() {
162            out.push(next);
163            at = next;
164        }
165        out
166    }
167
168    /// This infinitesimal and each it was declared much larger than, in turn.
169    fn smaller_chain(&self) -> Vec<&Scale> {
170        let mut out = vec![self];
171        let mut at = self;
172        while let Some(next) = at.much_larger_than.as_deref() {
173            out.push(next);
174            at = next;
175        }
176        out
177    }
178
179    /// `Less` when this infinitesimal is much smaller than `o`, `Greater` when much larger, `Equal`
180    /// for one infinitesimal; `None` when the declarations do not order them. `a` is much smaller than
181    /// `b` when some infinitesimal reached from `a` through the ones declared above it is reached
182    /// from `b` through the ones declared below it: every declaration states its bounds' order
183    /// already known, so no later one orders two earlier ones, and that meeting is the only route.
184    pub fn order(&self, o: &Scale) -> Option<Ordering> {
185        if self.same_infinitesimal(o) {
186            return Some(Ordering::Equal);
187        }
188        let meets = |low: &Scale, high: &Scale| {
189            let up = low.declaration().larger_chain();
190            let down = high.declaration().smaller_chain();
191            up.iter().any(|u| down.iter().any(|d| u.same_infinitesimal(d)))
192        };
193        if meets(self, o) {
194            Some(Ordering::Less)
195        } else if meets(o, self) {
196            Some(Ordering::Greater)
197        } else {
198            None
199        }
200    }
201
202    /// The refusal for two infinitesimals whose order the program does not state.
203    pub fn unordered(&self, o: &Scale) -> String {
204        format!(
205            "cannot combine values of two infinitesimals, {} and {}, whose order the program does not state; declare one much smaller than the other",
206            self.name, o.name
207        )
208    }
209
210    /// How the infinite generator is written in a dependence: `⌈1/dt⌉`.
211    pub fn generator_text(&self) -> String {
212        format!("⌈1/{}⌉", self.name)
213    }
214
215    /// A residue system the value would need, refused in the program's own words.
216    fn refuse(&self, e: ResidueError) -> String {
217        e.describe(&self.generator_text())
218    }
219}
220
221/// A hyperreal's representations: an exact rational function of `dt`; a real algebraic Puiseux
222/// series that is none, a root of one ([`crate::puiseux`]); the germ a flow leaves, known by its
223/// series in `dt`; or a value of several ordered infinitesimals ([`Multi`]). A Puiseux series compares
224/// and hashes by its value, a germ by its canonical encoding.
225#[derive(Debug, Clone)]
226pub enum HyperForm {
227    Rational(Hyperreal),
228    Puiseux(Puiseux),
229    Germ(Germ),
230    Multi(Multi),
231    /// An infinite integer of several infinitesimals — `⌊1/dt + 1/dx⌋`, a step count of `⌈1/(dt·dx)⌉`: a
232    /// value of several that is a polynomial in their reciprocals with rational coefficients and an
233    /// integer on every class the facts its scales carry admit (`Multi::is_integral`), as a polynomial
234    /// in one infinitesimal's reciprocal that is one is an infinite integer of it. It computes and
235    /// compares as the value it is, and prints as an infinite integer does.
236    Integer(Multi),
237    Nested(Arc<NestedGerm>),
238}
239
240impl PartialEq for HyperForm {
241    fn eq(&self, o: &Self) -> bool {
242        match (self, o) {
243            (HyperForm::Rational(a), HyperForm::Rational(b)) => a == b,
244            (HyperForm::Puiseux(a), HyperForm::Puiseux(b)) => {
245                Closed::Series(a.clone()) == Closed::Series(b.clone())
246            }
247            (HyperForm::Germ(a), HyperForm::Germ(b)) => a.to_bytes() == b.to_bytes(),
248            (HyperForm::Multi(a) | HyperForm::Integer(a), HyperForm::Multi(b) | HyperForm::Integer(b)) => a == b,
249            (HyperForm::Nested(a), HyperForm::Nested(b)) => NestedGerm::same_recipe(a, b),
250            _ => false,
251        }
252    }
253}
254
255impl Eq for HyperForm {}
256
257impl std::hash::Hash for HyperForm {
258    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
259        match self {
260            HyperForm::Rational(h) => {
261                0u8.hash(state);
262                h.hash(state);
263            }
264            HyperForm::Germ(g) => {
265                1u8.hash(state);
266                g.to_bytes().hash(state);
267            }
268            HyperForm::Puiseux(p) => {
269                2u8.hash(state);
270                Closed::Series(p.clone()).hash(state);
271            }
272            HyperForm::Multi(m) | HyperForm::Integer(m) => {
273                3u8.hash(state);
274                m.hash(state);
275            }
276            HyperForm::Nested(g) => {
277                4u8.hash(state);
278                g.scale.name.hash(state);
279            }
280        }
281    }
282}
283
284impl HyperForm {
285    /// The rational function, when the value is one.
286    pub fn rational(&self) -> Option<&Hyperreal> {
287        match self {
288            HyperForm::Rational(h) => Some(h),
289            HyperForm::Puiseux(_)
290            | HyperForm::Germ(_)
291            | HyperForm::Multi(_)
292            | HyperForm::Integer(_)
293            | HyperForm::Nested(_) => None,
294        }
295    }
296
297    /// How the value prints, its infinitesimal written `name`; a value of several prints each by its
298    /// own name.
299    pub fn render(&self, name: &str) -> String {
300        match self {
301            HyperForm::Rational(h) => h.render(name),
302            HyperForm::Puiseux(p) => Closed::Series(p.clone()).render(name),
303            HyperForm::Germ(g) => g.render(name),
304            HyperForm::Multi(m) | HyperForm::Integer(m) => m.render(),
305            HyperForm::Nested(g) => g.render(),
306        }
307    }
308}
309
310/// A hyperreal value with the infinitesimal it is written in.
311#[derive(Debug, Clone, PartialEq, Eq, Hash)]
312pub struct HyperValue {
313    pub value: HyperForm,
314    pub scale: Arc<Scale>,
315}
316
317/// An infinite integer with the infinitesimal whose reciprocal generates it.
318#[derive(Debug, Clone, PartialEq, Eq, Hash)]
319pub struct NaturalValue {
320    pub value: Hypernatural,
321    pub scale: Arc<Scale>,
322}
323
324/// One branch of a residue-dependent value, compared by value.
325#[derive(Debug, Clone)]
326pub struct Branch<V>(pub V);
327
328impl<V: TowerValue> PartialEq for Branch<V> {
329    fn eq(&self, o: &Self) -> bool {
330        self.0.values_equal(&o.0)
331    }
332}
333
334/// A value that depends on the residue of `⌈1/dt⌉`.
335#[derive(Debug, Clone)]
336pub struct DependsValue<V> {
337    pub value: Depends<Branch<V>>,
338    pub scale: Arc<Scale>,
339}
340
341/// A value of a value model seen as one of the types this module governs.
342pub enum ExactRef<'a, V> {
343    Algebraic(&'a Algebraic),
344    Real(&'a ExactReal),
345    Hyper(&'a HyperValue),
346    Natural(&'a NaturalValue),
347    Ordinal(&'a Ordinal),
348    Depends(&'a DependsValue<V>),
349    Converging(&'a Converging<V>),
350}
351
352/// A value model that holds the exact types: how to see a value as one of them or as a standard
353/// number, and how to build one. The interpreter's runtime value and a compiled program's value
354/// each implement it; every operation in this module is generic over it.
355pub trait TowerValue: Clone + Sized {
356    /// The value as one of the exact types, or `None` for any other value.
357    fn exact(&self) -> Option<ExactRef<'_, Self>>;
358    /// An integer, rational, decimal or finite float as the rational it denotes exactly.
359    fn standard_rational(&self) -> Option<Rational>;
360    /// An `Int` or big integer.
361    fn integer(&self) -> Option<BigInt>;
362    /// An integer or a rational: a number held exactly, never a float or a decimal.
363    fn exact_rational(&self) -> Option<Rational>;
364    /// An integer, rational, decimal or float: its own standard part.
365    fn is_standard_number(&self) -> bool;
366    /// A `Text` value's characters.
367    fn text(&self) -> Option<&str>;
368    /// The value's type as the language names it.
369    fn type_name(&self) -> String;
370    /// How the value prints.
371    fn display_string(&self) -> String;
372    /// The language's equality on two values.
373    fn values_equal(&self, other: &Self) -> bool;
374    /// Whether the value is `nothing`.
375    fn is_nothing(&self) -> bool;
376
377    /// A rational in its smallest form: an `Int` when it fits, a big integer, else a rational.
378    fn from_rational(r: Rational) -> Self;
379    /// An integer in its smallest form.
380    fn from_bigint(b: BigInt) -> Self;
381    fn boolean(b: bool) -> Self;
382    fn nothing() -> Self;
383    fn algebraic(a: Algebraic) -> Self;
384    fn exact_real(x: ExactReal) -> Self;
385    fn hyper(h: HyperValue) -> Self;
386    fn natural(n: NaturalValue) -> Self;
387    fn ordinal(o: Ordinal) -> Self;
388    fn depends(d: DependsValue<Self>) -> Self;
389    fn converging(c: Converging<Self>) -> Self;
390}
391
392/// A value's structure, as far as the supertask runtime reads it: the scalar kinds it treats apart,
393/// and the items of a list or a tuple.
394pub enum Shape<V> {
395    Bool,
396    Int(i64),
397    Float,
398    BigInt(BigInt),
399    Rational(Rational),
400    Decimal,
401    /// Text of this many bytes.
402    Text(usize),
403    List(Vec<V>),
404    Tuple(Vec<V>),
405    Other,
406}
407
408/// A value model's whole arithmetic and its lists: what the supertask runtime computes with. Each
409/// operation is the language's own on that model, exact types and standard numbers alike.
410pub trait ValueAlgebra: TowerValue {
411    fn add(a: Self, b: Self) -> Result<Self, String>;
412    fn subtract(a: Self, b: Self) -> Result<Self, String>;
413    fn multiply(a: Self, b: Self) -> Result<Self, String>;
414    /// `/` in an exact context: field division, integers included.
415    fn exact_divide(a: Self, b: Self) -> Result<Self, String>;
416    /// The language's `%`.
417    fn modulo(a: Self, b: Self) -> Result<Self, String>;
418    /// Whether `a rel b` holds, decided: an answer that depends on the residue, or a provisional
419    /// one, is the refusal of the branch.
420    fn holds(rel: Rel, a: &Self, b: &Self) -> Result<bool, String>;
421    /// The language's `**`.
422    fn power(a: Self, b: Self) -> Result<Self, String>;
423    /// The language's `floor`.
424    fn floor(v: Self) -> Result<Self, String>;
425    /// The language's `ceiling`.
426    fn ceil(v: Self) -> Result<Self, String>;
427    fn list(values: Vec<Self>) -> Self;
428    fn shape(&self) -> Shape<Self>;
429}
430
431/// The canonical value of an algebraic number: a rational is an `Int`/`BigInt`/`Rational`.
432pub fn from_algebraic<V: TowerValue>(a: Algebraic) -> V {
433    match a.to_rational() {
434        Some(r) => V::from_rational(r),
435        None => V::algebraic(a),
436    }
437}
438
439/// The canonical value of a computable real: an algebraic one is an algebraic number.
440pub fn from_exact_real<V: TowerValue>(x: ExactReal) -> V {
441    match x.exact_algebraic() {
442        Some(a) => from_algebraic(a),
443        None => V::exact_real(x),
444    }
445}
446
447/// The canonical value of a hyperreal: a standard value is its standard part, and a polynomial in
448/// `1/dt` that is an integer for every admitted `⌈1/dt⌉` is that infinite integer.
449pub fn from_hyper<V: TowerValue>(value: Hyperreal, scale: &Arc<Scale>) -> V {
450    if let Some(s) = value.as_standard() {
451        return from_algebraic(s);
452    }
453    if let Some(n) = value
454        .as_reciprocal_powers()
455        .and_then(|c| Hypernatural::from_polynomial(Poly::from_coeffs(c), &scale.residues))
456    {
457        return from_natural(n, scale);
458    }
459    V::hyper(HyperValue {
460        value: HyperForm::Rational(value),
461        scale: scale.clone(),
462    })
463}
464
465/// The canonical value of a value of the real closure: a rational function of `dt` is that
466/// hyperreal, in its own smallest form.
467pub fn from_closed<V: TowerValue>(c: Closed, scale: &Arc<Scale>) -> V {
468    match c {
469        Closed::Field(h) => from_hyper(h, scale),
470        Closed::Series(p) => V::hyper(HyperValue {
471            value: HyperForm::Puiseux(p),
472            scale: scale.clone(),
473        }),
474    }
475}
476
477/// The canonical value of a germ: one built as a rational function of `dt` is that hyperreal.
478pub fn from_germ<V: TowerValue>(g: Germ, scale: &Arc<Scale>) -> V {
479    if let Some(h) = g.as_hyperreal() {
480        return from_hyper(h.clone(), scale);
481    }
482    V::hyper(HyperValue {
483        value: HyperForm::Germ(g),
484        scale: scale.clone(),
485    })
486}
487
488/// The canonical value of an infinite integer: a standard one is an `Int`/`BigInt`, and one whose
489/// branches are standard but differ is a residue-dependent integer.
490pub fn from_natural<V: TowerValue>(value: Hypernatural, scale: &Arc<Scale>) -> V {
491    let finite = value.is_infinite();
492    if finite.single() == Some(&false) {
493        let ints = value.depends().map(|p| {
494            Branch(V::from_bigint(
495                p.coeff(0).to_bigint().expect("a standard branch is an integer"),
496            ))
497        });
498        return from_depends(ints, scale);
499    }
500    V::natural(NaturalValue {
501        value,
502        scale: scale.clone(),
503    })
504}
505
506/// The canonical value of a residue-dependent value: a branch that itself depends on the residue
507/// is read on its own class, a single branch is that value, and a dependence whose every branch is
508/// an integer polynomial in `1/dt` on its class is that infinite integer.
509pub fn from_depends<V: TowerValue>(value: Depends<Branch<V>>, scale: &Arc<Scale>) -> V {
510    let value = flatten(value, scale);
511    if let Some(renested) = coarsest_outside(&value, scale) {
512        return renested;
513    }
514    if let Some(b) = value.single() {
515        return b.0.clone();
516    }
517    if let Some(n) = as_infinite_integer(&value, scale) {
518        return from_natural(n, scale);
519    }
520    V::depends(DependsValue {
521        value,
522        scale: scale.clone(),
523    })
524}
525
526/// Whether a value is an integer — a standard one, an infinite integer of one infinitesimal or of
527/// several.
528fn is_integer_value<V: TowerValue>(v: &V) -> bool {
529    v.integer().is_some()
530        || matches!(v.exact(), Some(ExactRef::Natural(_)))
531        || matches!(v.exact(), Some(ExactRef::Hyper(h)) if matches!(h.value, HyperForm::Integer(_)))
532}
533
534/// The canonical value of a value of several infinitesimals: a standard number is that number, and a
535/// value of one infinitesimal is that infinitesimal's own.
536pub fn from_multi<V: TowerValue>(m: Multi) -> V {
537    match m {
538        Multi::Standard(a) => from_algebraic(a),
539        Multi::One(c, scale) => from_closed(c, &scale),
540        Multi::Over { .. } | Multi::Alg(_) => {
541            let scale = m.top().expect("a value of several infinitesimals has a smallest").clone();
542            let value = if m.is_integral() { HyperForm::Integer(m) } else { HyperForm::Multi(m) };
543            V::hyper(HyperValue { value, scale })
544        }
545    }
546}
547
548/// A finite ordinal is a natural number.
549pub fn from_ordinal<V: TowerValue>(o: Ordinal) -> V {
550    match o.to_natural() {
551        Some(n) => V::from_bigint(n),
552        None => V::ordinal(o),
553    }
554}
555
556/// `lcm` of residue moduli, when it is within the bound one value may hold.
557fn classes_lcm(moduli: impl Iterator<Item = u64>) -> Option<u64> {
558    moduli.into_iter().try_fold(1u64, |acc, m| {
559        let g = num_gcd(acc, m);
560        let l = u128::from(acc / g) * u128::from(m);
561        (l <= u128::from(crate::limit_value::MAX_MODULUS)).then_some(l as u64)
562    })
563}
564
565fn num_gcd(a: u64, b: u64) -> u64 {
566    if b == 0 {
567        a
568    } else {
569        num_gcd(b, a % b)
570    }
571}
572
573fn depends_of<V: TowerValue>(v: &V) -> Option<&DependsValue<V>> {
574    match v.exact()? {
575        ExactRef::Depends(d) => Some(d),
576        _ => None,
577    }
578}
579
580fn natural_of<V: TowerValue>(v: &V) -> Option<&NaturalValue> {
581    match v.exact()? {
582        ExactRef::Natural(n) => Some(n),
583        _ => None,
584    }
585}
586
587/// A dependence on `scale`'s generator whose branches read the residue of a coarser one — the
588/// generator of a larger infinitesimal — as the dependence on the coarsest of them whose branches
589/// read only finer ones: each class of the coarsest is a case, in which every branch is read on that
590/// class. `None` when no branch reads a coarser generator, or the classes would pass the bound.
591fn coarsest_outside<V: TowerValue>(value: &Depends<Branch<V>>, scale: &Arc<Scale>) -> Option<V> {
592    let mut outer = scale.clone();
593    for (_, b) in value.branches() {
594        if let Some(g) = residue_generator(&b.0) {
595            if g.order(&outer) == Some(Ordering::Greater) {
596                outer = g.clone();
597            }
598        }
599    }
600    if outer.same_infinitesimal(scale) {
601        return None;
602    }
603    let ty = outer.residues.clone();
604    let own = value
605        .branches()
606        .filter_map(|(_, b)| residue_branches(&b.0).filter(|d| d.scale.same_infinitesimal(&outer)))
607        .map(|d| d.value.modulus());
608    let m = classes_lcm([ty.modulus()].into_iter().chain(own))?;
609    let raw = (0..m)
610        .map(|h| {
611            ty.admits(h).then(|| {
612                let on_class = value.map(|b| match residue_branches(&b.0) {
613                    Some(d) if d.scale.same_infinitesimal(&outer) => {
614                        d.value.at(h).expect("an admitted class has a branch").clone()
615                    }
616                    _ => b.clone(),
617                });
618                Branch(from_depends(on_class, scale))
619            })
620        })
621        .collect();
622    Some(from_depends(Depends::from_branches(ty, m, raw)?, &outer))
623}
624
625/// Every branch that depends on the residue of the same reciprocal, read on its own class. A
626/// dependence whose classes together would pass the bound is left as it is.
627fn flatten<V: TowerValue>(value: Depends<Branch<V>>, scale: &Scale) -> Depends<Branch<V>> {
628    fn same<'v, V: TowerValue>(v: &'v V, scale: &Scale) -> Option<&'v DependsValue<V>> {
629        depends_of(v).filter(|d| d.scale.same_infinitesimal(scale))
630    }
631    let inner: Vec<u64> = value
632        .branches()
633        .filter_map(|(_, b)| same(&b.0, scale).map(|d| d.value.modulus()))
634        .collect();
635    if inner.is_empty() {
636        return value;
637    }
638    let ty = value.residue_type().clone();
639    let moduli = [value.modulus(), ty.modulus()].into_iter().chain(inner);
640    let Some(l) = classes_lcm(moduli) else {
641        return value;
642    };
643    let raw = (0..l)
644        .map(|x| {
645            let b = value.at(x)?;
646            Some(match same(&b.0, scale) {
647                Some(d) => d.value.at(x).expect("an admitted class has a branch").clone(),
648                None => b.clone(),
649            })
650        })
651        .collect();
652    Depends::from_branches(ty, l, raw).expect("the classes are the type's own")
653}
654
655/// The dependence as one infinite integer, when every branch is an integer polynomial in `1/dt`
656/// on its class and at least one is infinite.
657fn as_infinite_integer<V: TowerValue>(value: &Depends<Branch<V>>, scale: &Scale) -> Option<Hypernatural> {
658    let ty = value.residue_type().clone();
659    let own = value
660        .branches()
661        .filter_map(|(_, b)| natural_of(&b.0).filter(|n| n.scale.same_infinitesimal(scale)))
662        .map(|n| n.value.depends().modulus());
663    let l = classes_lcm([value.modulus(), ty.modulus()].into_iter().chain(own))?;
664    let mut infinite = false;
665    let mut raw = Vec::with_capacity(l as usize);
666    for x in 0..l {
667        let Some(b) = value.at(x) else {
668            raw.push(None);
669            continue;
670        };
671        let p = if let Some(n) = b.0.integer() {
672            Poly::constant(Rational::from_bigint(n))
673        } else {
674            match b.0.exact() {
675                Some(ExactRef::Natural(n)) if n.scale.same_infinitesimal(scale) => {
676                    infinite = true;
677                    n.value.depends().at(x)?.clone()
678                }
679                Some(ExactRef::Hyper(h)) if h.scale.same_infinitesimal(scale) => {
680                    infinite = true;
681                    Poly::from_coeffs(h.value.rational()?.as_reciprocal_powers()?)
682                }
683                _ => return None,
684            }
685        };
686        raw.push(Some(p));
687    }
688    if !infinite {
689        return None;
690    }
691    Hypernatural::from_branches(Depends::from_branches(ty, l, raw)?)
692}
693
694/// True for a value of one of the types this module governs.
695pub fn is_exact_value<V: TowerValue>(v: &V) -> bool {
696    v.exact().is_some()
697}
698
699/// A numeric operand seen through the exact lattice.
700enum Num {
701    Rat(Rational),
702    Alg(Algebraic),
703    Real(ExactReal),
704    Hyper(Hyperreal, Arc<Scale>),
705    Closed(Closed, Arc<Scale>),
706    Germ(Germ, Arc<Scale>),
707    Nat(Hypernatural, Arc<Scale>),
708    Ord(Ordinal),
709    Multi(Multi),
710    Nested(Arc<NestedGerm>),
711}
712
713fn classify<V: TowerValue>(v: &V) -> Option<Num> {
714    if let Some(r) = v.standard_rational() {
715        return Some(Num::Rat(r));
716    }
717    Some(match v.exact()? {
718        ExactRef::Algebraic(a) => Num::Alg(a.clone()),
719        ExactRef::Real(x) => Num::Real(x.clone()),
720        ExactRef::Hyper(h) => match &h.value {
721            HyperForm::Rational(r) => Num::Hyper(r.clone(), h.scale.clone()),
722            HyperForm::Puiseux(p) => Num::Closed(Closed::Series(p.clone()), h.scale.clone()),
723            HyperForm::Germ(g) => Num::Germ(g.clone(), h.scale.clone()),
724            HyperForm::Multi(m) | HyperForm::Integer(m) => Num::Multi(m.clone()),
725            HyperForm::Nested(g) => Num::Nested(g.clone()),
726        },
727        ExactRef::Natural(n) => Num::Nat(n.value.clone(), n.scale.clone()),
728        ExactRef::Ordinal(o) => Num::Ord(o.clone()),
729        ExactRef::Depends(_) | ExactRef::Converging(_) => return None,
730    })
731}
732
733fn scale_of(a: &Num, b: &Num) -> Option<Arc<Scale>> {
734    let s = |n: &Num| match n {
735        Num::Hyper(_, s) | Num::Closed(_, s) | Num::Germ(_, s) | Num::Nat(_, s) => Some(s.clone()),
736        Num::Multi(m) => m.top().cloned(),
737        Num::Nested(g) => Some(g.scale.clone()),
738        _ => None,
739    };
740    s(a).or_else(|| s(b))
741}
742
743/// Every infinitesimal an operand involves, each once.
744fn scales_of(n: &Num) -> Vec<Arc<Scale>> {
745    match n {
746        Num::Hyper(_, s) | Num::Closed(_, s) | Num::Germ(_, s) | Num::Nat(_, s) => vec![s.clone()],
747        Num::Multi(m) => m.scales(),
748        Num::Nested(g) => g.scales(),
749        Num::Rat(_) | Num::Alg(_) | Num::Real(_) | Num::Ord(_) => Vec::new(),
750    }
751}
752
753/// Every infinitesimal two operands involve, each once and every two ordered; the refusal naming the
754/// first two the program does not order.
755fn meeting(a: &Num, b: &Num) -> Result<Vec<Arc<Scale>>, String> {
756    let mut all: Vec<Arc<Scale>> = Vec::new();
757    for s in scales_of(a).into_iter().chain(scales_of(b)) {
758        if !all.iter().any(|t| t.same_infinitesimal(&s)) {
759            all.push(s);
760        }
761    }
762    for (i, x) in all.iter().enumerate() {
763        if let Some(y) = all[i + 1..].iter().find(|y| x.order(y).is_none()) {
764            return Err(x.unordered(y));
765        }
766    }
767    Ok(all)
768}
769
770fn same_scale(a: &Num, b: &Num) -> Result<(), String> {
771    match (scale_of(a, a), scale_of(b, b)) {
772        (Some(x), Some(y)) if !x.same_infinitesimal(&y) => Err(x.unordered(&y)),
773        _ => Ok(()),
774    }
775}
776
777fn to_alg(n: &Num) -> Option<Algebraic> {
778    match n {
779        Num::Rat(r) => Some(Algebraic::from_rational(r.clone())),
780        Num::Alg(a) => Some(a.clone()),
781        _ => None,
782    }
783}
784
785fn to_real(n: &Num) -> Option<ExactReal> {
786    match n {
787        Num::Rat(r) => Some(ExactReal::from_rational(r.clone())),
788        Num::Alg(a) => Some(ExactReal::from_algebraic(a.clone())),
789        Num::Real(x) => Some(x.clone()),
790        _ => None,
791    }
792}
793
794/// A standard, algebraic or infinite-integer operand as hyperreal branches.
795fn to_hyper_branches(n: &Num, ty: &ResidueType) -> Option<Depends<Hyperreal>> {
796    match n {
797        Num::Rat(r) => Some(Depends::constant(Hyperreal::from_rational(r.clone()), ty)),
798        Num::Alg(a) => Some(Depends::constant(Hyperreal::from_algebraic(a.clone()), ty)),
799        Num::Hyper(h, _) => Some(Depends::constant(h.clone(), ty)),
800        Num::Nat(n, _) => Some(n.to_hyperreal()),
801        _ => None,
802    }
803}
804
805/// A standard integer or an infinite integer, as an infinite integer.
806fn to_natural(n: &Num, ty: &ResidueType) -> Option<Hypernatural> {
807    match n {
808        Num::Rat(r) if r.is_integer() => Some(Hypernatural::from_integer(
809            r.to_bigint().expect("an integer"),
810            ty,
811        )),
812        Num::Nat(n, _) => Some(n.clone()),
813        _ => None,
814    }
815}
816
817/// The arithmetic operators the exact types take.
818#[derive(Clone, Copy, Debug, PartialEq, Eq)]
819pub enum Op {
820    Add,
821    Sub,
822    Mul,
823    /// The polymorphic `/`: field division for the exact types, floor division of two integers.
824    Div,
825    /// `/` in an exact context (`ExactDivide`): field division on every branch, integers included.
826    ExactDiv,
827    FloorDiv,
828    Mod,
829    Pow,
830}
831
832impl Op {
833    fn word(self) -> &'static str {
834        match self {
835            Op::Add => "add",
836            Op::Sub => "subtract",
837            Op::Mul => "multiply",
838            Op::Div | Op::ExactDiv => "divide",
839            Op::FloorDiv => "floor-divide",
840            Op::Mod => "take the remainder of",
841            Op::Pow => "raise",
842        }
843    }
844}
845
846/// Apply `op` when either operand is an exact type; `None` when neither is (the tower handles it),
847/// and for `+` with a `Text` operand, which joins the other value as it prints by the value model's
848/// own rule for every value. `recurse` is the value model's full arithmetic, used to lift an
849/// operation over residue branches and through provisional values.
850pub fn arith<V: TowerValue>(
851    op: Op,
852    left: &V,
853    right: &V,
854    recurse: &dyn Fn(Op, V, V) -> Result<V, String>,
855) -> Option<Result<V, String>> {
856    if !is_exact_value(left) && !is_exact_value(right) {
857        return None;
858    }
859    if matches!(op, Op::Add) && (left.text().is_some() || right.text().is_some()) {
860        return None;
861    }
862    if let Some(r) = lift(left, right, |a, b| recurse(op, a, b)) {
863        return Some(r);
864    }
865    let (Some(a), Some(b)) = (classify(left), classify(right)) else {
866        return Some(Err(format!(
867            "cannot {} {} and {}",
868            op.word(),
869            left.type_name(),
870            right.type_name()
871        )));
872    };
873    if let Some(r) = several_arith(op, &a, &b, left, right, recurse) {
874        return Some(r);
875    }
876    if let Some(r) = germ_arith(op, &a, &b, left, right, recurse) {
877        return Some(r);
878    }
879    Some(arith_num(op, a, b, left, right))
880}
881
882// ── several infinitesimals ────────────────────────────────────────────────────────────────────
883
884/// Whether two operands together involve more than one infinitesimal, or a value of several; the
885/// refusal when they involve two the program does not order.
886fn several(a: &Num, b: &Num) -> Result<bool, String> {
887    let all = meeting(a, b)?;
888    let held = |n: &Num| matches!(n, Num::Multi(_) | Num::Nested(_));
889    Ok(all.len() > 1 || held(a) || held(b))
890}
891
892/// Whether an operand of several infinitesimals calls for germs: a germ, a computable transcendental,
893/// or a germ of several.
894fn several_germs(a: &Num, b: &Num) -> bool {
895    let lazy = |n: &Num| matches!(n, Num::Germ(..) | Num::Real(_) | Num::Nested(_));
896    lazy(a) || lazy(b)
897}
898
899/// The smallest infinitesimal two operands involve.
900fn smallest_scale(a: &Num, b: &Num) -> Result<Arc<Scale>, String> {
901    let all = meeting(a, b)?;
902    let mut smallest = all.first().cloned().expect("several infinitesimals are involved");
903    for s in &all[1..] {
904        if s.order(&smallest) == Some(Ordering::Less) {
905            smallest = s.clone();
906        }
907    }
908    Ok(smallest)
909}
910
911/// An operand as a germ of several infinitesimals at `scale`, its smallest or one smaller.
912fn nested_operand<V: TowerValue>(n: &Num, v: &V, scale: &Arc<Scale>) -> Result<Arc<NestedGerm>, String> {
913    let constant = || -> Number { as_number(v) };
914    Ok(Arc::new(match n {
915        Num::Nested(g) if g.scale.same_infinitesimal(scale) => (**g).clone(),
916        Num::Germ(g, s) if s.same_infinitesimal(scale) => NestedGerm::germ(g, scale),
917        Num::Rat(_) | Num::Alg(_) | Num::Real(_) | Num::Germ(..) | Num::Nested(_) => NestedGerm::constant(constant(), scale),
918        Num::Hyper(..) | Num::Closed(..) | Num::Multi(_) | Num::Nat(..) => match several_operand(n) {
919            Some(m) => NestedGerm::exact(&m, scale),
920            None => return Err(format!("cannot read {} as a germ of {}", v.display_string(), scale.name)),
921        },
922        Num::Ord(_) => return Err(format!("an ordinal is no germ of {}", scale.name)),
923    }))
924}
925
926/// A number as a germ of several infinitesimals at `scale`, its smallest or one smaller.
927pub(crate) fn number_germ(n: &Number, scale: &Arc<Scale>) -> Result<Arc<NestedGerm>, String> {
928    match classify(n) {
929        Some(num) => nested_operand(&num, n, scale),
930        None => Err(format!("a {} is not a number", n.type_name())),
931    }
932}
933
934/// Every infinitesimal a number involves.
935pub(crate) fn number_scales(n: &Number) -> Vec<Arc<Scale>> {
936    classify(n).map(|num| scales_of(&num)).unwrap_or_default()
937}
938
939/// A value of a value model as base's own number, by its own exact form.
940pub(crate) fn as_number<V: TowerValue>(v: &V) -> Number {
941    if let Some(r) = v.standard_rational() {
942        return Number::from_rational(r);
943    }
944    match v.exact() {
945        Some(ExactRef::Algebraic(a)) => Number::algebraic(a.clone()),
946        Some(ExactRef::Real(x)) => Number::exact_real(x.clone()),
947        Some(ExactRef::Hyper(h)) => Number::hyper(h.clone()),
948        Some(ExactRef::Natural(n)) => Number::natural(n.clone()),
949        Some(ExactRef::Ordinal(o)) => Number::ordinal(o.clone()),
950        Some(ExactRef::Depends(d)) => Number::depends(DependsValue {
951            value: d.value.map(|b| Branch(as_number(&b.0))),
952            scale: d.scale.clone(),
953        }),
954        Some(ExactRef::Converging(c)) => Number::converging(c.with_value(as_number(c.value()))),
955        None => Number::nothing(),
956    }
957}
958
959/// Base's own number as a value of a value model.
960pub(crate) fn from_number<V: TowerValue>(n: Number) -> V {
961    match n {
962        Number::Int(b) => V::from_bigint(b),
963        Number::Rat(r) => V::from_rational(r),
964        Number::Bool(b) => V::boolean(b),
965        Number::Nothing => V::nothing(),
966        Number::Alg(a) => V::algebraic(a),
967        Number::Real(x) => V::exact_real(x),
968        Number::Hyper(h) => V::hyper(h),
969        Number::Nat(m) => V::natural(m),
970        Number::Ord(o) => V::ordinal(o),
971        Number::Dep(d) => V::depends(DependsValue {
972            value: d.value.map(|b| Branch(from_number(b.0.clone()))),
973            scale: d.scale.clone(),
974        }),
975        Number::Conv(c) => V::converging(c.with_value(from_number(c.value().clone()))),
976    }
977}
978
979/// A germ of several infinitesimals as a value of a value model.
980pub(crate) fn from_nested<V: TowerValue>(g: NestedGerm) -> V {
981    let scale = g.scale.clone();
982    V::hyper(HyperValue {
983        value: HyperForm::Nested(Arc::new(g)),
984        scale,
985    })
986}
987
988fn nested_arith<V: TowerValue>(op: Op, a: &Num, b: &Num, left: &V, right: &V) -> Result<V, String> {
989    let scale = smallest_scale(a, b)?;
990    let x = nested_operand(a, left, &scale)?;
991    let out = match op {
992        Op::Pow => match (integer_exponent(right), fractional_exponent(right)) {
993            (Some(k), _) => NestedGerm::pow(&x, k)?,
994            (None, Some((p, q))) => NestedGerm::pow(&Arc::new(NestedGerm::root(&x, q)?), p)?,
995            (None, None) => {
996                return Err("a value of the infinitesimal is raised only to an integer or a rational power".to_string())
997            }
998        },
999        Op::FloorDiv | Op::Mod => {
1000            return Err(
1001                "the integer part of a quotient of these values is not an exact value; divide exactly".to_string(),
1002            )
1003        }
1004        _ => {
1005            let y = nested_operand(b, right, &scale)?;
1006            match op {
1007                Op::Add => NestedGerm::add(&x, &y),
1008                Op::Sub if NestedGerm::same_recipe(&x, &y) => return Ok(V::from_bigint(BigInt::from_i64(0))),
1009                Op::Sub => NestedGerm::sub(&x, &y),
1010                Op::Mul => NestedGerm::mul(&x, &y),
1011                Op::Div | Op::ExactDiv => NestedGerm::mul(&x, &Arc::new(NestedGerm::recip(&y)?)),
1012                _ => unreachable!("handled above"),
1013            }
1014        }
1015    };
1016    Ok(from_nested(out))
1017}
1018
1019/// An operand of a value of several infinitesimals as a value of their field; `None` for a germ, a
1020/// computable transcendental, an infinite integer that depends on the residue and an ordinal.
1021fn several_operand(n: &Num) -> Option<Multi> {
1022    Some(match n {
1023        Num::Rat(r) => Multi::Standard(Algebraic::from_rational(r.clone())),
1024        Num::Alg(a) => Multi::Standard(a.clone()),
1025        Num::Hyper(h, s) => Multi::of_closed(Closed::from_hyperreal(h.clone()), s),
1026        Num::Closed(c, s) => Multi::of_closed(c.clone(), s),
1027        Num::Nat(n, s) => Multi::of_closed(Closed::from_hyperreal(n.to_hyperreal().single()?.clone()), s),
1028        Num::Multi(m) => m.clone(),
1029        Num::Real(_) | Num::Germ(..) | Num::Ord(_) | Num::Nested(_) => return None,
1030    })
1031}
1032
1033/// Both operands as exact values of their infinitesimals, or the refusal of a value that is none.
1034fn several_operands(a: &Num, b: &Num, left: &str, right: &str, word: &str) -> Result<(Multi, Multi), String> {
1035    let (Some(x), Some(y)) = (several_operand(a), several_operand(b)) else {
1036        return Err(format!(
1037            "cannot {word} {left} and {right}: only exact values of several infinitesimals combine"
1038        ));
1039    };
1040    Ok((x, y))
1041}
1042
1043fn several_arith<V: TowerValue>(
1044    op: Op,
1045    a: &Num,
1046    b: &Num,
1047    left: &V,
1048    right: &V,
1049    recurse: &dyn Fn(Op, V, V) -> Result<V, String>,
1050) -> Option<Result<V, String>> {
1051    match several(a, b) {
1052        Ok(false) => return None,
1053        Ok(true) => {}
1054        Err(e) => return Some(Err(e)),
1055    }
1056    if let Some(l) = lifted_natural(a) {
1057        return Some(recurse(op, l, right.clone()));
1058    }
1059    if let Some(r) = lifted_natural(b) {
1060        return Some(recurse(op, left.clone(), r));
1061    }
1062    if several_germs(a, b) {
1063        return Some(nested_arith(op, a, b, left, right));
1064    }
1065    let shown = |v: &V| if is_exact_value(v) { v.display_string() } else { v.type_name() };
1066    let (x, y) = match several_operands(a, b, &shown(left), &shown(right), op.word()) {
1067        Ok(pair) => pair,
1068        Err(e) => return Some(Err(e)),
1069    };
1070    let out = match op {
1071        Op::Add => Ok(x.add(&y)),
1072        Op::Sub => Ok(x.sub(&y)),
1073        Op::Mul => Ok(x.mul(&y)),
1074        Op::Div | Op::ExactDiv => y.recip().map(|r| x.mul(&r)).ok_or_else(|| "Division by zero".to_string()),
1075        Op::Pow => match (integer_exponent(right), fractional_exponent(right)) {
1076            (Some(k), _) => x.pow(k).map_err(|e| e.describe()),
1077            (None, Some((p, q))) => x.root(q).and_then(|r| r.pow(p).map_err(|e| e.describe())),
1078            (None, None) => Err("a hyperreal is raised only to an integer or a rational power".to_string()),
1079        },
1080        Op::FloorDiv | Op::Mod if is_integer_value(left) && is_integer_value(right) => {
1081            let quotient = match y.recip() {
1082                Some(r) => x.mul(&r),
1083                None => return Some(Err("Division by zero".to_string())),
1084            };
1085            let floor = match floor_number(&from_multi(quotient)) {
1086                Ok(n) => from_number::<V>(n),
1087                Err(e) => return Some(Err(e)),
1088            };
1089            return Some(match op {
1090                Op::FloorDiv => Ok(floor),
1091                _ => recurse(Op::Mul, right.clone(), floor).and_then(|m| recurse(Op::Sub, left.clone(), m)),
1092            });
1093        }
1094        Op::FloorDiv | Op::Mod => Err(
1095            "the integer part of a hyperreal quotient is not an exact hyperreal; divide exactly".to_string(),
1096        ),
1097    };
1098    Some(out.map(from_multi))
1099}
1100
1101fn several_relation<V: TowerValue>(
1102    rel: Rel,
1103    a: &Num,
1104    b: &Num,
1105    left: &V,
1106    right: &V,
1107    recurse: &dyn Fn(Rel, V, V) -> Result<V, String>,
1108) -> Option<Result<V, String>> {
1109    match several(a, b) {
1110        Ok(false) => return None,
1111        Ok(true) => {}
1112        Err(e) => return Some(Err(e)),
1113    }
1114    if let Some(l) = lifted_natural(a) {
1115        return Some(recurse(rel, l, right.clone()));
1116    }
1117    if let Some(r) = lifted_natural(b) {
1118        return Some(recurse(rel, left.clone(), r));
1119    }
1120    if several_germs(a, b) {
1121        let difference = smallest_scale(a, b).and_then(|scale| {
1122            let x = nested_operand(a, left, &scale)?;
1123            let y = nested_operand(b, right, &scale)?;
1124            if NestedGerm::same_recipe(&x, &y) {
1125                return Ok(0);
1126            }
1127            NestedGerm::sub(&x, &y).sign()
1128        });
1129        return Some(difference.map(|s| V::boolean(rel.holds(s.cmp(&0)))));
1130    }
1131    let shown = |v: &V| if is_exact_value(v) { v.display_string() } else { v.type_name() };
1132    let (x, y) = match several_operands(a, b, &shown(left), &shown(right), "compare") {
1133        Ok(pair) => pair,
1134        Err(e) => return Some(Err(e)),
1135    };
1136    Some(Ok(V::boolean(rel.holds(x.sub(&y).signum().cmp(&0)))))
1137}
1138
1139/// Whether an operation calls for germs: a germ on either side, or a computable transcendental
1140/// meeting a value of the infinitesimal.
1141fn calls_for_germs(a: &Num, b: &Num) -> bool {
1142    let germ = |n: &Num| matches!(n, Num::Germ(..));
1143    let real = |n: &Num| matches!(n, Num::Real(_));
1144    germ(a) || germ(b) || (scale_of(a, b).is_some() && (real(a) || real(b)))
1145}
1146
1147/// An operand as a germ: a standard number as a constant, a rational function or a value of the
1148/// real closure by its series, an infinite integer that does not depend on the residue by its
1149/// series; `None` otherwise.
1150fn to_germ(n: &Num) -> Option<Germ> {
1151    Some(match n {
1152        Num::Rat(r) => Germ::from_hyperreal(&Hyperreal::from_rational(r.clone())),
1153        Num::Alg(a) => Germ::from_hyperreal(&Hyperreal::from_algebraic(a.clone())),
1154        Num::Real(x) => Germ::constant(x),
1155        Num::Hyper(h, _) => Germ::from_hyperreal(h),
1156        Num::Closed(c, _) => closed_germ(c),
1157        Num::Germ(g, _) => g.clone(),
1158        Num::Nat(n, _) => Germ::from_hyperreal(n.to_hyperreal().single()?),
1159        Num::Ord(_) | Num::Multi(_) | Num::Nested(_) => return None,
1160    })
1161}
1162
1163/// A value of the real closure by its series.
1164fn closed_germ(c: &Closed) -> Germ {
1165    match c {
1166        Closed::Field(h) => Germ::from_hyperreal(h),
1167        Closed::Series(p) => Germ::from_puiseux(p),
1168    }
1169}
1170
1171/// A number as a germ: a standard number as a constant, a hyperreal by its series or as the germ
1172/// it is, an infinite integer that does not depend on the residue by its series; `None` otherwise.
1173pub fn germ_of<V: TowerValue>(v: &V) -> Option<Germ> {
1174    to_germ(&classify(v)?)
1175}
1176
1177/// An infinite integer that depends on the residue as the dependence its classes make — on each, the
1178/// infinite integer it is there, on that class's own scale, whose facts make it one — so an operation
1179/// with a germ or a value of another infinitesimal lifts over its classes and an integer stays one. The
1180/// dependence is left as its classes make it: in its canonical form it is the infinite integer again,
1181/// and the operation's answer is made canonical as it is joined ([`map_depends`]).
1182fn lifted_natural<V: TowerValue>(n: &Num) -> Option<V> {
1183    let Num::Nat(nat, scale) = n else {
1184        return None;
1185    };
1186    let classes = nat.depends();
1187    if classes.single().is_some() {
1188        return None;
1189    }
1190    let (ty, m) = (classes.residue_type().clone(), classes.modulus());
1191    let raw = (0..m)
1192        .map(|h| {
1193            let p = classes.at(h)?;
1194            let class = Arc::new(scale.with_residues(ty.and(&ResidueType::congruent(h, m)).ok()?));
1195            let on_class = Hypernatural::from_polynomial(p.clone(), &class.residues)?;
1196            Some(Branch(from_natural(on_class, &class)))
1197        })
1198        .collect();
1199    Some(V::depends(DependsValue {
1200        value: Depends::from_branches(ty, m, raw)?,
1201        scale: scale.clone(),
1202    }))
1203}
1204
1205fn germ_arith<V: TowerValue>(
1206    op: Op,
1207    a: &Num,
1208    b: &Num,
1209    left: &V,
1210    right: &V,
1211    recurse: &dyn Fn(Op, V, V) -> Result<V, String>,
1212) -> Option<Result<V, String>> {
1213    if !calls_for_germs(a, b) {
1214        return None;
1215    }
1216    if let Err(e) = same_scale(a, b) {
1217        return Some(Err(e));
1218    }
1219    if let Some(l) = lifted_natural(a) {
1220        return Some(recurse(op, l, right.clone()));
1221    }
1222    if let Some(r) = lifted_natural(b) {
1223        return Some(recurse(op, left.clone(), r));
1224    }
1225    if let Some(r) = germ_identity(op, a, b, left, right) {
1226        return Some(Ok(r));
1227    }
1228    let scale = scale_of(a, b).expect("a germ or an infinitesimal is on one side");
1229    let (Some(x), Some(y)) = (to_germ(a), to_germ(b)) else {
1230        return Some(Err(format!(
1231            "cannot {} {} and {}",
1232            op.word(),
1233            left.type_name(),
1234            right.type_name()
1235        )));
1236    };
1237    let text = |e: crate::germ::GermError| e.to_string();
1238    let same = || x.is_transmissible() && y.is_transmissible() && x.to_bytes() == y.to_bytes();
1239    let result = match op {
1240        Op::Add => Ok(x.add(&y)),
1241        Op::Sub if same() => Ok(Germ::from_i64(0)),
1242        Op::Sub => Ok(x.sub(&y)),
1243        Op::Mul => Ok(x.mul(&y)),
1244        Op::Div | Op::ExactDiv => x.div(&y).map_err(text),
1245        Op::Pow => match (integer_exponent(right), fractional_exponent(right)) {
1246            (Some(k), _) => germ_power(&x, k).map_err(text),
1247            (None, Some((p, q))) => x.root(q).and_then(|r| germ_power(&r, p)).map_err(text),
1248            (None, None) => {
1249                Err("a value of the infinitesimal is raised only to an integer or a rational power".to_string())
1250            }
1251        },
1252        Op::FloorDiv | Op::Mod => Err(
1253            "the integer part of a quotient of these values is not an exact value; divide exactly"
1254                .to_string(),
1255        ),
1256    };
1257    Some(result.map(|g| from_germ(g, &scale)))
1258}
1259
1260/// The value an operation with an exact `0` or `1` leaves as it was: `x + 0`, `x − 0`, `x·1`, `x/1`,
1261/// `x·0`. A germ is known by the recipe that built it, so the identities keep one value one recipe.
1262fn germ_identity<V: TowerValue>(op: Op, a: &Num, b: &Num, left: &V, right: &V) -> Option<V> {
1263    let is = |n: &Num, k: i64| matches!(n, Num::Rat(r) if *r == Rational::from_i64(k));
1264    match op {
1265        Op::Add if is(a, 0) => Some(right.clone()),
1266        Op::Add | Op::Sub if is(b, 0) => Some(left.clone()),
1267        Op::Mul if is(a, 1) => Some(right.clone()),
1268        Op::Mul | Op::Div | Op::ExactDiv if is(b, 1) => Some(left.clone()),
1269        Op::Mul if is(a, 0) || is(b, 0) => Some(V::from_bigint(BigInt::from_i64(0))),
1270        _ => None,
1271    }
1272}
1273
1274fn germ_power(x: &Germ, k: i32) -> Result<Germ, crate::germ::GermError> {
1275    let mut base = if k < 0 { x.recip()? } else { x.clone() };
1276    let mut acc = Germ::from_i64(1);
1277    let mut e = k.unsigned_abs();
1278    while e > 0 {
1279        if e & 1 == 1 {
1280            acc = acc.mul(&base);
1281        }
1282        e >>= 1;
1283        if e > 0 {
1284            base = base.mul(&base);
1285        }
1286    }
1287    Ok(acc)
1288}
1289
1290fn germ_relation<V: TowerValue>(
1291    rel: Rel,
1292    a: &Num,
1293    b: &Num,
1294    left: &V,
1295    right: &V,
1296    recurse: &dyn Fn(Rel, V, V) -> Result<V, String>,
1297) -> Option<Result<V, String>> {
1298    if !calls_for_germs(a, b) {
1299        return None;
1300    }
1301    if let Err(e) = same_scale(a, b) {
1302        return Some(Err(e));
1303    }
1304    if let Some(l) = lifted_natural(a) {
1305        return Some(recurse(rel, l, right.clone()));
1306    }
1307    if let Some(r) = lifted_natural(b) {
1308        return Some(recurse(rel, left.clone(), r));
1309    }
1310    let (Some(x), Some(y)) = (to_germ(a), to_germ(b)) else {
1311        return Some(Err(format!(
1312            "cannot compare {} and {}",
1313            left.type_name(),
1314            right.type_name()
1315        )));
1316    };
1317    if x.is_transmissible() && y.is_transmissible() && x.to_bytes() == y.to_bytes() {
1318        return Some(Ok(V::boolean(rel.holds(Ordering::Equal))));
1319    }
1320    Some(match x.sub(&y).signum() {
1321        Ok(s) => Ok(V::boolean(rel.holds(s.cmp(&0)))),
1322        Err(e) => Err(e.to_string()),
1323    })
1324}
1325
1326/// Lift a binary operation over residue branches or provisional values; `None` when neither
1327/// operand is one.
1328fn lift<V: TowerValue>(
1329    left: &V,
1330    right: &V,
1331    f: impl Fn(V, V) -> Result<V, String>,
1332) -> Option<Result<V, String>> {
1333    match (left.exact(), right.exact()) {
1334        (Some(ExactRef::Converging(c)), _) => {
1335            let inner = f(c.value().clone(), right.clone());
1336            Some(inner.map(|v| carry_evidence(c, v)))
1337        }
1338        (_, Some(ExactRef::Converging(c))) => {
1339            let inner = f(left.clone(), c.value().clone());
1340            Some(inner.map(|v| carry_evidence(c, v)))
1341        }
1342        _ if residue_generators_differ(left, right) => {
1343            let (a, b) = (residue_generator(left)?, residue_generator(right)?);
1344            if a.order(b).is_none() {
1345                return Some(Err(a.unordered(b)));
1346            }
1347            Some(map_depends(&residue_branches(left)?, |x| f(x, right.clone())))
1348        }
1349        (Some(ExactRef::Depends(a)), Some(ExactRef::Depends(b))) => {
1350            let err = RefCell::new(None);
1351            let joined = a
1352                .value
1353                .zip_with(&b.value, |x, y| capture(&err, f(x.0.clone(), y.0.clone())));
1354            Some(match (joined, err.into_inner()) {
1355                (Err(e), _) => Err(a.scale.refuse(e)),
1356                (_, Some(e)) => Err(e),
1357                (Ok(joined), None) => Ok(from_depends(joined, &a.scale)),
1358            })
1359        }
1360        (Some(ExactRef::Depends(a)), _) => Some(map_depends(a, |x| f(x, right.clone()))),
1361        (_, Some(ExactRef::Depends(b))) => Some(map_depends(b, |y| f(left.clone(), y))),
1362        _ => None,
1363    }
1364}
1365
1366/// The generator whose residue `v` reads at its top — a residue-dependent value's, or an infinite
1367/// integer's that depends on the residue — or `None` for any other value.
1368fn residue_generator<V: TowerValue>(v: &V) -> Option<&Arc<Scale>> {
1369    match v.exact()? {
1370        ExactRef::Depends(d) => Some(&d.scale),
1371        ExactRef::Natural(n) if n.value.depends().single().is_none() => Some(&n.scale),
1372        _ => None,
1373    }
1374}
1375
1376/// Every generator whose residue `v` reads, coarsest first, its branches' own included, each once.
1377fn generators_read<V: TowerValue>(v: &V, out: &mut Vec<Arc<Scale>>) {
1378    let Some(g) = residue_generator(v) else {
1379        return;
1380    };
1381    if !out.iter().any(|o| o.same_infinitesimal(g)) {
1382        out.push(g.clone());
1383    }
1384    if let Some(d) = depends_of(v) {
1385        for (_, b) in d.value.branches() {
1386            generators_read(&b.0, out);
1387        }
1388    }
1389}
1390
1391/// Whether both operands read the residue of a generator and the two are of different
1392/// infinitesimals. An operation on two such maps over the classes of either, and [`from_depends`]
1393/// nests the answer in its one form, a dependence on the coarsest — the generator of the largest
1394/// infinitesimal — whose branches read only finer ones: `(0 when ⌈1/dx⌉ is even, 1 when it is odd)`
1395/// added to a value that depends on `⌈1/dt⌉` is a dependence on `⌈1/dt⌉` whose branches depend on
1396/// `⌈1/dx⌉`. The residues of two generators are independent — a program states each one's alone —
1397/// so every pair of classes is a case.
1398fn residue_generators_differ<V: TowerValue>(left: &V, right: &V) -> bool {
1399    matches!((residue_generator(left), residue_generator(right)), (Some(a), Some(b)) if !a.same_infinitesimal(b))
1400}
1401
1402/// `v`'s dependence on the residue of its generator, branch by branch: a residue-dependent value's
1403/// own, and an infinite integer's as the hyperreal it is on each class.
1404fn residue_branches<V: TowerValue>(v: &V) -> Option<DependsValue<V>> {
1405    match v.exact()? {
1406        ExactRef::Depends(d) => Some(d.clone()),
1407        ExactRef::Natural(n) => Some(DependsValue {
1408            value: n.value.to_hyperreal().map(|h| Branch(from_hyper(h.clone(), &n.scale))),
1409            scale: n.scale.clone(),
1410        }),
1411        _ => None,
1412    }
1413}
1414
1415/// A branch's value, or the first error any branch raised (kept in `err`; the branch itself is
1416/// then a placeholder the caller discards).
1417fn capture<V: TowerValue>(err: &RefCell<Option<String>>, r: Result<V, String>) -> Branch<V> {
1418    match r {
1419        Ok(v) => Branch(v),
1420        Err(e) => {
1421            err.borrow_mut().get_or_insert(e);
1422            Branch(V::nothing())
1423        }
1424    }
1425}
1426
1427/// `f` on every branch of a residue-dependent value, or the first error a branch raises.
1428pub fn map_depends<V: TowerValue>(
1429    d: &DependsValue<V>,
1430    f: impl Fn(V) -> Result<V, String>,
1431) -> Result<V, String> {
1432    let err = RefCell::new(None);
1433    let mapped = d.value.map(|x| capture(&err, f(x.0.clone())));
1434    match err.into_inner() {
1435        Some(e) => Err(e),
1436        None => Ok(from_depends(mapped, &d.scale)),
1437    }
1438}
1439
1440/// `v` carrying the evidence a provisional or settled answer `c` carries. An answer never holds
1441/// another: when `v` carries evidence of its own, the two join into one ([`Converging::joined`]).
1442pub fn carry_evidence<V: TowerValue, U>(c: &Converging<U>, v: V) -> V {
1443    if let Some(ExactRef::Converging(own)) = v.exact() {
1444        return V::converging(c.joined(own, own.value().clone()));
1445    }
1446    match c.certificate() {
1447        Some(cert) => V::converging(Converging::settled(v, cert)),
1448        None => V::converging(Converging::provisional(v, c.steps(), c.revisions())),
1449    }
1450}
1451
1452fn arith_num<V: TowerValue>(op: Op, a: Num, b: Num, left: &V, right: &V) -> Result<V, String> {
1453    same_scale(&a, &b)?;
1454    let refuse = || {
1455        Err(format!(
1456            "cannot {} {} and {}",
1457            op.word(),
1458            left.type_name(),
1459            right.type_name()
1460        ))
1461    };
1462    // Ordinals meet only ordinals and naturals.
1463    if matches!(a, Num::Ord(_)) || matches!(b, Num::Ord(_)) {
1464        return ordinal_arith(op, &a, &b).unwrap_or_else(refuse);
1465    }
1466    // An infinite integer with a standard integer keeps integer meaning.
1467    let integral = |n: &Num, v: &V| matches!(n, Num::Nat(..)) || v.integer().is_some();
1468    if (matches!(a, Num::Nat(..)) || matches!(b, Num::Nat(..)))
1469        && integral(&a, left)
1470        && integral(&b, right)
1471        && !matches!(op, Op::Div | Op::ExactDiv)
1472    {
1473        let scale = scale_of(&a, &b).expect("an infinite integer has a scale");
1474        let x = to_natural(&a, &scale.residues).expect("integral");
1475        let y = to_natural(&b, &scale.residues).expect("integral");
1476        return natural_arith(op, x, y, right, &scale);
1477    }
1478    if let Some(r) = closed_arith(op, &a, &b, right) {
1479        return r;
1480    }
1481    // The infinitesimal generates the hyperreals over the algebraic numbers.
1482    if let Some(scale) = scale_of(&a, &b) {
1483        let x = to_hyper_branches(&a, &scale.residues).expect("hyperreal operand");
1484        let y = to_hyper_branches(&b, &scale.residues).expect("hyperreal operand");
1485        let err = RefCell::new(None);
1486        let out = x.zip_with(&y, |p, q| {
1487            capture(&err, hyper_op(op, p, q, right, &scale).map(|v| from_hyper(v, &scale)))
1488        });
1489        return match (out, err.into_inner()) {
1490            (Err(e), _) => Err(scale.refuse(e)),
1491            (_, Some(e)) => Err(e),
1492            (Ok(out), None) => Ok(from_depends(out, &scale)),
1493        };
1494    }
1495    // Computable reals above the algebraic numbers.
1496    if matches!(a, Num::Real(_)) || matches!(b, Num::Real(_)) {
1497        let (x, y) = (to_real(&a).expect("real operand"), to_real(&b).expect("real operand"));
1498        return real_op(op, &x, &y, right).map(from_exact_real);
1499    }
1500    match (to_alg(&a), to_alg(&b)) {
1501        (Some(x), Some(y)) => alg_op(op, &x, &y, right).map(from_algebraic),
1502        _ => refuse(),
1503    }
1504}
1505
1506fn integer_exponent<V: TowerValue>(v: &V) -> Option<i32> {
1507    v.integer()
1508        .and_then(|b| b.to_i64())
1509        .and_then(|e| i32::try_from(e).ok())
1510}
1511
1512/// An exponent `p/q` held exactly with `q > 1`: a root to take and a power to raise it to.
1513fn fractional_exponent<V: TowerValue>(v: &V) -> Option<(i32, u32)> {
1514    let r = v.exact_rational().filter(|r| !r.is_integer())?;
1515    let p = i32::try_from(r.numerator().to_i64()?).ok()?;
1516    let q = u32::try_from(r.denominator().to_i64()?).ok()?;
1517    Some((p, q))
1518}
1519
1520/// An operand of the real closure, on each residue class of `⌈1/dt⌉` an infinite integer depends
1521/// on; `None` for a germ, a computable real or an ordinal.
1522fn to_closed_branches(n: &Num, ty: &ResidueType) -> Option<Depends<Closed>> {
1523    match n {
1524        Num::Rat(r) => Some(Depends::constant(Closed::Field(Hyperreal::from_rational(r.clone())), ty)),
1525        Num::Alg(a) => Some(Depends::constant(Closed::Field(Hyperreal::from_algebraic(a.clone())), ty)),
1526        Num::Hyper(h, _) => Some(Depends::constant(Closed::Field(h.clone()), ty)),
1527        Num::Closed(c, _) => Some(Depends::constant(c.clone(), ty)),
1528        Num::Nat(n, _) => Some(n.to_hyperreal().map(|h| Closed::Field(h.clone()))),
1529        Num::Real(_) | Num::Germ(..) | Num::Ord(_) | Num::Multi(_) | Num::Nested(_) => None,
1530    }
1531}
1532
1533/// An operation in the real closure of the hyperreals: when a root of a hyperreal is an operand, or
1534/// a hyperreal or an infinite integer is raised to a fractional power.
1535fn closed_arith<V: TowerValue>(op: Op, a: &Num, b: &Num, right: &V) -> Option<Result<V, String>> {
1536    let rooted = matches!(a, Num::Closed(..)) || matches!(b, Num::Closed(..));
1537    let fractional = matches!(op, Op::Pow)
1538        && matches!(a, Num::Hyper(..) | Num::Nat(..))
1539        && fractional_exponent(right).is_some();
1540    if !rooted && !fractional {
1541        return None;
1542    }
1543    let scale = scale_of(a, b)?;
1544    let x = to_closed_branches(a, &scale.residues)?;
1545    let y = to_closed_branches(b, &scale.residues)?;
1546    let err = RefCell::new(None);
1547    let out = x.zip_with(&y, |p, q| capture(&err, closed_op(op, p, q, right, &scale).map(|c| from_closed(c, &scale))));
1548    Some(match (out, err.into_inner()) {
1549        (Err(e), _) => Err(scale.refuse(e)),
1550        (_, Some(e)) => Err(e),
1551        (Ok(out), None) => Ok(from_depends(out, &scale)),
1552    })
1553}
1554
1555fn closed_op<V: TowerValue>(op: Op, x: &Closed, y: &Closed, right: &V, scale: &Scale) -> Result<Closed, String> {
1556    match op {
1557        Op::Add => Ok(x.add(y)),
1558        Op::Sub => Ok(x.sub(y)),
1559        Op::Mul => Ok(x.mul(y)),
1560        Op::Div | Op::ExactDiv => x.div(y).ok_or_else(|| "Division by zero".to_string()),
1561        Op::Pow => match (integer_exponent(right), fractional_exponent(right)) {
1562            (Some(k), _) => x.pow(k).map_err(|e| e.describe(&scale.name)),
1563            (None, Some((p, q))) => x.root(q)?.pow(p).map_err(|e| e.describe(&scale.name)),
1564            (None, None) => Err("a hyperreal is raised only to an integer or a rational power".to_string()),
1565        },
1566        Op::FloorDiv | Op::Mod => Err(
1567            "the integer part of a hyperreal quotient is not an exact hyperreal; divide exactly".to_string(),
1568        ),
1569    }
1570}
1571
1572fn alg_op<V: TowerValue>(op: Op, x: &Algebraic, y: &Algebraic, right: &V) -> Result<Algebraic, String> {
1573    match op {
1574        Op::Add => Ok(x.add(y)),
1575        Op::Sub => Ok(x.sub(y)),
1576        Op::Mul => Ok(x.mul(y)),
1577        Op::Div | Op::ExactDiv => x.div(y).ok_or_else(|| "Division by zero".to_string()),
1578        Op::FloorDiv => {
1579            let q = x.div(y).ok_or_else(|| "Division by zero".to_string())?;
1580            Ok(Algebraic::from_rational(Rational::from_bigint(q.floor())))
1581        }
1582        Op::Mod => {
1583            let q = x.div(y).ok_or_else(|| "Division by zero".to_string())?;
1584            Ok(x.sub(&y.mul(&Algebraic::from_rational(Rational::from_bigint(q.floor())))))
1585        }
1586        Op::Pow => match (integer_exponent(right), fractional_exponent(right)) {
1587            (Some(k), _) => x
1588                .pow(k)
1589                .ok_or_else(|| "zero cannot be raised to a negative power".to_string()),
1590            (None, Some((p, q))) => x
1591                .nth_root(q)
1592                .ok_or_else(|| negative_root(q))?
1593                .pow(p)
1594                .ok_or_else(|| "zero cannot be raised to a negative power".to_string()),
1595            (None, None) => Err("an algebraic number is raised only to an integer or a rational power".to_string()),
1596        },
1597    }
1598}
1599
1600fn real_op<V: TowerValue>(op: Op, x: &ExactReal, y: &ExactReal, right: &V) -> Result<ExactReal, String> {
1601    match op {
1602        Op::Add => Ok(x.add(y)),
1603        Op::Sub => Ok(x.sub(y)),
1604        Op::Mul => Ok(x.mul(y)),
1605        Op::Div | Op::ExactDiv => x.div(y).map_err(|e| e.to_string()),
1606        Op::FloorDiv | Op::Mod => {
1607            let q = x.div(y).map_err(|e| e.to_string())?;
1608            let f = ExactReal::from_rational(Rational::from_bigint(
1609                q.floor(DEFAULT_BUDGET).map_err(|e| e.to_string())?,
1610            ));
1611            Ok(if op == Op::FloorDiv { f } else { x.sub(&y.mul(&f)) })
1612        }
1613        Op::Pow => match (integer_exponent(right), fractional_exponent(right)) {
1614            (Some(k), _) => x
1615                .pow(k)
1616                .ok_or_else(|| "zero cannot be raised to a negative power".to_string()),
1617            (None, Some((p, q))) => real_fractional_power(x, p, q),
1618            (None, None) => Err("a computable real is raised only to an integer or a rational power".to_string()),
1619        },
1620    }
1621}
1622
1623/// `x^(p/q)` for `q > 1`: the power of its real `q`-th root ([`ExactReal::nth_root`]), refused for an
1624/// even root of a negative `x` and for zero to a negative power.
1625fn real_fractional_power(x: &ExactReal, p: i32, q: u32) -> Result<ExactReal, String> {
1626    let sign = x.compare(&ExactReal::from_i64(0), DEFAULT_BUDGET).map_err(|e| e.to_string())?;
1627    match sign {
1628        Ordering::Equal if p > 0 => return Ok(ExactReal::from_i64(0)),
1629        Ordering::Equal => return Err("zero cannot be raised to a negative power".to_string()),
1630        Ordering::Less if q % 2 == 0 => return Err(negative_root(q)),
1631        _ => {}
1632    }
1633    let root = x.nth_root(q).map_err(|e| e.to_string())?;
1634    root.pow(p).ok_or_else(|| "zero cannot be raised to a negative power".to_string())
1635}
1636
1637fn hyper_op<V: TowerValue>(
1638    op: Op,
1639    x: &Hyperreal,
1640    y: &Hyperreal,
1641    right: &V,
1642    scale: &Scale,
1643) -> Result<Hyperreal, String> {
1644    match op {
1645        Op::Add => Ok(x.add(y)),
1646        Op::Sub => Ok(x.sub(y)),
1647        Op::Mul => Ok(x.mul(y)),
1648        Op::Div | Op::ExactDiv => x.div(y).ok_or_else(|| "Division by zero".to_string()),
1649        Op::Pow => match integer_exponent(right) {
1650            Some(k) => x.pow(k).map_err(|e| e.describe(&scale.name)),
1651            None => Err("a hyperreal is raised only to an integer power".to_string()),
1652        },
1653        Op::FloorDiv | Op::Mod => Err(
1654            "the integer part of a hyperreal quotient is not an exact hyperreal; divide exactly"
1655                .to_string(),
1656        ),
1657    }
1658}
1659
1660fn natural_arith<V: TowerValue>(
1661    op: Op,
1662    x: Hypernatural,
1663    y: Hypernatural,
1664    right: &V,
1665    scale: &Arc<Scale>,
1666) -> Result<V, String> {
1667    let standard_divisor = || -> Result<BigInt, String> {
1668        right
1669            .integer()
1670            .ok_or_else(|| "an infinite integer is divided only by a standard integer".to_string())
1671    };
1672    let refuse = |e| scale.refuse(e);
1673    match op {
1674        Op::Add => Ok(from_natural(x.add(&y).map_err(refuse)?, scale)),
1675        Op::Sub => Ok(from_natural(x.sub(&y).map_err(refuse)?, scale)),
1676        Op::Mul => Ok(from_natural(x.mul(&y).map_err(refuse)?, scale)),
1677        Op::FloorDiv => {
1678            let k = standard_divisor()?;
1679            if k.is_zero() {
1680                return Err("Division by zero".to_string());
1681            }
1682            let t = Rational::new(BigInt::from_i64(1), k).expect("k ≠ 0");
1683            Ok(from_natural(x.scaled_floor(&t).map_err(refuse)?, scale))
1684        }
1685        Op::Mod => {
1686            let k = standard_divisor()?;
1687            if !k.is_positive() {
1688                return Err(
1689                    "an infinite integer's remainder is taken by a positive standard integer"
1690                        .to_string(),
1691                );
1692            }
1693            let residues = x
1694                .rem(&k)
1695                .map_err(refuse)?
1696                .map(|r| Branch(V::from_bigint(r.clone())));
1697            Ok(from_depends(residues, scale))
1698        }
1699        Op::Pow => match right.integer().and_then(|b| b.to_u64()) {
1700            Some(k) => Ok(from_natural(
1701                x.pow(k).map_err(|e| e.describe(&scale.name))?,
1702                scale,
1703            )),
1704            None => Err("an infinite integer is raised only to a natural power".to_string()),
1705        },
1706        Op::Div | Op::ExactDiv => {
1707            unreachable!("exact division of infinite integers goes through the hyperreals")
1708        }
1709    }
1710}
1711
1712fn as_ordinal(n: &Num) -> Option<Ordinal> {
1713    match n {
1714        Num::Ord(o) => Some(o.clone()),
1715        Num::Rat(r) if r.is_integer() && !r.is_negative() => {
1716            Some(Ordinal::from_natural(r.to_bigint().expect("an integer")))
1717        }
1718        _ => None,
1719    }
1720}
1721
1722fn ordinal_arith<V: TowerValue>(op: Op, a: &Num, b: &Num) -> Option<Result<V, String>> {
1723    let (x, y) = (as_ordinal(a)?, as_ordinal(b)?);
1724    Some(match op {
1725        Op::Add => Ok(from_ordinal(x.add(&y))),
1726        Op::Mul => Ok(from_ordinal(x.mul(&y))),
1727        Op::Pow => Ok(from_ordinal(x.pow(&y))),
1728        _ => Err(format!(
1729            "ordinals add, multiply and exponentiate; they do not {}",
1730            op.word()
1731        )),
1732    })
1733}
1734
1735/// The relational operators the exact types answer.
1736#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1737pub enum Rel {
1738    Lt,
1739    Gt,
1740    LtEq,
1741    GtEq,
1742    Eq,
1743    NotEq,
1744}
1745
1746impl Rel {
1747    fn holds(self, o: Ordering) -> bool {
1748        match self {
1749            Rel::Lt => o == Ordering::Less,
1750            Rel::Gt => o == Ordering::Greater,
1751            Rel::LtEq => o != Ordering::Greater,
1752            Rel::GtEq => o != Ordering::Less,
1753            Rel::Eq => o == Ordering::Equal,
1754            Rel::NotEq => o != Ordering::Equal,
1755        }
1756    }
1757}
1758
1759/// Apply `rel` when either operand is an exact type; `None` when neither is. The answer is a
1760/// `Bool`, or a residue-dependent `Bool` when it depends on `⌈1/dt⌉`; a comparison no theorem
1761/// decides within the budget is a loud error.
1762pub fn relation<V: TowerValue>(
1763    rel: Rel,
1764    left: &V,
1765    right: &V,
1766    recurse: &dyn Fn(Rel, V, V) -> Result<V, String>,
1767) -> Option<Result<V, String>> {
1768    if !is_exact_value(left) && !is_exact_value(right) {
1769        return None;
1770    }
1771    if let Some(r) = lift(left, right, |a, b| recurse(rel, a, b)) {
1772        return Some(r);
1773    }
1774    let (Some(a), Some(b)) = (classify(left), classify(right)) else {
1775        if matches!(rel, Rel::Eq | Rel::NotEq) {
1776            return Some(Ok(V::boolean(rel == Rel::NotEq)));
1777        }
1778        return Some(Err(format!(
1779            "cannot compare {} and {}",
1780            left.type_name(),
1781            right.type_name()
1782        )));
1783    };
1784    if let Some(r) = several_relation(rel, &a, &b, left, right, recurse) {
1785        return Some(r);
1786    }
1787    if let Some(r) = germ_relation(rel, &a, &b, left, right, recurse) {
1788        return Some(r);
1789    }
1790    Some(relation_num(rel, a, b))
1791}
1792
1793fn relation_num<V: TowerValue>(rel: Rel, a: Num, b: Num) -> Result<V, String> {
1794    same_scale(&a, &b)?;
1795    let answer = |o: Ordering| Ok(V::boolean(rel.holds(o)));
1796    if matches!(a, Num::Ord(_)) || matches!(b, Num::Ord(_)) {
1797        return match (as_ordinal(&a), as_ordinal(&b)) {
1798            (Some(x), Some(y)) => answer(x.cmp(&y)),
1799            _ => Err("an ordinal compares only with ordinals and naturals".to_string()),
1800        };
1801    }
1802    if let Some(scale) = scale_of(&a, &b) {
1803        if matches!(a, Num::Closed(..)) || matches!(b, Num::Closed(..)) {
1804            let x = to_closed_branches(&a, &scale.residues).expect("an operand of the real closure");
1805            let y = to_closed_branches(&b, &scale.residues).expect("an operand of the real closure");
1806            let out = x
1807                .zip_with(&y, |p, q| Branch(V::boolean(rel.holds(p.compare(q)))))
1808                .map_err(|e| scale.refuse(e))?;
1809            return Ok(from_depends(out, &scale));
1810        }
1811        let x = to_hyper_branches(&a, &scale.residues).expect("hyperreal operand");
1812        let y = to_hyper_branches(&b, &scale.residues).expect("hyperreal operand");
1813        let out = x
1814            .zip_with(&y, |p, q| Branch(V::boolean(rel.holds(p.cmp(q)))))
1815            .map_err(|e| scale.refuse(e))?;
1816        return Ok(from_depends(out, &scale));
1817    }
1818    if matches!(a, Num::Real(_)) || matches!(b, Num::Real(_)) {
1819        let (x, y) = (to_real(&a).expect("real"), to_real(&b).expect("real"));
1820        return x
1821            .compare(&y, DEFAULT_BUDGET)
1822            .map_err(|e| e.to_string())
1823            .and_then(answer);
1824    }
1825    match (to_alg(&a), to_alg(&b)) {
1826        (Some(x), Some(y)) => answer(x.cmp(&y)),
1827        _ => Err("cannot compare these values".to_string()),
1828    }
1829}
1830
1831/// Structural equality for collections and hashing: exact forms by value, a general computable
1832/// real by the formula that built it; `None` when neither value is an exact type.
1833pub fn structurally_equal<V: TowerValue>(left: &V, right: &V) -> Option<bool> {
1834    Some(match (left.exact(), right.exact()) {
1835        (Some(ExactRef::Algebraic(a)), Some(ExactRef::Algebraic(b))) => a == b,
1836        (Some(ExactRef::Hyper(a)), Some(ExactRef::Hyper(b))) => a.value == b.value,
1837        (Some(ExactRef::Natural(a)), Some(ExactRef::Natural(b))) => a.value == b.value,
1838        (Some(ExactRef::Ordinal(a)), Some(ExactRef::Ordinal(b))) => a == b,
1839        (Some(ExactRef::Real(a)), Some(ExactRef::Real(b))) => {
1840            if a.is_exact_form() && b.is_exact_form() {
1841                a.compare(b, DEFAULT_BUDGET) == Ok(Ordering::Equal)
1842            } else {
1843                a.describe() == b.describe()
1844            }
1845        }
1846        (Some(ExactRef::Depends(a)), Some(ExactRef::Depends(b))) => a.value == b.value,
1847        (Some(ExactRef::Converging(a)), Some(ExactRef::Converging(b))) => {
1848            a.value().values_equal(b.value())
1849                && a.certificate() == b.certificate()
1850                && a.steps() == b.steps()
1851                && a.revisions() == b.revisions()
1852        }
1853        (None, None) => return None,
1854        _ => false,
1855    })
1856}
1857
1858/// How an exact value prints; `None` for any other value.
1859pub fn display<V: TowerValue>(v: &V) -> Option<String> {
1860    Some(match v.exact()? {
1861        ExactRef::Algebraic(a) => a.to_string(),
1862        ExactRef::Real(x) => x.to_string(),
1863        ExactRef::Hyper(h) => h.value.render(&h.scale.name),
1864        ExactRef::Natural(n) => n.value.render_reciprocal(&n.scale.name),
1865        ExactRef::Ordinal(o) => o.to_string(),
1866        ExactRef::Depends(d) => d.value.render(&d.scale.generator_text(), |b| match residue_generator(&b.0) {
1867            Some(_) => format!("({})", b.0.display_string()),
1868            None => b.0.display_string(),
1869        }),
1870        ExactRef::Converging(c) => c.render(|v| v.display_string()),
1871    })
1872}
1873
1874/// The standard part: a hyperreal's standard value, branch by branch for a residue-dependent
1875/// value; a standard value is its own. An infinite value has none.
1876pub fn standard_part<V: TowerValue>(v: &V) -> Result<V, String> {
1877    if v.is_standard_number() {
1878        return Ok(v.clone());
1879    }
1880    match v.exact() {
1881        Some(ExactRef::Hyper(h)) => match &h.value {
1882            HyperForm::Rational(r) => match r.standard_part() {
1883                Some(s) => Ok(from_algebraic(s)),
1884                None => Err(format!(
1885                    "{} is infinite and has no standard part",
1886                    r.render(&h.scale.name)
1887                )),
1888            },
1889            HyperForm::Puiseux(p) => {
1890                let value = Closed::Series(p.clone());
1891                match value.standard_part() {
1892                    Some(s) => Ok(from_algebraic(s)),
1893                    None => Err(format!(
1894                        "{} is infinite and has no standard part",
1895                        value.render(&h.scale.name)
1896                    )),
1897                }
1898            }
1899            HyperForm::Germ(g) => match g.standard_part().map_err(|e| e.to_string())? {
1900                Some(s) => Ok(from_exact_real(s)),
1901                None => Err(format!(
1902                    "{} is infinite and has no standard part",
1903                    g.render(&h.scale.name)
1904                )),
1905            },
1906            HyperForm::Multi(m) | HyperForm::Integer(m) => match m.standard_part() {
1907                Some(s) => Ok(from_algebraic(s)),
1908                None => Err(format!("{} is infinite and has no standard part", m.render())),
1909            },
1910            HyperForm::Nested(g) => match g.standard_part_at(None)? {
1911                Some(s) => Ok(from_number(s)),
1912                None => Err(format!("{} is infinite and has no standard part", g.render())),
1913            },
1914        },
1915        Some(ExactRef::Natural(n)) => Err(format!(
1916            "{} is infinite and has no standard part",
1917            n.value.render_reciprocal(&n.scale.name)
1918        )),
1919        Some(ExactRef::Depends(d)) => map_depends(d, |b| standard_part(&b)),
1920        Some(ExactRef::Converging(c)) => standard_part(c.value()).map(|s| carry_evidence(c, s)),
1921        Some(ExactRef::Algebraic(_)) | Some(ExactRef::Real(_)) => Ok(v.clone()),
1922        Some(ExactRef::Ordinal(_)) | None => Err(format!(
1923            "the standard part of a {} is undefined",
1924            v.type_name()
1925        )),
1926    }
1927}
1928
1929/// How an integer part rounds: down, up, or to the nearest integer with ties away from zero (the
1930/// tower's `round`).
1931#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1932pub enum Rounding {
1933    Floor,
1934    Ceil,
1935    Nearest,
1936}
1937
1938/// The integer part of an exact value under `mode`; `None` when `v` is not one (the tower handles
1939/// it). `recurse` is the builtin itself, for the standard values inside a dependence or a
1940/// provisional answer.
1941pub fn integer_part<V: TowerValue>(
1942    v: &V,
1943    mode: Rounding,
1944    recurse: &dyn Fn(V) -> Result<V, String>,
1945) -> Option<Result<V, String>> {
1946    Some(match v.exact()? {
1947        ExactRef::Natural(_) | ExactRef::Ordinal(_) => Ok(v.clone()),
1948        ExactRef::Depends(d) => map_depends(d, recurse),
1949        ExactRef::Converging(c) => recurse(c.value().clone()).map(|x| carry_evidence(c, x)),
1950        ExactRef::Algebraic(a) => Ok(V::from_bigint(algebraic_integer_part(a, mode))),
1951        ExactRef::Real(x) => real_integer_part(x, mode).map(V::from_bigint),
1952        ExactRef::Hyper(h) => hyper_integer_part(h, mode),
1953    })
1954}
1955
1956fn half() -> Rational {
1957    Rational::from_ratio_i64(1, 2).expect("a nonzero denominator")
1958}
1959
1960fn algebraic_integer_part(a: &Algebraic, mode: Rounding) -> BigInt {
1961    match mode {
1962        Rounding::Floor => a.floor(),
1963        Rounding::Ceil => a.ceil(),
1964        Rounding::Nearest => {
1965            let magnitude = if a.signum() < 0 { a.neg() } else { a.clone() };
1966            let m = magnitude.add(&Algebraic::from_rational(half())).floor();
1967            if a.signum() < 0 {
1968                m.negated()
1969            } else {
1970                m
1971            }
1972        }
1973    }
1974}
1975
1976fn real_integer_part(x: &ExactReal, mode: Rounding) -> Result<BigInt, String> {
1977    let floor = |y: &ExactReal| y.floor(DEFAULT_BUDGET).map_err(|e| e.to_string());
1978    match mode {
1979        Rounding::Floor => floor(x),
1980        Rounding::Ceil => Ok(floor(&x.neg())?.negated()),
1981        Rounding::Nearest => {
1982            let negative = x
1983                .compare(&ExactReal::from_i64(0), DEFAULT_BUDGET)
1984                .map_err(|e| e.to_string())?
1985                == Ordering::Less;
1986            let magnitude = if negative { x.neg() } else { x.clone() };
1987            let m = floor(&magnitude.add(&ExactReal::from_rational(half())))?;
1988            Ok(if negative { m.negated() } else { m })
1989        }
1990    }
1991}
1992
1993fn hyper_integer_part<V: TowerValue>(h: &HyperValue, mode: Rounding) -> Result<V, String> {
1994    let value = match &h.value {
1995        HyperForm::Rational(r) => r,
1996        HyperForm::Puiseux(p) => return closed_integer_part(&Closed::Series(p.clone()), mode, &h.scale.name),
1997        HyperForm::Germ(g) => return germ_integer_part(g, mode),
1998        HyperForm::Multi(m) => return multi_integer_part(m, mode),
1999        HyperForm::Integer(_) => return Ok(V::hyper(h.clone())),
2000        HyperForm::Nested(g) => return nested_integer_part(g, mode),
2001    };
2002    let ty = &h.scale.residues;
2003    let refuse = |e: crate::hypernatural::FloorError| e.describe(&h.scale.name);
2004    let natural = match mode {
2005        Rounding::Floor => Hypernatural::floor_of(value, ty).map_err(refuse)?,
2006        Rounding::Ceil => Hypernatural::ceil_of(value, ty).map_err(refuse)?,
2007        Rounding::Nearest => {
2008            let negative = value.signum() < 0;
2009            let magnitude = if negative { value.neg() } else { value.clone() };
2010            let m = Hypernatural::floor_of(&magnitude.add(&Hyperreal::from_rational(half())), ty)
2011                .map_err(refuse)?;
2012            if negative {
2013                m.neg()
2014            } else {
2015                m
2016            }
2017        }
2018    };
2019    Ok(from_natural(natural, &h.scale))
2020}
2021
2022/// The integer part of a limited root of a hyperreal: the floor of its standard part, one less when
2023/// the standard part is an integer the value lies below. An infinite one has no integer part this
2024/// value model holds, its floor being no polynomial in `⌈1/dt⌉`.
2025fn closed_integer_part<V: TowerValue>(x: &Closed, mode: Rounding, name: &str) -> Result<V, String> {
2026    let floor_of = |x: &Closed| -> Result<BigInt, String> {
2027        let st = x.standard_part().ok_or_else(|| {
2028            format!(
2029                "the integer part of {} is no polynomial in ⌈1/{name}⌉, the infinite integers a program holds",
2030                x.render(name)
2031            )
2032        })?;
2033        let fl = st.floor();
2034        let whole = Closed::Field(Hyperreal::from_rational(Rational::from_bigint(fl.clone())));
2035        if x.compare(&whole) == Ordering::Less {
2036            Ok(fl.sub(&BigInt::from_i64(1)))
2037        } else {
2038            Ok(fl)
2039        }
2040    };
2041    let n = match mode {
2042        Rounding::Floor => floor_of(x)?,
2043        Rounding::Ceil => floor_of(&x.neg())?.negated(),
2044        Rounding::Nearest => {
2045            let negative = x.signum() < 0;
2046            let magnitude = if negative { x.neg() } else { x.clone() };
2047            let half = Closed::Field(Hyperreal::from_rational(half()));
2048            let m = floor_of(&magnitude.add(&half))?;
2049            if negative {
2050                m.negated()
2051            } else {
2052                m
2053            }
2054        }
2055    };
2056    Ok(V::from_bigint(n))
2057}
2058
2059// ── integer parts of several infinitesimals ──────────────────────────────────────────────────
2060
2061/// The integer part of a value of several infinitesimals. See [`polar_floor`].
2062fn multi_integer_part<V: TowerValue>(x: &Multi, mode: Rounding) -> Result<V, String> {
2063    several_integer_part(x, mode, &|m| multi_polar(m), &Multi::neg, &|m| {
2064        m.add(&Multi::Standard(Algebraic::from_rational(half())))
2065    }, &|m| m.signum())
2066}
2067
2068/// The integer part of a germ of several infinitesimals. See [`polar_floor`].
2069fn nested_integer_part<V: TowerValue>(g: &Arc<NestedGerm>, mode: Rounding) -> Result<V, String> {
2070    let half = Arc::new(NestedGerm::constant(Number::from_rational(half()), &g.scale));
2071    let sign = |g: &Arc<NestedGerm>| g.sign().unwrap_or(0);
2072    several_integer_part(
2073        g,
2074        mode,
2075        &|g| nested_polar(g),
2076        &|g| Arc::new(NestedGerm::neg(g)),
2077        &|g| Arc::new(NestedGerm::add(g, &half)),
2078        &sign,
2079    )
2080}
2081
2082/// The integer part under `mode` of a value whose floor [`polar_floor`] reads from its `polar` split:
2083/// the ceiling the negated floor of the negation, the nearest integer the floor of the magnitude plus
2084/// a half, its sign restored.
2085fn several_integer_part<V: TowerValue, X: Clone>(
2086    x: &X,
2087    mode: Rounding,
2088    polar: &dyn Fn(&X) -> Result<Polar, String>,
2089    neg: &dyn Fn(&X) -> X,
2090    plus_half: &dyn Fn(&X) -> X,
2091    sign: &dyn Fn(&X) -> i32,
2092) -> Result<V, String> {
2093    let negated = |n: Number| Number::arith(Op::Sub, Number::from_bigint(BigInt::from_i64(0)), n);
2094    let n = match mode {
2095        Rounding::Floor => polar_floor(polar(x)?)?,
2096        Rounding::Ceil => negated(polar_floor(polar(&neg(x))?)?)?,
2097        Rounding::Nearest => {
2098            let negative = sign(x) < 0;
2099            let magnitude = if negative { neg(x) } else { x.clone() };
2100            let m = polar_floor(polar(&plus_half(&magnitude))?)?;
2101            if negative {
2102                negated(m)?
2103            } else {
2104                m
2105            }
2106        }
2107    };
2108    Ok(from_number(n))
2109}
2110
2111/// A value read in its smallest infinitesimal `ε`, over the larger ones: the coefficients of its terms
2112/// infinite in `ε`, its part constant in `ε`, and the sign of the rest — infinitesimal from every
2113/// larger infinitesimal's standpoint — read only when the floor needs it.
2114struct Polar {
2115    scale: Arc<Scale>,
2116    q: u32,
2117    /// The coefficient of `ε^(k/q)` for each `k < 0` with a nonzero one, a value of the larger
2118    /// infinitesimals.
2119    infinite: Vec<(i64, Number)>,
2120    constant: Number,
2121    rest: Box<dyn Fn() -> Result<i32, String>>,
2122    shown: String,
2123    generators: Vec<Arc<Scale>>,
2124}
2125
2126fn multi_polar(m: &Multi) -> Result<Polar, String> {
2127    let scale = m.top().expect("a value of several infinitesimals has a smallest").clone();
2128    let expansion = crate::closure::AlgValue::at(m, &scale).expansion;
2129    let (floor, q) = (expansion.floor().min(0), expansion.ramification());
2130    let terms: Vec<Multi> = (floor..=0)
2131        .map(|k| expansion.coefficient(k).map_err(|e| e.to_string()))
2132        .collect::<Result<_, _>>()?;
2133    let mut den = vec![Multi::zero(); (-floor) as usize + 1];
2134    den[(-floor) as usize] = Multi::Standard(Algebraic::from_i64(1));
2135    let polar = Multi::make(&scale, q, PolyOver::from(terms.clone()), PolyOver::from(den));
2136    let rest = m.sub(&polar);
2137    Ok(Polar {
2138        scale: scale.clone(),
2139        q,
2140        infinite: (floor..0)
2141            .zip(&terms)
2142            .filter(|(_, c)| !c.is_zero())
2143            .map(|(k, c)| (k, from_multi(c.clone())))
2144            .collect(),
2145        constant: from_multi(terms.last().expect("order 0 is read").clone()),
2146        rest: Box::new(move || Ok(rest.signum())),
2147        shown: m.render(),
2148        generators: m.scales(),
2149    })
2150}
2151
2152fn nested_polar(g: &Arc<NestedGerm>) -> Result<Polar, String> {
2153    let (floor, q) = (g.expansion.floor().min(0), g.expansion.ramification());
2154    let terms: Vec<Number> = (floor..=0)
2155        .map(|k| g.expansion.coefficient(k).map_err(|e| e.to_string()))
2156        .collect::<Result<_, _>>()?;
2157    let expansion = g.expansion.clone();
2158    let reach = crate::germ::SIGN_ORDERS * i64::from(q);
2159    Ok(Polar {
2160        scale: g.scale.clone(),
2161        q,
2162        infinite: (floor..0)
2163            .zip(&terms)
2164            .filter(|(_, c)| !matches!(c.standard_rational(), Some(r) if r.is_zero()))
2165            .map(|(k, c)| (k, c.clone()))
2166            .collect(),
2167        constant: terms.last().expect("order 0 is read").clone(),
2168        rest: Box::new(move || {
2169            for k in 1..=reach {
2170                let c = expansion.coefficient(k).map_err(|e| e.to_string())?;
2171                let s = crate::expansion::Coefficient::sign(&c).map_err(|e| e.to_string())?;
2172                if s != 0 {
2173                    return Ok(s);
2174                }
2175            }
2176            Err(crate::germ::GermError::Flat.to_string())
2177        }),
2178        shown: g.render(),
2179        generators: g.scales(),
2180    })
2181}
2182
2183/// The floor of a value `x` of several infinitesimals, from its split in its smallest one, `ε`:
2184/// `x = P + a + ρ`, `P = Σ_{j≥1} c_j·(1/ε)^j` its part infinite in `ε`, `a` a value of the larger
2185/// infinitesimals and `ρ` infinitesimal from all of their standpoints.
2186///
2187/// The floor is an infinite integer a program holds — a polynomial in the reciprocals of the
2188/// infinitesimals with rational coefficients on each residue class of each — exactly when every `c_j`
2189/// is one of the larger infinitesimals' reciprocals: `1/(dt·dx)` is `⌈1/dt⌉·⌈1/dx⌉`. A coefficient
2190/// that is not, `dt` in `dt/dx`, leaves a fraction that no residue of `⌈1/ε⌉` decides, and so does a
2191/// root of `1/ε`. With `D` the coefficients' common denominator, on each class `h` of `⌈1/ε⌉` modulo `D`,
2192/// `P − R_h` is an integer for `R_h = Σ c_j·h^j`, a value of the larger infinitesimals, so
2193/// `⌊x⌋ = P − R_h + ⌊R_h + a + ρ⌋`: the same floor one infinitesimal up, `⌈R_h + a⌉ − 1` when `ρ` is
2194/// negative. The classes' answers join as one value ([`from_depends`]): an infinite integer of one
2195/// infinitesimal where they all are, otherwise a dependence on the coarsest residue whose branches
2196/// read the finer.
2197fn polar_floor(p: Polar) -> Result<Number, String> {
2198    let mut generators = p.generators.clone();
2199    generators.sort_by(|a, b| b.order(a).unwrap_or(Ordering::Equal));
2200    let names: Vec<String> = generators.iter().map(|g| g.generator_text()).collect();
2201    let held = match names.split_last() {
2202        Some((last, [])) => last.clone(),
2203        Some((last, init)) => format!("{} and {last}", init.join(", ")),
2204        None => String::new(),
2205    };
2206    let refuse = |why: String| {
2207        format!(
2208            "the integer part of {} is no polynomial in {held}, the infinite integers a program holds: {why}",
2209            p.shown
2210        )
2211    };
2212    let name = &p.scale.name;
2213    let mut powers: Vec<(u32, Number)> = Vec::new();
2214    let mut denominator = BigInt::from_i64(1);
2215    for (k, c) in &p.infinite {
2216        if k % i64::from(p.q) != 0 {
2217            return Err(refuse(format!("it holds a root of 1/{name}")));
2218        }
2219        let Some(d) = reciprocal_denominator(c) else {
2220            return Err(refuse(format!(
2221                "it multiplies a power of 1/{name} by {}, which is no polynomial in the reciprocals of the infinitesimals \
2222                 larger than {name} with rational coefficients",
2223                c.display_string()
2224            )));
2225        };
2226        denominator = big_lcm(&denominator, &d);
2227        powers.push(((-k / i64::from(p.q)) as u32, c.clone()));
2228    }
2229    let ty = p.scale.residues.clone();
2230    let classes = denominator
2231        .to_i64()
2232        .and_then(|d| u64::try_from(d).ok())
2233        .ok_or_else(|| ResidueError::TooFine { classes: denominator.clone() })
2234        .and_then(|d| crate::limit_value::bounded_lcm(ty.modulus(), d))
2235        .map_err(|e| refuse(e.describe(&p.scale.generator_text())))?;
2236    let reciprocal = from_hyper::<Number>(Hyperreal::from_reciprocal_powers(&[Rational::zero(), Rational::one()]), &p.scale);
2237    let add = |a: Number, b: Number| Number::arith(Op::Add, a, b);
2238    let mul = |a: Number, b: Number| Number::arith(Op::Mul, a, b);
2239    let mut infinite = Number::from_bigint(BigInt::from_i64(0));
2240    for (j, c) in &powers {
2241        let power = Number::arith(Op::Pow, reciprocal.clone(), Number::from_bigint(BigInt::from_i64(i64::from(*j))))?;
2242        infinite = add(infinite, mul(c.clone(), power)?)?;
2243    }
2244    let mut rest: Option<i32> = None;
2245    let mut raw = Vec::with_capacity(classes as usize);
2246    for h in 0..classes {
2247        if !ty.admits(h) {
2248            raw.push(None);
2249            continue;
2250        }
2251        let mut r_h = Number::from_bigint(BigInt::from_i64(0));
2252        for (j, c) in &powers {
2253            let at = Rational::from_i64(h as i64).pow(*j as i32).expect("a natural power");
2254            r_h = add(r_h, mul(c.clone(), Number::from_rational(at))?)?;
2255        }
2256        let c = add(r_h.clone(), p.constant.clone())?;
2257        let below = floor_number(&c)?;
2258        let above = Number::arith(
2259            Op::Sub,
2260            negate(floor_number(&negate(c)?)?)?,
2261            Number::from_bigint(BigInt::from_i64(1)),
2262        )?;
2263        let inner = if below.values_equal(&above) {
2264            below
2265        } else {
2266            let sign = match rest {
2267                Some(s) => s,
2268                None => *rest.insert((p.rest)()?),
2269            };
2270            if sign < 0 {
2271                above
2272            } else {
2273                below
2274            }
2275        };
2276        let whole = integral_on(Number::arith(Op::Sub, infinite.clone(), r_h)?, &p.scale, &ty, h, classes)?;
2277        raw.push(Some(Branch(add(whole, inner)?)));
2278    }
2279    let joined = Depends::from_branches(ty, classes, raw).expect("the classes are the type's own");
2280    Ok(from_depends(joined, &p.scale))
2281}
2282
2283fn big_lcm(a: &BigInt, b: &BigInt) -> BigInt {
2284    let g = a.gcd(b);
2285    a.div_rem(&g).expect("a nonzero divisor").0.mul(b).abs()
2286}
2287
2288/// `whole`, a polynomial in the reciprocals that is an integer on the class `h` modulo `m` of `scale`'s
2289/// generator, as the integer it is there: one of one infinitesimal on that class's own scale, whose facts
2290/// make it one; one of several is one by its scales already ([`from_multi`]).
2291fn integral_on(whole: Number, scale: &Arc<Scale>, ty: &ResidueType, h: u64, m: u64) -> Result<Number, String> {
2292    let Some(ExactRef::Hyper(x)) = whole.exact() else {
2293        return Ok(whole);
2294    };
2295    match &x.value {
2296        HyperForm::Rational(r) if x.scale.same_infinitesimal(scale) => {
2297            let class = Arc::new(scale.with_residues(ty.and(&ResidueType::congruent(h, m)).map_err(|e| scale.refuse(e))?));
2298            let natural = r
2299                .as_reciprocal_powers()
2300                .and_then(|p| Hypernatural::from_polynomial(Poly::from_coeffs(p), &class.residues))
2301                .expect("the part of a floor infinite in its smallest infinitesimal is an integer on its class");
2302            Ok(from_natural(natural, &class))
2303        }
2304        _ => Ok(whole),
2305    }
2306}
2307
2308fn negate(n: Number) -> Result<Number, String> {
2309    Number::arith(Op::Sub, Number::from_bigint(BigInt::from_i64(0)), n)
2310}
2311
2312/// The common denominator of a polynomial in the reciprocals of infinitesimals with rational
2313/// coefficients — `1/(2·dt) + 1/3` has `6` — or `None` for a number that is no such polynomial.
2314fn reciprocal_denominator(n: &Number) -> Option<BigInt> {
2315    if let Some(r) = n.standard_rational() {
2316        return Some(r.denominator().clone());
2317    }
2318    match n.exact()? {
2319        ExactRef::Natural(m) => {
2320            let mut d = BigInt::from_i64(1);
2321            for (_, poly) in m.value.depends().branches() {
2322                for c in poly.coeffs() {
2323                    d = big_lcm(&d, c.denominator());
2324                }
2325            }
2326            Some(d)
2327        }
2328        ExactRef::Hyper(h) => match &h.value {
2329            HyperForm::Rational(r) => Some(
2330                r.as_reciprocal_powers()?
2331                    .iter()
2332                    .fold(BigInt::from_i64(1), |d, c| big_lcm(&d, c.denominator())),
2333            ),
2334            HyperForm::Multi(m) | HyperForm::Integer(m) => {
2335                let polar = multi_polar(m).ok()?;
2336                if polar.infinite.iter().any(|(k, _)| k % i64::from(polar.q) != 0) || (polar.rest)().ok()? != 0 {
2337                    return None;
2338                }
2339                polar
2340                    .infinite
2341                    .iter()
2342                    .map(|(_, c)| c)
2343                    .chain(std::iter::once(&polar.constant))
2344                    .try_fold(BigInt::from_i64(1), |d, c| Some(big_lcm(&d, &reciprocal_denominator(c)?)))
2345            }
2346            _ => None,
2347        },
2348        _ => None,
2349    }
2350}
2351
2352/// The floor of a number, in base's own value model.
2353fn floor_number(x: &Number) -> Result<Number, String> {
2354    if let Some(r) = x.standard_rational() {
2355        return Ok(Number::from_bigint(r.floor()));
2356    }
2357    integer_part(x, Rounding::Floor, &|v| floor_number(&v))
2358        .unwrap_or_else(|| Err(format!("cannot take the integer part of {}", x.display_string())))
2359}
2360
2361/// The integer part of a germ: the floor of its standard part, one less when the standard part
2362/// is an integer the germ approaches from below.
2363fn germ_integer_part<V: TowerValue>(g: &Germ, mode: Rounding) -> Result<V, String> {
2364    let text = |e: crate::germ::GermError| e.to_string();
2365    let floor_of = |g: &Germ| -> Result<BigInt, String> {
2366        let st = g.standard_part().map_err(text)?.ok_or_else(|| {
2367            "the integer part of a value with a pole in the infinitesimal past a polynomial in its reciprocal is not computed".to_string()
2368        })?;
2369        let fl = st.floor(DEFAULT_BUDGET).map_err(|e| e.to_string())?;
2370        let whole = ExactReal::from_rational(Rational::from_bigint(fl.clone()));
2371        let on_integer = st.compare(&whole, DEFAULT_BUDGET).map_err(|e| e.to_string())? == Ordering::Equal;
2372        if on_integer && g.sub(&Germ::constant(&whole)).signum().map_err(text)? < 0 {
2373            Ok(fl.sub(&BigInt::from_i64(1)))
2374        } else {
2375            Ok(fl)
2376        }
2377    };
2378    let n = match mode {
2379        Rounding::Floor => floor_of(g)?,
2380        Rounding::Ceil => floor_of(&g.neg())?.negated(),
2381        Rounding::Nearest => {
2382            let negative = g.signum().map_err(text)? < 0;
2383            let magnitude = if negative { g.neg() } else { g.clone() };
2384            let half = Germ::constant(&ExactReal::from_rational(half()));
2385            let m = floor_of(&magnitude.add(&half))?;
2386            if negative {
2387                m.negated()
2388            } else {
2389                m
2390            }
2391        }
2392    };
2393    Ok(V::from_bigint(n))
2394}
2395
2396/// `x ≈ 0`: zero or an infinitesimal.
2397pub fn is_infinitesimal<V: TowerValue>(v: &V) -> Result<V, String> {
2398    match v.exact() {
2399        Some(ExactRef::Hyper(h)) => match &h.value {
2400            HyperForm::Rational(r) => Ok(V::boolean(r.is_infinitesimal())),
2401            HyperForm::Puiseux(p) => Ok(V::boolean(Closed::Series(p.clone()).is_infinitesimal())),
2402            HyperForm::Germ(g) => match g.standard_part().map_err(|e| e.to_string())? {
2403                None => Ok(V::boolean(false)),
2404                Some(s) => Ok(V::boolean(
2405                    s.compare(&ExactReal::from_i64(0), DEFAULT_BUDGET)
2406                        .map_err(|e| e.to_string())?
2407                        == Ordering::Equal,
2408                )),
2409            },
2410            HyperForm::Multi(m) | HyperForm::Integer(m) => Ok(V::boolean(m.is_infinitesimal())),
2411            HyperForm::Nested(g) => Ok(V::boolean(matches!(
2412                g.standard_part_at(None)?,
2413                Some(s) if s.standard_rational().is_some_and(|r| r.is_zero())
2414            ))),
2415        },
2416        Some(ExactRef::Natural(_)) => Ok(V::boolean(false)),
2417        Some(ExactRef::Depends(d)) => map_depends(d, |b| is_infinitesimal(&b)),
2418        _ => match classify(v) {
2419            Some(Num::Rat(r)) => Ok(V::boolean(r.is_zero())),
2420            Some(Num::Alg(a)) => Ok(V::boolean(a.is_zero())),
2421            Some(Num::Real(x)) => Ok(V::boolean(x.is_exactly_zero())),
2422            _ => Err(format!("a {} is not a number", v.type_name())),
2423        },
2424    }
2425}
2426
2427/// Bounded by a standard number.
2428pub fn is_limited<V: TowerValue>(v: &V) -> Result<V, String> {
2429    match v.exact() {
2430        Some(ExactRef::Hyper(h)) => match &h.value {
2431            HyperForm::Rational(r) => Ok(V::boolean(r.is_limited())),
2432            HyperForm::Puiseux(p) => Ok(V::boolean(Closed::Series(p.clone()).is_limited())),
2433            HyperForm::Germ(g) => Ok(V::boolean(
2434                g.standard_part().map_err(|e| e.to_string())?.is_some(),
2435            )),
2436            HyperForm::Multi(m) | HyperForm::Integer(m) => Ok(V::boolean(m.is_limited())),
2437            HyperForm::Nested(g) => Ok(V::boolean(g.standard_part_at(None)?.is_some())),
2438        },
2439        Some(ExactRef::Natural(n)) => Ok(from_depends(
2440            n.value.is_infinite().map(|inf| Branch(V::boolean(!inf))),
2441            &n.scale,
2442        )),
2443        Some(ExactRef::Depends(d)) => map_depends(d, |b| is_limited(&b)),
2444        _ => match classify(v) {
2445            Some(Num::Rat(_)) | Some(Num::Alg(_)) | Some(Num::Real(_)) => Ok(V::boolean(true)),
2446            _ => Err(format!("a {} is not a number", v.type_name())),
2447        },
2448    }
2449}
2450
2451// ── relative to an infinitesimal ──────────────────────────────────────────────────────────────
2452
2453/// What a value is from the standpoint of an infinitesimal `at`, where every value of `at` and of the
2454/// infinitesimals larger than it is an ordinary number: itself when it involves no smaller one, the
2455/// value it is infinitely close to there when it is limited from that standpoint, and none when it is
2456/// infinite from it.
2457enum Relative<V> {
2458    Ordinary,
2459    Close(V),
2460    Infinite,
2461}
2462
2463/// The infinitesimal `relative to` names: the infinitesimal itself.
2464fn standpoint<V: TowerValue>(at: &V) -> Result<Arc<Scale>, String> {
2465    infinitesimal_scale(at)
2466        .ok_or_else(|| format!("`relative to` names an infinitesimal itself, not {}", at.display_string()))
2467}
2468
2469fn read_relative<V: TowerValue>(v: &V, at: &Arc<Scale>) -> Result<Relative<V>, String> {
2470    let ordered = |s: &Arc<Scale>| -> Result<Ordering, String> {
2471        s.order(at).ok_or_else(|| {
2472            format!(
2473                "cannot read a value of {} relative to {}, whose order the program does not state; declare one much smaller than the other",
2474                s.name, at.name
2475            )
2476        })
2477    };
2478    let Some(n) = classify(v) else {
2479        return Err(format!("a {} is not a number", v.type_name()));
2480    };
2481    if let Num::Multi(m) = &n {
2482        for s in m.scales() {
2483            ordered(&s)?;
2484        }
2485        return Ok(match m.standard_part_at(Some(at)) {
2486            None => Relative::Infinite,
2487            Some(c) if c == *m => Relative::Ordinary,
2488            Some(c) => Relative::Close(from_multi(c)),
2489        });
2490    }
2491    if let Num::Nested(g) = &n {
2492        for s in g.scales() {
2493            ordered(&s)?;
2494        }
2495        if g.scale.order(at) != Some(Ordering::Less) {
2496            return Ok(Relative::Ordinary);
2497        }
2498        return Ok(match g.standard_part_at(Some(at))? {
2499            None => Relative::Infinite,
2500            Some(c) => Relative::Close(from_number(c)),
2501        });
2502    }
2503    let Some(scale) = scale_of(&n, &n) else {
2504        return match n {
2505            Num::Ord(_) => Err(format!("the standard part of a {} is undefined", v.type_name())),
2506            _ => Ok(Relative::Ordinary),
2507        };
2508    };
2509    if ordered(&scale)? != Ordering::Less {
2510        return Ok(Relative::Ordinary);
2511    }
2512    let limited = is_limited(v)?;
2513    if limited.values_equal(&V::boolean(false)) {
2514        return Ok(Relative::Infinite);
2515    }
2516    if let Some(why) = undecided_branch(&limited) {
2517        return Err(why);
2518    }
2519    standard_part(v).map(Relative::Close)
2520}
2521
2522/// The standard part relative to the infinitesimal `at`: what `v` is infinitely close to among the
2523/// values of `at` and the infinitesimals larger than it, every smaller infinitesimal read at zero — the
2524/// inner limit with `at` held fixed. `the standard part of dt + dx relative to dt` is `dt`.
2525pub fn standard_part_relative<V: TowerValue>(v: &V, at: &V) -> Result<V, String> {
2526    match v.exact() {
2527        Some(ExactRef::Depends(d)) => return map_depends(d, |b| standard_part_relative(&b, at)),
2528        Some(ExactRef::Converging(c)) => {
2529            return standard_part_relative(c.value(), at).map(|s| carry_evidence(c, s));
2530        }
2531        _ => {}
2532    }
2533    let scale = standpoint(at)?;
2534    match read_relative(v, &scale)? {
2535        Relative::Ordinary => Ok(v.clone()),
2536        Relative::Close(s) => Ok(s),
2537        Relative::Infinite => Err(format!(
2538            "{} is infinite relative to {} and has no standard part relative to it",
2539            v.display_string(),
2540            scale.name
2541        )),
2542    }
2543}
2544
2545/// Zero, or smaller than every positive value of `at` and of the infinitesimals larger than it.
2546pub fn is_infinitesimal_relative<V: TowerValue>(v: &V, at: &V) -> Result<V, String> {
2547    match v.exact() {
2548        Some(ExactRef::Depends(d)) => return map_depends(d, |b| is_infinitesimal_relative(&b, at)),
2549        Some(ExactRef::Converging(c)) => {
2550            return is_infinitesimal_relative(c.value(), at).map(|s| carry_evidence(c, s));
2551        }
2552        _ => {}
2553    }
2554    let scale = standpoint(at)?;
2555    Ok(V::boolean(match read_relative(v, &scale)? {
2556        Relative::Ordinary => is_standard_zero(v),
2557        Relative::Close(s) => is_standard_zero(&s),
2558        Relative::Infinite => false,
2559    }))
2560}
2561
2562/// Bounded by a value of `at` and of the infinitesimals larger than it.
2563pub fn is_limited_relative<V: TowerValue>(v: &V, at: &V) -> Result<V, String> {
2564    match v.exact() {
2565        Some(ExactRef::Depends(d)) => return map_depends(d, |b| is_limited_relative(&b, at)),
2566        Some(ExactRef::Converging(c)) => {
2567            return is_limited_relative(c.value(), at).map(|s| carry_evidence(c, s));
2568        }
2569        _ => {}
2570    }
2571    let scale = standpoint(at)?;
2572    Ok(V::boolean(!matches!(read_relative(v, &scale)?, Relative::Infinite)))
2573}
2574
2575/// Whether a value is the number zero.
2576fn is_standard_zero<V: TowerValue>(v: &V) -> bool {
2577    v.standard_rational().is_some_and(|r| r.is_zero())
2578}
2579
2580/// A function of the reals the exact types take: the square root, the exponential, the natural
2581/// logarithm.
2582#[derive(Clone, Copy, Debug, PartialEq, Eq)]
2583pub enum RealFn {
2584    Sqrt,
2585    Exp,
2586    Ln,
2587}
2588
2589impl RealFn {
2590    fn noun(self) -> &'static str {
2591        match self {
2592            RealFn::Sqrt => "square root",
2593            RealFn::Exp => "exponential",
2594            RealFn::Ln => "natural logarithm",
2595        }
2596    }
2597}
2598
2599/// `f` of `v`, exactly. A standard number goes in as the rational it denotes (a float as its dyadic
2600/// rational), an algebraic number or a computable real as itself, and the answer is held in its
2601/// smallest exact form: `sqrt(4)` is `2`, `sqrt(2)` is `√2`, `exp(0)` is `1`, `ln(e)` is `1`. The
2602/// square root of a hyperreal or an infinite integer is its root in the real closure
2603/// ([`crate::puiseux`]): `sqrt(dt)` is `√dt`. Every other function of a value of the infinitesimal is
2604/// the germ of it ([`Germ`]): `exp(dt)` is `1 + dt + O(dt^2)`, `ln(1 + dt)` is
2605/// `dt - (1/2)·dt^2 + O(dt^3)`, and the root of a germ is a germ. What is no germ is refused by name:
2606/// the exponential of an infinite value, beyond every power of `dt`, and the logarithm of a positive
2607/// infinitesimal or an infinite value, which carries `ln(dt)`. A residue-dependent value is mapped
2608/// branch by branch and a provisional one keeps its evidence; a function of an ordinal has no exact
2609/// form.
2610pub fn real_fn<V: TowerValue>(f: RealFn, v: &V) -> Result<V, String> {
2611    match v.exact() {
2612        Some(ExactRef::Depends(d)) => return map_depends(d, |b| real_fn(f, &b)),
2613        Some(ExactRef::Converging(c)) => {
2614            return real_fn(f, c.value()).map(|x| carry_evidence(c, x));
2615        }
2616        _ => {}
2617    }
2618    let x = match classify(v) {
2619        Some(Num::Rat(r)) => ExactReal::from_rational(r),
2620        Some(Num::Alg(a)) => ExactReal::from_algebraic(a),
2621        Some(Num::Real(x)) => x,
2622        Some(n @ (Num::Hyper(..) | Num::Nat(..) | Num::Closed(..))) if f == RealFn::Sqrt => {
2623            let scale = scale_of(&n, &n).expect("a hyperreal has its infinitesimal");
2624            let branches = to_closed_branches(&n, &scale.residues).expect("a value of the real closure");
2625            let err = RefCell::new(None);
2626            let out = branches.map(|c| capture(&err, c.root(2).map(|r| from_closed(r, &scale))));
2627            return match err.into_inner() {
2628                Some(e) => Err(e),
2629                None => Ok(from_depends(out, &scale)),
2630            };
2631        }
2632        Some(Num::Germ(g, scale)) => return germ_fn(f, &g, v, &scale).map(|g| from_germ(g, &scale)),
2633        Some(Num::Multi(m)) => {
2634            if f == RealFn::Sqrt {
2635                return m.root(2).map(from_multi);
2636            }
2637            let scale = m.top().expect("a value of several infinitesimals has a smallest").clone();
2638            let g = Arc::new(NestedGerm::exact(&m, &scale));
2639            return nested_fn(f, &g, &v.display_string()).map(from_nested);
2640        }
2641        Some(Num::Nested(g)) => return nested_fn(f, &g, &v.display_string()).map(from_nested),
2642        Some(n @ (Num::Hyper(..) | Num::Nat(..) | Num::Closed(..))) => {
2643            let scale = scale_of(&n, &n).expect("a hyperreal has its infinitesimal");
2644            let branches = to_closed_branches(&n, &scale.residues).expect("a value of the real closure");
2645            let err = RefCell::new(None);
2646            let out = branches.map(|c| {
2647                capture(&err, germ_fn(f, &closed_germ(c), v, &scale).map(|g| from_germ(g, &scale)))
2648            });
2649            return match err.into_inner() {
2650                Some(e) => Err(e),
2651                None => Ok(from_depends(out, &scale)),
2652            };
2653        }
2654        Some(Num::Ord(_)) => {
2655            return Err(format!(
2656                "the {} of {} has no exact form",
2657                f.noun(),
2658                v.display_string()
2659            ))
2660        }
2661        None => return Err(format!("a {} is not a number", v.type_name())),
2662    };
2663    let y = match f {
2664        RealFn::Sqrt => x.sqrt(),
2665        RealFn::Exp => Ok(x.exp()),
2666        RealFn::Ln => x.log(),
2667    };
2668    y.map(from_exact_real).map_err(|e| e.to_string())
2669}
2670
2671/// `f` of a germ of several infinitesimals; what has no germ refused in the words `shown` prints.
2672fn nested_fn(f: RealFn, g: &Arc<NestedGerm>, shown: &str) -> Result<NestedGerm, String> {
2673    match f {
2674        RealFn::Sqrt => NestedGerm::root(g, 2),
2675        RealFn::Exp => NestedGerm::exp(g, shown),
2676        RealFn::Ln => NestedGerm::ln(g, shown),
2677    }
2678}
2679
2680/// `f` of a germ, the germ of `v`; what has no germ refused in the words of `v` and the program's
2681/// infinitesimal.
2682fn germ_fn<V: TowerValue>(f: RealFn, g: &Germ, v: &V, scale: &Scale) -> Result<Germ, String> {
2683    use crate::germ::GermError;
2684    let out = match f {
2685        RealFn::Sqrt => g.root(2),
2686        RealFn::Exp => g.exp(),
2687        RealFn::Ln => g.ln(),
2688    };
2689    out.map_err(|e| match e {
2690        GermError::BeyondEveryPower => format!(
2691            "the exponential of {} is beyond every power of {}",
2692            v.display_string(),
2693            scale.name
2694        ),
2695        GermError::CarriesLog { infinite } => format!(
2696            "the logarithm of {} carries ln({}{})",
2697            v.display_string(),
2698            if infinite { "1/" } else { "" },
2699            scale.name
2700        ),
2701        e => e.to_string(),
2702    })
2703}
2704
2705/// `base ** exponent` for an exponent that is an exact number — what `**` and `pow` are when their
2706/// exponent is one: a fraction `p/q` takes the real `q`-th root and raises it to `p` (`2 ** (1/2)` is
2707/// `√2`, `dt ** (1/2)` is `√dt`, an even root of a negative number refused), and any other exponent is
2708/// the language's own `**`, a float on either side the float power. A residue-dependent or provisional
2709/// operand is followed branch by branch.
2710pub fn exact_power<V: ValueAlgebra>(base: &V, exponent: &V) -> Result<V, String> {
2711    if let Some(r) = lift(base, exponent, |a, b| exact_power(&a, &b)) {
2712        return r;
2713    }
2714    let Some((p, q)) = fractional_exponent(exponent) else {
2715        return V::power(base.clone(), exponent.clone());
2716    };
2717    if is_exact_value(base) {
2718        let recurse = |op: Op, a: V, b: V| -> Result<V, String> {
2719            match op {
2720                Op::Pow => exact_power(&a, &b),
2721                Op::Add => V::add(a, b),
2722                Op::Sub => V::subtract(a, b),
2723                Op::Mul => V::multiply(a, b),
2724                Op::Div | Op::ExactDiv => V::exact_divide(a, b),
2725                Op::Mod => V::modulo(a, b),
2726                Op::FloorDiv => Err("an exact power floors nothing".to_string()),
2727            }
2728        };
2729        return arith(Op::Pow, base, exponent, &recurse).expect("an exact base is the tower's");
2730    }
2731    match base.exact_rational() {
2732        Some(r) => Algebraic::from_rational(r)
2733            .nth_root(q)
2734            .ok_or_else(|| negative_root(q))?
2735            .pow(p)
2736            .map(from_algebraic)
2737            .ok_or_else(|| "zero cannot be raised to a negative power".to_string()),
2738        None => V::power(base.clone(), exponent.clone()),
2739    }
2740}
2741
2742/// π, exactly.
2743pub fn pi<V: TowerValue>() -> V {
2744    from_exact_real(ExactReal::pi())
2745}
2746
2747/// e, exactly.
2748pub fn euler<V: TowerValue>() -> V {
2749    from_exact_real(ExactReal::e())
2750}
2751
2752/// ω, the first infinite ordinal.
2753pub fn omega<V: TowerValue>() -> V {
2754    from_ordinal(Ordinal::omega())
2755}
2756
2757/// The program's infinitesimal: `Let <name> be an infinitesimal …`, its reciprocal's residues
2758/// modulo `modulus` limited to `allowed` (the parser has already intersected the stated facts),
2759/// or the contradiction refused when nothing is allowed.
2760pub fn new_infinitesimal<V: TowerValue>(name: &str, modulus: u64, allowed: &[u64]) -> Result<V, String> {
2761    let residues = ResidueType::from_allowed(modulus.max(1), allowed)
2762        .map_err(|e| e.describe(&format!("1/{name}")))?;
2763    Ok(V::hyper(HyperValue {
2764        value: HyperForm::Rational(Hyperreal::dt()),
2765        scale: Arc::new(Scale::new(name, residues)),
2766    }))
2767}
2768
2769/// `Let <name> be an infinitesimal much smaller than <larger> [and much larger than <smaller>] …`: an
2770/// infinitesimal below `larger` and above `smaller`, each an infinitesimal itself or nothing, with its
2771/// reciprocal's residues as [`new_infinitesimal`] reads them. Refused when a bound is no infinitesimal,
2772/// when the two bounds are not already ordered, and when the name is one an infinitesimal it would be
2773/// ordered with already has.
2774pub fn new_ordered_infinitesimal<V: TowerValue>(
2775    name: &str,
2776    larger: &V,
2777    smaller: &V,
2778    modulus: u64,
2779    allowed: &[u64],
2780) -> Result<V, String> {
2781    let bound = |v: &V, relation: &str| -> Result<Option<Arc<Scale>>, String> {
2782        if v.is_nothing() {
2783            return Ok(None);
2784        }
2785        infinitesimal_scale(v).map(Some).ok_or_else(|| {
2786            format!(
2787                "an infinitesimal is declared {relation} another infinitesimal itself, not than {}",
2788                v.display_string()
2789            )
2790        })
2791    };
2792    let larger = bound(larger, "much smaller than")?;
2793    let smaller = bound(smaller, "much larger than")?;
2794    let residues = ResidueType::from_allowed(modulus.max(1), allowed)
2795        .map_err(|e| e.describe(&format!("1/{name}")))?;
2796    let scale = Scale::ordered(name, residues, larger, smaller)?;
2797    Ok(V::hyper(HyperValue {
2798        value: HyperForm::Rational(Hyperreal::dt()),
2799        scale: Arc::new(scale),
2800    }))
2801}
2802
2803/// The infinitesimal a value is, when it is an infinitesimal itself.
2804fn infinitesimal_scale<V: TowerValue>(v: &V) -> Option<Arc<Scale>> {
2805    match v.exact()? {
2806        ExactRef::Hyper(h) if h.value == HyperForm::Rational(Hyperreal::dt()) => Some(h.scale.clone()),
2807        _ => None,
2808    }
2809}
2810
2811/// The infinite natural `⌈1/dt⌉` generated by an infinitesimal value.
2812pub fn generator_of<V: TowerValue>(v: &V) -> Result<V, String> {
2813    match v.exact() {
2814        Some(ExactRef::Hyper(h)) if h.value == HyperForm::Rational(Hyperreal::dt()) => {
2815            Ok(V::natural(NaturalValue {
2816                value: Hypernatural::generator(&h.scale.residues),
2817                scale: h.scale.clone(),
2818            }))
2819        }
2820        _ => Err(format!(
2821            "the infinite generator is taken of the infinitesimal itself, not of {}",
2822            v.display_string()
2823        )),
2824    }
2825}
2826
2827/// A limit rule by its English name.
2828pub fn limit_rule(name: &str) -> Result<LimitRule, String> {
2829    Ok(match name {
2830        "the standard part" | "standard part" => LimitRule::StandardPart,
2831        "the limit" | "limit" => LimitRule::Limit,
2832        "the limit superior" | "limit superior" => LimitRule::LimitSuperior,
2833        "the limit inferior" | "limit inferior" => LimitRule::LimitInferior,
2834        "the Cesàro mean" | "the Cesaro mean" | "Cesàro mean" | "Cesaro mean" => LimitRule::CesaroMean,
2835        other => return Err(format!("unknown limit rule: {other}")),
2836    })
2837}
2838
2839/// Resolve a residue-dependent value under a limit rule; a value that does not depend on the
2840/// residue is its own limit under every rule. A value that depends on the residues of several
2841/// generators resolves each branch's finer dependence first: the residues of different generators
2842/// are independent, so the rule over every pair of classes is the rule over the coarser generator's
2843/// classes of the rule over the finer one's.
2844pub fn apply_limit<V: TowerValue>(v: &V, rule: LimitRule) -> Result<V, String> {
2845    let Some(d) = depends_of(v) else {
2846        return Ok(v.clone());
2847    };
2848    if d.value.branches().any(|(_, b)| residue_generator(&b.0).is_some()) {
2849        let inner = map_depends(d, |b| apply_limit(&b, rule)).map_err(|e| match rule {
2850            LimitRule::Limit | LimitRule::StandardPart => {
2851                format!("no limit: the value is {}", display(v).expect("a dependence displays"))
2852            }
2853            _ => e,
2854        })?;
2855        return apply_limit(&inner, rule);
2856    }
2857    let as_alg = d.value.map(|b| match classify(&b.0) {
2858        Some(Num::Rat(r)) => Some(Algebraic::from_rational(r)),
2859        Some(Num::Alg(a)) => Some(a),
2860        _ => None,
2861    });
2862    let all_numeric = as_alg.branches().all(|(_, a)| a.is_some());
2863    if !all_numeric {
2864        return match (rule, d.value.single()) {
2865            (_, Some(b)) => Ok(b.0.clone()),
2866            (LimitRule::Limit | LimitRule::StandardPart, None) => Err(format!(
2867                "no limit: the value is {}",
2868                display(v).expect("a dependence displays")
2869            )),
2870            _ => Err("only a numeric value has a limit superior, inferior or mean".to_string()),
2871        };
2872    }
2873    let algebraic = as_alg.map(|a| a.clone().expect("checked numeric"));
2874    algebraic
2875        .apply_with(rule, &d.scale.generator_text())
2876        .map(from_algebraic)
2877}
2878
2879/// A provisional answer: the current guess after `steps` cases with `revisions` changes. A guess
2880/// that is already an answer joins this evidence to its own.
2881pub fn provisional<V: TowerValue>(value: V, steps: u64, revisions: u64) -> V {
2882    carry_evidence(&Converging::provisional((), steps, revisions), value)
2883}
2884
2885/// Why a value cannot decide a branch — a residue-dependent answer, or a provisional one no proof
2886/// settled — or `None` for any other value. Every tier refuses such a branch with this sentence.
2887pub fn undecided_branch<V: TowerValue>(v: &V) -> Option<String> {
2888    match v.exact()? {
2889        ExactRef::Depends(_) => {
2890            let mut generators = Vec::new();
2891            generators_read(v, &mut generators);
2892            let listed = |each: &dyn Fn(&Scale) -> String| {
2893                let words: Vec<String> = generators.iter().map(|g| each(g)).collect();
2894                match words.split_last() {
2895                    Some((last, [])) => last.clone(),
2896                    Some((last, init)) => format!("{} and {last}", init.join(", ")),
2897                    None => unreachable!("a dependence reads a generator"),
2898                }
2899            };
2900            Some(format!(
2901                "this condition depends on the residue{} of {}: it is {}; declare what is known about {} or take a limit",
2902                if generators.len() > 1 { "s" } else { "" },
2903                listed(&|g| g.generator_text()),
2904                display(v).expect("a dependence displays"),
2905                listed(&|g| format!("1/{}", g.name)),
2906            ))
2907        }
2908        ExactRef::Converging(c) if !c.is_settled() => Some(format!(
2909            "a provisional answer cannot decide a condition: {}",
2910            display(v).expect("a provisional answer displays")
2911        )),
2912        _ => None,
2913    }
2914}
2915
2916/// `not` lifted over residue branches and through provisional values; `None` for any other value.
2917pub fn not<V: TowerValue>(
2918    v: &V,
2919    recurse: &dyn Fn(V) -> Result<V, String>,
2920) -> Option<Result<V, String>> {
2921    match v.exact()? {
2922        ExactRef::Depends(d) => Some(map_depends(d, recurse)),
2923        ExactRef::Converging(c) => Some(recurse(c.value().clone()).map(|x| carry_evidence(c, x))),
2924        _ => None,
2925    }
2926}
2927
2928// ── transport ─────────────────────────────────────────────────────────────────────────────────
2929
2930/// Whether a value of the exact types can travel as data — to a task, through a channel, over the
2931/// wire: every value but one holding a real built from a function a program defines, in itself, in a
2932/// germ, in a branch of a residue-dependent value or as a provisional answer. A value model's own
2933/// lists are its own to walk.
2934pub fn transmissible<V: TowerValue>(v: &V) -> bool {
2935    match v.exact() {
2936        Some(ExactRef::Real(x)) => x.is_transmissible(),
2937        Some(ExactRef::Hyper(h)) => match &h.value {
2938            HyperForm::Germ(g) => g.is_transmissible(),
2939            HyperForm::Nested(g) => g.is_transmissible(),
2940            HyperForm::Rational(_) | HyperForm::Puiseux(_) | HyperForm::Multi(_) | HyperForm::Integer(_) => true,
2941        },
2942        Some(ExactRef::Depends(d)) => d.value.branches().all(|(_, b)| transmissible(&b.0)),
2943        Some(ExactRef::Converging(c)) => transmissible(c.value()),
2944        Some(ExactRef::Algebraic(_) | ExactRef::Natural(_) | ExactRef::Ordinal(_)) | None => true,
2945    }
2946}
2947
2948/// An algebraic number (`0`), computable real (`1`) or ordinal (`2`) as its canonical bytes; `None`
2949/// for any other value, and for a real built from a function a program defines, which stays with the
2950/// program.
2951pub fn exact_bytes<V: TowerValue>(v: &V) -> Option<(u8, Vec<u8>)> {
2952    Some(match v.exact()? {
2953        ExactRef::Algebraic(a) => (0, a.to_bytes()),
2954        ExactRef::Real(x) if x.is_transmissible() => (1, x.to_bytes()),
2955        ExactRef::Ordinal(o) => (2, o.to_bytes()),
2956        _ => return None,
2957    })
2958}
2959
2960/// The value [`exact_bytes`] wrote; `None` for a forged or non-canonical encoding.
2961pub fn from_exact_bytes<V: TowerValue>(kind: u8, bytes: &[u8]) -> Option<V> {
2962    let v: V = match kind {
2963        0 => from_algebraic(Algebraic::from_bytes(bytes)?),
2964        1 => from_exact_real(ExactReal::from_bytes(bytes)?),
2965        2 => from_ordinal(Ordinal::from_bytes(bytes)?),
2966        _ => return None,
2967    };
2968    (exact_bytes(&v)? == (kind, bytes.to_vec())).then_some(v)
2969}
2970
2971/// The infinitesimal's name and its declaration's bytes ([`Scale::to_bytes`]): its reciprocal's
2972/// residue facts, and where it stands among the others.
2973pub fn scale_parts(scale: &Scale) -> (String, Vec<u8>) {
2974    (scale.name.clone(), scale.to_bytes())
2975}
2976
2977/// The scale [`scale_parts`] wrote.
2978pub fn scale_from_parts(name: &str, bytes: &[u8]) -> Option<Arc<Scale>> {
2979    Scale::from_bytes(name, bytes)
2980}
2981
2982impl Scale {
2983    /// The declaration's canonical bytes: the residue type of the reciprocal, and for an infinitesimal
2984    /// declared much smaller or much larger than another, a `1` and each of those two in turn — a `0`
2985    /// for none, or a `1`, its name and its own bytes. An infinitesimal declared on its own writes its
2986    /// residue type alone. A residue class's copy writes the declaration it refines.
2987    pub fn to_bytes(&self) -> Vec<u8> {
2988        let mut out = Vec::new();
2989        self.write_declaration(&mut out);
2990        out
2991    }
2992
2993    fn write_declaration(&self, out: &mut Vec<u8>) {
2994        let scale = self.declaration();
2995        scale.residues.write(out);
2996        if scale.much_smaller_than.is_none() && scale.much_larger_than.is_none() {
2997            return;
2998        }
2999        out.push(1);
3000        for bound in [&scale.much_smaller_than, &scale.much_larger_than] {
3001            match bound {
3002                None => out.push(0),
3003                Some(b) => {
3004                    out.push(1);
3005                    crate::exact_codec::write_len(b.name.len(), out);
3006                    out.extend_from_slice(b.name.as_bytes());
3007                    let bytes = b.to_bytes();
3008                    crate::exact_codec::write_len(bytes.len(), out);
3009                    out.extend_from_slice(&bytes);
3010                }
3011            }
3012        }
3013    }
3014
3015    /// The infinitesimal [`Scale::to_bytes`] wrote under `name`; `None` for a forged or non-canonical
3016    /// encoding, or a declaration its bounds refuse.
3017    pub fn from_bytes(name: &str, bytes: &[u8]) -> Option<Arc<Scale>> {
3018        Scale::read_declaration(name, bytes, 0)
3019    }
3020
3021    fn read_declaration(name: &str, bytes: &[u8], depth: usize) -> Option<Arc<Scale>> {
3022        use crate::exact_codec::{read_byte, read_len, MAX_WIRE_DEPTH, MAX_WIRE_LEN};
3023        if depth > MAX_WIRE_DEPTH {
3024            return None;
3025        }
3026        let mut pos = 0;
3027        let residues = ResidueType::read(bytes, &mut pos)?;
3028        let scale = if pos == bytes.len() {
3029            Scale::new(name, residues)
3030        } else {
3031            if read_byte(bytes, &mut pos)? != 1 {
3032                return None;
3033            }
3034            let mut bounds = Vec::with_capacity(2);
3035            for _ in 0..2 {
3036                bounds.push(match read_byte(bytes, &mut pos)? {
3037                    0 => None,
3038                    1 => {
3039                        let n = read_len(bytes, &mut pos, MAX_WIRE_LEN)?;
3040                        let bound_name = std::str::from_utf8(bytes.get(pos..pos.checked_add(n)?)?).ok()?.to_string();
3041                        pos += n;
3042                        let n = read_len(bytes, &mut pos, MAX_WIRE_LEN)?;
3043                        let inner = bytes.get(pos..pos.checked_add(n)?)?;
3044                        pos += n;
3045                        Some(Scale::read_declaration(&bound_name, inner, depth + 1)?)
3046                    }
3047                    _ => return None,
3048                });
3049            }
3050            let smaller = bounds.pop().expect("two bounds");
3051            let larger = bounds.pop().expect("two bounds");
3052            if larger.is_none() && smaller.is_none() {
3053                return None;
3054            }
3055            Scale::ordered(name, residues, larger, smaller).ok()?
3056        };
3057        (pos == bytes.len() && scale.to_bytes() == bytes).then(|| Arc::new(scale))
3058    }
3059}
3060
3061/// A hyperreal (`0`), infinite integer (`1`), germ (`2`), root of a hyperreal (`3`), exact value of
3062/// several infinitesimals (`4`), germ of several (`5`) or infinite integer of several (`6`) as its
3063/// scale and canonical bytes — the scale of
3064/// a value of several its smallest infinitesimal, the bytes naming every one it involves; `None` for any
3065/// other value, and for a germ holding a real built from a function a program defines.
3066pub fn scaled_bytes<V: TowerValue>(v: &V) -> Option<(u8, String, Vec<u8>, Vec<u8>)> {
3067    Some(match v.exact()? {
3068        ExactRef::Hyper(h) => {
3069            let (name, residues) = scale_parts(&h.scale);
3070            match &h.value {
3071                HyperForm::Rational(r) => (0, name, residues, r.to_bytes()),
3072                HyperForm::Puiseux(p) => (3, name, residues, p.to_bytes()),
3073                HyperForm::Germ(g) if g.is_transmissible() => (2, name, residues, g.to_bytes()),
3074                HyperForm::Germ(_) => return None,
3075                HyperForm::Multi(m) => (4, name, residues, m.to_bytes()),
3076                HyperForm::Integer(m) => (6, name, residues, m.to_bytes()),
3077                HyperForm::Nested(g) if g.is_transmissible() => (5, name, residues, g.to_bytes()),
3078                HyperForm::Nested(_) => return None,
3079            }
3080        }
3081        ExactRef::Natural(n) => {
3082            let (name, residues) = scale_parts(&n.scale);
3083            (1, name, residues, n.value.to_bytes())
3084        }
3085        _ => return None,
3086    })
3087}
3088
3089/// The value [`scaled_bytes`] wrote; `None` for a forged or non-canonical encoding.
3090pub fn from_scaled_bytes<V: TowerValue>(kind: u8, name: &str, residues: &[u8], bytes: &[u8]) -> Option<V> {
3091    let scale = scale_from_parts(name, residues)?;
3092    let v: V = match kind {
3093        0 => from_hyper(Hyperreal::from_bytes(bytes)?, &scale),
3094        1 => from_natural(Hypernatural::from_bytes(bytes)?, &scale),
3095        2 => from_germ(Germ::from_bytes(bytes)?, &scale),
3096        3 => from_closed(Closed::Series(Puiseux::from_bytes(bytes)?), &scale),
3097        4 => from_multi(Multi::from_bytes(bytes)?),
3098        5 => from_nested(NestedGerm::from_bytes(bytes)?),
3099        6 => from_multi(Multi::from_bytes(bytes)?),
3100        _ => return None,
3101    };
3102    let canonical = scaled_bytes(&v)?;
3103    (canonical == (kind, name.to_string(), residues.to_vec(), bytes.to_vec())).then_some(v)
3104}
3105
3106/// A residue-dependent value rebuilt from its scale, modulus and per-class values.
3107pub fn depends_from_parts<V: TowerValue>(
3108    name: &str,
3109    residues: &[u8],
3110    modulus: u64,
3111    branches: Vec<Option<V>>,
3112) -> Option<V> {
3113    let scale = scale_from_parts(name, residues)?;
3114    let raw = branches.into_iter().map(|b| b.map(Branch)).collect();
3115    let value = Depends::from_branches(scale.residues.clone(), modulus, raw)?;
3116    let built: V = from_depends(value.clone(), &scale);
3117    match depends_of(&built) {
3118        Some(d) if d.value == value => Some(built),
3119        _ => None,
3120    }
3121}
3122
3123#[cfg(test)]
3124#[path = "../../logicaffeine_tests/unit/logicaffeine_base/tower/tests.rs"]
3125pub(crate) mod tests;