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