1use crate::FLOAT_PRECISION;
3
4use crate::rug::float::OrdFloat;
5use crate::rug::ops::{NegAssign, NotAssign, Pow};
6use crate::rug::{Float, Integer};
7use std::borrow::Cow;
8use std::fmt;
9use std::fmt::Write;
10use std::sync::OnceLock;
11
12pub mod recommended {
13 pub const NUMBER_DECIMALS_SCIENTIFIC: usize = 30;
14}
15static NUMBER_DECIMALS_SCIENTIFIC: OnceLock<usize> = OnceLock::new();
16
17use crate::AlreadyInit;
18pub fn init(number_decimals_scientific: usize) -> Result<(), AlreadyInit> {
19 static INITIALIZING: std::sync::Mutex<()> = std::sync::Mutex::new(());
20 let _guard = INITIALIZING.lock();
21 NUMBER_DECIMALS_SCIENTIFIC
22 .set(number_decimals_scientific)
23 .map_err(|_| AlreadyInit)?;
24 Ok(())
25}
26pub fn init_default() -> Result<(), AlreadyInit> {
27 init(recommended::NUMBER_DECIMALS_SCIENTIFIC)
28}
29
30impl fmt::Debug for CalculationResult {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 fn truncate<T: fmt::Debug>(val: &T) -> String {
33 let s = format!("{val:?}");
34 if s.len() > 25 {
35 format!("{}...", &s[..20])
36 } else {
37 s
38 }
39 }
40
41 match self {
42 CalculationResult::Exact(n) => write!(f, "Exact({})", truncate(n)),
43 CalculationResult::Approximate(of, int) => {
44 write!(
45 f,
46 "Approximate({}, {})",
47 truncate(&of.as_float()),
48 truncate(int)
49 )
50 }
51 CalculationResult::ApproximateDigits(i, n) => {
52 write!(f, "ApproximateDigits({}, {})", i, truncate(n))
53 }
54 CalculationResult::ApproximateDigitsTower(i, b, u, n) => {
55 write!(
56 f,
57 "ApproximateDigitsTower({}, {}, {}, {})",
58 i,
59 b,
60 u,
61 truncate(n)
62 )
63 }
64 CalculationResult::Float(of) => write!(f, "Float({})", truncate(&of.as_float())),
65 CalculationResult::ComplexInfinity => write!(f, "ComplexInfinity"),
66 }
67 }
68}
69
70#[derive(Clone, PartialEq, Ord, Eq, Hash, PartialOrd)]
72pub enum CalculationResult {
73 Exact(Integer),
74 Approximate(OrdFloat, Integer),
76 ApproximateDigits(bool, Integer),
78 ApproximateDigitsTower(bool, bool, u32, Integer),
80 Float(OrdFloat),
81 ComplexInfinity,
82}
83
84pub type Number = CalculationResult;
86
87impl Number {
88 pub fn negate(&mut self) {
89 match self {
90 Self::Approximate(x, _) | Self::Float(x) => x.as_float_mut().neg_assign(),
91 Self::Exact(n) => n.neg_assign(),
92 Self::ApproximateDigitsTower(n, _, _, _) | Self::ApproximateDigits(n, _) => {
93 n.not_assign()
94 }
95 Self::ComplexInfinity => {}
96 }
97 }
98 pub fn is_too_long(&self, too_big_number: &Integer) -> bool {
99 let n = match self {
100 CalculationResult::Exact(n)
101 | CalculationResult::ApproximateDigits(_, n)
102 | CalculationResult::Approximate(_, n)
103 | CalculationResult::ApproximateDigitsTower(_, _, _, n) => n,
104 CalculationResult::Float(_) | CalculationResult::ComplexInfinity => return false,
105 };
106 n > too_big_number
107 }
108}
109impl From<Integer> for Number {
110 fn from(value: Integer) -> Self {
111 Number::Exact(value)
112 }
113}
114impl From<i32> for Number {
115 fn from(value: i32) -> Self {
116 Number::Exact(value.into())
117 }
118}
119impl From<Float> for Number {
120 fn from(value: Float) -> Self {
121 Number::Float(value.into())
122 }
123}
124impl std::fmt::Display for Number {
125 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126 self.format(f, f.alternate(), f.sign_minus())
127 }
128}
129
130impl CalculationResult {
131 fn format(
135 &self,
136 f: &mut std::fmt::Formatter<'_>,
137 shorten: bool,
138 agressive: bool,
139 ) -> std::fmt::Result {
140 use std::fmt::Display;
141 match &self {
142 CalculationResult::Exact(factorial) => {
143 if shorten {
144 f.write_str(&truncate(factorial, true))
145 } else {
146 factorial.fmt(f)
147 }
148 }
149 CalculationResult::Approximate(base, exponent) => {
150 let base = base.as_float();
151 if !base.to_f64().is_finite() {
152 f.write_fmt(format_args!("{base:.30}"))?;
153 } else {
154 base.to_f64().fmt(f)?;
155 };
156 f.write_str(" × 10^")?;
157 if shorten {
158 f.write_str("(")?;
159 f.write_str(&truncate(exponent, false))?;
160 f.write_str(")")
161 } else {
162 exponent.fmt(f)
163 }
164 }
165 CalculationResult::ApproximateDigits(_, digits) => {
166 if shorten {
167 f.write_str(&truncate(digits, false))?;
168 } else {
169 digits.fmt(f)?;
170 }
171 f.write_str(" digits")
172 }
173 CalculationResult::ApproximateDigitsTower(_, negative, depth, exponent) => {
174 f.write_str(if *negative { "-" } else { "" })?;
175 if !agressive {
176 if *depth > 0 {
177 f.write_fmt(format_args!("10^("))?;
178 }
179 if *depth > 1 {
180 f.write_str(&"10\\^".repeat(*depth as usize - 1))?;
181 f.write_str("(")?;
182 }
183 if shorten {
184 f.write_str(&truncate(exponent, false))?;
185 } else {
186 exponent.fmt(f)?;
187 }
188 if *depth > 1 {
189 f.write_str("\\)")?;
190 }
191 if *depth > 0 {
192 f.write_str(")")?;
193 }
194 } else {
195 let mut extra = 0;
196 let mut exponent = Float::with_val(
197 *FLOAT_PRECISION
198 .get()
199 .expect("FLOAT_PRECISION unititialized, use init"),
200 exponent,
201 );
202 while exponent >= 10 {
203 extra += 1;
204 exponent = exponent.log10();
205 }
206 f.write_str("^(")?;
207 (depth + extra).fmt(f)?;
208 f.write_str(")10")?;
209 }
210 f.write_str(" digits")
211 }
212 CalculationResult::Float(gamma) => {
213 if !gamma.as_float().to_f64().is_finite() {
214 f.write_fmt(format_args!("{:.30}", gamma.as_float()))
215 } else {
216 gamma.as_float().to_f64().fmt(f)
217 }
218 }
219 CalculationResult::ComplexInfinity => f.write_str("∞\u{0303}"),
220 }
221 }
222}
223
224#[derive(Debug, Clone, PartialEq, Ord, Eq, Hash, PartialOrd)]
225pub struct Calculation {
226 pub value: Number,
228 pub steps: Vec<(i32, u32)>,
230 pub result: CalculationResult,
231}
232
233impl Calculation {
234 pub fn is_digit_tower(&self) -> bool {
235 matches!(
236 self,
237 Calculation {
238 result: CalculationResult::ApproximateDigitsTower(_, _, _, _),
239 ..
240 }
241 )
242 }
243 pub fn is_aproximate_digits(&self) -> bool {
244 matches!(
245 self,
246 Calculation {
247 result: CalculationResult::ApproximateDigits(_, _),
248 ..
249 }
250 )
251 }
252 pub fn is_approximate(&self) -> bool {
253 matches!(
254 self,
255 Calculation {
256 result: CalculationResult::Approximate(_, _),
257 ..
258 }
259 )
260 }
261 pub fn is_rounded(&self) -> bool {
262 matches!(
263 self,
264 Calculation {
265 value: Number::Float(_),
266 ..
267 }
268 ) && !matches!(
269 self,
270 Calculation {
271 result: CalculationResult::Float(_),
272 ..
273 }
274 )
275 }
276 pub fn is_too_long(&self, too_big_number: &Integer) -> bool {
277 self.result.is_too_long(too_big_number) || self.value.is_too_long(too_big_number)
278 }
279}
280
281impl Calculation {
282 pub fn format(
287 &self,
288 acc: &mut String,
289 force_shorten: bool,
290 agressive_shorten: bool,
291 too_big_number: &Integer,
292 ) -> Result<(), std::fmt::Error> {
293 let mut factorial_string = if !agressive_shorten {
294 self.steps.iter().rev().fold(String::new(), |mut a, e| {
295 let negative_str = if e.1 > 0 { "negative " } else { "" };
296 let negative_strength = if e.1 > 1 {
297 format!("{}y ", Self::get_factorial_level_string(e.1 as i32))
298 } else {
299 String::new()
300 };
301 let _ = match e.0 {
302 -1 => write!(a, "the {negative_strength}{negative_str}termial of "),
303 ..-1 => write!(
304 a,
305 "{}{}{}termial of ",
306 negative_strength,
307 negative_str,
308 Self::get_factorial_level_string(-e.0),
309 ),
310 1 => write!(a, "the {negative_strength}{negative_str}factorial of "),
311 0 | 2.. => write!(
312 a,
313 "{}{}{}factorial of ",
314 negative_strength,
315 negative_str,
316 Self::get_factorial_level_string(e.0),
317 ),
318 };
319 a
320 })
321 } else {
322 "all that of ".to_string()
323 };
324 factorial_string[..1].make_ascii_uppercase();
325 let number = &self.value;
326 let is = if matches!(
327 self.result,
328 CalculationResult::ApproximateDigits(_, _)
329 | CalculationResult::ApproximateDigitsTower(_, _, _, _)
330 ) {
331 "has"
332 } else {
333 "is"
334 };
335 use CalculationResult as Cr;
336 let approximate = match (&self.result, &self.value) {
337 (Cr::ApproximateDigitsTower(_, _, _, _), _) => " on the order of",
338 (Cr::Approximate(_, _) | Cr::ApproximateDigits(_, _) | Cr::Float(_), _)
339 | (_, Number::Float(_)) => " approximately",
340 _ => "",
341 };
342 let factorial = &self.result;
343 write!(acc, "{factorial_string}")?;
344 if agressive_shorten {
345 write!(acc, "{number:-#}")?
346 } else if number.is_too_long(too_big_number) || force_shorten {
347 write!(acc, "{number:#}")?
348 } else {
349 write!(acc, "{number}")?
350 }
351 write!(acc, " {is}{approximate} ")?;
352 if agressive_shorten {
353 write!(acc, "{factorial:-#}")?
354 } else if factorial.is_too_long(too_big_number) || force_shorten {
355 write!(acc, "{factorial:#}")?
356 } else {
357 write!(acc, "{factorial}")?
358 }
359 write!(acc, " \n\n")
360 }
361
362 fn get_factorial_level_string(level: i32) -> Cow<'static, str> {
363 match level {
364 0 => "sub".into(),
365 1 => "the ".into(),
366 2 => "double-".into(),
367 3 => "triple-".into(),
368 4 => "quadruple-".into(),
369 5 => "quintuple-".into(),
370 6 => "sextuple-".into(),
371 7 => "septuple-".into(),
372 8 => "octuple-".into(),
373 9 => "nonuple-".into(),
374 10 => "decuple-".into(),
375 11 => "undecuple-".into(),
376 12 => "duodecuple-".into(),
377 13 => "tredecuple-".into(),
378 14 => "quattuordecuple-".into(),
379 15 => "quindecuple-".into(),
380 16 => "sexdecuple-".into(),
381 17 => "septendecuple-".into(),
382 18 => "octodecuple-".into(),
383 19 => "novemdecuple-".into(),
384 20 => "vigintuple-".into(),
385 21 => "unvigintuple-".into(),
386 22 => "duovigintuple-".into(),
387 23 => "trevigintuple-".into(),
388 24 => "quattuorvigintuple-".into(),
389 25 => "quinvigintuple-".into(),
390 26 => "sexvigintuple-".into(),
391 27 => "septenvigintuple-".into(),
392 28 => "octovigintuple-".into(),
393 29 => "novemvigintuple-".into(),
394 30 => "trigintuple-".into(),
395 31 => "untrigintuple-".into(),
396 32 => "duotrigintuple-".into(),
397 33 => "tretrigintuple-".into(),
398 34 => "quattuortrigintuple-".into(),
399 35 => "quintrigintuple-".into(),
400 36 => "sextrigintuple-".into(),
401 37 => "septentrigintuple-".into(),
402 38 => "octotrigintuple-".into(),
403 39 => "novemtrigintuple-".into(),
404 40 => "quadragintuple-".into(),
405 41 => "unquadragintuple-".into(),
406 42 => "duoquadragintuple-".into(),
407 43 => "trequadragintuple-".into(),
408 44 => "quattuorquadragintuple-".into(),
409 45 => "quinquadragintuple-".into(),
410 _ => {
411 let mut suffix = String::new();
412 write!(&mut suffix, "{level}-").unwrap();
413 suffix.into()
414 }
415 }
416 }
417}
418fn round(number: &mut String) {
426 if let Some(digit) = number
428 .pop()
429 .map(|n| n.to_digit(10).expect("Not a base 10 number"))
430 {
431 if digit >= 5 {
432 let mut last_digit = number
433 .pop()
434 .and_then(|n| n.to_digit(10))
435 .expect("Not a base 10 number");
436 while last_digit == 9 {
438 let Some(digit) = number
439 .pop()
440 .map(|n| n.to_digit(10).expect("Not a base 10 number"))
441 else {
442 number.push_str("10");
444 return;
445 };
446 last_digit = digit;
447 }
448 let _ = write!(number, "{}", last_digit + 1);
450 }
451 }
452}
453fn truncate(number: &Integer, add_roughly: bool) -> String {
454 let prec = *FLOAT_PRECISION
455 .get()
456 .expect("FLOAT_PRECISION unititialized, use init");
457 if number == &0 {
458 return number.to_string();
459 }
460 let negative = number.is_negative();
461 let orig_number = number;
462 let number = number.clone().abs();
463 let length = (Float::with_val(prec, &number).ln() / Float::with_val(prec, 10).ln())
464 .to_integer_round(crate::rug::float::Round::Down)
465 .unwrap()
466 .0;
467 let truncated_number: Integer = &number
468 / (Float::with_val(prec, 10)
469 .pow(
470 (length.clone()
471 - NUMBER_DECIMALS_SCIENTIFIC
472 .get()
473 .expect("NUMBER_DECIMALS_SCIENTIFIC uninitialized, use init")
474 - 1u8)
475 .max(Integer::ZERO),
476 )
477 .to_integer()
478 .unwrap());
479 let mut truncated_number = truncated_number.to_string();
480 if truncated_number.len()
481 > *NUMBER_DECIMALS_SCIENTIFIC
482 .get()
483 .expect("NUMBER_DECIMALS_SCIENTIFIC uninitialized, use init")
484 {
485 round(&mut truncated_number);
486 }
487 if let Some(mut digit) = truncated_number.pop() {
488 while digit == '0' {
489 digit = match truncated_number.pop() {
490 Some(x) => x,
491 None => break,
492 }
493 }
494 truncated_number.push(digit);
495 }
496 if truncated_number.len() > 1 {
498 truncated_number.insert(1, '.'); }
500 if negative {
501 truncated_number.insert(0, '-');
502 }
503 if length
504 > NUMBER_DECIMALS_SCIENTIFIC
505 .get()
506 .expect("NUMBER_DECIMALS_SCIENTIFIC uninitialized, use init")
507 + 1
508 {
509 format!(
510 "{}{} × 10^{}",
511 if add_roughly { "roughly " } else { "" },
512 truncated_number,
513 length
514 )
515 } else {
516 orig_number.to_string()
517 }
518}
519#[cfg(test)]
520mod tests {
521 use super::*;
522 use crate::recommended::FLOAT_PRECISION;
523 use crate::rug::Integer;
524 use std::{str::FromStr, sync::LazyLock};
525
526 static TOO_BIG_NUMBER: LazyLock<Integer> =
527 LazyLock::new(|| Integer::from_str(&format!("1{}", "0".repeat(9999))).unwrap());
528
529 #[test]
530 fn test_round_down() {
531 let _ = crate::init_default();
532 let mut number = String::from("1929472373");
533 round(&mut number);
534 assert_eq!(number, "192947237");
535 }
536
537 #[test]
538 fn test_round_up() {
539 let _ = crate::init_default();
540 let mut number = String::from("74836748625");
541 round(&mut number);
542 assert_eq!(number, "7483674863");
543 }
544
545 #[test]
546 fn test_round_carry() {
547 let _ = crate::init_default();
548 let mut number = String::from("24999999995");
549 round(&mut number);
550 assert_eq!(number, "25");
551 }
552
553 #[test]
554 fn test_factorial_level_string() {
555 let _ = crate::init_default();
556 assert_eq!(Calculation::get_factorial_level_string(1), "the ");
557 assert_eq!(Calculation::get_factorial_level_string(2), "double-");
558 assert_eq!(Calculation::get_factorial_level_string(3), "triple-");
559 assert_eq!(
560 Calculation::get_factorial_level_string(45),
561 "quinquadragintuple-"
562 );
563 assert_eq!(Calculation::get_factorial_level_string(50), "50-");
564 }
565
566 #[test]
567 fn test_truncate() {
568 let _ = crate::init_default();
569 assert_eq!(truncate(&Integer::from_str("0").unwrap(), false), "0");
570 assert_eq!(truncate(&Integer::from_str("-1").unwrap(), false), "-1");
571 assert_eq!(
572 truncate(
573 &Integer::from_str(&format!("1{}", "0".repeat(300))).unwrap(),
574 false
575 ),
576 "1 × 10^300"
577 );
578 assert_eq!(
579 truncate(
580 &-Integer::from_str(&format!("1{}", "0".repeat(300))).unwrap(),
581 false
582 ),
583 "-1 × 10^300"
584 );
585 assert_eq!(
586 truncate(
587 &Integer::from_str(&format!("1{}", "0".repeat(2000000))).unwrap(),
588 false
589 ),
590 "1 × 10^2000000"
591 );
592 }
593
594 #[test]
595 fn test_factorial_format() {
596 let _ = crate::init_default();
597 let mut acc = String::new();
598 let factorial = Calculation {
599 value: 5.into(),
600 steps: vec![(1, 0)],
601 result: CalculationResult::Exact(Integer::from(120)),
602 };
603 factorial
604 .format(&mut acc, false, false, &TOO_BIG_NUMBER)
605 .unwrap();
606 assert_eq!(acc, "The factorial of 5 is 120 \n\n");
607
608 let mut acc = String::new();
609 let factorial = Calculation {
610 value: 5.into(),
611 steps: vec![(0, 0)],
612 result: CalculationResult::Exact(Integer::from(120)),
613 };
614 factorial
615 .format(&mut acc, false, false, &TOO_BIG_NUMBER)
616 .unwrap();
617 assert_eq!(acc, "Subfactorial of 5 is 120 \n\n");
618
619 let mut acc = String::new();
620 let factorial = Calculation {
621 value: 5.into(),
622 steps: vec![(1, 0)],
623 result: CalculationResult::Approximate(
624 Float::with_val(FLOAT_PRECISION, 1.2).into(),
625 5.into(),
626 ),
627 };
628 factorial
629 .format(&mut acc, false, false, &TOO_BIG_NUMBER)
630 .unwrap();
631 assert_eq!(acc, "The factorial of 5 is approximately 1.2 × 10^5 \n\n");
632
633 let mut acc = String::new();
634 let factorial = Calculation {
635 value: 5.into(),
636 steps: vec![(1, 0)],
637 result: CalculationResult::ApproximateDigits(false, 3.into()),
638 };
639 factorial
640 .format(&mut acc, false, false, &TOO_BIG_NUMBER)
641 .unwrap();
642 assert_eq!(acc, "The factorial of 5 has approximately 3 digits \n\n");
643
644 let mut acc = String::new();
645 let factorial = Calculation {
646 value: 5.into(),
647 steps: vec![(1, 0)],
648 result: CalculationResult::Exact(Integer::from(120)),
649 };
650 factorial
651 .format(&mut acc, true, false, &TOO_BIG_NUMBER)
652 .unwrap();
653 assert_eq!(acc, "The factorial of 5 is 120 \n\n");
654 }
655}
656
657#[cfg(test)]
658mod test {
659 use std::{str::FromStr, sync::LazyLock};
660
661 use super::*;
662
663 use crate::recommended::FLOAT_PRECISION;
664 static TOO_BIG_NUMBER: LazyLock<Integer> =
665 LazyLock::new(|| Integer::from_str(&format!("1{}", "0".repeat(9999))).unwrap());
666
667 #[test]
670 fn test_format_factorial() {
671 let _ = crate::init_default();
672 let fact = Calculation {
673 value: 10.into(),
674 steps: vec![(3, 0)],
675 result: CalculationResult::Exact(280.into()),
676 };
677 let mut s = String::new();
678 fact.format(&mut s, false, false, &TOO_BIG_NUMBER).unwrap();
679 assert_eq!(s, "Triple-factorial of 10 is 280 \n\n");
680 }
681 #[test]
682 fn test_format_factorial_exact_of_decimal() {
683 let _ = crate::init_default();
684 let fact = Calculation {
685 value: Number::Float(Float::with_val(FLOAT_PRECISION, 0.5).into()),
686 steps: vec![(3, 0)],
687 result: CalculationResult::Exact(280.into()),
688 };
689 let mut s = String::new();
690 fact.format(&mut s, false, false, &TOO_BIG_NUMBER).unwrap();
691 assert_eq!(s, "Triple-factorial of 0.5 is approximately 280 \n\n");
692 }
693 #[test]
694 fn test_format_factorial_force_shorten_small() {
695 let _ = crate::init_default();
696 let fact = Calculation {
697 value: 10.into(),
698 steps: vec![(3, 0)],
699 result: CalculationResult::Exact(280.into()),
700 };
701 let mut s = String::new();
702 fact.format(&mut s, true, false, &TOO_BIG_NUMBER).unwrap();
703 assert_eq!(s, "Triple-factorial of 10 is 280 \n\n");
704 }
705 #[test]
706 fn test_format_factorial_force_shorten_large() {
707 let _ = crate::init_default();
708 let fact = Calculation {
709 value: 100.into(),
710 steps: vec![(1, 0)],
711 result: CalculationResult::Exact(
712 Integer::from_str("232019615953125000000000000000000").unwrap(),
713 ),
714 };
715 let mut s = String::new();
716 fact.format(&mut s, false, false, &TOO_BIG_NUMBER).unwrap();
717 assert_eq!(
718 s,
719 "The factorial of 100 is 232019615953125000000000000000000 \n\n"
720 );
721 }
722 #[test]
723 fn test_format_factorial_auto_shorten() {
724 let _ = crate::init_default();
725 let fact = Calculation {
726 value: 3249.into(),
727 steps: vec![(1,0)],
728 result: CalculationResult::Exact(
729 Integer::from_str("64123376882765521838840963030568127691878727205333658692200854486404915724268122521695176119279253635876611090137291969570276913721864797759577004121543081865516901512445483449601769965060634861857064173938704305418376606356891014609023859758096597956259938348528946750437026172549655426092377089294607836520057856104816993984697675759579496157280331714452191401635250556082973306115574519424960196953201395066132365440977075392087489735146885581823595966673458107135041749084983583726462930633422893526599365244406644257808664472819062579590372326362859263197427382391737724371130194668325697913147795807287917882271125437793075279592752221056089408917956641344121781056494896664298954714463291743622978314854242079926982168325256172879601086193725507405771749789801611825741625380077209528888301112734777086106637653242107578812065387025070985682845983714635115865868052531038040737170581029905537322341939002838113744745962782070030988628668438192063964391415488312555937962867645737183703289987989371752808444472206166983181218698452231772212240017445423758860236449146575513014084114116542491422920779703202877962388772371297148878539228082497149672927873860981295756607109411429871735683677151117763870227460722732815888175758276344884954699572217509595160880510811349033936358665103889507929390456055037630508759624182491412136058522758117862715726418213812122827526330257260872329993280938592007320434494018056858434839424498517707440601396194949605570023576625190771463278168007414358018195714385208103590743168343592988436427551751120123934640886569178657972642734992568217335134536548423867468448461752994160896483162496996197629537563875663545967947035030506174219867102227347745166308776568259737417457622753953177779829173739659562549005900681020920836575654282170728038645671253311902327576757877160190593437037925134089334990083104974051379653937615220306281104735360028696101767109606466502484676624025302461421267416025443536877684785195571046059926349413586237838043863850610251583618438829618642246353724734656122845609571531588284708710081901687161770748138296656576032229319208279032435434327330035540657667361558905445221013396376775953367966087790302411507662731788873698999846238792500590360394500083923341408008981770566937535640769993694293230514231436990415482012055539596871513163008100690298424743718490882019179903258642028365049142613374709689558800856050749214398290563852574062566904927777093160819034619946818734041081848355062039645388238813669985569729968236449074797273410844560761607809842265309788155248298117938165414543689689754240992067831705834383207309250573018855640140957274364918049364842508738871690383100660359882462072065885517245667353800113210423157317762013988734352812105163694758108035856505778854524789188318600594132430921277654972526820920812190785994887939816114878915385423211996897729890266102145491069991647131611614465930571202528403443141981609375073983780241828798986101030035167624885608168623694530984934856402415662119456280967778213695343026782085453754332973412779641743296676142192492849866399186979810426206090031375249707803725234273693273721779240257093247268647749842459507965336971004339619911629224227060334233904444450352505466038312828689977755744971204784911189528493222070017894145493878499832441010771999957866634720057779638435426615168763950876432375766350648344132624416041623318009761058787995614968607413528076499437020919653085121078341947075546317831737787160036257151637941590867306372647047747729689844801136819011517526975033214302293538465503160183447374945622710595033673253137034231320031041035890947260824330728621640030383790059199531556893062561713763583025693789382680375603227866194301270004745201382665157844733507781537231595412109690534099208802055220457258238249940538761563309465648945964188442431661762589082015016756223358648046396366827537498425276338958018446839292802529780142385903309447658806351362744163752044896322012923382835852429065564336560491610071025646451525782856813152304143339115660276089535216189729579966851236899105440783686498435516601131545345163557980985342246336986737955743799192164259513473592703473521185371309681754246866522812455448210758136891890444056252857117200446002038652603259983493405505521897860879586618028713025173570291196046254005672495787117170419665767607647184551353826735583363126537373726390620854105626900247296291639985561481625404296348051054604042180512892657285238147263167051884385297470314430200590079012539964786079859359747123150407661818942489735756835032462952010303051169237940063644470670372188286551571968317499183600768353941744706305961785518398629201507525785967571188931895809109770264983907551256060144219899670118351808815620474425273993244741972143504134827047237929839845492209316520698259428270901257484509899386082594602760813392081897348940617781009158927227690469330327639146118508499255466535663882163793101115885899345523332216762566667486023534622719542192198250458735391090024294254053186440646305309340840685145289223131431157156390489399333752075193525158125680201419183806547205312873264380358849214095835479613319512867197427682723250079990981586869733293245764804577570764831692705888317075918673294669326798053736223321604803330275717540789920865913177228227111643923604665959921096208765542277777829882980225810940866410254096689483571105776785837917708633884075471298045453873223073787369262426626913405098535070631297346400765749139515252242178612533747493270131589184346851060077512732273563896936880596142362061341020737937605198462006142952423931616201569440226926787162077801883794168906567939864710313203688516686488132607069944238278930371283198545637735863991249832218463680910774912311493673518088306563853170521159963238305666024221618323515872866318153226269712890565361382209276094137857215708859605439920538254391240145615109307534437972388439697355227469268959991826344643967606862639207957142695059497774782782862380576527665249011786632721781635858363134217267161265609789721847126531549373639397319541419174824349828634414533913160986280670700117904134971824878639490677063427559640621162799757094469987184056964512589036737188936656494184932005003301076625555129466247988108160104882718140259576746243025950653945267030862681712132414998384138315991964228278130346276982182371619123375659027762342810200791337975076096607162500887202849331840711439619934443487228446573730294798389422723901661778354768525095757656920903185278358954945675520361768231577076750321654682566951617894418024879897723932943778739392625374786945631297844013055183788373235917906391604745846654356151085578611880261515860397623972021392725059655970516681719822949498069366408864396412928494605832710960284204937215373010567096882590065428759248976242854170628853902061231484918006271406155707387649451852150396381227895427254475130432845540997751264574249884576973754475522081887586009543117655192564603663203594121977491966995919938707026254622729082886656923266824175261927609862131917883084745112234024557978747561458733390353402381353061864973111801478933098174668694254024372053350135966105816774315863351432700501507214833910835095241116220945368287364828423032249431110250529198415073098056537298790818802403747860478015395740166511031245261193793854201285682331906071528112005073514650997116494101706639070013374677115821301361236988511929513457351929738018793684759539098410509535113338894579685309152120362751957602730649344150813012563246391457667149097699631546631367291707994927436193366185835774355812730356484690902974319470019544218388669048171395399380611906621586431005917959473642252829970939300283923684023821586277795276767391621510747281802893209607052311085173753725616353413592446675522238914835135290803927878090361225614843018882327106532840756094139114333346621153175254833577042328095480536834801026590432360931424294133543336408702705440236553526213058195627059654976746315636170233701887454392139871178240463495036735780991998499617099173145932919728906603992606395026374552882029156921168342421270810263586384930758466962518032019544198713384832174173447126633137813741748004660781750992387224960402183367639878315847417040125065349322346833085734948541674565230896990919815801676540094611430605654337096768783494147476599630304276589463660992695730097812987784061106253993478908686689107637583574009574525664941872851644555317421340687668414081763994364249671165252652825318436095248164540239487724330276498957490699548343852181838068378612444949106850962864407345130509165857647406496109100001533123176834579856292423765079015513705518869769002090306548513909235083737585930276738943593954668225536658208962591163051195501324651032924378645456520478535714079874404144783894706654731307268880764144813567558473827034967105368425271973138213726718055181321006250745589786136935583735915890517993411416086214277469794370188740010736604373520529352427775875772577651690552630708696044935360500197728514057299685757816479040563926362665221456966339198099627395349937057349473111399655105587183432516687910987518148931239145857422059143761070545360054386871218955184209375241453611589548642653321253873363792347807426924575722280463634222994099258528815002881358362491008896204800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()
730 ),
731 };
732 let mut s = String::new();
733 fact.format(&mut s, false, false, &TOO_BIG_NUMBER).unwrap();
734 assert_eq!(
735 s,
736 "The factorial of 3249 is roughly 6.412337688276552183884096303057 × 10^10000 \n\n"
737 );
738 }
739 #[test]
740 fn test_format_factorial_chain() {
741 let _ = crate::init_default();
742 let fact = Calculation {
743 value: 5.into(),
744 steps: vec![(3, 0), (1, 0)],
745 result: CalculationResult::Exact(3628800.into()),
746 };
747 let mut s = String::new();
748 fact.format(&mut s, false, false, &TOO_BIG_NUMBER).unwrap();
749 assert_eq!(s, "The factorial of triple-factorial of 5 is 3628800 \n\n");
750 }
751 #[test]
752 fn test_format_factorial_negative() {
753 let _ = crate::init_default();
754 let fact = Calculation {
755 value: 0.into(),
756 steps: vec![(1, 3)],
757 result: CalculationResult::Exact(3628800.into()),
758 };
759 let mut s = String::new();
760 fact.format(&mut s, false, false, &TOO_BIG_NUMBER).unwrap();
761 assert_eq!(s, "The triple-y negative factorial of 0 is 3628800 \n\n");
762 let fact = Calculation {
763 value: 0.into(),
764 steps: vec![(1, 1)],
765 result: CalculationResult::Exact(3628800.into()),
766 };
767 let mut s = String::new();
768 fact.format(&mut s, false, false, &TOO_BIG_NUMBER).unwrap();
769 assert_eq!(s, "The negative factorial of 0 is 3628800 \n\n");
770 }
771 #[test]
772 fn test_format_approximate_factorial() {
773 let _ = crate::init_default();
774 let fact = Calculation {
775 value: 0.into(),
776 steps: vec![(1, 0)],
777 result: CalculationResult::Approximate(
778 Float::with_val(FLOAT_PRECISION, 2.83947).into(),
779 10043.into(),
780 ),
781 };
782 let mut s = String::new();
783 fact.format(&mut s, false, false, &TOO_BIG_NUMBER).unwrap();
784 assert_eq!(
785 s,
786 "The factorial of 0 is approximately 2.83947 × 10^10043 \n\n"
787 );
788 }
789 #[test]
790 fn test_format_approximate_digits_factorial() {
791 let _ = crate::init_default();
792 let fact = Calculation {
793 value: 0.into(),
794 steps: vec![(1, 0)],
795 result: CalculationResult::ApproximateDigits(false, 10043394.into()),
796 };
797 let mut s = String::new();
798 fact.format(&mut s, false, false, &TOO_BIG_NUMBER).unwrap();
799 assert_eq!(
800 s,
801 "The factorial of 0 has approximately 10043394 digits \n\n"
802 );
803 }
804 #[test]
805 fn test_format_complex_infinity_factorial() {
806 let _ = crate::init_default();
807 let fact = Calculation {
808 value: 0.into(),
809 steps: vec![(1, 0)],
810 result: CalculationResult::ComplexInfinity,
811 };
812 let mut s = String::new();
813 fact.format(&mut s, false, false, &TOO_BIG_NUMBER).unwrap();
814 assert_eq!(s, "The factorial of 0 is ∞\u{0303} \n\n");
815 }
816 #[test]
817 fn test_format_digits_tower() {
818 let _ = crate::init_default();
819 let fact = Calculation {
820 value: 0.into(),
821 steps: vec![(1, 0)],
822 result: CalculationResult::ApproximateDigitsTower(false, false, 9, 10375.into()),
823 };
824 let mut s = String::new();
825 fact.format(&mut s, false, false, &TOO_BIG_NUMBER).unwrap();
826 assert_eq!(
827 s,
828 "The factorial of 0 has on the order of 10^(10\\^10\\^10\\^10\\^10\\^10\\^10\\^10\\^(10375\\)) digits \n\n"
829 );
830 }
831 #[test]
832 fn test_format_digits_tower_negative() {
833 let _ = crate::init_default();
834 let fact = Calculation {
835 value: 0.into(),
836 steps: vec![(1, 0)],
837 result: CalculationResult::ApproximateDigitsTower(false, true, 9, 10375.into()),
838 };
839 let mut s = String::new();
840 fact.format(&mut s, false, false, &TOO_BIG_NUMBER).unwrap();
841 assert_eq!(
842 s,
843 "The factorial of 0 has on the order of -10^(10\\^10\\^10\\^10\\^10\\^10\\^10\\^10\\^(10375\\)) digits \n\n"
844 );
845 }
846 #[test]
847 fn test_format_digits_tower_tet() {
848 let _ = crate::init_default();
849 let fact = Calculation {
850 value: 0.into(),
851 steps: vec![(1, 0)],
852 result: CalculationResult::ApproximateDigitsTower(false, false, 9, 10375.into()),
853 };
854 let mut s = String::new();
855 fact.format(&mut s, false, true, &TOO_BIG_NUMBER).unwrap();
856 assert_eq!(s, "All that of 0 has on the order of ^(10)10 digits \n\n");
857 }
858 #[test]
859 fn test_format_gamma() {
860 let _ = crate::init_default();
861 let fact = Calculation {
862 value: Number::Float(Float::with_val(FLOAT_PRECISION, 9.2).into()),
863 steps: vec![(1, 0)],
864 result: CalculationResult::Float(Float::with_val(FLOAT_PRECISION, 893.83924421).into()),
865 };
866 let mut s = String::new();
867 fact.format(&mut s, false, false, &TOO_BIG_NUMBER).unwrap();
868 assert_eq!(s, "The factorial of 9.2 is approximately 893.83924421 \n\n");
869 }
870 #[test]
871 fn test_format_gamma_fallback() {
872 let _ = crate::init_default();
873 let fact = Calculation {
874 value: Number::Float(Float::with_val(FLOAT_PRECISION, 0).into()),
875 steps: vec![(1, 0)],
876 result: {
877 let mut m = Float::with_val(FLOAT_PRECISION, f64::MAX);
878 m.next_up();
879 CalculationResult::Float(m.into())
880 },
881 };
882 let mut s = String::new();
883 fact.format(&mut s, false, false, &TOO_BIG_NUMBER).unwrap();
884 assert_eq!(
885 s,
886 "The factorial of 0 is approximately 179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \n\n"
887 );
888 }
889 #[test]
890 fn test_format_approximate_factorial_shorten() {
891 let _ = crate::init_default();
892 let fact = Calculation {
893 value: Number::Exact(
894 Integer::from_str("2018338437429423744923849374833232131").unwrap(),
895 ),
896 steps: vec![(1, 0)],
897 result: CalculationResult::Approximate(
898 Float::with_val(FLOAT_PRECISION, 2.8394792834).into(),
899 Integer::from_str("10094283492304894983443984102489842984271").unwrap(),
900 ),
901 };
902 let mut s = String::new();
903 fact.format(&mut s, true, false, &TOO_BIG_NUMBER).unwrap();
904 assert_eq!(
905 s,
906 "The factorial of roughly 2.018338437429423744923849374833 × 10^36 is approximately 2.8394792834 × 10^(1.009428349230489498344398410249 × 10^40) \n\n"
907 );
908 }
909 #[test]
910 fn test_format_approximate_digits_factorial_shorten() {
911 let _ = crate::init_default();
912 let fact = Calculation {
913 value: Number::Exact(
914 Integer::from_str("2313820948092579283573259490834298719").unwrap(),
915 ),
916 steps: vec![(1, 0)],
917 result: CalculationResult::ApproximateDigits(
918 false,
919 Integer::from_str("9842371208573508275237815084709374240128347012847").unwrap(),
920 ),
921 };
922 let mut s = String::new();
923 fact.format(&mut s, true, false, &TOO_BIG_NUMBER).unwrap();
924 assert_eq!(
925 s,
926 "The factorial of roughly 2.313820948092579283573259490834 × 10^36 has approximately 9.842371208573508275237815084709 × 10^48 digits \n\n"
927 );
928 }
929 #[test]
930 fn test_format_digits_tower_shorten() {
931 let _ = crate::init_default();
932 let fact = Calculation {
933 value: Number::Exact(
934 Integer::from_str("13204814708471087502685784603872164320053271").unwrap(),
935 ),
936 steps: vec![(1, 0)],
937 result: CalculationResult::ApproximateDigitsTower(
938 false,
939 false,
940 9,
941 Integer::from_str("7084327410873502875032857120358730912469148632").unwrap(),
942 ),
943 };
944 let mut s = String::new();
945 fact.format(&mut s, true, false, &TOO_BIG_NUMBER).unwrap();
946 assert_eq!(
947 s,
948 "The factorial of roughly 1.320481470847108750268578460387 × 10^43 has on the order of 10^(10\\^10\\^10\\^10\\^10\\^10\\^10\\^10\\^(7.084327410873502875032857120359 × 10^45\\)) digits \n\n"
949 );
950 }
951 #[test]
952 fn test_format_huge() {
953 let _ = crate::init_default();
954 let fact = Calculation {
955 value: 0.into(),
956 steps: vec![(1, 0)],
957 result: CalculationResult::Exact({
958 let mut r = Float::with_val(FLOAT_PRECISION, crate::rug::float::Special::Infinity);
959 r.next_down();
960 r.to_integer().unwrap()
961 }),
962 };
963 let mut s = String::new();
964 fact.format(&mut s, false, false, &TOO_BIG_NUMBER).unwrap();
965 assert_eq!(
966 s,
967 "The factorial of 0 is roughly 2.098578716467387692404358116884 × 10^323228496 \n\n"
968 );
969 }
970
971 #[test]
972 fn test_calculation_is_approximate() {
973 let _ = crate::init_default();
974 let c1 = Calculation {
975 value: 0.into(),
976 steps: vec![],
977 result: CalculationResult::Approximate(
978 Float::with_val(FLOAT_PRECISION, 2.0).into(),
979 1.into(),
980 ),
981 };
982 assert!(c1.is_approximate());
983 let c2 = Calculation {
984 value: 0.into(),
985 steps: vec![],
986 result: CalculationResult::Exact(1.into()),
987 };
988 assert!(!c2.is_approximate());
989 }
990
991 #[test]
992 fn test_calculation_is_rounded() {
993 let _ = crate::init_default();
994 let c1 = Calculation {
995 value: Number::Float(Float::with_val(FLOAT_PRECISION, 1.23).into()),
996 steps: vec![],
997 result: CalculationResult::Approximate(
998 Float::with_val(FLOAT_PRECISION, 0.0).into(),
999 0.into(),
1000 ),
1001 };
1002 assert!(c1.is_rounded());
1003 let c2 = Calculation {
1004 value: Number::Float(Float::with_val(FLOAT_PRECISION, 1.23).into()),
1005 steps: vec![],
1006 result: CalculationResult::Float(Float::with_val(FLOAT_PRECISION, 1.23).into()),
1007 };
1008 assert!(!c2.is_rounded());
1009 let c3 = Calculation {
1010 value: 1.into(),
1011 steps: vec![],
1012 result: CalculationResult::Exact(1.into()),
1013 };
1014 assert!(!c3.is_rounded());
1015 }
1016
1017 #[test]
1018 fn test_is_too_long() {
1019 let _ = crate::init_default();
1020 let small = Calculation {
1021 value: 1.into(),
1022 steps: vec![],
1023 result: CalculationResult::Exact(1.into()),
1024 };
1025 assert!(!small.is_too_long(&TOO_BIG_NUMBER));
1026 let big = Calculation {
1027 value: 1.into(),
1028 steps: vec![],
1029 result: CalculationResult::Exact((*TOO_BIG_NUMBER).clone() + 1),
1030 };
1031 assert!(big.is_too_long(&TOO_BIG_NUMBER));
1032 let fl = Calculation {
1033 value: 1.into(),
1034 steps: vec![],
1035 result: CalculationResult::Float(Float::with_val(FLOAT_PRECISION, 1.0).into()),
1036 };
1037 assert!(!fl.is_too_long(&TOO_BIG_NUMBER));
1038 }
1039}