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