factorion_lib/
calculation_results.rs

1//! This module handles the formatting of the calculations (`The factorial of Subfactorial of 5 is`, etc.)
2
3#[cfg(any(feature = "serde", test))]
4use serde::{Deserialize, Serialize};
5
6use crate::rug::float::OrdFloat;
7use crate::rug::ops::{NegAssign, NotAssign, Pow};
8use crate::rug::{Float, Integer};
9use crate::{Consts, locale};
10use std::borrow::Cow;
11use std::fmt;
12use std::fmt::Write;
13
14pub mod recommended {
15    pub const NUMBER_DECIMALS_SCIENTIFIC: usize = 30;
16}
17
18impl fmt::Debug for CalculationResult {
19    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20        fn truncate<T: fmt::Debug>(val: &T) -> String {
21            let s = format!("{val:?}");
22            if s.len() > 25 {
23                format!("{}...", &s[..20])
24            } else {
25                s
26            }
27        }
28
29        match self {
30            CalculationResult::Exact(n) => write!(f, "Exact({})", truncate(n)),
31            CalculationResult::Approximate(of, int) => {
32                write!(
33                    f,
34                    "Approximate({}, {})",
35                    truncate(&of.as_float()),
36                    truncate(int)
37                )
38            }
39            CalculationResult::ApproximateDigits(i, n) => {
40                write!(f, "ApproximateDigits({}, {})", i, truncate(n))
41            }
42            CalculationResult::ApproximateDigitsTower(i, b, u, n) => {
43                write!(
44                    f,
45                    "ApproximateDigitsTower({}, {}, {}, {})",
46                    i,
47                    b,
48                    u,
49                    truncate(n)
50                )
51            }
52            CalculationResult::Float(of) => write!(f, "Float({})", truncate(&of.as_float())),
53            CalculationResult::ComplexInfinity => write!(f, "ComplexInfinity"),
54        }
55    }
56}
57
58/// The result of a calculation in various formats.
59#[derive(Clone, PartialEq, Ord, Eq, Hash, PartialOrd)]
60#[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
61pub enum CalculationResult {
62    Exact(Integer),
63    /// a * 10^b
64    Approximate(OrdFloat, Integer),
65    /// b digits (a is whether the number is negative)
66    ApproximateDigits(bool, Integer),
67    /// (^(c)10)^d digits (a is whether is negative, b is negative number of digits (super small))
68    ApproximateDigitsTower(bool, bool, u32, Integer),
69    Float(OrdFloat),
70    ComplexInfinity,
71}
72
73/// A number in various formats. An alias of [CalculationResult].
74pub type Number = CalculationResult;
75
76impl Number {
77    pub fn negate(&mut self) {
78        match self {
79            Self::Approximate(x, _) | Self::Float(x) => x.as_float_mut().neg_assign(),
80            Self::Exact(n) => n.neg_assign(),
81            Self::ApproximateDigitsTower(n, _, _, _) | Self::ApproximateDigits(n, _) => {
82                n.not_assign()
83            }
84            Self::ComplexInfinity => {}
85        }
86    }
87    pub fn is_too_long(&self, too_big_number: &Integer) -> bool {
88        let n = match self {
89            CalculationResult::Exact(n)
90            | CalculationResult::ApproximateDigits(_, n)
91            | CalculationResult::Approximate(_, n)
92            | CalculationResult::ApproximateDigitsTower(_, _, _, n) => n,
93            CalculationResult::Float(_) | CalculationResult::ComplexInfinity => return false,
94        };
95        n > too_big_number
96    }
97}
98impl From<Integer> for Number {
99    fn from(value: Integer) -> Self {
100        Number::Exact(value)
101    }
102}
103impl From<i32> for Number {
104    fn from(value: i32) -> Self {
105        Number::Exact(value.into())
106    }
107}
108impl From<Float> for Number {
109    fn from(value: Float) -> Self {
110        Number::Float(value.into())
111    }
112}
113
114impl CalculationResult {
115    /// Formats a number. \
116    /// Shorten turns integers into scientific notation if that makes them shorter. \
117    /// Aggressive enables tertation for towers.
118    fn format(
119        &self,
120        acc: &mut String,
121        rough: &mut bool,
122        shorten: bool,
123        agressive: bool,
124        consts: &Consts,
125        locale: &locale::NumFormat,
126    ) -> std::fmt::Result {
127        let mut start = acc.len();
128        match &self {
129            CalculationResult::Exact(factorial) => {
130                if shorten {
131                    let (s, r) = truncate(factorial, consts);
132                    *rough = r;
133                    acc.write_str(&s)?;
134                } else {
135                    write!(acc, "{factorial}")?;
136                }
137            }
138            CalculationResult::Approximate(base, exponent) => {
139                let base = base.as_float();
140                if !base.to_f64().is_finite() {
141                    write!(acc, "{base:.30}")?;
142                } else {
143                    write!(acc, "{}", base.to_f64())?;
144                };
145                acc.write_str(" × 10^")?;
146                if shorten {
147                    acc.write_str("(")?;
148                    acc.write_str(&truncate(exponent, consts).0)?;
149                    acc.write_str(")")?;
150                } else {
151                    write!(acc, "{exponent}")?;
152                }
153            }
154            CalculationResult::ApproximateDigits(_, digits) => {
155                if shorten {
156                    acc.write_str(&truncate(digits, consts).0)?;
157                } else {
158                    write!(acc, "{digits}")?;
159                }
160            }
161            CalculationResult::ApproximateDigitsTower(_, negative, depth, exponent) => {
162                acc.write_str(if *negative { "-" } else { "" })?;
163                if !agressive {
164                    if *depth > 0 {
165                        acc.write_str("10^(")?;
166                    }
167                    if *depth > 1 {
168                        acc.write_str(&"10\\^".repeat(*depth as usize - 1))?;
169                        acc.write_str("(")?;
170                    }
171                    if shorten {
172                        acc.write_str(&truncate(exponent, consts).0)?;
173                    } else {
174                        write!(acc, "{exponent}")?;
175                    }
176                    if *depth > 1 {
177                        acc.write_str("\\)")?;
178                    }
179                    if *depth > 0 {
180                        acc.write_str(")")?;
181                    }
182                } else {
183                    let mut extra = 0;
184                    let mut exponent = Float::with_val(consts.float_precision, exponent);
185                    while exponent >= 10 {
186                        extra += 1;
187                        exponent = exponent.log10();
188                    }
189                    acc.write_str("^(")?;
190                    write!(acc, "{}", depth + extra)?;
191                    acc.write_str(")10")?;
192                }
193            }
194            CalculationResult::Float(gamma) => {
195                if !gamma.as_float().to_f64().is_finite() {
196                    write!(acc, "{:.30}", gamma.as_float())?;
197                } else {
198                    write!(acc, "{}", gamma.as_float().to_f64())?;
199                }
200            }
201            CalculationResult::ComplexInfinity => {
202                acc.write_str("∞\u{0303}")?;
203            }
204        }
205        if *locale.decimal() != '.' {
206            let decimal = locale.decimal().to_string();
207            while start < acc.len() {
208                start = replace(acc, start, ".", &decimal);
209            }
210        }
211        Ok(())
212    }
213}
214
215#[derive(Debug, Clone, PartialEq, Ord, Eq, Hash, PartialOrd)]
216#[cfg_attr(any(feature = "serde", test), derive(Serialize, Deserialize))]
217pub struct Calculation {
218    /// The base number
219    pub value: Number,
220    /// Steps taken during calculation (level, negation)
221    pub steps: Vec<(i32, bool)>,
222    pub result: CalculationResult,
223}
224
225impl Calculation {
226    pub fn is_digit_tower(&self) -> bool {
227        matches!(
228            self,
229            Calculation {
230                result: CalculationResult::ApproximateDigitsTower(_, _, _, _),
231                ..
232            }
233        )
234    }
235    pub fn is_aproximate_digits(&self) -> bool {
236        matches!(
237            self,
238            Calculation {
239                result: CalculationResult::ApproximateDigits(_, _),
240                ..
241            }
242        )
243    }
244    pub fn is_approximate(&self) -> bool {
245        matches!(
246            self,
247            Calculation {
248                result: CalculationResult::Approximate(_, _),
249                ..
250            }
251        )
252    }
253    pub fn is_rounded(&self) -> bool {
254        matches!(
255            self,
256            Calculation {
257                value: Number::Float(_),
258                ..
259            }
260        ) && !matches!(
261            self,
262            Calculation {
263                result: CalculationResult::Float(_),
264                ..
265            }
266        )
267    }
268    pub fn is_too_long(&self, too_big_number: &Integer) -> bool {
269        self.result.is_too_long(too_big_number) || self.value.is_too_long(too_big_number)
270    }
271}
272
273impl Calculation {
274    /// Formats a Calcucation. \
275    /// Force shorten shortens all integers, if that makes them smaller. \
276    /// Agressive shorten replaces the description of what steps were taken with "All that of" and truns towers into tetration. \
277    /// Too big number is from when the integer part automatically gets shortened.
278    pub fn format(
279        &self,
280        acc: &mut String,
281        force_shorten: bool,
282        agressive_shorten: bool,
283        too_big_number: &Integer,
284        consts: &Consts,
285        locale: &locale::Format<'_>,
286    ) -> Result<(), std::fmt::Error> {
287        let frame_start = acc.len();
288        acc.write_str(match (&self.value, &self.result, agressive_shorten) {
289            // All that
290            (_, _, true) => locale.all_that(),
291            // on the order
292            (_, CalculationResult::ApproximateDigitsTower(_, _, _, _), _) => locale.order(),
293            // digits
294            (_, CalculationResult::ApproximateDigits(_, _), _) => locale.digits(),
295            // approximately
296            (Number::Float(_), _, _) | (_, CalculationResult::Approximate(_, _), _) => {
297                locale.approx()
298            }
299            // is
300            _ => locale.exact(),
301        })?;
302        acc.write_str(" \n\n")?;
303
304        let mut number = String::new();
305        let mut rough = false;
306        self.value.format(
307            &mut number,
308            &mut rough,
309            force_shorten || self.result.is_too_long(too_big_number) || agressive_shorten,
310            agressive_shorten,
311            consts,
312            &locale.number_format(),
313        )?;
314        if rough {
315            replace(acc, frame_start, "{number}", locale.rough_number());
316        }
317        replace(acc, frame_start, "{number}", &number);
318        replace(acc, frame_start, "{result}", "{number}");
319        let mut number = String::new();
320        let mut rough = false;
321        self.result.format(
322            &mut number,
323            &mut rough,
324            force_shorten || self.result.is_too_long(too_big_number) || agressive_shorten,
325            agressive_shorten,
326            consts,
327            &locale.number_format(),
328        )?;
329        if rough {
330            replace(acc, frame_start, "{number}", locale.rough_number());
331        }
332        replace(acc, frame_start, "{number}", &number);
333
334        let len = self.steps.len();
335        let mut start = frame_start;
336        for (i, (level, neg)) in self.steps.iter().copied().rev().enumerate() {
337            if i != len - 1 {
338                replace(acc, start, "{factorial}", locale.nest());
339            }
340
341            if neg {
342                replace(acc, start, "{factorial}", "negative {factorial}");
343            }
344
345            let calc_start = replace(
346                acc,
347                start,
348                "{factorial}",
349                &Self::get_factorial_level_string(level.abs(), locale),
350            );
351
352            replace(
353                acc,
354                start,
355                "{factorial}",
356                if level < 0 {
357                    locale.termial()
358                } else {
359                    locale.factorial()
360                },
361            );
362            if *locale.capitalize_calc() {
363                let mut ind = acc[calc_start..].char_indices();
364                if let Some((start, _)) = ind.next()
365                    && let Some((end, _)) = ind.next()
366                {
367                    acc[calc_start..][start..end].make_ascii_uppercase();
368                }
369            }
370
371            if i != len - 1 {
372                start = replace(acc, start, "{next}", "{factorial}");
373            }
374        }
375        let mut ind = acc[frame_start..].char_indices();
376        if let Some((start, _)) = ind.next()
377            && let Some((end, _)) = ind.next()
378        {
379            acc[frame_start..][start..end].make_ascii_uppercase();
380        }
381
382        Ok(())
383    }
384
385    fn get_factorial_level_string<'a>(level: i32, locale: &'a locale::Format<'a>) -> Cow<'a, str> {
386        const SINGLES: [&str; 10] = [
387            "", "un", "duo", "tre", "quattuor", "quin", "sex", "septen", "octo", "novem",
388        ];
389        const SINGLES_LAST: [&str; 10] = [
390            "", "un", "du", "tr", "quadr", "quint", "sext", "sept", "oct", "non",
391        ];
392        const TENS: [&str; 10] = [
393            "",
394            "dec",
395            "vigin",
396            "trigin",
397            "quadragin",
398            "quinquagin",
399            "sexagin",
400            "septuagin",
401            "octogin",
402            "nonagin",
403        ];
404        const HUNDREDS: [&str; 10] = [
405            "",
406            "cen",
407            "ducen",
408            // Note this differs from the wikipedia list to disambiguate from 103, which continuing the pattern should be trecentuple
409            "tricen",
410            "quadringen",
411            "quingen",
412            "sescen",
413            "septingen",
414            "octingen ",
415            "nongen",
416        ];
417        // Note that other than milluple, these are not found in a list, but continue the pattern from mill with different starts
418        const THOUSANDS: [&str; 10] = [
419            "", "mill", "bill", "trill", "quadrill", "quintill", "sextill", "septill", "octill",
420            "nonill",
421        ];
422        const BINDING_T: [[bool; 10]; 4] = [
423            // Singles
424            [
425                false, false, false, false, false, false, false, false, false, false,
426            ],
427            // Tens
428            [false, false, true, true, true, true, true, true, true, true],
429            // Hundreds
430            [false, true, true, true, true, true, true, true, true, true],
431            // Thousands
432            [
433                false, false, false, false, false, false, false, false, false, false,
434            ],
435        ];
436        if let Some(s) = locale.num_overrides().get(&level) {
437            return s.as_ref().into();
438        }
439        match level {
440            0 => locale.sub().as_ref().into(),
441            1 => "{factorial}".into(),
442            ..=9999 if !locale.force_num() => {
443                let singles = if level < 10 { SINGLES_LAST } else { SINGLES };
444                let mut acc = String::new();
445                let mut n = level;
446                let s = n % 10;
447                n /= 10;
448                acc.write_str(singles[s as usize]).unwrap();
449                let t = n % 10;
450                n /= 10;
451                acc.write_str(TENS[t as usize]).unwrap();
452                let h = n % 10;
453                n /= 10;
454                acc.write_str(HUNDREDS[h as usize]).unwrap();
455                let th = n % 10;
456                acc.write_str(THOUSANDS[th as usize]).unwrap();
457                // Check if we need tuple not uple
458                let last_written = [s, t, h, th]
459                    .iter()
460                    .cloned()
461                    .enumerate()
462                    .rev()
463                    .find(|(_, n)| *n != 0)
464                    .unwrap();
465                if BINDING_T[last_written.0][last_written.1 as usize] {
466                    acc.write_str("t").unwrap();
467                }
468                acc.write_str(locale.uple()).unwrap();
469
470                acc.into()
471            }
472            _ => {
473                let mut suffix = String::new();
474                write!(&mut suffix, "{level}-{{factorial}}").unwrap();
475                suffix.into()
476            }
477        }
478    }
479}
480/// Rounds a base 10 number string. \
481/// Uses the last digit to decide the rounding direction. \
482/// Rounds over 9s. This does **not** keep the length or turn rounded over digits into zeros. \
483/// If the input is all 9s, this will round to 10. \
484///
485/// # Panic
486/// This function may panic if less than two digits are supplied, or if it contains a non-digit of base 10.
487fn round(number: &mut String) {
488    // Check additional digit if we need to round
489    if let Some(digit) = number
490        .pop()
491        .map(|n| n.to_digit(10).expect("Not a base 10 number"))
492        && digit >= 5
493    {
494        let mut last_digit = number
495            .pop()
496            .and_then(|n| n.to_digit(10))
497            .expect("Not a base 10 number");
498        // Carry over at 9s
499        while last_digit == 9 {
500            let Some(digit) = number
501                .pop()
502                .map(|n| n.to_digit(10).expect("Not a base 10 number"))
503            else {
504                // If we reached the end we get 10
505                number.push_str("10");
506                return;
507            };
508            last_digit = digit;
509        }
510        // Round up
511        let _ = write!(number, "{}", last_digit + 1);
512    }
513}
514fn truncate(number: &Integer, consts: &Consts) -> (String, bool) {
515    let prec = consts.float_precision;
516    if number == &0 {
517        return (number.to_string(), false);
518    }
519    let negative = number.is_negative();
520    let orig_number = number;
521    let number = number.clone().abs();
522    let length = (Float::with_val(prec, &number).ln() / Float::with_val(prec, 10).ln())
523        .to_integer_round(crate::rug::float::Round::Down)
524        .unwrap()
525        .0;
526    let truncated_number: Integer = &number
527        / (Float::with_val(prec, 10)
528            .pow((length.clone() - consts.number_decimals_scientific - 1u8).max(Integer::ZERO))
529            .to_integer()
530            .unwrap());
531    let mut truncated_number = truncated_number.to_string();
532    if truncated_number.len() > consts.number_decimals_scientific {
533        round(&mut truncated_number);
534    }
535    if let Some(mut digit) = truncated_number.pop() {
536        while digit == '0' {
537            digit = match truncated_number.pop() {
538                Some(x) => x,
539                None => break,
540            }
541        }
542        truncated_number.push(digit);
543    }
544    // Only add decimal if we have more than one digit
545    if truncated_number.len() > 1 {
546        truncated_number.insert(1, '.'); // Decimal point
547    }
548    if negative {
549        truncated_number.insert(0, '-');
550    }
551    if length > consts.number_decimals_scientific + 1 {
552        (format!("{truncated_number} × 10^{length}"), true)
553    } else {
554        (orig_number.to_string(), false)
555    }
556}
557
558fn replace(s: &mut String, search_start: usize, from: &str, to: &str) -> usize {
559    if let Some(start) = s[search_start..].find(from) {
560        let start = start + search_start;
561        s.replace_range(start..(start + from.len()), to);
562        start
563    } else {
564        s.len()
565    }
566}
567#[cfg(test)]
568mod tests {
569    use super::*;
570    use crate::recommended::FLOAT_PRECISION;
571    use crate::rug::Integer;
572    use std::{str::FromStr, sync::LazyLock};
573
574    static TOO_BIG_NUMBER: LazyLock<Integer> =
575        LazyLock::new(|| Integer::from_str(&format!("1{}", "0".repeat(9999))).unwrap());
576
577    #[test]
578    fn test_round_down() {
579        let mut number = String::from("1929472373");
580        round(&mut number);
581        assert_eq!(number, "192947237");
582    }
583
584    #[test]
585    fn test_round_up() {
586        let mut number = String::from("74836748625");
587        round(&mut number);
588        assert_eq!(number, "7483674863");
589    }
590
591    #[test]
592    fn test_round_carry() {
593        let mut number = String::from("24999999995");
594        round(&mut number);
595        assert_eq!(number, "25");
596    }
597
598    #[test]
599    fn test_factorial_level_string() {
600        let en = locale::get_en();
601        assert_eq!(
602            Calculation::get_factorial_level_string(1, &en.format()),
603            "{factorial}"
604        );
605        assert_eq!(
606            Calculation::get_factorial_level_string(2, &en.format()),
607            "double-{factorial}"
608        );
609        assert_eq!(
610            Calculation::get_factorial_level_string(3, &en.format()),
611            "triple-{factorial}"
612        );
613        assert_eq!(
614            Calculation::get_factorial_level_string(10, &en.format()),
615            "decuple-{factorial}"
616        );
617        assert_eq!(
618            Calculation::get_factorial_level_string(45, &en.format()),
619            "quinquadragintuple-{factorial}"
620        );
621        assert_eq!(
622            Calculation::get_factorial_level_string(50, &en.format()),
623            "quinquagintuple-{factorial}"
624        );
625        assert_eq!(
626            Calculation::get_factorial_level_string(100, &en.format()),
627            "centuple-{factorial}"
628        );
629        assert_eq!(
630            Calculation::get_factorial_level_string(521, &en.format()),
631            "unviginquingentuple-{factorial}"
632        );
633        assert_eq!(
634            Calculation::get_factorial_level_string(1000, &en.format()),
635            "milluple-{factorial}"
636        );
637        assert_eq!(
638            Calculation::get_factorial_level_string(4321, &en.format()),
639            "unvigintricenquadrilluple-{factorial}"
640        );
641        assert_eq!(
642            Calculation::get_factorial_level_string(10000, &en.format()),
643            "10000-{factorial}"
644        );
645        let de = locale::get_de();
646        assert_eq!(
647            Calculation::get_factorial_level_string(1, &de.format()),
648            "{factorial}"
649        );
650        assert_eq!(
651            Calculation::get_factorial_level_string(2, &de.format()),
652            "doppel{factorial}"
653        );
654        assert_eq!(
655            Calculation::get_factorial_level_string(3, &de.format()),
656            "trippel{factorial}"
657        );
658        assert_eq!(
659            Calculation::get_factorial_level_string(45, &de.format()),
660            "quinquadragintupel{factorial}"
661        );
662    }
663
664    #[test]
665    fn test_truncate() {
666        let consts = Consts::default();
667        assert_eq!(truncate(&Integer::from_str("0").unwrap(), &consts,).0, "0");
668        assert_eq!(
669            truncate(&Integer::from_str("-1").unwrap(), &consts,).0,
670            "-1"
671        );
672        assert_eq!(
673            truncate(
674                &Integer::from_str(&format!("1{}", "0".repeat(300))).unwrap(),
675                &consts
676            )
677            .0,
678            "1 × 10^300"
679        );
680        assert_eq!(
681            truncate(
682                &-Integer::from_str(&format!("1{}", "0".repeat(300))).unwrap(),
683                &consts
684            )
685            .0,
686            "-1 × 10^300"
687        );
688        assert_eq!(
689            truncate(
690                &Integer::from_str(&format!("1{}", "0".repeat(2000000))).unwrap(),
691                &consts
692            )
693            .0,
694            "1 × 10^2000000"
695        );
696    }
697
698    #[test]
699    fn test_factorial_format() {
700        let consts = Consts::default();
701        let mut acc = String::new();
702        let factorial = Calculation {
703            value: 5.into(),
704            steps: vec![(1, false)],
705            result: CalculationResult::Exact(Integer::from(120)),
706        };
707        factorial
708            .format(
709                &mut acc,
710                false,
711                false,
712                &TOO_BIG_NUMBER,
713                &consts,
714                &consts.locales.get("en").unwrap().format(),
715            )
716            .unwrap();
717        assert_eq!(acc, "Factorial of 5 is 120 \n\n");
718
719        let mut acc = String::new();
720        let factorial = Calculation {
721            value: 5.into(),
722            steps: vec![(0, false)],
723            result: CalculationResult::Exact(Integer::from(120)),
724        };
725        factorial
726            .format(
727                &mut acc,
728                false,
729                false,
730                &TOO_BIG_NUMBER,
731                &consts,
732                &consts.locales.get("en").unwrap().format(),
733            )
734            .unwrap();
735        assert_eq!(acc, "Subfactorial of 5 is 120 \n\n");
736
737        let mut acc = String::new();
738        let factorial = Calculation {
739            value: 5.into(),
740            steps: vec![(1, false)],
741            result: CalculationResult::Approximate(
742                Float::with_val(FLOAT_PRECISION, 1.2).into(),
743                5.into(),
744            ),
745        };
746        factorial
747            .format(
748                &mut acc,
749                false,
750                false,
751                &TOO_BIG_NUMBER,
752                &consts,
753                &consts.locales.get("en").unwrap().format(),
754            )
755            .unwrap();
756        assert_eq!(acc, "Factorial of 5 is approximately 1.2 × 10^5 \n\n");
757
758        let mut acc = String::new();
759        let factorial = Calculation {
760            value: 5.into(),
761            steps: vec![(1, false)],
762            result: CalculationResult::ApproximateDigits(false, 3.into()),
763        };
764        factorial
765            .format(
766                &mut acc,
767                false,
768                false,
769                &TOO_BIG_NUMBER,
770                &consts,
771                &consts.locales.get("en").unwrap().format(),
772            )
773            .unwrap();
774        assert_eq!(acc, "Factorial of 5 has approximately 3 digits \n\n");
775
776        let mut acc = String::new();
777        let factorial = Calculation {
778            value: 5.into(),
779            steps: vec![(1, false)],
780            result: CalculationResult::Exact(Integer::from(120)),
781        };
782        factorial
783            .format(
784                &mut acc,
785                true,
786                false,
787                &TOO_BIG_NUMBER,
788                &consts,
789                &consts.locales.get("en").unwrap().format(),
790            )
791            .unwrap();
792        assert_eq!(acc, "Factorial of 5 is 120 \n\n");
793    }
794}
795
796#[cfg(test)]
797mod test {
798    use std::{str::FromStr, sync::LazyLock};
799
800    use super::*;
801
802    use crate::recommended::FLOAT_PRECISION;
803    static TOO_BIG_NUMBER: LazyLock<Integer> =
804        LazyLock::new(|| Integer::from_str(&format!("1{}", "0".repeat(9999))).unwrap());
805
806    // NOTE: The factorials here might be wrong, but we don't care, we are just testing the formatting
807
808    #[test]
809    fn test_format_factorial() {
810        let consts = Consts::default();
811        let fact = Calculation {
812            value: 10.into(),
813            steps: vec![(3, false)],
814            result: CalculationResult::Exact(280.into()),
815        };
816        let mut s = String::new();
817        fact.format(
818            &mut s,
819            false,
820            false,
821            &TOO_BIG_NUMBER,
822            &consts,
823            &consts.locales.get("en").unwrap().format(),
824        )
825        .unwrap();
826        assert_eq!(s, "Triple-factorial of 10 is 280 \n\n");
827    }
828    #[test]
829    fn test_format_factorial_exact_of_decimal() {
830        let consts = Consts::default();
831        let fact = Calculation {
832            value: Number::Float(Float::with_val(FLOAT_PRECISION, 0.5).into()),
833            steps: vec![(3, false)],
834            result: CalculationResult::Exact(280.into()),
835        };
836        let mut s = String::new();
837        fact.format(
838            &mut s,
839            false,
840            false,
841            &TOO_BIG_NUMBER,
842            &consts,
843            &consts.locales.get("en").unwrap().format(),
844        )
845        .unwrap();
846        assert_eq!(s, "Triple-factorial of 0.5 is approximately 280 \n\n");
847    }
848    #[test]
849    fn test_format_factorial_force_shorten_small() {
850        let consts = Consts::default();
851        let fact = Calculation {
852            value: 10.into(),
853            steps: vec![(3, false)],
854            result: CalculationResult::Exact(280.into()),
855        };
856        let mut s = String::new();
857        fact.format(
858            &mut s,
859            true,
860            false,
861            &TOO_BIG_NUMBER,
862            &consts,
863            &consts.locales.get("en").unwrap().format(),
864        )
865        .unwrap();
866        assert_eq!(s, "Triple-factorial of 10 is 280 \n\n");
867    }
868    #[test]
869    fn test_format_factorial_force_shorten_large() {
870        let consts = Consts::default();
871        let fact = Calculation {
872            value: 100.into(),
873            steps: vec![(1, false)],
874            result: CalculationResult::Exact(
875                Integer::from_str("232019615953125000000000000000000").unwrap(),
876            ),
877        };
878        let mut s = String::new();
879        fact.format(
880            &mut s,
881            false,
882            false,
883            &TOO_BIG_NUMBER,
884            &consts,
885            &consts.locales.get("en").unwrap().format(),
886        )
887        .unwrap();
888        assert_eq!(
889            s,
890            "Factorial of 100 is 232019615953125000000000000000000 \n\n"
891        );
892    }
893    #[test]
894    fn test_format_factorial_auto_shorten() {
895        let consts = Consts::default();
896        let fact = Calculation {
897            value: 3249.into(),
898            steps: vec![(1,false)],
899            result: CalculationResult::Exact(
900                Integer::from_str("64123376882765521838840963030568127691878727205333658692200854486404915724268122521695176119279253635876611090137291969570276913721864797759577004121543081865516901512445483449601769965060634861857064173938704305418376606356891014609023859758096597956259938348528946750437026172549655426092377089294607836520057856104816993984697675759579496157280331714452191401635250556082973306115574519424960196953201395066132365440977075392087489735146885581823595966673458107135041749084983583726462930633422893526599365244406644257808664472819062579590372326362859263197427382391737724371130194668325697913147795807287917882271125437793075279592752221056089408917956641344121781056494896664298954714463291743622978314854242079926982168325256172879601086193725507405771749789801611825741625380077209528888301112734777086106637653242107578812065387025070985682845983714635115865868052531038040737170581029905537322341939002838113744745962782070030988628668438192063964391415488312555937962867645737183703289987989371752808444472206166983181218698452231772212240017445423758860236449146575513014084114116542491422920779703202877962388772371297148878539228082497149672927873860981295756607109411429871735683677151117763870227460722732815888175758276344884954699572217509595160880510811349033936358665103889507929390456055037630508759624182491412136058522758117862715726418213812122827526330257260872329993280938592007320434494018056858434839424498517707440601396194949605570023576625190771463278168007414358018195714385208103590743168343592988436427551751120123934640886569178657972642734992568217335134536548423867468448461752994160896483162496996197629537563875663545967947035030506174219867102227347745166308776568259737417457622753953177779829173739659562549005900681020920836575654282170728038645671253311902327576757877160190593437037925134089334990083104974051379653937615220306281104735360028696101767109606466502484676624025302461421267416025443536877684785195571046059926349413586237838043863850610251583618438829618642246353724734656122845609571531588284708710081901687161770748138296656576032229319208279032435434327330035540657667361558905445221013396376775953367966087790302411507662731788873698999846238792500590360394500083923341408008981770566937535640769993694293230514231436990415482012055539596871513163008100690298424743718490882019179903258642028365049142613374709689558800856050749214398290563852574062566904927777093160819034619946818734041081848355062039645388238813669985569729968236449074797273410844560761607809842265309788155248298117938165414543689689754240992067831705834383207309250573018855640140957274364918049364842508738871690383100660359882462072065885517245667353800113210423157317762013988734352812105163694758108035856505778854524789188318600594132430921277654972526820920812190785994887939816114878915385423211996897729890266102145491069991647131611614465930571202528403443141981609375073983780241828798986101030035167624885608168623694530984934856402415662119456280967778213695343026782085453754332973412779641743296676142192492849866399186979810426206090031375249707803725234273693273721779240257093247268647749842459507965336971004339619911629224227060334233904444450352505466038312828689977755744971204784911189528493222070017894145493878499832441010771999957866634720057779638435426615168763950876432375766350648344132624416041623318009761058787995614968607413528076499437020919653085121078341947075546317831737787160036257151637941590867306372647047747729689844801136819011517526975033214302293538465503160183447374945622710595033673253137034231320031041035890947260824330728621640030383790059199531556893062561713763583025693789382680375603227866194301270004745201382665157844733507781537231595412109690534099208802055220457258238249940538761563309465648945964188442431661762589082015016756223358648046396366827537498425276338958018446839292802529780142385903309447658806351362744163752044896322012923382835852429065564336560491610071025646451525782856813152304143339115660276089535216189729579966851236899105440783686498435516601131545345163557980985342246336986737955743799192164259513473592703473521185371309681754246866522812455448210758136891890444056252857117200446002038652603259983493405505521897860879586618028713025173570291196046254005672495787117170419665767607647184551353826735583363126537373726390620854105626900247296291639985561481625404296348051054604042180512892657285238147263167051884385297470314430200590079012539964786079859359747123150407661818942489735756835032462952010303051169237940063644470670372188286551571968317499183600768353941744706305961785518398629201507525785967571188931895809109770264983907551256060144219899670118351808815620474425273993244741972143504134827047237929839845492209316520698259428270901257484509899386082594602760813392081897348940617781009158927227690469330327639146118508499255466535663882163793101115885899345523332216762566667486023534622719542192198250458735391090024294254053186440646305309340840685145289223131431157156390489399333752075193525158125680201419183806547205312873264380358849214095835479613319512867197427682723250079990981586869733293245764804577570764831692705888317075918673294669326798053736223321604803330275717540789920865913177228227111643923604665959921096208765542277777829882980225810940866410254096689483571105776785837917708633884075471298045453873223073787369262426626913405098535070631297346400765749139515252242178612533747493270131589184346851060077512732273563896936880596142362061341020737937605198462006142952423931616201569440226926787162077801883794168906567939864710313203688516686488132607069944238278930371283198545637735863991249832218463680910774912311493673518088306563853170521159963238305666024221618323515872866318153226269712890565361382209276094137857215708859605439920538254391240145615109307534437972388439697355227469268959991826344643967606862639207957142695059497774782782862380576527665249011786632721781635858363134217267161265609789721847126531549373639397319541419174824349828634414533913160986280670700117904134971824878639490677063427559640621162799757094469987184056964512589036737188936656494184932005003301076625555129466247988108160104882718140259576746243025950653945267030862681712132414998384138315991964228278130346276982182371619123375659027762342810200791337975076096607162500887202849331840711439619934443487228446573730294798389422723901661778354768525095757656920903185278358954945675520361768231577076750321654682566951617894418024879897723932943778739392625374786945631297844013055183788373235917906391604745846654356151085578611880261515860397623972021392725059655970516681719822949498069366408864396412928494605832710960284204937215373010567096882590065428759248976242854170628853902061231484918006271406155707387649451852150396381227895427254475130432845540997751264574249884576973754475522081887586009543117655192564603663203594121977491966995919938707026254622729082886656923266824175261927609862131917883084745112234024557978747561458733390353402381353061864973111801478933098174668694254024372053350135966105816774315863351432700501507214833910835095241116220945368287364828423032249431110250529198415073098056537298790818802403747860478015395740166511031245261193793854201285682331906071528112005073514650997116494101706639070013374677115821301361236988511929513457351929738018793684759539098410509535113338894579685309152120362751957602730649344150813012563246391457667149097699631546631367291707994927436193366185835774355812730356484690902974319470019544218388669048171395399380611906621586431005917959473642252829970939300283923684023821586277795276767391621510747281802893209607052311085173753725616353413592446675522238914835135290803927878090361225614843018882327106532840756094139114333346621153175254833577042328095480536834801026590432360931424294133543336408702705440236553526213058195627059654976746315636170233701887454392139871178240463495036735780991998499617099173145932919728906603992606395026374552882029156921168342421270810263586384930758466962518032019544198713384832174173447126633137813741748004660781750992387224960402183367639878315847417040125065349322346833085734948541674565230896990919815801676540094611430605654337096768783494147476599630304276589463660992695730097812987784061106253993478908686689107637583574009574525664941872851644555317421340687668414081763994364249671165252652825318436095248164540239487724330276498957490699548343852181838068378612444949106850962864407345130509165857647406496109100001533123176834579856292423765079015513705518869769002090306548513909235083737585930276738943593954668225536658208962591163051195501324651032924378645456520478535714079874404144783894706654731307268880764144813567558473827034967105368425271973138213726718055181321006250745589786136935583735915890517993411416086214277469794370188740010736604373520529352427775875772577651690552630708696044935360500197728514057299685757816479040563926362665221456966339198099627395349937057349473111399655105587183432516687910987518148931239145857422059143761070545360054386871218955184209375241453611589548642653321253873363792347807426924575722280463634222994099258528815002881358362491008896204800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()
901            ),
902        };
903        let mut s = String::new();
904        fact.format(
905            &mut s,
906            false,
907            false,
908            &TOO_BIG_NUMBER,
909            &consts,
910            &consts.locales.get("en").unwrap().format(),
911        )
912        .unwrap();
913        assert_eq!(
914            s,
915            "Factorial of 3249 is roughly 6.412337688276552183884096303057 × 10^10000 \n\n"
916        );
917    }
918    #[test]
919    fn test_format_factorial_chain() {
920        let consts = Consts::default();
921        let fact = Calculation {
922            value: 5.into(),
923            steps: vec![(3, false), (1, false)],
924            result: CalculationResult::Exact(3628800.into()),
925        };
926        let mut s = String::new();
927        fact.format(
928            &mut s,
929            false,
930            false,
931            &TOO_BIG_NUMBER,
932            &consts,
933            &consts.locales.get("en").unwrap().format(),
934        )
935        .unwrap();
936        assert_eq!(s, "Factorial of triple-factorial of 5 is 3628800 \n\n");
937    }
938    #[test]
939    fn test_format_factorial_negative() {
940        let consts = Consts::default();
941        let fact = Calculation {
942            value: 0.into(),
943            steps: vec![(1, true)],
944            result: CalculationResult::Exact(3628800.into()),
945        };
946        let mut s = String::new();
947        fact.format(
948            &mut s,
949            false,
950            false,
951            &TOO_BIG_NUMBER,
952            &consts,
953            &consts.locales.get("en").unwrap().format(),
954        )
955        .unwrap();
956        assert_eq!(s, "Negative factorial of 0 is 3628800 \n\n");
957    }
958    #[test]
959    fn test_format_approximate_factorial() {
960        let consts = Consts::default();
961        let fact = Calculation {
962            value: 0.into(),
963            steps: vec![(1, false)],
964            result: CalculationResult::Approximate(
965                Float::with_val(FLOAT_PRECISION, 2.83947).into(),
966                10043.into(),
967            ),
968        };
969        let mut s = String::new();
970        fact.format(
971            &mut s,
972            false,
973            false,
974            &TOO_BIG_NUMBER,
975            &consts,
976            &consts.locales.get("en").unwrap().format(),
977        )
978        .unwrap();
979        assert_eq!(s, "Factorial of 0 is approximately 2.83947 × 10^10043 \n\n");
980    }
981    #[test]
982    fn test_format_approximate_digits_factorial() {
983        let consts = Consts::default();
984        let fact = Calculation {
985            value: 0.into(),
986            steps: vec![(1, false)],
987            result: CalculationResult::ApproximateDigits(false, 10043394.into()),
988        };
989        let mut s = String::new();
990        fact.format(
991            &mut s,
992            false,
993            false,
994            &TOO_BIG_NUMBER,
995            &consts,
996            &consts.locales.get("en").unwrap().format(),
997        )
998        .unwrap();
999        assert_eq!(s, "Factorial of 0 has approximately 10043394 digits \n\n");
1000    }
1001    #[test]
1002    fn test_format_complex_infinity_factorial() {
1003        let consts = Consts::default();
1004        let fact = Calculation {
1005            value: 0.into(),
1006            steps: vec![(1, false)],
1007            result: CalculationResult::ComplexInfinity,
1008        };
1009        let mut s = String::new();
1010        fact.format(
1011            &mut s,
1012            false,
1013            false,
1014            &TOO_BIG_NUMBER,
1015            &consts,
1016            &consts.locales.get("en").unwrap().format(),
1017        )
1018        .unwrap();
1019        assert_eq!(s, "Factorial of 0 is ∞\u{0303} \n\n");
1020    }
1021    #[test]
1022    fn test_format_digits_tower() {
1023        let consts = Consts::default();
1024        let fact = Calculation {
1025            value: 0.into(),
1026            steps: vec![(1, false)],
1027            result: CalculationResult::ApproximateDigitsTower(false, false, 9, 10375.into()),
1028        };
1029        let mut s = String::new();
1030        fact.format(
1031            &mut s,
1032            false,
1033            false,
1034            &TOO_BIG_NUMBER,
1035            &consts,
1036            &consts.locales.get("en").unwrap().format(),
1037        )
1038        .unwrap();
1039        assert_eq!(
1040            s,
1041            "Factorial of 0 has on the order of 10^(10\\^10\\^10\\^10\\^10\\^10\\^10\\^10\\^(10375\\)) digits \n\n"
1042        );
1043    }
1044    #[test]
1045    fn test_format_digits_tower_negative() {
1046        let consts = Consts::default();
1047        let fact = Calculation {
1048            value: 0.into(),
1049            steps: vec![(1, false)],
1050            result: CalculationResult::ApproximateDigitsTower(false, true, 9, 10375.into()),
1051        };
1052        let mut s = String::new();
1053        fact.format(
1054            &mut s,
1055            false,
1056            false,
1057            &TOO_BIG_NUMBER,
1058            &consts,
1059            &consts.locales.get("en").unwrap().format(),
1060        )
1061        .unwrap();
1062        assert_eq!(
1063            s,
1064            "Factorial of 0 has on the order of -10^(10\\^10\\^10\\^10\\^10\\^10\\^10\\^10\\^(10375\\)) digits \n\n"
1065        );
1066    }
1067    #[test]
1068    fn test_format_digits_tower_tet() {
1069        let consts = Consts::default();
1070        let fact = Calculation {
1071            value: 0.into(),
1072            steps: vec![(1, false)],
1073            result: CalculationResult::ApproximateDigitsTower(false, false, 9, 10375.into()),
1074        };
1075        let mut s = String::new();
1076        fact.format(
1077            &mut s,
1078            false,
1079            true,
1080            &TOO_BIG_NUMBER,
1081            &consts,
1082            &consts.locales.get("en").unwrap().format(),
1083        )
1084        .unwrap();
1085        assert_eq!(s, "All that of 0 has on the order of ^(10)10 digits \n\n");
1086    }
1087    #[test]
1088    fn test_format_gamma() {
1089        let consts = Consts::default();
1090        let fact = Calculation {
1091            value: Number::Float(Float::with_val(FLOAT_PRECISION, 9.2).into()),
1092            steps: vec![(1, false)],
1093            result: CalculationResult::Float(Float::with_val(FLOAT_PRECISION, 893.83924421).into()),
1094        };
1095        let mut s = String::new();
1096        fact.format(
1097            &mut s,
1098            false,
1099            false,
1100            &TOO_BIG_NUMBER,
1101            &consts,
1102            &consts.locales.get("en").unwrap().format(),
1103        )
1104        .unwrap();
1105        assert_eq!(s, "Factorial of 9.2 is approximately 893.83924421 \n\n");
1106    }
1107    #[test]
1108    fn test_format_gamma_fallback() {
1109        let consts = Consts::default();
1110        let fact = Calculation {
1111            value: Number::Float(Float::with_val(FLOAT_PRECISION, 0).into()),
1112            steps: vec![(1, false)],
1113            result: {
1114                let mut m = Float::with_val(FLOAT_PRECISION, f64::MAX);
1115                m.next_up();
1116                CalculationResult::Float(m.into())
1117            },
1118        };
1119        let mut s = String::new();
1120        fact.format(
1121            &mut s,
1122            false,
1123            false,
1124            &TOO_BIG_NUMBER,
1125            &consts,
1126            &consts.locales.get("en").unwrap().format(),
1127        )
1128        .unwrap();
1129        assert_eq!(
1130            s,
1131            "Factorial of 0 is approximately 179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 \n\n"
1132        );
1133    }
1134    #[test]
1135    fn test_format_approximate_factorial_shorten() {
1136        let consts = Consts::default();
1137        let fact = Calculation {
1138            value: Number::Exact(
1139                Integer::from_str("2018338437429423744923849374833232131").unwrap(),
1140            ),
1141            steps: vec![(1, false)],
1142            result: CalculationResult::Approximate(
1143                Float::with_val(FLOAT_PRECISION, 2.8394792834).into(),
1144                Integer::from_str("10094283492304894983443984102489842984271").unwrap(),
1145            ),
1146        };
1147        let mut s = String::new();
1148        fact.format(
1149            &mut s,
1150            true,
1151            false,
1152            &TOO_BIG_NUMBER,
1153            &consts,
1154            &consts.locales.get("en").unwrap().format(),
1155        )
1156        .unwrap();
1157        assert_eq!(
1158            s,
1159            "Factorial of roughly 2.018338437429423744923849374833 × 10^36 is approximately 2.8394792834 × 10^(1.009428349230489498344398410249 × 10^40) \n\n"
1160        );
1161    }
1162    #[test]
1163    fn test_format_approximate_digits_factorial_shorten() {
1164        let consts = Consts::default();
1165        let fact = Calculation {
1166            value: Number::Exact(
1167                Integer::from_str("2313820948092579283573259490834298719").unwrap(),
1168            ),
1169            steps: vec![(1, false)],
1170            result: CalculationResult::ApproximateDigits(
1171                false,
1172                Integer::from_str("9842371208573508275237815084709374240128347012847").unwrap(),
1173            ),
1174        };
1175        let mut s = String::new();
1176        fact.format(
1177            &mut s,
1178            true,
1179            false,
1180            &TOO_BIG_NUMBER,
1181            &consts,
1182            &consts.locales.get("en").unwrap().format(),
1183        )
1184        .unwrap();
1185        assert_eq!(
1186            s,
1187            "Factorial of roughly 2.313820948092579283573259490834 × 10^36 has approximately 9.842371208573508275237815084709 × 10^48 digits \n\n"
1188        );
1189    }
1190    #[test]
1191    fn test_format_digits_tower_shorten() {
1192        let consts = Consts::default();
1193        let fact = Calculation {
1194            value: Number::Exact(
1195                Integer::from_str("13204814708471087502685784603872164320053271").unwrap(),
1196            ),
1197            steps: vec![(1, false)],
1198            result: CalculationResult::ApproximateDigitsTower(
1199                false,
1200                false,
1201                9,
1202                Integer::from_str("7084327410873502875032857120358730912469148632").unwrap(),
1203            ),
1204        };
1205        let mut s = String::new();
1206        fact.format(
1207            &mut s,
1208            true,
1209            false,
1210            &TOO_BIG_NUMBER,
1211            &consts,
1212            &consts.locales.get("en").unwrap().format(),
1213        )
1214        .unwrap();
1215        assert_eq!(
1216            s,
1217            "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"
1218        );
1219    }
1220    #[test]
1221    fn test_format_huge() {
1222        let consts = Consts::default();
1223        let fact = Calculation {
1224            value: 0.into(),
1225            steps: vec![(1, false)],
1226            result: CalculationResult::Exact({
1227                let mut r = Float::with_val(FLOAT_PRECISION, crate::rug::float::Special::Infinity);
1228                r.next_down();
1229                r.to_integer().unwrap()
1230            }),
1231        };
1232        let mut s = String::new();
1233        fact.format(
1234            &mut s,
1235            false,
1236            false,
1237            &TOO_BIG_NUMBER,
1238            &consts,
1239            &consts.locales.get("en").unwrap().format(),
1240        )
1241        .unwrap();
1242        assert_eq!(
1243            s,
1244            "Factorial of 0 is roughly 2.098578716467387692404358116884 × 10^323228496 \n\n"
1245        );
1246    }
1247
1248    #[test]
1249    fn test_calculation_is_approximate() {
1250        let c1 = Calculation {
1251            value: 0.into(),
1252            steps: vec![],
1253            result: CalculationResult::Approximate(
1254                Float::with_val(FLOAT_PRECISION, 2.0).into(),
1255                1.into(),
1256            ),
1257        };
1258        assert!(c1.is_approximate());
1259        let c2 = Calculation {
1260            value: 0.into(),
1261            steps: vec![],
1262            result: CalculationResult::Exact(1.into()),
1263        };
1264        assert!(!c2.is_approximate());
1265    }
1266
1267    #[test]
1268    fn test_calculation_is_rounded() {
1269        let c1 = Calculation {
1270            value: Number::Float(Float::with_val(FLOAT_PRECISION, 1.23).into()),
1271            steps: vec![],
1272            result: CalculationResult::Approximate(
1273                Float::with_val(FLOAT_PRECISION, 0.0).into(),
1274                0.into(),
1275            ),
1276        };
1277        assert!(c1.is_rounded());
1278        let c2 = Calculation {
1279            value: Number::Float(Float::with_val(FLOAT_PRECISION, 1.23).into()),
1280            steps: vec![],
1281            result: CalculationResult::Float(Float::with_val(FLOAT_PRECISION, 1.23).into()),
1282        };
1283        assert!(!c2.is_rounded());
1284        let c3 = Calculation {
1285            value: 1.into(),
1286            steps: vec![],
1287            result: CalculationResult::Exact(1.into()),
1288        };
1289        assert!(!c3.is_rounded());
1290    }
1291
1292    #[test]
1293    fn test_is_too_long() {
1294        let small = Calculation {
1295            value: 1.into(),
1296            steps: vec![],
1297            result: CalculationResult::Exact(1.into()),
1298        };
1299        assert!(!small.is_too_long(&TOO_BIG_NUMBER));
1300        let big = Calculation {
1301            value: 1.into(),
1302            steps: vec![],
1303            result: CalculationResult::Exact((*TOO_BIG_NUMBER).clone() + 1),
1304        };
1305        assert!(big.is_too_long(&TOO_BIG_NUMBER));
1306        let fl = Calculation {
1307            value: 1.into(),
1308            steps: vec![],
1309            result: CalculationResult::Float(Float::with_val(FLOAT_PRECISION, 1.0).into()),
1310        };
1311        assert!(!fl.is_too_long(&TOO_BIG_NUMBER));
1312    }
1313}