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