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