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_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}