1use 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#[derive(Debug, PartialEq, Eq, Hash)]
57pub struct Scale {
58 pub name: String,
59 pub residues: ResidueType,
60 pub much_smaller_than: Option<Arc<Scale>>,
62 pub much_larger_than: Option<Arc<Scale>>,
64 pub refines: Option<Arc<Scale>>,
67}
68
69impl Scale {
70 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 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 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 fn declaration(&self) -> &Scale {
149 self.refines.as_deref().unwrap_or(self)
150 }
151
152 pub fn same_infinitesimal(&self, o: &Scale) -> bool {
154 std::ptr::eq(self.declaration(), o.declaration()) || self.declaration() == o.declaration()
155 }
156
157 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 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 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 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 pub fn generator_text(&self) -> String {
212 format!("⌈1/{}⌉", self.name)
213 }
214
215 fn refuse(&self, e: ResidueError) -> String {
217 e.describe(&self.generator_text())
218 }
219}
220
221#[derive(Debug, Clone)]
226pub enum HyperForm {
227 Rational(Hyperreal),
228 Puiseux(Puiseux),
229 Germ(Germ),
230 Multi(Multi),
231 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 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 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#[derive(Debug, Clone, PartialEq, Eq, Hash)]
312pub struct HyperValue {
313 pub value: HyperForm,
314 pub scale: Arc<Scale>,
315}
316
317#[derive(Debug, Clone, PartialEq, Eq, Hash)]
319pub struct NaturalValue {
320 pub value: Hypernatural,
321 pub scale: Arc<Scale>,
322}
323
324#[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#[derive(Debug, Clone)]
336pub struct DependsValue<V> {
337 pub value: Depends<Branch<V>>,
338 pub scale: Arc<Scale>,
339}
340
341pub 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
352pub trait TowerValue: Clone + Sized {
356 fn exact(&self) -> Option<ExactRef<'_, Self>>;
358 fn standard_rational(&self) -> Option<Rational>;
360 fn integer(&self) -> Option<BigInt>;
362 fn exact_rational(&self) -> Option<Rational>;
364 fn is_standard_number(&self) -> bool;
366 fn text(&self) -> Option<&str>;
368 fn type_name(&self) -> String;
370 fn display_string(&self) -> String;
372 fn values_equal(&self, other: &Self) -> bool;
374 fn is_nothing(&self) -> bool;
376
377 fn from_rational(r: Rational) -> Self;
379 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
392pub enum Shape<V> {
395 Bool,
396 Int(i64),
397 Float,
398 BigInt(BigInt),
399 Rational(Rational),
400 Decimal,
401 Text(usize),
403 List(Vec<V>),
404 Tuple(Vec<V>),
405 Other,
406}
407
408pub 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 fn exact_divide(a: Self, b: Self) -> Result<Self, String>;
416 fn modulo(a: Self, b: Self) -> Result<Self, String>;
418 fn holds(rel: Rel, a: &Self, b: &Self) -> Result<bool, String>;
421 fn power(a: Self, b: Self) -> Result<Self, String>;
423 fn floor(v: Self) -> Result<Self, String>;
425 fn ceil(v: Self) -> Result<Self, String>;
427 fn list(values: Vec<Self>) -> Self;
428 fn shape(&self) -> Shape<Self>;
429}
430
431pub 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
439pub 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
447pub 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
465pub 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
477pub 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
488pub 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
506pub 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
526fn 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
534pub 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
548pub 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
556fn 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
587fn 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
625fn 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
655fn 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
694pub fn is_exact_value<V: TowerValue>(v: &V) -> bool {
696 v.exact().is_some()
697}
698
699enum 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
743fn 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
753fn 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
794fn 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
805fn 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#[derive(Clone, Copy, Debug, PartialEq, Eq)]
819pub enum Op {
820 Add,
821 Sub,
822 Mul,
823 Div,
825 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
846pub 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
882fn 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
892fn 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
899fn 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
911fn 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
926pub(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
934pub(crate) fn number_scales(n: &Number) -> Vec<Arc<Scale>> {
936 classify(n).map(|num| scales_of(&num)).unwrap_or_default()
937}
938
939pub(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
959pub(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
979pub(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
1019fn 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
1033fn 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
1139fn 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
1147fn 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
1163fn 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
1171pub fn germ_of<V: TowerValue>(v: &V) -> Option<Germ> {
1174 to_germ(&classify(v)?)
1175}
1176
1177fn 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
1260fn 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
1326fn 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
1366fn 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
1376fn 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
1391fn 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
1402fn 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
1415fn 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
1427pub 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
1440pub 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 if matches!(a, Num::Ord(_)) || matches!(b, Num::Ord(_)) {
1464 return ordinal_arith(op, &a, &b).unwrap_or_else(refuse);
1465 }
1466 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 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 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
1512fn 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
1520fn 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
1533fn 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
1623fn 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#[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
1759pub 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
1831pub 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
1858pub 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
1874pub 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#[derive(Clone, Copy, Debug, PartialEq, Eq)]
1932pub enum Rounding {
1933 Floor,
1934 Ceil,
1935 Nearest,
1936}
1937
1938pub 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
2022fn 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
2059fn 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
2068fn 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
2082fn 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
2111struct Polar {
2115 scale: Arc<Scale>,
2116 q: u32,
2117 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
2183fn 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
2288fn 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
2312fn 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
2352fn 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
2361fn 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
2396pub 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
2427pub 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
2451enum Relative<V> {
2458 Ordinary,
2459 Close(V),
2460 Infinite,
2461}
2462
2463fn 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
2522pub 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
2545pub 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
2562pub 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
2575fn is_standard_zero<V: TowerValue>(v: &V) -> bool {
2577 v.standard_rational().is_some_and(|r| r.is_zero())
2578}
2579
2580#[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
2599pub 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
2671fn 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
2680fn 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
2705pub 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
2742pub fn pi<V: TowerValue>() -> V {
2744 from_exact_real(ExactReal::pi())
2745}
2746
2747pub fn euler<V: TowerValue>() -> V {
2749 from_exact_real(ExactReal::e())
2750}
2751
2752pub fn omega<V: TowerValue>() -> V {
2754 from_ordinal(Ordinal::omega())
2755}
2756
2757pub 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
2769pub 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
2803fn 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
2811pub 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
2827pub 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
2839pub 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
2879pub fn provisional<V: TowerValue>(value: V, steps: u64, revisions: u64) -> V {
2882 carry_evidence(&Converging::provisional((), steps, revisions), value)
2883}
2884
2885pub 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
2916pub 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
2928pub 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
2948pub 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
2960pub 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
2971pub fn scale_parts(scale: &Scale) -> (String, Vec<u8>) {
2974 (scale.name.clone(), scale.to_bytes())
2975}
2976
2977pub fn scale_from_parts(name: &str, bytes: &[u8]) -> Option<Arc<Scale>> {
2979 Scale::from_bytes(name, bytes)
2980}
2981
2982impl Scale {
2983 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 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
3061pub 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
3089pub 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
3106pub 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;