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