1use num_bigint::BigInt;
10
11use crate::algebraic::AlgebraicNumber;
12use crate::computable::ComputableReal;
13use crate::primes::factorize;
14use crate::rational::RnsRational;
15use crate::rns::{Channels, RnsInt};
16use crate::symbolic::{IdentityGraph, SymbolicExpr};
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
20pub enum TowerLevel {
21 Integer = 0,
22 Rational = 1,
23 Algebraic = 2,
24 Computable = 3,
25 Symbolic = 4,
26}
27
28#[derive(Clone)]
30pub enum TowerValue {
31 Integer(RnsInt),
32 Rational(RnsRational),
33 Algebraic(AlgebraicNumber),
34 Computable(ComputableReal),
35 Symbolic(SymbolicExpr),
36}
37
38impl TowerValue {
39 pub fn level(&self) -> TowerLevel {
41 match self {
42 TowerValue::Integer(_) => TowerLevel::Integer,
43 TowerValue::Rational(_) => TowerLevel::Rational,
44 TowerValue::Algebraic(_) => TowerLevel::Algebraic,
45 TowerValue::Computable(_) => TowerLevel::Computable,
46 TowerValue::Symbolic(_) => TowerLevel::Symbolic,
47 }
48 }
49
50 pub fn channels(&self) -> Channels {
52 match self {
53 TowerValue::Integer(i) => i.channels.clone(),
54 TowerValue::Rational(r) => r.channels.clone(),
55 TowerValue::Algebraic(a) => a.channels.clone(),
56 TowerValue::Computable(c) => c.channels(),
57 TowerValue::Symbolic(_) => Channels::standard(32),
58 }
59 }
60
61 pub fn reduce(&self) -> TowerValue {
63 let mut current = self.clone();
64 loop {
65 let next = current.reduce_once();
66 if next.level() == current.level() {
67 return next;
68 }
69 current = next;
70 }
71 }
72
73 fn reduce_once(&self) -> TowerValue {
74 match self {
75 TowerValue::Algebraic(a) if a.degree() == 1 => {
76 TowerValue::Rational(a.to_rational().unwrap())
77 }
78 TowerValue::Rational(r) if r.is_integer() => {
79 let p = r.to_pair().0;
80 TowerValue::Integer(RnsInt::from_bigint(&p, r.channels.clone()))
81 }
82 TowerValue::Symbolic(e) => {
83 let simplified = IdentityGraph::standard().simplify(e.clone());
84 match symbolic_to_value(&simplified, &self.channels()) {
85 Some(v) => v,
86 None => TowerValue::Symbolic(simplified),
87 }
88 }
89 other => other.clone(),
90 }
91 }
92
93 pub fn elevate_to(&self, target: TowerLevel) -> TowerValue {
96 let mut current = self.clone();
97 while current.level() < target {
98 current = current.elevate_once();
99 }
100 current
101 }
102
103 fn elevate_once(&self) -> TowerValue {
104 match self {
105 TowerValue::Integer(i) => {
106 TowerValue::Rational(RnsRational::new(i.to_bigint(), BigInt::from(1), i.channels.clone()))
107 }
108 TowerValue::Rational(r) => TowerValue::Algebraic(AlgebraicNumber::from_rational(r.clone())),
109 TowerValue::Algebraic(a) => TowerValue::Computable(a.to_computable()),
110 TowerValue::Computable(_) => self.clone(), TowerValue::Symbolic(_) => self.clone(),
112 }
113 }
114
115 pub fn to_f64(&self) -> Option<f64> {
117 match self {
118 TowerValue::Integer(i) => {
119 Some(RnsRational::new(i.to_bigint(), BigInt::from(1), i.channels.clone()).to_f64())
120 }
121 TowerValue::Rational(r) => Some(r.to_f64()),
122 TowerValue::Algebraic(a) => Some(a.to_f64()),
123 TowerValue::Computable(c) => Some(c.evaluate_f64()),
124 TowerValue::Symbolic(_) => self.reduce().non_symbolic_to_f64(),
125 }
126 }
127
128 fn non_symbolic_to_f64(&self) -> Option<f64> {
129 match self {
130 TowerValue::Symbolic(e) => {
131 let ch = self.channels();
133 symbolic_to_computable(e, &ch).map(|c| c.evaluate_f64())
134 }
135 other => other.to_f64(),
136 }
137 }
138
139 pub fn digits(&self, precision: u64) -> RnsRational {
141 match self {
142 TowerValue::Integer(i) => {
143 RnsRational::new(i.to_bigint(), BigInt::from(1), i.channels.clone())
144 }
145 TowerValue::Rational(r) => r.clone(),
146 TowerValue::Algebraic(a) => {
147 let mut clone = a.clone();
148 let target = RnsRational::new(
149 BigInt::from(1),
150 BigInt::from(10u8).pow((precision + 1) as u32),
151 a.channels.clone(),
152 );
153 clone.refine_interval(&target);
154 clone.interval.0.midpoint(&clone.interval.1)
155 }
156 TowerValue::Computable(c) => c.evaluate(precision),
157 TowerValue::Symbolic(e) => {
158 let ch = self.channels();
159 let simplified = IdentityGraph::standard().simplify(e.clone());
160 if let Some(v) = symbolic_to_value(&simplified, &ch) {
161 return v.digits(precision);
162 }
163 match symbolic_to_computable(&simplified, &ch) {
164 Some(c) => c.evaluate(precision),
165 None => panic!("cannot produce digits for irreducible symbolic expression"),
166 }
167 }
168 }
169 }
170
171 pub fn add(&self, other: &TowerValue) -> TowerValue {
175 self.binop(other, Op::Add).reduce()
176 }
177
178 pub fn mul(&self, other: &TowerValue) -> TowerValue {
180 self.binop(other, Op::Mul).reduce()
181 }
182
183 fn binop(&self, other: &TowerValue, op: Op) -> TowerValue {
184 let lvl = self.level().max(other.level());
185 if lvl == TowerLevel::Symbolic {
186 let a = self.to_symbolic();
187 let b = other.to_symbolic();
188 let expr = match op {
189 Op::Add => SymbolicExpr::Add(vec![a, b]),
190 Op::Mul => SymbolicExpr::Mul(vec![a, b]),
191 };
192 return TowerValue::Symbolic(IdentityGraph::standard().simplify(expr));
193 }
194 let a = self.elevate_to(lvl);
195 let b = other.elevate_to(lvl);
196 match (a, b) {
197 (TowerValue::Integer(x), TowerValue::Integer(y)) => TowerValue::Integer(match op {
198 Op::Add => x.add(&y),
199 Op::Mul => x.mul(&y),
200 }),
201 (TowerValue::Rational(x), TowerValue::Rational(y)) => TowerValue::Rational(match op {
202 Op::Add => x.add(&y),
203 Op::Mul => x.mul(&y),
204 }),
205 (TowerValue::Algebraic(x), TowerValue::Algebraic(y)) => TowerValue::Algebraic(match op {
206 Op::Add => x.add(&y),
207 Op::Mul => x.mul(&y),
208 }),
209 (TowerValue::Computable(x), TowerValue::Computable(y)) => TowerValue::Computable(match op {
210 Op::Add => x.add(&y),
211 Op::Mul => x.mul(&y),
212 }),
213 _ => unreachable!("levels were equalized before the operation"),
214 }
215 }
216
217 pub fn sqrt(&self) -> TowerValue {
220 let ch = self.channels();
221 if let TowerValue::Integer(i) = self {
222 let n = i.to_bigint();
223 if let Some(nu) = bigint_to_u64(&n) {
224 let root = (nu as f64).sqrt().round() as u64;
225 if root * root == nu {
226 return TowerValue::Integer(RnsInt::from_bigint(&BigInt::from(root), ch));
227 }
228 return TowerValue::Algebraic(AlgebraicNumber::sqrt(nu, ch)).reduce();
229 }
230 }
231 let v = self.to_f64().unwrap_or(f64::NAN);
233 if v >= 0.0 && v.fract() == 0.0 {
234 return TowerValue::Algebraic(AlgebraicNumber::sqrt(v as u64, ch)).reduce();
235 }
236 panic!("sqrt of non-integer values is not supported at the tower level yet");
237 }
238
239 pub fn sin(&self) -> TowerValue {
241 let expr = SymbolicExpr::Sin(Box::new(self.to_symbolic()));
242 TowerValue::Symbolic(IdentityGraph::standard().simplify(expr)).reduce()
243 }
244
245 fn to_symbolic(&self) -> SymbolicExpr {
246 match self {
247 TowerValue::Integer(i) => SymbolicExpr::Integer(i.to_bigint()),
248 TowerValue::Rational(r) => {
249 let (p, q) = r.to_pair();
250 SymbolicExpr::Rational(p, q)
251 }
252 TowerValue::Symbolic(e) => e.clone(),
253 TowerValue::Algebraic(a) => {
255 if let Some(r) = a.to_rational() {
256 let (p, q) = r.to_pair();
257 SymbolicExpr::Rational(p, q)
258 } else {
259 panic!("cannot lift this algebraic number to symbolic form")
260 }
261 }
262 TowerValue::Computable(_) => panic!("cannot lift a computable real to symbolic form"),
263 }
264 }
265}
266
267#[derive(Clone, Copy)]
268enum Op {
269 Add,
270 Mul,
271}
272
273fn bigint_to_u64(n: &BigInt) -> Option<u64> {
274 use num_traits::ToPrimitive;
275 n.to_u64()
276}
277
278fn symbolic_to_value(e: &SymbolicExpr, ch: &Channels) -> Option<TowerValue> {
280 match e {
281 SymbolicExpr::Integer(n) => Some(TowerValue::Integer(RnsInt::from_bigint(n, ch.clone()))),
282 SymbolicExpr::Rational(p, q) => {
283 Some(TowerValue::Rational(RnsRational::new(p.clone(), q.clone(), ch.clone())))
284 }
285 SymbolicExpr::Sqrt { radicand } => {
286 let nu = bigint_to_u64(radicand)?;
287 Some(TowerValue::Algebraic(AlgebraicNumber::sqrt(nu, ch.clone())))
288 }
289 SymbolicExpr::ScaledSqrt { coeff: (a, b), rad } => {
290 let nu = bigint_to_u64(rad)?;
291 let s = AlgebraicNumber::sqrt(nu, ch.clone());
292 let coeff = RnsRational::new(a.clone(), b.clone(), ch.clone());
293 Some(TowerValue::Algebraic(s).mul(&TowerValue::Rational(coeff)))
294 }
295 _ => None,
296 }
297}
298
299fn symbolic_to_computable(e: &SymbolicExpr, ch: &Channels) -> Option<ComputableReal> {
302 match e {
303 SymbolicExpr::Integer(n) => Some(ComputableReal::from_rational(RnsRational::new(
304 n.clone(),
305 BigInt::from(1),
306 ch.clone(),
307 ))),
308 SymbolicExpr::Rational(p, q) => Some(ComputableReal::from_rational(RnsRational::new(
309 p.clone(),
310 q.clone(),
311 ch.clone(),
312 ))),
313 SymbolicExpr::Pi => Some(ComputableReal::pi(ch.clone())),
314 SymbolicExpr::E => Some(ComputableReal::e(ch.clone())),
315 SymbolicExpr::Sqrt { radicand } => {
316 let r = RnsRational::new(radicand.clone(), BigInt::from(1), ch.clone());
317 Some(ComputableReal::sqrt(r))
318 }
319 SymbolicExpr::Add(terms) => {
320 let mut acc: Option<ComputableReal> = None;
321 for t in terms {
322 let c = symbolic_to_computable(t, ch)?;
323 acc = Some(match acc {
324 Some(a) => a.add(&c),
325 None => c,
326 });
327 }
328 acc
329 }
330 SymbolicExpr::Mul(factors) => {
331 let mut acc: Option<ComputableReal> = None;
332 for f in factors {
333 let c = symbolic_to_computable(f, ch)?;
334 acc = Some(match acc {
335 Some(a) => a.mul(&c),
336 None => c,
337 });
338 }
339 acc
340 }
341 _ => None,
342 }
343}
344
345pub fn is_perfect_square(n: u64) -> bool {
347 let r = (n as f64).sqrt().round() as u64;
348 r * r == n
349}
350
351#[allow(dead_code)]
352fn _uses_factorize() {
353 let _ = factorize(12);
354}
355
356#[cfg(test)]
357mod tests {
358 use super::*;
359
360 fn ch() -> Channels {
361 Channels::standard(32)
362 }
363
364 #[test]
365 fn rational_level() {
366 let v = TowerValue::Rational(RnsRational::from_fraction(2, 3, ch()));
367 assert_eq!(v.level(), TowerLevel::Rational);
368 }
369
370 #[test]
371 fn rational_with_denom_one_reduces_to_integer() {
372 let v = TowerValue::Rational(RnsRational::from_fraction(6, 2, ch()));
373 assert_eq!(v.reduce().level(), TowerLevel::Integer);
374 }
375
376 #[test]
377 fn sqrt2_times_sqrt2_drops_to_integer() {
378 let s = TowerValue::Algebraic(AlgebraicNumber::sqrt(2, ch()));
379 let prod = s.mul(&s);
380 assert_eq!(prod.level(), TowerLevel::Integer);
381 assert_eq!(prod.to_f64().unwrap().round(), 2.0);
382 }
383
384 #[test]
385 fn mixed_level_add() {
386 let a = TowerValue::Integer(RnsInt::from_i64(1, ch()));
388 let b = TowerValue::Rational(RnsRational::from_fraction(1, 2, ch()));
389 let sum = a.add(&b);
390 assert_eq!(sum.level(), TowerLevel::Rational);
391 assert!((sum.to_f64().unwrap() - 1.5).abs() < 1e-12);
392 }
393
394 #[test]
395 fn pi_plus_one_digits() {
396 let pi = TowerValue::Symbolic(SymbolicExpr::Pi);
398 let one = TowerValue::Integer(RnsInt::from_i64(1, ch()));
399 let sum = pi.add(&one);
400 let d = sum.digits(20);
401 assert!((d.to_f64() - (std::f64::consts::PI + 1.0)).abs() < 1e-12);
402 }
403
404 #[test]
405 fn sin_pi_is_zero() {
406 let pi = TowerValue::Symbolic(SymbolicExpr::Pi);
407 let s = pi.sin();
408 assert_eq!(s.to_f64().unwrap(), 0.0);
409 }
410}