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}