Skip to main content

logicaffeine_base/
number.rs

1//! A number of the exact tower as base holds one itself: the coefficient of an expansion of a value of
2//! several infinitesimals whose coefficients are not all exact — `exp(dt + dx)`, whose coefficients in
3//! `dx` are the germ of `e^dt` — and the value the flows of such expansions start from.
4//!
5//! Every operation is the tower's own ([`crate::tower`]), with integers and rationals below it, so a
6//! coefficient computes, compares, refuses and prints exactly as a program's value of the same kind.
7
8use crate::algebraic::Algebraic;
9use crate::exact_real::ExactReal;
10use crate::expansion::{Coefficient, ExpansionError};
11use crate::limit_value::Converging;
12use crate::numeric::{BigInt, Rational};
13use crate::ordinal::Ordinal;
14use crate::tower::{
15    self, display, structurally_equal, DependsValue, ExactRef, HyperValue, NaturalValue, Op, RealFn, Rel, TowerValue,
16};
17
18/// A number of the exact tower. See the module documentation.
19#[derive(Clone, Debug)]
20pub enum Number {
21    Int(BigInt),
22    Rat(Rational),
23    Bool(bool),
24    Nothing,
25    Alg(Algebraic),
26    Real(ExactReal),
27    Hyper(HyperValue),
28    Nat(NaturalValue),
29    Ord(Ordinal),
30    Dep(Box<DependsValue<Number>>),
31    Conv(Box<Converging<Number>>),
32}
33
34impl TowerValue for Number {
35    fn exact(&self) -> Option<ExactRef<'_, Self>> {
36        Some(match self {
37            Number::Alg(a) => ExactRef::Algebraic(a),
38            Number::Real(x) => ExactRef::Real(x),
39            Number::Hyper(h) => ExactRef::Hyper(h),
40            Number::Nat(n) => ExactRef::Natural(n),
41            Number::Ord(o) => ExactRef::Ordinal(o),
42            Number::Dep(d) => ExactRef::Depends(d),
43            Number::Conv(c) => ExactRef::Converging(c),
44            Number::Int(_) | Number::Rat(_) | Number::Bool(_) | Number::Nothing => return None,
45        })
46    }
47
48    fn standard_rational(&self) -> Option<Rational> {
49        match self {
50            Number::Int(n) => Some(Rational::from_bigint(n.clone())),
51            Number::Rat(r) => Some(r.clone()),
52            _ => None,
53        }
54    }
55
56    fn integer(&self) -> Option<BigInt> {
57        match self {
58            Number::Int(n) => Some(n.clone()),
59            _ => None,
60        }
61    }
62
63    fn exact_rational(&self) -> Option<Rational> {
64        self.standard_rational()
65    }
66
67    fn is_standard_number(&self) -> bool {
68        matches!(self, Number::Int(_) | Number::Rat(_))
69    }
70
71    fn text(&self) -> Option<&str> {
72        None
73    }
74
75    fn type_name(&self) -> String {
76        match self {
77            Number::Int(_) => "Int",
78            Number::Rat(_) => "Rational",
79            Number::Bool(_) => "Bool",
80            Number::Nothing => "Nothing",
81            Number::Alg(_) => "Algebraic",
82            Number::Real(_) => "ExactReal",
83            Number::Hyper(_) => "Hyperreal",
84            Number::Nat(_) => "Hypernatural",
85            Number::Ord(_) => "Ordinal",
86            Number::Dep(_) => "Depends",
87            Number::Conv(_) => "Converging",
88        }
89        .to_string()
90    }
91
92    fn display_string(&self) -> String {
93        match self {
94            Number::Int(n) => n.to_string(),
95            Number::Rat(r) => r.to_string(),
96            Number::Bool(b) => b.to_string(),
97            Number::Nothing => "nothing".to_string(),
98            other => display(other).expect("an exact value displays"),
99        }
100    }
101
102    fn values_equal(&self, other: &Self) -> bool {
103        if let Some(same) = structurally_equal(self, other) {
104            return same;
105        }
106        match (self, other) {
107            (Number::Bool(a), Number::Bool(b)) => a == b,
108            (Number::Nothing, Number::Nothing) => true,
109            _ => match (self.standard_rational(), other.standard_rational()) {
110                (Some(a), Some(b)) => a == b,
111                _ => false,
112            },
113        }
114    }
115
116    fn is_nothing(&self) -> bool {
117        matches!(self, Number::Nothing)
118    }
119
120    fn from_rational(r: Rational) -> Self {
121        match r.to_bigint() {
122            Some(n) if r.is_integer() => Number::Int(n),
123            _ => Number::Rat(r),
124        }
125    }
126
127    fn from_bigint(b: BigInt) -> Self {
128        Number::Int(b)
129    }
130
131    fn boolean(b: bool) -> Self {
132        Number::Bool(b)
133    }
134
135    fn nothing() -> Self {
136        Number::Nothing
137    }
138
139    fn algebraic(a: Algebraic) -> Self {
140        Number::Alg(a)
141    }
142
143    fn exact_real(x: ExactReal) -> Self {
144        Number::Real(x)
145    }
146
147    fn hyper(h: HyperValue) -> Self {
148        Number::Hyper(h)
149    }
150
151    fn natural(n: NaturalValue) -> Self {
152        Number::Nat(n)
153    }
154
155    fn ordinal(o: Ordinal) -> Self {
156        Number::Ord(o)
157    }
158
159    fn depends(d: DependsValue<Self>) -> Self {
160        Number::Dep(Box::new(d))
161    }
162
163    fn converging(c: Converging<Self>) -> Self {
164        Number::Conv(Box::new(c))
165    }
166}
167
168impl Number {
169    /// `a op b`: the exact tower first, then integers and rationals, exact division exact.
170    pub fn arith(op: Op, a: Number, b: Number) -> Result<Number, String> {
171        if let Some(r) = tower::arith(op, &a, &b, &Number::arith) {
172            return r;
173        }
174        let (Some(x), Some(y)) = (a.standard_rational(), b.standard_rational()) else {
175            return Err(format!("cannot combine {} and {}", a.type_name(), b.type_name()));
176        };
177        let zero = || "Division by zero".to_string();
178        Ok(match op {
179            Op::Add => Number::from_rational(x.add(&y)),
180            Op::Sub => Number::from_rational(x.sub(&y)),
181            Op::Mul => Number::from_rational(x.mul(&y)),
182            Op::Div | Op::ExactDiv => Number::from_rational(x.div(&y).ok_or_else(zero)?),
183            Op::FloorDiv => Number::from_bigint(x.div(&y).ok_or_else(zero)?.floor()),
184            Op::Mod => {
185                let q = x.div(&y).ok_or_else(zero)?.floor();
186                Number::from_rational(x.sub(&y.mul(&Rational::from_bigint(q))))
187            }
188            Op::Pow => match b.integer().and_then(|k| k.to_i64()).and_then(|k| i32::try_from(k).ok()) {
189                Some(k) => Number::from_rational(
190                    x.pow(k).ok_or_else(|| "zero cannot be raised to a negative power".to_string())?,
191                ),
192                None => match b.exact_rational() {
193                    Some(_) => match tower::arith(Op::Pow, &Number::algebraic(Algebraic::from_rational(x)), &b, &Number::arith) {
194                        Some(r) => r?,
195                        None => return Err(format!("cannot raise {} to the {} power", a.type_name(), b.type_name())),
196                    },
197                    None => return Err(format!("cannot raise {} to the {} power", a.type_name(), b.type_name())),
198                },
199            },
200        })
201    }
202
203    /// `a rel b`, a `Bool`, or the refusal of an answer that depends on the residue or is provisional.
204    pub fn holds(rel: Rel, a: &Number, b: &Number) -> Result<bool, String> {
205        let answer = Number::relation(rel, a.clone(), b.clone())?;
206        if let Some(why) = tower::undecided_branch(&answer) {
207            return Err(why);
208        }
209        match answer {
210            Number::Bool(b) => Ok(b),
211            other => Err(format!("a comparison answered {}", other.display_string())),
212        }
213    }
214
215    fn relation(rel: Rel, a: Number, b: Number) -> Result<Number, String> {
216        if let Some(r) = tower::relation(rel, &a, &b, &Number::relation) {
217            return r;
218        }
219        let (Some(x), Some(y)) = (a.standard_rational(), b.standard_rational()) else {
220            return Ok(Number::Bool(match rel {
221                Rel::Eq => a.values_equal(&b),
222                Rel::NotEq => !a.values_equal(&b),
223                _ => return Err(format!("cannot compare {} and {}", a.type_name(), b.type_name())),
224            }));
225        };
226        let o = x.cmp(&y);
227        Ok(Number::Bool(match rel {
228            Rel::Lt => o.is_lt(),
229            Rel::Gt => o.is_gt(),
230            Rel::LtEq => o.is_le(),
231            Rel::GtEq => o.is_ge(),
232            Rel::Eq => o.is_eq(),
233            Rel::NotEq => o.is_ne(),
234        }))
235    }
236}
237
238fn refused(e: String) -> ExpansionError {
239    ExpansionError::Coefficient(e)
240}
241
242impl Coefficient for Number {
243    fn zero() -> Self {
244        Number::Int(BigInt::from_i64(0))
245    }
246    fn one() -> Self {
247        Number::Int(BigInt::from_i64(1))
248    }
249    fn of_rational(r: Rational) -> Self {
250        <Number as TowerValue>::from_rational(r)
251    }
252    fn add(&self, o: &Self) -> Result<Self, ExpansionError> {
253        Number::arith(Op::Add, self.clone(), o.clone()).map_err(refused)
254    }
255    fn sub(&self, o: &Self) -> Result<Self, ExpansionError> {
256        Number::arith(Op::Sub, self.clone(), o.clone()).map_err(refused)
257    }
258    fn neg(&self) -> Result<Self, ExpansionError> {
259        Number::arith(Op::Sub, Number::zero(), self.clone()).map_err(refused)
260    }
261    fn mul(&self, o: &Self) -> Result<Self, ExpansionError> {
262        Number::arith(Op::Mul, self.clone(), o.clone()).map_err(refused)
263    }
264    fn is_zero(&self) -> Result<bool, ExpansionError> {
265        if let Some(r) = self.standard_rational() {
266            return Ok(r.is_zero());
267        }
268        Number::holds(Rel::Eq, self, &Number::zero()).map_err(refused)
269    }
270    fn recip(&self) -> Result<Self, ExpansionError> {
271        if self.is_zero()? {
272            return Err(ExpansionError::DivisionByZero);
273        }
274        Number::arith(Op::ExactDiv, Number::one(), self.clone()).map_err(refused)
275    }
276    fn sign(&self) -> Result<i32, ExpansionError> {
277        if Number::holds(Rel::Lt, self, &Number::zero()).map_err(refused)? {
278            return Ok(-1);
279        }
280        Ok(i32::from(Number::holds(Rel::Gt, self, &Number::zero()).map_err(refused)?))
281    }
282    fn nth_root(&self, n: u32) -> Result<Self, ExpansionError> {
283        let exponent = <Number as TowerValue>::from_rational(Rational::from_ratio_i64(1, i64::from(n)).expect("n ≥ 1"));
284        Number::arith(Op::Pow, self.clone(), exponent).map_err(refused)
285    }
286    fn exp(&self) -> Result<Self, ExpansionError> {
287        tower::real_fn(RealFn::Exp, self).map_err(refused)
288    }
289    fn ln(&self) -> Result<Self, ExpansionError> {
290        tower::real_fn(RealFn::Ln, self).map_err(refused)
291    }
292}