malachite_nz/integer/conversion/string/to_sci.rs
1// Copyright © 2025 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::integer::Integer;
10use core::fmt::{Formatter, Write};
11use malachite_base::num::conversion::string::options::ToSciOptions;
12use malachite_base::num::conversion::traits::ToSci;
13
14impl ToSci for Integer {
15 /// Determines whether an [`Integer`] can be converted to a string using
16 /// [`to_sci`](`Self::to_sci`) and a particular set of options.
17 ///
18 /// # Worst-case complexity
19 /// $T(n) = O(n \log n \log\log n)$
20 ///
21 /// $M(n) = O(n \log n)$
22 ///
23 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
24 ///
25 /// # Examples
26 /// ```
27 /// use malachite_base::num::conversion::string::options::ToSciOptions;
28 /// use malachite_base::num::conversion::traits::ToSci;
29 /// use malachite_base::rounding_modes::RoundingMode::*;
30 /// use malachite_nz::integer::Integer;
31 ///
32 /// let mut options = ToSciOptions::default();
33 /// assert!(Integer::from(123).fmt_sci_valid(options));
34 /// assert!(Integer::from(u128::MAX).fmt_sci_valid(options));
35 /// // u128::MAX has more than 16 significant digits
36 /// options.set_rounding_mode(Exact);
37 /// assert!(!Integer::from(u128::MAX).fmt_sci_valid(options));
38 /// options.set_precision(50);
39 /// assert!(Integer::from(u128::MAX).fmt_sci_valid(options));
40 /// ```
41 #[inline]
42 fn fmt_sci_valid(&self, options: ToSciOptions) -> bool {
43 self.unsigned_abs_ref().fmt_sci_valid(options)
44 }
45
46 /// Converts an [`Integer`] to a string using a specified base, possibly formatting the number
47 /// using scientific notation.
48 ///
49 /// See [`ToSciOptions`] for details on the available options. Note that setting
50 /// `neg_exp_threshold` has no effect, since there is never a need to use negative exponents
51 /// when representing an [`Integer`].
52 ///
53 /// # Worst-case complexity
54 /// $T(n) = O(n (\log n)^2 \log\log n)$
55 ///
56 /// $M(n) = O(n \log n)$
57 ///
58 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
59 ///
60 /// # Panics
61 /// Panics if `options.rounding_mode` is `Exact`, but the size options are such that the input
62 /// must be rounded.
63 ///
64 /// # Examples
65 /// ```
66 /// use malachite_base::num::conversion::string::options::ToSciOptions;
67 /// use malachite_base::num::conversion::traits::ToSci;
68 /// use malachite_base::rounding_modes::RoundingMode::*;
69 /// use malachite_nz::integer::Integer;
70 ///
71 /// assert_eq!(
72 /// Integer::from(u128::MAX).to_sci().to_string(),
73 /// "3.402823669209385e38"
74 /// );
75 /// assert_eq!(
76 /// Integer::from(i128::MIN).to_sci().to_string(),
77 /// "-1.701411834604692e38"
78 /// );
79 ///
80 /// let n = Integer::from(123456u32);
81 /// let mut options = ToSciOptions::default();
82 /// assert_eq!(n.to_sci_with_options(options).to_string(), "123456");
83 ///
84 /// options.set_precision(3);
85 /// assert_eq!(n.to_sci_with_options(options).to_string(), "1.23e5");
86 ///
87 /// options.set_rounding_mode(Ceiling);
88 /// assert_eq!(n.to_sci_with_options(options).to_string(), "1.24e5");
89 ///
90 /// options.set_e_uppercase();
91 /// assert_eq!(n.to_sci_with_options(options).to_string(), "1.24E5");
92 ///
93 /// options.set_force_exponent_plus_sign(true);
94 /// assert_eq!(n.to_sci_with_options(options).to_string(), "1.24E+5");
95 ///
96 /// options = ToSciOptions::default();
97 /// options.set_base(36);
98 /// assert_eq!(n.to_sci_with_options(options).to_string(), "2n9c");
99 ///
100 /// options.set_uppercase();
101 /// assert_eq!(n.to_sci_with_options(options).to_string(), "2N9C");
102 ///
103 /// options.set_base(2);
104 /// options.set_precision(10);
105 /// assert_eq!(n.to_sci_with_options(options).to_string(), "1.1110001e16");
106 ///
107 /// options.set_include_trailing_zeros(true);
108 /// assert_eq!(n.to_sci_with_options(options).to_string(), "1.111000100e16");
109 /// ```
110 fn fmt_sci(&self, f: &mut Formatter, mut options: ToSciOptions) -> core::fmt::Result {
111 let abs = self.unsigned_abs_ref();
112 if *self >= 0u32 {
113 abs.fmt_sci(f, options)
114 } else {
115 options.set_rounding_mode(-options.get_rounding_mode());
116 f.write_char('-')?;
117 abs.fmt_sci(f, options)
118 }
119 }
120}