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();
576 let exponent = number
577 .clone()
578 .log10()
579 .max(&Float::new(consts.float_precision))
580 .to_integer_round(factorion_math::rug::float::Round::Down)
581 .expect("Could not round exponent")
582 .0;
583 if exponent > consts.number_decimals_scientific {
584 number = number / Float::with_val(consts.float_precision, &exponent).exp10();
585 }
586 let whole_number = number
587 .to_integer_round(factorion_math::rug::float::Round::Down)
588 .expect("Could not get integer part")
589 .0;
590 let decimal_part = number - &whole_number + 1;
591 let mut decimal_part = format!("{decimal_part}");
592 decimal_part.remove(0);
594 decimal_part.remove(0);
595 decimal_part.truncate(consts.number_decimals_scientific + 1);
596 if decimal_part.len() > consts.number_decimals_scientific {
597 round(&mut decimal_part);
598 }
599 if let Some(mut digit) = decimal_part.pop() {
600 while digit == '0' {
601 digit = match decimal_part.pop() {
602 Some(x) => x,
603 None => break,
604 }
605 }
606 decimal_part.push(digit);
607 }
608 write!(acc, "{whole_number}")?;
609 if !decimal_part.is_empty() && decimal_part != "0" {
610 acc.write_str(".")?;
611 acc.write_str(&decimal_part)?;
612 }
613 if exponent > consts.number_decimals_scientific {
614 write!(acc, " × 10^{exponent}")?;
615 }
616 Ok(())
617}
618
619fn replace(s: &mut String, search_start: usize, from: &str, to: &str) -> usize {
620 if let Some(start) = s[search_start..].find(from) {
621 let start = start + search_start;
622 s.replace_range(start..(start + from.len()), to);
623 start
624 } else {
625 s.len()
626 }
627}
628#[cfg(test)]
629mod tests {
630 use super::*;
631 use crate::recommended::FLOAT_PRECISION;
632 use crate::rug::Integer;
633 use std::{str::FromStr, sync::LazyLock};
634
635 static TOO_BIG_NUMBER: LazyLock<Integer> =
636 LazyLock::new(|| Integer::from_str(&format!("1{}", "0".repeat(9999))).unwrap());
637
638 #[test]
639 fn test_round_down() {
640 let mut number = String::from("1929472373");
641 round(&mut number);
642 assert_eq!(number, "192947237");
643 }
644
645 #[test]
646 fn test_round_up() {
647 let mut number = String::from("74836748625");
648 round(&mut number);
649 assert_eq!(number, "7483674863");
650 }
651
652 #[test]
653 fn test_round_carry() {
654 let mut number = String::from("24999999995");
655 round(&mut number);
656 assert_eq!(number, "25");
657 }
658
659 #[test]
660 fn test_factorial_level_string() {
661 let en = locale::get_en();
662 assert_eq!(
663 Calculation::get_factorial_level_string(1, &en.format()),
664 "{factorial}"
665 );
666 assert_eq!(
667 Calculation::get_factorial_level_string(2, &en.format()),
668 "double-{factorial}"
669 );
670 assert_eq!(
671 Calculation::get_factorial_level_string(3, &en.format()),
672 "triple-{factorial}"
673 );
674 assert_eq!(
675 Calculation::get_factorial_level_string(10, &en.format()),
676 "decuple-{factorial}"
677 );
678 assert_eq!(
679 Calculation::get_factorial_level_string(45, &en.format()),
680 "quinquadragintuple-{factorial}"
681 );
682 assert_eq!(
683 Calculation::get_factorial_level_string(50, &en.format()),
684 "quinquagintuple-{factorial}"
685 );
686 assert_eq!(
687 Calculation::get_factorial_level_string(100, &en.format()),
688 "centuple-{factorial}"
689 );
690 assert_eq!(
691 Calculation::get_factorial_level_string(521, &en.format()),
692 "unviginquingentuple-{factorial}"
693 );
694 assert_eq!(
695 Calculation::get_factorial_level_string(1000, &en.format()),
696 "milluple-{factorial}"
697 );
698 assert_eq!(
699 Calculation::get_factorial_level_string(4321, &en.format()),
700 "unvigintricenquadrilluple-{factorial}"
701 );
702 assert_eq!(
703 Calculation::get_factorial_level_string(10000, &en.format()),
704 "10000-{factorial}"
705 );
706 let de = locale::get_de();
707 assert_eq!(
708 Calculation::get_factorial_level_string(1, &de.format()),
709 "{factorial}"
710 );
711 assert_eq!(
712 Calculation::get_factorial_level_string(2, &de.format()),
713 "doppel{factorial}"
714 );
715 assert_eq!(
716 Calculation::get_factorial_level_string(3, &de.format()),
717 "trippel{factorial}"
718 );
719 assert_eq!(
720 Calculation::get_factorial_level_string(45, &de.format()),
721 "quinquadragintupel{factorial}"
722 );
723 }
724
725 #[test]
726 fn test_truncate() {
727 let consts = Consts::default();
728 assert_eq!(truncate(&Integer::from_str("0").unwrap(), &consts,).0, "0");
729 assert_eq!(
730 truncate(&Integer::from_str("-1").unwrap(), &consts,).0,
731 "-1"
732 );
733 assert_eq!(
734 truncate(
735 &Integer::from_str(&format!("1{}", "0".repeat(300))).unwrap(),
736 &consts
737 )
738 .0,
739 "1 × 10^300"
740 );
741 assert_eq!(
742 truncate(
743 &-Integer::from_str(&format!("1{}", "0".repeat(300))).unwrap(),
744 &consts
745 )
746 .0,
747 "-1 × 10^300"
748 );
749 assert_eq!(
750 truncate(
751 &Integer::from_str(&format!("1{}", "0".repeat(2000000))).unwrap(),
752 &consts
753 )
754 .0,
755 "1 × 10^2000000"
756 );
757 }
758
759 #[test]
760 fn test_factorial_format() {
761 let consts = Consts::default();
762 let mut acc = String::new();
763 let factorial = Calculation {
764 value: 5.into(),
765 steps: vec![(1, false)],
766 result: CalculationResult::Exact(Integer::from(120)),
767 };
768 factorial
769 .format(
770 &mut acc,
771 false,
772 false,
773 &TOO_BIG_NUMBER,
774 &consts,
775 &consts.locales.get("en").unwrap().format(),
776 )
777 .unwrap();
778 assert_eq!(acc, "Factorial of 5 is 120 \n\n");
779
780 let mut acc = String::new();
781 let factorial = Calculation {
782 value: 5.into(),
783 steps: vec![(0, false)],
784 result: CalculationResult::Exact(Integer::from(120)),
785 };
786 factorial
787 .format(
788 &mut acc,
789 false,
790 false,
791 &TOO_BIG_NUMBER,
792 &consts,
793 &consts.locales.get("en").unwrap().format(),
794 )
795 .unwrap();
796 assert_eq!(acc, "Subfactorial of 5 is 120 \n\n");
797
798 let mut acc = String::new();
799 let factorial = Calculation {
800 value: 5.into(),
801 steps: vec![(1, false)],
802 result: CalculationResult::Approximate(
803 Float::with_val(FLOAT_PRECISION, Float::parse("1.2").unwrap()).into(),
804 5.into(),
805 ),
806 };
807 factorial
808 .format(
809 &mut acc,
810 false,
811 false,
812 &TOO_BIG_NUMBER,
813 &consts,
814 &consts.locales.get("en").unwrap().format(),
815 )
816 .unwrap();
817 assert_eq!(acc, "Factorial of 5 is approximately 1.2 × 10^5 \n\n");
818
819 let mut acc = String::new();
820 let factorial = Calculation {
821 value: 5.into(),
822 steps: vec![(1, false)],
823 result: CalculationResult::ApproximateDigits(false, 3.into()),
824 };
825 factorial
826 .format(
827 &mut acc,
828 false,
829 false,
830 &TOO_BIG_NUMBER,
831 &consts,
832 &consts.locales.get("en").unwrap().format(),
833 )
834 .unwrap();
835 assert_eq!(acc, "Factorial of 5 has approximately 3 digits \n\n");
836
837 let mut acc = String::new();
838 let factorial = Calculation {
839 value: 5.into(),
840 steps: vec![(1, false)],
841 result: CalculationResult::Exact(Integer::from(120)),
842 };
843 factorial
844 .format(
845 &mut acc,
846 true,
847 false,
848 &TOO_BIG_NUMBER,
849 &consts,
850 &consts.locales.get("en").unwrap().format(),
851 )
852 .unwrap();
853 assert_eq!(acc, "Factorial of 5 is 120 \n\n");
854 }
855}
856
857#[cfg(test)]
858mod test {
859 use std::{str::FromStr, sync::LazyLock};
860
861 use factorion_math::rug::Complete;
862
863 use super::*;
864
865 use crate::recommended::FLOAT_PRECISION;
866 static TOO_BIG_NUMBER: LazyLock<Integer> =
867 LazyLock::new(|| Integer::from_str(&format!("1{}", "0".repeat(9999))).unwrap());
868
869 #[test]
872 fn test_format_factorial() {
873 let consts = Consts::default();
874 let fact = Calculation {
875 value: 10.into(),
876 steps: vec![(3, false)],
877 result: CalculationResult::Exact(280.into()),
878 };
879 let mut s = String::new();
880 fact.format(
881 &mut s,
882 false,
883 false,
884 &TOO_BIG_NUMBER,
885 &consts,
886 &consts.locales.get("en").unwrap().format(),
887 )
888 .unwrap();
889 assert_eq!(s, "Triple-factorial of 10 is 280 \n\n");
890 }
891 #[test]
892 fn test_format_factorial_exact_of_decimal() {
893 let consts = Consts::default();
894 let fact = Calculation {
895 value: Number::Float(Float::with_val(FLOAT_PRECISION, 0.5).into()),
896 steps: vec![(3, false)],
897 result: CalculationResult::Exact(280.into()),
898 };
899 let mut s = String::new();
900 fact.format(
901 &mut s,
902 false,
903 false,
904 &TOO_BIG_NUMBER,
905 &consts,
906 &consts.locales.get("en").unwrap().format(),
907 )
908 .unwrap();
909 assert_eq!(s, "Triple-factorial of 0.5 is approximately 280 \n\n");
910 }
911 #[test]
912 fn test_format_factorial_force_shorten_small() {
913 let consts = Consts::default();
914 let fact = Calculation {
915 value: 10.into(),
916 steps: vec![(3, false)],
917 result: CalculationResult::Exact(280.into()),
918 };
919 let mut s = String::new();
920 fact.format(
921 &mut s,
922 true,
923 false,
924 &TOO_BIG_NUMBER,
925 &consts,
926 &consts.locales.get("en").unwrap().format(),
927 )
928 .unwrap();
929 assert_eq!(s, "Triple-factorial of 10 is 280 \n\n");
930 }
931 #[test]
932 fn test_format_factorial_force_shorten_large() {
933 let consts = Consts::default();
934 let fact = Calculation {
935 value: 100.into(),
936 steps: vec![(1, false)],
937 result: CalculationResult::Exact(
938 Integer::from_str("232019615953125000000000000000000").unwrap(),
939 ),
940 };
941 let mut s = String::new();
942 fact.format(
943 &mut s,
944 false,
945 false,
946 &TOO_BIG_NUMBER,
947 &consts,
948 &consts.locales.get("en").unwrap().format(),
949 )
950 .unwrap();
951 assert_eq!(
952 s,
953 "Factorial of 100 is 232019615953125000000000000000000 \n\n"
954 );
955 }
956 #[test]
957 fn test_format_factorial_auto_shorten() {
958 let consts = Consts::default();
959 let fact = Calculation {
960 value: 3249.into(),
961 steps: vec![(1,false)],
962 result: CalculationResult::Exact(
963 Integer::from_str("64123376882765521838840963030568127691878727205333658692200854486404915724268122521695176119279253635876611090137291969570276913721864797759577004121543081865516901512445483449601769965060634861857064173938704305418376606356891014609023859758096597956259938348528946750437026172549655426092377089294607836520057856104816993984697675759579496157280331714452191401635250556082973306115574519424960196953201395066132365440977075392087489735146885581823595966673458107135041749084983583726462930633422893526599365244406644257808664472819062579590372326362859263197427382391737724371130194668325697913147795807287917882271125437793075279592752221056089408917956641344121781056494896664298954714463291743622978314854242079926982168325256172879601086193725507405771749789801611825741625380077209528888301112734777086106637653242107578812065387025070985682845983714635115865868052531038040737170581029905537322341939002838113744745962782070030988628668438192063964391415488312555937962867645737183703289987989371752808444472206166983181218698452231772212240017445423758860236449146575513014084114116542491422920779703202877962388772371297148878539228082497149672927873860981295756607109411429871735683677151117763870227460722732815888175758276344884954699572217509595160880510811349033936358665103889507929390456055037630508759624182491412136058522758117862715726418213812122827526330257260872329993280938592007320434494018056858434839424498517707440601396194949605570023576625190771463278168007414358018195714385208103590743168343592988436427551751120123934640886569178657972642734992568217335134536548423867468448461752994160896483162496996197629537563875663545967947035030506174219867102227347745166308776568259737417457622753953177779829173739659562549005900681020920836575654282170728038645671253311902327576757877160190593437037925134089334990083104974051379653937615220306281104735360028696101767109606466502484676624025302461421267416025443536877684785195571046059926349413586237838043863850610251583618438829618642246353724734656122845609571531588284708710081901687161770748138296656576032229319208279032435434327330035540657667361558905445221013396376775953367966087790302411507662731788873698999846238792500590360394500083923341408008981770566937535640769993694293230514231436990415482012055539596871513163008100690298424743718490882019179903258642028365049142613374709689558800856050749214398290563852574062566904927777093160819034619946818734041081848355062039645388238813669985569729968236449074797273410844560761607809842265309788155248298117938165414543689689754240992067831705834383207309250573018855640140957274364918049364842508738871690383100660359882462072065885517245667353800113210423157317762013988734352812105163694758108035856505778854524789188318600594132430921277654972526820920812190785994887939816114878915385423211996897729890266102145491069991647131611614465930571202528403443141981609375073983780241828798986101030035167624885608168623694530984934856402415662119456280967778213695343026782085453754332973412779641743296676142192492849866399186979810426206090031375249707803725234273693273721779240257093247268647749842459507965336971004339619911629224227060334233904444450352505466038312828689977755744971204784911189528493222070017894145493878499832441010771999957866634720057779638435426615168763950876432375766350648344132624416041623318009761058787995614968607413528076499437020919653085121078341947075546317831737787160036257151637941590867306372647047747729689844801136819011517526975033214302293538465503160183447374945622710595033673253137034231320031041035890947260824330728621640030383790059199531556893062561713763583025693789382680375603227866194301270004745201382665157844733507781537231595412109690534099208802055220457258238249940538761563309465648945964188442431661762589082015016756223358648046396366827537498425276338958018446839292802529780142385903309447658806351362744163752044896322012923382835852429065564336560491610071025646451525782856813152304143339115660276089535216189729579966851236899105440783686498435516601131545345163557980985342246336986737955743799192164259513473592703473521185371309681754246866522812455448210758136891890444056252857117200446002038652603259983493405505521897860879586618028713025173570291196046254005672495787117170419665767607647184551353826735583363126537373726390620854105626900247296291639985561481625404296348051054604042180512892657285238147263167051884385297470314430200590079012539964786079859359747123150407661818942489735756835032462952010303051169237940063644470670372188286551571968317499183600768353941744706305961785518398629201507525785967571188931895809109770264983907551256060144219899670118351808815620474425273993244741972143504134827047237929839845492209316520698259428270901257484509899386082594602760813392081897348940617781009158927227690469330327639146118508499255466535663882163793101115885899345523332216762566667486023534622719542192198250458735391090024294254053186440646305309340840685145289223131431157156390489399333752075193525158125680201419183806547205312873264380358849214095835479613319512867197427682723250079990981586869733293245764804577570764831692705888317075918673294669326798053736223321604803330275717540789920865913177228227111643923604665959921096208765542277777829882980225810940866410254096689483571105776785837917708633884075471298045453873223073787369262426626913405098535070631297346400765749139515252242178612533747493270131589184346851060077512732273563896936880596142362061341020737937605198462006142952423931616201569440226926787162077801883794168906567939864710313203688516686488132607069944238278930371283198545637735863991249832218463680910774912311493673518088306563853170521159963238305666024221618323515872866318153226269712890565361382209276094137857215708859605439920538254391240145615109307534437972388439697355227469268959991826344643967606862639207957142695059497774782782862380576527665249011786632721781635858363134217267161265609789721847126531549373639397319541419174824349828634414533913160986280670700117904134971824878639490677063427559640621162799757094469987184056964512589036737188936656494184932005003301076625555129466247988108160104882718140259576746243025950653945267030862681712132414998384138315991964228278130346276982182371619123375659027762342810200791337975076096607162500887202849331840711439619934443487228446573730294798389422723901661778354768525095757656920903185278358954945675520361768231577076750321654682566951617894418024879897723932943778739392625374786945631297844013055183788373235917906391604745846654356151085578611880261515860397623972021392725059655970516681719822949498069366408864396412928494605832710960284204937215373010567096882590065428759248976242854170628853902061231484918006271406155707387649451852150396381227895427254475130432845540997751264574249884576973754475522081887586009543117655192564603663203594121977491966995919938707026254622729082886656923266824175261927609862131917883084745112234024557978747561458733390353402381353061864973111801478933098174668694254024372053350135966105816774315863351432700501507214833910835095241116220945368287364828423032249431110250529198415073098056537298790818802403747860478015395740166511031245261193793854201285682331906071528112005073514650997116494101706639070013374677115821301361236988511929513457351929738018793684759539098410509535113338894579685309152120362751957602730649344150813012563246391457667149097699631546631367291707994927436193366185835774355812730356484690902974319470019544218388669048171395399380611906621586431005917959473642252829970939300283923684023821586277795276767391621510747281802893209607052311085173753725616353413592446675522238914835135290803927878090361225614843018882327106532840756094139114333346621153175254833577042328095480536834801026590432360931424294133543336408702705440236553526213058195627059654976746315636170233701887454392139871178240463495036735780991998499617099173145932919728906603992606395026374552882029156921168342421270810263586384930758466962518032019544198713384832174173447126633137813741748004660781750992387224960402183367639878315847417040125065349322346833085734948541674565230896990919815801676540094611430605654337096768783494147476599630304276589463660992695730097812987784061106253993478908686689107637583574009574525664941872851644555317421340687668414081763994364249671165252652825318436095248164540239487724330276498957490699548343852181838068378612444949106850962864407345130509165857647406496109100001533123176834579856292423765079015513705518869769002090306548513909235083737585930276738943593954668225536658208962591163051195501324651032924378645456520478535714079874404144783894706654731307268880764144813567558473827034967105368425271973138213726718055181321006250745589786136935583735915890517993411416086214277469794370188740010736604373520529352427775875772577651690552630708696044935360500197728514057299685757816479040563926362665221456966339198099627395349937057349473111399655105587183432516687910987518148931239145857422059143761070545360054386871218955184209375241453611589548642653321253873363792347807426924575722280463634222994099258528815002881358362491008896204800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap()
964 ),
965 };
966 let mut s = String::new();
967 fact.format(
968 &mut s,
969 false,
970 false,
971 &TOO_BIG_NUMBER,
972 &consts,
973 &consts.locales.get("en").unwrap().format(),
974 )
975 .unwrap();
976 assert_eq!(
977 s,
978 "Factorial of 3249 is roughly 6.412337688276552183884096303057 × 10^10000 \n\n"
979 );
980 }
981 #[test]
982 fn test_format_factorial_chain() {
983 let consts = Consts::default();
984 let fact = Calculation {
985 value: 5.into(),
986 steps: vec![(3, false), (1, false)],
987 result: CalculationResult::Exact(3628800.into()),
988 };
989 let mut s = String::new();
990 fact.format(
991 &mut s,
992 false,
993 false,
994 &TOO_BIG_NUMBER,
995 &consts,
996 &consts.locales.get("en").unwrap().format(),
997 )
998 .unwrap();
999 assert_eq!(s, "Factorial of triple-factorial of 5 is 3628800 \n\n");
1000 }
1001 #[test]
1002 fn test_format_factorial_negative() {
1003 let consts = Consts::default();
1004 let fact = Calculation {
1005 value: 0.into(),
1006 steps: vec![(1, true)],
1007 result: CalculationResult::Exact(3628800.into()),
1008 };
1009 let mut s = String::new();
1010 fact.format(
1011 &mut s,
1012 false,
1013 false,
1014 &TOO_BIG_NUMBER,
1015 &consts,
1016 &consts.locales.get("en").unwrap().format(),
1017 )
1018 .unwrap();
1019 assert_eq!(s, "Negative factorial of 0 is 3628800 \n\n");
1020 }
1021 #[test]
1022 fn test_format_approximate_factorial() {
1023 let consts = Consts::default();
1024 let fact = Calculation {
1025 value: 0.into(),
1026 steps: vec![(1, false)],
1027 result: CalculationResult::Approximate(
1028 Float::with_val(FLOAT_PRECISION, Float::parse("2.83947").unwrap()).into(),
1029 10043.into(),
1030 ),
1031 };
1032 let mut s = String::new();
1033 fact.format(
1034 &mut s,
1035 false,
1036 false,
1037 &TOO_BIG_NUMBER,
1038 &consts,
1039 &consts.locales.get("en").unwrap().format(),
1040 )
1041 .unwrap();
1042 assert_eq!(s, "Factorial of 0 is approximately 2.83947 × 10^10043 \n\n");
1043 }
1044 #[test]
1045 fn test_format_approximate_digits_factorial() {
1046 let consts = Consts::default();
1047 let fact = Calculation {
1048 value: 0.into(),
1049 steps: vec![(1, false)],
1050 result: CalculationResult::ApproximateDigits(false, 10043394.into()),
1051 };
1052 let mut s = String::new();
1053 fact.format(
1054 &mut s,
1055 false,
1056 false,
1057 &TOO_BIG_NUMBER,
1058 &consts,
1059 &consts.locales.get("en").unwrap().format(),
1060 )
1061 .unwrap();
1062 assert_eq!(s, "Factorial of 0 has approximately 10043394 digits \n\n");
1063 }
1064 #[test]
1065 fn test_format_complex_infinity_factorial() {
1066 let consts = Consts::default();
1067 let fact = Calculation {
1068 value: 0.into(),
1069 steps: vec![(1, false)],
1070 result: CalculationResult::ComplexInfinity,
1071 };
1072 let mut s = String::new();
1073 fact.format(
1074 &mut s,
1075 false,
1076 false,
1077 &TOO_BIG_NUMBER,
1078 &consts,
1079 &consts.locales.get("en").unwrap().format(),
1080 )
1081 .unwrap();
1082 assert_eq!(s, "Factorial of 0 is ∞\u{0303} \n\n");
1083 }
1084 #[test]
1085 fn test_format_digits_tower() {
1086 let consts = Consts::default();
1087 let fact = Calculation {
1088 value: 0.into(),
1089 steps: vec![(1, false)],
1090 result: CalculationResult::ApproximateDigitsTower(false, false, 9.into(), 10375.into()),
1091 };
1092 let mut s = String::new();
1093 fact.format(
1094 &mut s,
1095 false,
1096 false,
1097 &TOO_BIG_NUMBER,
1098 &consts,
1099 &consts.locales.get("en").unwrap().format(),
1100 )
1101 .unwrap();
1102 assert_eq!(
1103 s,
1104 "Factorial of 0 has on the order of 10^(10\\^10\\^10\\^10\\^10\\^10\\^10\\^10\\^(10375\\)) digits \n\n"
1105 );
1106 }
1107 #[test]
1108 fn test_format_digits_tower_negative() {
1109 let consts = Consts::default();
1110 let fact = Calculation {
1111 value: 0.into(),
1112 steps: vec![(1, false)],
1113 result: CalculationResult::ApproximateDigitsTower(false, true, 9.into(), 10375.into()),
1114 };
1115 let mut s = String::new();
1116 fact.format(
1117 &mut s,
1118 false,
1119 false,
1120 &TOO_BIG_NUMBER,
1121 &consts,
1122 &consts.locales.get("en").unwrap().format(),
1123 )
1124 .unwrap();
1125 assert_eq!(
1126 s,
1127 "Factorial of 0 has on the order of -10^(10\\^10\\^10\\^10\\^10\\^10\\^10\\^10\\^(10375\\)) digits \n\n"
1128 );
1129 }
1130 #[test]
1131 fn test_format_digits_tower_tet() {
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 true,
1143 &TOO_BIG_NUMBER,
1144 &consts,
1145 &consts.locales.get("en").unwrap().format(),
1146 )
1147 .unwrap();
1148 assert_eq!(s, "All that of 0 has on the order of ^(10)10 digits \n\n");
1149 }
1150 #[test]
1151 fn test_format_gamma() {
1152 let consts = Consts::default();
1153 let fact = Calculation {
1154 value: Number::Float(
1155 Float::with_val(FLOAT_PRECISION, Float::parse("9.2").unwrap()).into(),
1156 ),
1157 steps: vec![(1, false)],
1158 result: CalculationResult::Float(
1159 Float::with_val(FLOAT_PRECISION, Float::parse("893.83924421").unwrap()).into(),
1160 ),
1161 };
1162 let mut s = String::new();
1163 fact.format(
1164 &mut s,
1165 false,
1166 false,
1167 &TOO_BIG_NUMBER,
1168 &consts,
1169 &consts.locales.get("en").unwrap().format(),
1170 )
1171 .unwrap();
1172 assert_eq!(s, "Factorial of 9.2 is approximately 893.83924421 \n\n");
1173 }
1174 #[test]
1175 fn test_format_gamma_fallback() {
1176 let consts = Consts::default();
1177 let fact = Calculation {
1178 value: Number::Float(Float::with_val(FLOAT_PRECISION, 0).into()),
1179 steps: vec![(1, false)],
1180 result: {
1181 let mut m = Float::with_val(FLOAT_PRECISION, f64::MAX);
1182 m.next_up();
1183 CalculationResult::Float(m.into())
1184 },
1185 };
1186 let mut s = String::new();
1187 fact.format(
1188 &mut s,
1189 false,
1190 false,
1191 &TOO_BIG_NUMBER,
1192 &consts,
1193 &consts.locales.get("en").unwrap().format(),
1194 )
1195 .unwrap();
1196 assert_eq!(
1197 s,
1198 "Factorial of 0 is approximately 1.797693134862315708145274237317 × 10^308 \n\n"
1199 );
1200 }
1201 #[test]
1202 fn test_format_approximate_factorial_shorten() {
1203 let consts = Consts::default();
1204 let fact = Calculation {
1205 value: Number::Exact(
1206 Integer::from_str("2018338437429423744923849374833232131").unwrap(),
1207 ),
1208 steps: vec![(1, false)],
1209 result: CalculationResult::Approximate(
1210 Float::with_val(FLOAT_PRECISION, Float::parse("2.8394792834").unwrap()).into(),
1211 Integer::from_str("10094283492304894983443984102489842984271").unwrap(),
1212 ),
1213 };
1214 let mut s = String::new();
1215 fact.format(
1216 &mut s,
1217 true,
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 roughly 2.018338437429423744923849374833 × 10^36 is approximately 2.8394792834 × 10^(1.009428349230489498344398410249 × 10^40) \n\n"
1227 );
1228 }
1229 #[test]
1230 fn test_format_approximate_digits_factorial_shorten() {
1231 let consts = Consts::default();
1232 let fact = Calculation {
1233 value: Number::Exact(
1234 Integer::from_str("2313820948092579283573259490834298719").unwrap(),
1235 ),
1236 steps: vec![(1, false)],
1237 result: CalculationResult::ApproximateDigits(
1238 false,
1239 Integer::from_str("9842371208573508275237815084709374240128347012847").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.313820948092579283573259490834 × 10^36 has approximately 9.842371208573508275237815084709 × 10^48 digits \n\n"
1255 );
1256 }
1257 #[test]
1258 fn test_format_digits_tower_shorten() {
1259 let consts = Consts::default();
1260 let fact = Calculation {
1261 value: Number::Exact(
1262 Integer::from_str("13204814708471087502685784603872164320053271").unwrap(),
1263 ),
1264 steps: vec![(1, false)],
1265 result: CalculationResult::ApproximateDigitsTower(
1266 false,
1267 false,
1268 9.into(),
1269 Integer::from_str("7084327410873502875032857120358730912469148632").unwrap(),
1270 ),
1271 };
1272 let mut s = String::new();
1273 fact.format(
1274 &mut s,
1275 true,
1276 false,
1277 &TOO_BIG_NUMBER,
1278 &consts,
1279 &consts.locales.get("en").unwrap().format(),
1280 )
1281 .unwrap();
1282 assert_eq!(
1283 s,
1284 "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"
1285 );
1286 }
1287 #[test]
1288 fn test_format_huge() {
1289 let consts = Consts::default();
1290 let fact = Calculation {
1291 value: 0.into(),
1292 steps: vec![(1, false)],
1293 result: CalculationResult::Exact({
1294 let mut r = Float::with_val(FLOAT_PRECISION, crate::rug::float::Special::Infinity);
1295 r.next_down();
1296 r.to_integer().unwrap()
1297 }),
1298 };
1299 let mut s = String::new();
1300 fact.format(
1301 &mut s,
1302 false,
1303 false,
1304 &TOO_BIG_NUMBER,
1305 &consts,
1306 &consts.locales.get("en").unwrap().format(),
1307 )
1308 .unwrap();
1309 assert_eq!(
1310 s,
1311 "Factorial of 0 is roughly 2.098578716467387692404358116884 × 10^323228496 \n\n"
1312 );
1313 }
1314
1315 #[test]
1316 fn test_tower_value_with_one_top() {
1317 let consts = Consts::default();
1318 let fact = Calculation {
1319 value: 0.into(),
1320 steps: vec![(1, false)],
1321 result: CalculationResult::ApproximateDigitsTower(false, false, 4.into(), 1.into()),
1322 };
1323 let mut s = String::new();
1324 fact.format(
1325 &mut s,
1326 false,
1327 false,
1328 &TOO_BIG_NUMBER,
1329 &consts,
1330 &consts.locales.get("en").unwrap().format(),
1331 )
1332 .unwrap();
1333 assert_eq!(s, "Factorial of 0 has on the order of ^(4)10 digits \n\n");
1334 }
1335
1336 #[test]
1337 fn test_calculation_is_approximate() {
1338 let c1 = Calculation {
1339 value: 0.into(),
1340 steps: vec![],
1341 result: CalculationResult::Approximate(
1342 Float::with_val(FLOAT_PRECISION, 2.0).into(),
1343 1.into(),
1344 ),
1345 };
1346 assert!(c1.is_approximate());
1347 let c2 = Calculation {
1348 value: 0.into(),
1349 steps: vec![],
1350 result: CalculationResult::Exact(1.into()),
1351 };
1352 assert!(!c2.is_approximate());
1353 }
1354
1355 #[test]
1356 fn test_calculation_is_rounded() {
1357 let c1 = Calculation {
1358 value: Number::Float(Float::with_val(FLOAT_PRECISION, 1.23).into()),
1359 steps: vec![],
1360 result: CalculationResult::Approximate(
1361 Float::with_val(FLOAT_PRECISION, 0.0).into(),
1362 0.into(),
1363 ),
1364 };
1365 assert!(c1.is_rounded());
1366 let c2 = Calculation {
1367 value: Number::Float(Float::with_val(FLOAT_PRECISION, 1.23).into()),
1368 steps: vec![],
1369 result: CalculationResult::Float(Float::with_val(FLOAT_PRECISION, 1.23).into()),
1370 };
1371 assert!(!c2.is_rounded());
1372 let c3 = Calculation {
1373 value: 1.into(),
1374 steps: vec![],
1375 result: CalculationResult::Exact(1.into()),
1376 };
1377 assert!(!c3.is_rounded());
1378 }
1379
1380 #[test]
1381 fn test_is_too_long() {
1382 let small = Calculation {
1383 value: 1.into(),
1384 steps: vec![],
1385 result: CalculationResult::Exact(1.into()),
1386 };
1387 assert!(!small.is_too_long(&TOO_BIG_NUMBER));
1388 let big = Calculation {
1389 value: 1.into(),
1390 steps: vec![],
1391 result: CalculationResult::Exact((*TOO_BIG_NUMBER).clone() + 1),
1392 };
1393 assert!(big.is_too_long(&TOO_BIG_NUMBER));
1394 let fl = Calculation {
1395 value: 1.into(),
1396 steps: vec![],
1397 result: CalculationResult::Float(Float::with_val(FLOAT_PRECISION, 1.0).into()),
1398 };
1399 assert!(!fl.is_too_long(&TOO_BIG_NUMBER));
1400 }
1401
1402 #[test]
1403 fn test_number_decimals_scientific_respected() {
1404 let mut consts = Consts::default();
1405 consts.number_decimals_scientific = 10;
1406 let mut acc = String::new();
1407 CalculationResult::Exact(Integer::u_pow_u(10, 1000).complete() * 498149837492347328u64)
1408 .format(
1409 &mut acc,
1410 &mut false,
1411 true,
1412 false,
1413 false,
1414 &consts,
1415 &locale::NumFormat::V1(&locale::v1::NumFormat { decimal: '.' }),
1416 )
1417 .unwrap();
1418 assert_eq!(acc, "4.9814983749 × 10^1017");
1419 let mut acc = String::new();
1420 CalculationResult::Approximate(
1421 Float::with_val(FLOAT_PRECISION, 4.98149837492347328f64).into(),
1422 1017.into(),
1423 )
1424 .format(
1425 &mut acc,
1426 &mut false,
1427 true,
1428 false,
1429 false,
1430 &consts,
1431 &locale::NumFormat::V1(&locale::v1::NumFormat { decimal: '.' }),
1432 )
1433 .unwrap();
1434 assert_eq!(acc, "4.9814983749 × 10^(1017)");
1435 consts.number_decimals_scientific = 50;
1436 let mut acc = String::new();
1437 CalculationResult::Exact(
1438 Integer::u_pow_u(10, 1000).complete() * 49814983749234732849839849898438493843u128,
1439 )
1440 .format(
1441 &mut acc,
1442 &mut false,
1443 true,
1444 false,
1445 false,
1446 &consts,
1447 &locale::NumFormat::V1(&locale::v1::NumFormat { decimal: '.' }),
1448 )
1449 .unwrap();
1450 assert_eq!(acc, "4.9814983749234732849839849898438493843 × 10^1037");
1451 let mut acc = String::new();
1452 CalculationResult::Approximate(
1453 Float::with_val(
1454 FLOAT_PRECISION,
1455 Float::parse("4.9814983749234732849839849898438493843").unwrap(),
1456 )
1457 .into(),
1458 1037.into(),
1459 )
1460 .format(
1461 &mut acc,
1462 &mut false,
1463 true,
1464 false,
1465 false,
1466 &consts,
1467 &locale::NumFormat::V1(&locale::v1::NumFormat { decimal: '.' }),
1468 )
1469 .unwrap();
1470 assert_eq!(acc, "4.9814983749234732849839849898438493843 × 10^(1037)");
1471 }
1472}