Skip to main content

factorion_lib/
calculation_results.rs

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