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