Skip to main content

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