1use 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#[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 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 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}