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