factorion_lib/
calculation_results.rs

1//! This module handles the formatting of the calculations (`The factorial of Subfactorial of 5 is`, etc.)
2use 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/// The result of a calculation in various formats.
71#[derive(Clone, PartialEq, Ord, Eq, Hash, PartialOrd)]
72pub enum CalculationResult {
73    Exact(Integer),
74    /// a * 10^b
75    Approximate(OrdFloat, Integer),
76    /// b digits (a is whether the number is negative)
77    ApproximateDigits(bool, Integer),
78    /// (^(c)10)^d digits (a is whether is negative, b is negative number of digits (super small))
79    ApproximateDigitsTower(bool, bool, u32, Integer),
80    Float(OrdFloat),
81    ComplexInfinity,
82}
83
84/// A number in various formats. An alias of [CalculationResult].
85pub 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    /// Formats a number. \
132    /// Shorten turns integers into scientific notation if that makes them shorter. \
133    /// Aggressive enables tertation for towers.
134    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    /// The base number
227    pub value: Number,
228    /// Steps taken during calculation (level, negation)
229    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    /// Formats a Calcucation. \
283    /// Force shorten shortens all integers, if that makes them smaller. \
284    /// Agressive shorten replaces the description of what steps were taken with "All that of" and truns towers into tetration. \
285    /// Too big number is from when the integer part automatically gets shortened.
286    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}
418/// Rounds a base 10 number string. \
419/// Uses the last digit to decide the rounding direction. \
420/// Rounds over 9s. This does **not** keep the length or turn rounded over digits into zeros. \
421/// If the input is all 9s, this will round to 10. \
422///
423/// # Panic
424/// This function may panic if less than two digits are supplied, or if it contains a non-digit of base 10.
425fn round(number: &mut String) {
426    // Check additional digit if we need to round
427    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            // Carry over at 9s
437            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                    // If we reached the end we get 10
443                    number.push_str("10");
444                    return;
445                };
446                last_digit = digit;
447            }
448            // Round up
449            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    // Only add decimal if we have more than one digit
497    if truncated_number.len() > 1 {
498        truncated_number.insert(1, '.'); // Decimal point
499    }
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    // NOTE: The factorials here might be wrong, but we don't care, we are just testing the formatting
668
669    #[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}