malachite_float/float/conversion/string/to_string.rs
1// Copyright © 2026 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::InnerFloat::Finite;
10use crate::float::conversion::string::get_str::get_str_digit_count;
11use crate::float::conversion::string::to_sci::to_sci_string;
12use crate::{ComparableFloat, ComparableFloatRef, Float};
13use alloc::string::String;
14use core::fmt::{Binary, Debug, Display, Formatter, LowerHex, Octal, Result, UpperHex, Write};
15use malachite_base::num::arithmetic::traits::{DivRound, Mod, PowerOf2};
16use malachite_base::num::conversion::string::options::ToSciOptions;
17use malachite_base::num::conversion::traits::{ExactFrom, ToStringBase};
18use malachite_base::rounding_modes::RoundingMode::Ceiling;
19
20// The number of base-2^`digit_bits` digits that exactly cover a `Float` with binary exponent
21// `exponent` and precision `precision`, with the digits aligned to the base-2^`digit_bits` point:
22// the first digit holds `exponent mod digit_bits` significant bits (all `digit_bits` of them when
23// the exponent is a multiple), and the rest of the precision fills subsequent digits.
24fn power_of_2_digit_count(exponent: i32, precision: u64, digit_bits: u64) -> u64 {
25 let m = u64::exact_from(exponent.mod_op(i32::exact_from(digit_bits)));
26 let mut count = precision.saturating_sub(m).div_round(digit_bits, Ceiling).0;
27 if m != 0 {
28 count += 1;
29 }
30 count
31}
32
33// Writes `x` in the base 2^`digit_bits`, with exactly enough digits to represent it. When the
34// formatter's alternate flag is set, `prefix` follows the sign for zero and finite values (but not
35// NaN or the infinities).
36fn fmt_power_of_2_base(
37 x: &Float,
38 f: &mut Formatter,
39 digit_bits: u64,
40 uppercase: bool,
41 prefix: &str,
42) -> Result {
43 let mut options = ToSciOptions::default();
44 options.set_base(u8::power_of_2(digit_bits));
45 options.set_e_uppercase();
46 if uppercase {
47 options.set_uppercase();
48 }
49 if let Float(Finite {
50 exponent,
51 precision,
52 ..
53 }) = x
54 {
55 options.set_precision(power_of_2_digit_count(*exponent, *precision, digit_bits));
56 options.set_include_trailing_zeros(true);
57 }
58 let s = to_sci_string(x, options);
59 if !x.is_nan() && !x.is_infinite() {
60 let (sign, body) = match s.strip_prefix('-') {
61 Some(body) => ("-", body),
62 None => ("", s.as_str()),
63 };
64 f.write_str(sign)?;
65 if f.alternate() {
66 f.write_str(prefix)?;
67 }
68 f.write_str(body)
69 } else {
70 f.write_str(&s)
71 }
72}
73
74// The options that `to_string_base` and `to_string_base_upper` share, chosen so that each base
75// agrees with the corresponding formatting impl: a power-of-2 base writes the exact digits, as
76// `Binary`, `Octal`, and the hexadecimal impls do, and any other base writes the round-trip digit
77// count, as `Display` does in base 10.
78fn to_string_base_options(x: &Float, base: u8, uppercase: bool) -> ToSciOptions {
79 let mut options = ToSciOptions::default();
80 options.set_base(base);
81 if uppercase {
82 options.set_uppercase();
83 // so that the whole string, exponent marker included, is the uppercase of the lowercase
84 // form; from base 15 up the mandatory sign on the exponent keeps `E` the digit distinct
85 // from `E` the marker
86 options.set_e_uppercase();
87 }
88 if base.is_power_of_two() {
89 options.set_e_uppercase();
90 if let Float(Finite {
91 exponent,
92 precision,
93 ..
94 }) = x
95 {
96 options.set_precision(power_of_2_digit_count(
97 *exponent,
98 *precision,
99 u64::from(base.trailing_zeros()),
100 ));
101 options.set_include_trailing_zeros(true);
102 }
103 } else if let Float(Finite { precision, .. }) = x {
104 options.set_precision(u64::exact_from(get_str_digit_count(
105 u64::from(base),
106 *precision,
107 )));
108 options.set_include_trailing_zeros(true);
109 }
110 options
111}
112
113impl ToStringBase for Float {
114 /// Converts a [`Float`] to a [`String`] using a specified base.
115 ///
116 /// Digits from 0 to 9 become [`char`]s from `'0'` to `'9'`, and digits from 10 to 35 become the
117 /// lowercase [`char`]s `'a'` to `'z'`.
118 ///
119 /// The output agrees with the formatting impls: base 10 writes what [`Display`] writes, and
120 /// bases 2, 8, and 16 write what `{:b}`, `{:o}`, and `{:x}` write, without the prefix that the
121 /// `#` flag would add. The number of digits follows from that. In a power-of-2 base the value
122 /// is exactly representable, so exactly enough digits are written to reproduce it; in any other
123 /// base the count is the one that round-trips a [`Float`] of this precision, with trailing
124 /// zeros kept to reach it. The count therefore depends only on the precision, so a printed
125 /// string does not by itself determine a [`Float`]; see [`ComparableFloat`], whose output also
126 /// records the precision.
127 ///
128 /// Values whose exponent is far from zero use scientific notation. From base 15 upward the
129 /// exponent always carries an explicit sign, since `'e'` is a digit in those bases and the sign
130 /// is what distinguishes the exponent from the digits.
131 ///
132 /// The special values are `NaN`, `Infinity`, and `-Infinity` in every base, and the zeros are
133 /// `0.0` and `-0.0`.
134 ///
135 /// # Worst-case complexity
136 /// $T(n) = O(n (\log n)^2 \log\log n)$
137 ///
138 /// $M(n) = O(n \log n)$
139 ///
140 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.complexity()`.
141 ///
142 /// # Panics
143 /// Panics if `base` is less than 2 or greater than 36. Unlike
144 /// [`Natural`](malachite_nz::natural::Natural) and [`Integer`](malachite_nz::integer::Integer),
145 /// whose strings reach base 62, a [`Float`] is limited to base 36 in both directions: see
146 /// [`FromStringBase`](malachite_base::num::conversion::traits::FromStringBase), which this
147 /// inverts.
148 ///
149 /// # Examples
150 /// ```
151 /// use malachite_base::num::conversion::traits::ToStringBase;
152 /// use malachite_float::Float;
153 ///
154 /// assert_eq!(Float::from(255).to_string_base(10), "255.0");
155 /// assert_eq!(Float::from(255).to_string_base(16), "ff.0");
156 /// assert_eq!(Float::from(255).to_string_base(2), "11111111.0");
157 /// assert_eq!(Float::from(1.5).to_string_base(10), "1.5");
158 /// assert_eq!(Float::from(1.5).to_string_base(16), "1.8");
159 ///
160 /// // base 10 agrees with `Display`, and base 16 with `{:x}`
161 /// let x = Float::from(core::f64::consts::PI);
162 /// assert_eq!(x.to_string_base(10), x.to_string());
163 /// assert_eq!(x.to_string_base(16), format!("{x:x}"));
164 /// ```
165 fn to_string_base(&self, base: u8) -> String {
166 assert!((2..=36).contains(&base), "base out of range");
167 to_sci_string(self, to_string_base_options(self, base, false))
168 }
169
170 /// Converts a [`Float`] to a [`String`] using a specified base, with digits being uppercase.
171 ///
172 /// Digits from 0 to 9 become [`char`]s from `'0'` to `'9'`, and digits from 10 to 35 become the
173 /// uppercase [`char`]s `'A'` to `'Z'`.
174 ///
175 /// This is [`to_string_base`](ToStringBase::to_string_base) with the whole string uppercased,
176 /// the exponent marker included; in base 16 it writes what `{:X}` writes, without the prefix
177 /// that the `#` flag would add. The special values `NaN`, `Infinity`, and `-Infinity` keep
178 /// their spelling, as they do in every base.
179 ///
180 /// # Worst-case complexity
181 /// $T(n) = O(n (\log n)^2 \log\log n)$
182 ///
183 /// $M(n) = O(n \log n)$
184 ///
185 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.complexity()`.
186 ///
187 /// # Panics
188 /// Panics if `base` is less than 2 or greater than 36.
189 ///
190 /// # Examples
191 /// ```
192 /// use malachite_base::num::conversion::traits::ToStringBase;
193 /// use malachite_float::Float;
194 ///
195 /// assert_eq!(Float::from(255).to_string_base_upper(16), "FF.0");
196 /// assert_eq!(Float::from(1.5).to_string_base_upper(16), "1.8");
197 ///
198 /// let x = Float::from(core::f64::consts::PI);
199 /// assert_eq!(x.to_string_base_upper(16), format!("{x:X}"));
200 /// ```
201 fn to_string_base_upper(&self, base: u8) -> String {
202 assert!((2..=36).contains(&base), "base out of range");
203 to_sci_string(self, to_string_base_options(self, base, true))
204 }
205}
206
207impl Display for Float {
208 /// Converts a [`Float`] to a [`String`].
209 ///
210 /// The output has enough digits to round-trip: a [`Float`] of precision $p$ is written with
211 /// $1+\lceil p \log_{10} 2 \rceil$ significant digits, correctly rounded to nearest. That count
212 /// depends only on the precision, so it is the same for every value of a given precision, and
213 /// trailing zeros are kept to reach it; a value of precision 1 prints as `"1.0"` where the same
214 /// value at precision 100 prints as `"1.0000000000000000000000000000000"`. A printed string
215 /// therefore does not by itself determine a [`Float`]; see [`ComparableFloat`], whose output
216 /// also records the precision.
217 ///
218 /// The output of a finite value always contains a point. Values whose exponent is far from zero
219 /// use scientific notation, zeros are `0.0` and `-0.0`, and the special values are `NaN`,
220 /// `Infinity`, and `-Infinity`.
221 ///
222 /// # Worst-case complexity
223 /// $T(n) = O(n (\log n)^2 \log\log n)$
224 ///
225 /// $M(n) = O(n \log n)$
226 ///
227 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.complexity()`.
228 ///
229 /// # Examples
230 /// ```
231 /// use malachite_base::num::arithmetic::traits::PowerOf2;
232 /// use malachite_base::num::basic::traits::{
233 /// Infinity, NaN, NegativeInfinity, NegativeZero, One, Zero,
234 /// };
235 /// use malachite_float::Float;
236 ///
237 /// assert_eq!(Float::NAN.to_string(), "NaN");
238 /// assert_eq!(Float::INFINITY.to_string(), "Infinity");
239 /// assert_eq!(Float::NEGATIVE_INFINITY.to_string(), "-Infinity");
240 /// assert_eq!(Float::ZERO.to_string(), "0.0");
241 /// assert_eq!(Float::NEGATIVE_ZERO.to_string(), "-0.0");
242 ///
243 /// assert_eq!(Float::ONE.to_string(), "1.0");
244 /// assert_eq!(Float::from(1.5).to_string(), "1.5");
245 /// assert_eq!(Float::from(255).to_string(), "255.0");
246 /// assert_eq!(
247 /// Float::from(core::f64::consts::PI).to_string(),
248 /// "3.1415926535897931"
249 /// );
250 ///
251 /// // The digit count is determined by the precision, not by the value.
252 /// assert_eq!(
253 /// Float::one_prec(100).to_string(),
254 /// "1.0000000000000000000000000000000"
255 /// );
256 ///
257 /// // Values far from 1 use scientific notation.
258 /// assert_eq!(Float::power_of_2(100u64).to_string(), "1.3e30");
259 /// assert_eq!(Float::power_of_2(-100i64).to_string(), "7.9e-31");
260 /// ```
261 fn fmt(&self, f: &mut Formatter) -> Result {
262 let mut options = ToSciOptions::default();
263 if let Self(Finite { precision, .. }) = self {
264 options.set_precision(u64::exact_from(get_str_digit_count(10, *precision)));
265 options.set_include_trailing_zeros(true);
266 }
267 f.write_str(&to_sci_string(self, options))
268 }
269}
270
271impl Debug for Float {
272 /// Converts a [`Float`] to a [`String`].
273 ///
274 /// This is the same implementation as for [`Display`].
275 ///
276 /// # Worst-case complexity
277 /// $T(n) = O(n (\log n)^2 \log\log n)$
278 ///
279 /// $M(n) = O(n \log n)$
280 ///
281 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.complexity()`.
282 ///
283 /// # Examples
284 /// ```
285 /// use malachite_base::num::basic::traits::{NaN, One, Zero};
286 /// use malachite_base::strings::ToDebugString;
287 /// use malachite_float::Float;
288 ///
289 /// assert_eq!(Float::NAN.to_debug_string(), "NaN");
290 /// assert_eq!(Float::ZERO.to_debug_string(), "0.0");
291 /// assert_eq!(Float::ONE.to_debug_string(), "1.0");
292 /// assert_eq!(Float::from(1.5).to_debug_string(), "1.5");
293 /// ```
294 #[inline]
295 fn fmt(&self, f: &mut Formatter) -> Result {
296 Display::fmt(self, f)
297 }
298}
299
300impl Binary for Float {
301 /// Converts a [`Float`] to a binary [`String`].
302 ///
303 /// Using the `#` format flag prepends `"0b"` to the string, after any sign.
304 ///
305 /// Two is a power of two, so every [`Float`] is exactly representable in this base: the output
306 /// has exactly as many digits as are needed to write the value, one per bit of precision, and
307 /// is never rounded. The exponent, when one is shown, is a decimal number following an `E`.
308 ///
309 /// # Worst-case complexity
310 /// $T(n) = O(n)$
311 ///
312 /// $M(n) = O(n)$
313 ///
314 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.complexity()`.
315 ///
316 /// # Examples
317 /// ```
318 /// use malachite_base::num::arithmetic::traits::PowerOf2;
319 /// use malachite_base::num::basic::traits::{NaN, One, Zero};
320 /// use malachite_base::strings::ToBinaryString;
321 /// use malachite_float::Float;
322 ///
323 /// assert_eq!(Float::NAN.to_binary_string(), "NaN");
324 /// assert_eq!(Float::ZERO.to_binary_string(), "0.0");
325 /// assert_eq!(Float::ONE.to_binary_string(), "1.0");
326 /// assert_eq!(Float::from(1.5).to_binary_string(), "1.1");
327 /// assert_eq!(Float::from(255).to_binary_string(), "11111111.0");
328 /// assert_eq!(Float::power_of_2(100u64).to_binary_string(), "1.0E100");
329 ///
330 /// assert_eq!(format!("{:#b}", Float::ZERO), "0b0.0");
331 /// assert_eq!(format!("{:#b}", Float::from(1.5)), "0b1.1");
332 /// assert_eq!(format!("{:#b}", Float::from(-1.5)), "-0b1.1");
333 /// // The specials are never prefixed.
334 /// assert_eq!(format!("{:#b}", Float::NAN), "NaN");
335 /// ```
336 #[inline]
337 fn fmt(&self, f: &mut Formatter) -> Result {
338 fmt_power_of_2_base(self, f, 1, false, "0b")
339 }
340}
341
342impl Octal for Float {
343 /// Converts a [`Float`] to an octal [`String`].
344 ///
345 /// Using the `#` format flag prepends `"0o"` to the string, after any sign.
346 ///
347 /// Eight is a power of two, so every [`Float`] is exactly representable in this base: the
348 /// output has exactly as many digits as are needed to write the value, and is never rounded.
349 /// The exponent, when one is shown, is a decimal number following an `E`.
350 ///
351 /// # Worst-case complexity
352 /// $T(n) = O(n)$
353 ///
354 /// $M(n) = O(n)$
355 ///
356 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.complexity()`.
357 ///
358 /// # Examples
359 /// ```
360 /// use malachite_base::num::arithmetic::traits::PowerOf2;
361 /// use malachite_base::num::basic::traits::{NaN, One, Zero};
362 /// use malachite_base::strings::ToOctalString;
363 /// use malachite_float::Float;
364 ///
365 /// assert_eq!(Float::NAN.to_octal_string(), "NaN");
366 /// assert_eq!(Float::ZERO.to_octal_string(), "0.0");
367 /// assert_eq!(Float::ONE.to_octal_string(), "1.0");
368 /// assert_eq!(Float::from(1.5).to_octal_string(), "1.4");
369 /// assert_eq!(Float::from(255).to_octal_string(), "377.0");
370 /// assert_eq!(Float::power_of_2(100u64).to_octal_string(), "2.0E33");
371 ///
372 /// assert_eq!(format!("{:#o}", Float::ZERO), "0o0.0");
373 /// assert_eq!(format!("{:#o}", Float::from(1.5)), "0o1.4");
374 /// assert_eq!(format!("{:#o}", Float::from(-1.5)), "-0o1.4");
375 /// ```
376 #[inline]
377 fn fmt(&self, f: &mut Formatter) -> Result {
378 fmt_power_of_2_base(self, f, 3, false, "0o")
379 }
380}
381
382impl LowerHex for Float {
383 /// Converts a [`Float`] to a hexadecimal [`String`], using lowercase digits.
384 ///
385 /// Using the `#` format flag prepends `"0x"` to the string, after any sign.
386 ///
387 /// Sixteen is a power of two, so every [`Float`] is exactly representable in this base: the
388 /// output has exactly as many digits as are needed to write the value, and is never rounded.
389 /// The exponent, when one is shown, is a decimal number following an `E`.
390 ///
391 /// # Worst-case complexity
392 /// $T(n) = O(n)$
393 ///
394 /// $M(n) = O(n)$
395 ///
396 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.complexity()`.
397 ///
398 /// # Examples
399 /// ```
400 /// use malachite_base::num::arithmetic::traits::PowerOf2;
401 /// use malachite_base::num::basic::traits::{NaN, One, Zero};
402 /// use malachite_base::strings::ToLowerHexString;
403 /// use malachite_float::Float;
404 ///
405 /// assert_eq!(Float::NAN.to_lower_hex_string(), "NaN");
406 /// assert_eq!(Float::ZERO.to_lower_hex_string(), "0.0");
407 /// assert_eq!(Float::ONE.to_lower_hex_string(), "1.0");
408 /// assert_eq!(Float::from(1.5).to_lower_hex_string(), "1.8");
409 /// assert_eq!(Float::from(255).to_lower_hex_string(), "ff.0");
410 /// assert_eq!(Float::power_of_2(100u64).to_lower_hex_string(), "1.0E+25");
411 ///
412 /// assert_eq!(format!("{:#x}", Float::ZERO), "0x0.0");
413 /// assert_eq!(format!("{:#x}", Float::from(1.5)), "0x1.8");
414 /// assert_eq!(format!("{:#x}", Float::from(-1.5)), "-0x1.8");
415 /// ```
416 #[inline]
417 fn fmt(&self, f: &mut Formatter) -> Result {
418 fmt_power_of_2_base(self, f, 4, false, "0x")
419 }
420}
421
422impl UpperHex for Float {
423 /// Converts a [`Float`] to a hexadecimal [`String`], using uppercase digits.
424 ///
425 /// Using the `#` format flag prepends `"0x"` to the string, after any sign. As for the
426 /// primitive integers, the prefix stays lowercase.
427 ///
428 /// This is the same as [`LowerHex`] apart from the case of the digits; see it for the
429 /// properties of the base.
430 ///
431 /// # Worst-case complexity
432 /// $T(n) = O(n)$
433 ///
434 /// $M(n) = O(n)$
435 ///
436 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.complexity()`.
437 ///
438 /// # Examples
439 /// ```
440 /// use malachite_base::num::basic::traits::{NaN, One, Zero};
441 /// use malachite_base::strings::ToUpperHexString;
442 /// use malachite_float::Float;
443 ///
444 /// assert_eq!(Float::NAN.to_upper_hex_string(), "NaN");
445 /// assert_eq!(Float::ZERO.to_upper_hex_string(), "0.0");
446 /// assert_eq!(Float::ONE.to_upper_hex_string(), "1.0");
447 /// assert_eq!(Float::from(1.5).to_upper_hex_string(), "1.8");
448 /// assert_eq!(Float::from(255).to_upper_hex_string(), "FF.0");
449 ///
450 /// assert_eq!(format!("{:#X}", Float::from(255)), "0xFF.0");
451 /// assert_eq!(format!("{:#X}", Float::from(-1.5)), "-0x1.8");
452 /// ```
453 #[inline]
454 fn fmt(&self, f: &mut Formatter) -> Result {
455 fmt_power_of_2_base(self, f, 4, true, "0x")
456 }
457}
458
459impl Display for ComparableFloat {
460 /// Converts a [`ComparableFloat`] to a [`String`].
461 ///
462 /// This is the same implementation as for [`ComparableFloatRef`]: the wrapped [`Float`]'s
463 /// [`Display`] output, followed by `#` and the precision.
464 ///
465 /// # Worst-case complexity
466 /// $T(n) = O(n (\log n)^2 \log\log n)$
467 ///
468 /// $M(n) = O(n \log n)$
469 ///
470 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
471 ///
472 /// # Examples
473 /// ```
474 /// use malachite_base::num::basic::traits::One;
475 /// use malachite_float::{ComparableFloat, Float};
476 ///
477 /// assert_eq!(ComparableFloat(Float::ONE).to_string(), "1.0#1");
478 /// assert_eq!(ComparableFloat(Float::one_prec(100)).to_string().len(), 37);
479 /// assert_eq!(ComparableFloat(Float::from(1.5)).to_string(), "1.5#2");
480 /// ```
481 #[inline]
482 fn fmt(&self, f: &mut Formatter) -> Result {
483 Display::fmt(&ComparableFloatRef(&self.0), f)
484 }
485}
486
487impl Debug for ComparableFloat {
488 /// Converts a [`ComparableFloat`] to a [`String`].
489 ///
490 /// This is the same implementation as for [`Display`].
491 ///
492 /// # Worst-case complexity
493 /// $T(n) = O(n (\log n)^2 \log\log n)$
494 ///
495 /// $M(n) = O(n \log n)$
496 ///
497 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
498 ///
499 /// # Examples
500 /// ```
501 /// use malachite_base::num::basic::traits::One;
502 /// use malachite_base::strings::ToDebugString;
503 /// use malachite_float::{ComparableFloat, Float};
504 ///
505 /// assert_eq!(ComparableFloat(Float::ONE).to_debug_string(), "1.0#1");
506 /// assert_eq!(ComparableFloat(Float::from(1.5)).to_debug_string(), "1.5#2");
507 /// ```
508 #[inline]
509 fn fmt(&self, f: &mut Formatter) -> Result {
510 Debug::fmt(&ComparableFloatRef(&self.0), f)
511 }
512}
513
514impl LowerHex for ComparableFloat {
515 /// Converts a [`ComparableFloat`] to a hexadecimal [`String`].
516 ///
517 /// This is the same implementation as for [`ComparableFloatRef`]: the wrapped [`Float`]'s
518 /// [`LowerHex`] output, followed by `#` and the precision. Using the `#` format flag prepends
519 /// `"0x"` to the value, after any sign.
520 ///
521 /// This is the form that identifies a [`Float`] exactly, and the one the tests use as their
522 /// canonical label: the digits are exact because the base is a power of two, and the suffix
523 /// records the precision, which the digits alone may not determine.
524 ///
525 /// # Worst-case complexity
526 /// $T(n) = O(n)$
527 ///
528 /// $M(n) = O(n)$
529 ///
530 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
531 ///
532 /// # Examples
533 /// ```
534 /// use malachite_base::num::basic::traits::One;
535 /// use malachite_float::{ComparableFloat, Float};
536 ///
537 /// assert_eq!(format!("{:x}", ComparableFloat(Float::ONE)), "1.0#1");
538 /// assert_eq!(format!("{:#x}", ComparableFloat(Float::ONE)), "0x1.0#1");
539 /// assert_eq!(
540 /// format!("{:#x}", ComparableFloat(Float::from(1.5))),
541 /// "0x1.8#2"
542 /// );
543 /// assert_eq!(
544 /// format!("{:#x}", ComparableFloat(Float::from(-1.5))),
545 /// "-0x1.8#2"
546 /// );
547 /// ```
548 #[inline]
549 fn fmt(&self, f: &mut Formatter) -> Result {
550 LowerHex::fmt(&ComparableFloatRef(&self.0), f)
551 }
552}
553
554impl Binary for ComparableFloat {
555 /// Converts a [`ComparableFloat`] to a binary [`String`].
556 ///
557 /// This is the same implementation as for [`ComparableFloatRef`]: the wrapped [`Float`]'s
558 /// [`Binary`] output, followed by `#` and the precision. Using the `#` format flag prepends
559 /// `"0b"` to the value, after any sign.
560 ///
561 /// # Worst-case complexity
562 /// $T(n) = O(n)$
563 ///
564 /// $M(n) = O(n)$
565 ///
566 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
567 ///
568 /// # Examples
569 /// ```
570 /// use malachite_base::num::basic::traits::One;
571 /// use malachite_float::{ComparableFloat, Float};
572 ///
573 /// assert_eq!(format!("{:b}", ComparableFloat(Float::ONE)), "1.0#1");
574 /// assert_eq!(format!("{:#b}", ComparableFloat(Float::ONE)), "0b1.0#1");
575 /// assert_eq!(
576 /// format!("{:#b}", ComparableFloat(Float::from(-1.5))),
577 /// "-0b1.1#2"
578 /// );
579 /// ```
580 #[inline]
581 fn fmt(&self, f: &mut Formatter) -> Result {
582 Binary::fmt(&ComparableFloatRef(&self.0), f)
583 }
584}
585
586impl Octal for ComparableFloat {
587 /// Converts a [`ComparableFloat`] to an octal [`String`].
588 ///
589 /// This is the same implementation as for [`ComparableFloatRef`]: the wrapped [`Float`]'s
590 /// [`Octal`] output, followed by `#` and the precision. Using the `#` format flag prepends
591 /// `"0o"` to the value, after any sign.
592 ///
593 /// # Worst-case complexity
594 /// $T(n) = O(n)$
595 ///
596 /// $M(n) = O(n)$
597 ///
598 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
599 ///
600 /// # Examples
601 /// ```
602 /// use malachite_base::num::basic::traits::One;
603 /// use malachite_float::{ComparableFloat, Float};
604 ///
605 /// assert_eq!(format!("{:o}", ComparableFloat(Float::ONE)), "1.0#1");
606 /// assert_eq!(format!("{:#o}", ComparableFloat(Float::ONE)), "0o1.0#1");
607 /// assert_eq!(
608 /// format!("{:#o}", ComparableFloat(Float::from(-1.5))),
609 /// "-0o1.4#2"
610 /// );
611 /// ```
612 #[inline]
613 fn fmt(&self, f: &mut Formatter) -> Result {
614 Octal::fmt(&ComparableFloatRef(&self.0), f)
615 }
616}
617
618impl UpperHex for ComparableFloat {
619 /// Converts a [`ComparableFloat`] to a hexadecimal [`String`].
620 ///
621 /// This is the same implementation as for [`ComparableFloatRef`]: the wrapped [`Float`]'s
622 /// [`UpperHex`] output, followed by `#` and the precision. Using the `#` format flag prepends
623 /// `"0x"` to the value, after any sign.
624 ///
625 /// # Worst-case complexity
626 /// $T(n) = O(n)$
627 ///
628 /// $M(n) = O(n)$
629 ///
630 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
631 ///
632 /// # Examples
633 /// ```
634 /// use malachite_base::num::basic::traits::One;
635 /// use malachite_float::{ComparableFloat, Float};
636 ///
637 /// assert_eq!(format!("{:X}", ComparableFloat(Float::ONE)), "1.0#1");
638 /// assert_eq!(format!("{:#X}", ComparableFloat(Float::ONE)), "0x1.0#1");
639 /// assert_eq!(
640 /// format!("{:#X}", ComparableFloat(Float::from(255))),
641 /// "0xFF.0#8"
642 /// );
643 /// ```
644 #[inline]
645 fn fmt(&self, f: &mut Formatter) -> Result {
646 UpperHex::fmt(&ComparableFloatRef(&self.0), f)
647 }
648}
649
650impl Display for ComparableFloatRef<'_> {
651 /// Converts a [`ComparableFloatRef`] to a [`String`].
652 ///
653 /// The output is the wrapped [`Float`]'s [`Display`] output, followed by `#` and the precision,
654 /// as in `"1.5#2"`. Because a [`Float`]'s decimal digits do not determine its precision, the
655 /// suffix is what makes the output identify the value that [`ComparableFloatRef`]'s [`Eq`]
656 /// compares. The special values and the zeros have no precision, so they are written exactly as
657 /// [`Float`] writes them.
658 ///
659 /// # Worst-case complexity
660 /// $T(n) = O(n (\log n)^2 \log\log n)$
661 ///
662 /// $M(n) = O(n \log n)$
663 ///
664 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
665 ///
666 /// # Examples
667 /// ```
668 /// use malachite_base::num::basic::traits::{NaN, One, Zero};
669 /// use malachite_float::{ComparableFloatRef, Float};
670 ///
671 /// assert_eq!(ComparableFloatRef(&Float::ONE).to_string(), "1.0#1");
672 /// assert_eq!(ComparableFloatRef(&Float::from(1.5)).to_string(), "1.5#2");
673 /// assert_eq!(ComparableFloatRef(&Float::from(255)).to_string(), "255.0#8");
674 ///
675 /// // The specials and the zeros carry no precision.
676 /// assert_eq!(ComparableFloatRef(&Float::NAN).to_string(), "NaN");
677 /// assert_eq!(ComparableFloatRef(&Float::ZERO).to_string(), "0.0");
678 /// ```
679 fn fmt(&self, f: &mut Formatter) -> Result {
680 if let x @ Float(Finite { precision, .. }) = &self.0 {
681 write!(f, "{x}")?;
682 f.write_char('#')?;
683 write!(f, "{precision}")
684 } else {
685 Display::fmt(&self.0, f)
686 }
687 }
688}
689
690impl LowerHex for ComparableFloatRef<'_> {
691 /// Converts a [`ComparableFloatRef`] to a hexadecimal [`String`].
692 ///
693 /// The output is the wrapped [`Float`]'s [`LowerHex`] output, followed by `#` and the
694 /// precision, as in `"1.8#2"`. Using the `#` format flag prepends `"0x"` to the value, after
695 /// any sign, giving `"0x1.8#2"`.
696 ///
697 /// This is the form that identifies a [`Float`] exactly: the digits are exact because the base
698 /// is a power of two, and the suffix supplies the precision. It is also what a base-16
699 /// [`FromStringBase`](malachite_base::num::conversion::traits::FromStringBase) parse accepts,
700 /// so the two round-trip, which is why the tests use it as their canonical label.
701 ///
702 /// # Worst-case complexity
703 /// $T(n) = O(n)$
704 ///
705 /// $M(n) = O(n)$
706 ///
707 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
708 ///
709 /// # Examples
710 /// ```
711 /// use malachite_base::num::basic::traits::{NaN, One};
712 /// use malachite_float::{ComparableFloatRef, Float};
713 ///
714 /// assert_eq!(format!("{:x}", ComparableFloatRef(&Float::ONE)), "1.0#1");
715 /// assert_eq!(format!("{:#x}", ComparableFloatRef(&Float::ONE)), "0x1.0#1");
716 /// assert_eq!(
717 /// format!("{:#x}", ComparableFloatRef(&Float::from(1.5))),
718 /// "0x1.8#2"
719 /// );
720 /// assert_eq!(
721 /// format!("{:#x}", ComparableFloatRef(&Float::from(255))),
722 /// "0xff.0#8"
723 /// );
724 /// assert_eq!(format!("{:#x}", ComparableFloatRef(&Float::NAN)), "NaN");
725 /// ```
726 fn fmt(&self, f: &mut Formatter) -> Result {
727 if let x @ Float(Finite { precision, .. }) = &self.0 {
728 if f.alternate() {
729 write!(f, "{x:#x}")?;
730 } else {
731 write!(f, "{x:x}")?;
732 }
733 f.write_char('#')?;
734 write!(f, "{precision}")
735 } else {
736 LowerHex::fmt(&self.0, f)
737 }
738 }
739}
740
741impl Binary for ComparableFloatRef<'_> {
742 /// Converts a [`ComparableFloatRef`] to a binary [`String`].
743 ///
744 /// The output is the wrapped [`Float`]'s [`Binary`] output, followed by `#` and the precision.
745 /// Using the `#` format flag prepends `"0b"` to the value, after any sign.
746 ///
747 /// Like the hexadecimal form, this identifies a [`Float`] exactly: the digits are exact because
748 /// the base is a power of two, and the suffix supplies the precision, which the digits alone
749 /// may not determine.
750 ///
751 /// # Worst-case complexity
752 /// $T(n) = O(n)$
753 ///
754 /// $M(n) = O(n)$
755 ///
756 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
757 ///
758 /// # Examples
759 /// ```
760 /// use malachite_base::num::basic::traits::{NaN, One};
761 /// use malachite_float::{ComparableFloatRef, Float};
762 ///
763 /// assert_eq!(format!("{:b}", ComparableFloatRef(&Float::ONE)), "1.0#1");
764 /// assert_eq!(format!("{:#b}", ComparableFloatRef(&Float::ONE)), "0b1.0#1");
765 /// assert_eq!(
766 /// format!("{:#b}", ComparableFloatRef(&Float::from(1.5))),
767 /// "0b1.1#2"
768 /// );
769 /// assert_eq!(
770 /// format!("{:#b}", ComparableFloatRef(&Float::from(255))),
771 /// "0b11111111.0#8"
772 /// );
773 /// assert_eq!(format!("{:#b}", ComparableFloatRef(&Float::NAN)), "NaN");
774 /// ```
775 fn fmt(&self, f: &mut Formatter) -> Result {
776 if let x @ Float(Finite { precision, .. }) = &self.0 {
777 if f.alternate() {
778 write!(f, "{x:#b}")?;
779 } else {
780 write!(f, "{x:b}")?;
781 }
782 f.write_char('#')?;
783 write!(f, "{precision}")
784 } else {
785 Binary::fmt(&self.0, f)
786 }
787 }
788}
789
790impl Octal for ComparableFloatRef<'_> {
791 /// Converts a [`ComparableFloatRef`] to an octal [`String`].
792 ///
793 /// The output is the wrapped [`Float`]'s [`Octal`] output, followed by `#` and the precision.
794 /// Using the `#` format flag prepends `"0o"` to the value, after any sign.
795 ///
796 /// Like the hexadecimal form, this identifies a [`Float`] exactly: the digits are exact because
797 /// the base is a power of two, and the suffix supplies the precision, which the digits alone
798 /// may not determine.
799 ///
800 /// # Worst-case complexity
801 /// $T(n) = O(n)$
802 ///
803 /// $M(n) = O(n)$
804 ///
805 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
806 ///
807 /// # Examples
808 /// ```
809 /// use malachite_base::num::basic::traits::{NaN, One};
810 /// use malachite_float::{ComparableFloatRef, Float};
811 ///
812 /// assert_eq!(format!("{:o}", ComparableFloatRef(&Float::ONE)), "1.0#1");
813 /// assert_eq!(format!("{:#o}", ComparableFloatRef(&Float::ONE)), "0o1.0#1");
814 /// assert_eq!(
815 /// format!("{:#o}", ComparableFloatRef(&Float::from(1.5))),
816 /// "0o1.4#2"
817 /// );
818 /// assert_eq!(
819 /// format!("{:#o}", ComparableFloatRef(&Float::from(255))),
820 /// "0o377.0#8"
821 /// );
822 /// assert_eq!(format!("{:#o}", ComparableFloatRef(&Float::NAN)), "NaN");
823 /// ```
824 fn fmt(&self, f: &mut Formatter) -> Result {
825 if let x @ Float(Finite { precision, .. }) = &self.0 {
826 if f.alternate() {
827 write!(f, "{x:#o}")?;
828 } else {
829 write!(f, "{x:o}")?;
830 }
831 f.write_char('#')?;
832 write!(f, "{precision}")
833 } else {
834 Octal::fmt(&self.0, f)
835 }
836 }
837}
838
839impl UpperHex for ComparableFloatRef<'_> {
840 /// Converts a [`ComparableFloatRef`] to a hexadecimal [`String`].
841 ///
842 /// The output is the wrapped [`Float`]'s [`UpperHex`] output, followed by `#` and the
843 /// precision. Using the `#` format flag prepends `"0x"` to the value, after any sign.
844 ///
845 /// Like the hexadecimal form, this identifies a [`Float`] exactly: the digits are exact because
846 /// the base is a power of two, and the suffix supplies the precision, which the digits alone
847 /// may not determine.
848 ///
849 /// # Worst-case complexity
850 /// $T(n) = O(n)$
851 ///
852 /// $M(n) = O(n)$
853 ///
854 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
855 ///
856 /// # Examples
857 /// ```
858 /// use malachite_base::num::basic::traits::{NaN, One};
859 /// use malachite_float::{ComparableFloatRef, Float};
860 ///
861 /// assert_eq!(format!("{:X}", ComparableFloatRef(&Float::ONE)), "1.0#1");
862 /// assert_eq!(format!("{:#X}", ComparableFloatRef(&Float::ONE)), "0x1.0#1");
863 /// assert_eq!(
864 /// format!("{:#X}", ComparableFloatRef(&Float::from(255))),
865 /// "0xFF.0#8"
866 /// );
867 /// // As for `Float`, the prefix stays lowercase, matching the primitive integers.
868 /// assert_eq!(
869 /// format!("{:#X}", ComparableFloatRef(&Float::from(-1.5))),
870 /// "-0x1.8#2"
871 /// );
872 /// assert_eq!(format!("{:#X}", ComparableFloatRef(&Float::NAN)), "NaN");
873 /// ```
874 fn fmt(&self, f: &mut Formatter) -> Result {
875 if let x @ Float(Finite { precision, .. }) = &self.0 {
876 if f.alternate() {
877 write!(f, "{x:#X}")?;
878 } else {
879 write!(f, "{x:X}")?;
880 }
881 f.write_char('#')?;
882 write!(f, "{precision}")
883 } else {
884 UpperHex::fmt(&self.0, f)
885 }
886 }
887}
888
889impl Debug for ComparableFloatRef<'_> {
890 /// Converts a [`ComparableFloatRef`] to a [`String`].
891 ///
892 /// This is the same implementation as for [`Display`].
893 ///
894 /// # Worst-case complexity
895 /// $T(n) = O(n (\log n)^2 \log\log n)$
896 ///
897 /// $M(n) = O(n \log n)$
898 ///
899 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.0.complexity()`.
900 ///
901 /// # Examples
902 /// ```
903 /// use malachite_base::num::basic::traits::One;
904 /// use malachite_base::strings::ToDebugString;
905 /// use malachite_float::{ComparableFloatRef, Float};
906 ///
907 /// assert_eq!(ComparableFloatRef(&Float::ONE).to_debug_string(), "1.0#1");
908 /// assert_eq!(
909 /// ComparableFloatRef(&Float::from(1.5)).to_debug_string(),
910 /// "1.5#2"
911 /// );
912 /// ```
913 #[inline]
914 fn fmt(&self, f: &mut Formatter) -> Result {
915 Display::fmt(self, f)
916 }
917}