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