Skip to main content

malachite_float/float/conversion/string/
typst.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::{ComparableFloat, ComparableFloatRef, Float};
10use alloc::string::ToString;
11use core::fmt::{Formatter, Result, Write};
12use malachite_base::strings::typst::ToTypst;
13
14impl ToTypst for Float {
15    /// Writes a [`Float`] as a Typst math-mode fragment.
16    ///
17    /// This is as the primitive floats are written. A NaN becomes `"NaN"` and the infinities become
18    /// `infinity` and `-infinity`. A finite [`Float`] is written as [`Display`](core::fmt::Display)
19    /// writes it, with the exponent, if there is one, lifted into a real power of ten: `1.3e30`
20    /// becomes ``1.3 times 10^(30)``.
21    ///
22    /// As with [`Display`](core::fmt::Display), the digit count is determined by the [`Float`]'s
23    /// precision rather than by its value, and the two zeros are kept apart.
24    ///
25    /// # Worst-case complexity
26    /// $T(n) = O(n (\log n)^2 \log\log n)$
27    ///
28    /// $M(n) = O(n \log n)$
29    ///
30    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
31    ///
32    /// # Examples
33    /// ```
34    /// use malachite_base::num::arithmetic::traits::PowerOf2;
35    /// use malachite_base::num::basic::traits::{
36    ///     Infinity, NaN, NegativeInfinity, NegativeZero, One, Zero,
37    /// };
38    /// use malachite_base::strings::typst::ToTypst;
39    /// use malachite_float::Float;
40    ///
41    /// assert_eq!(Float::NAN.to_typst_string(), r#""NaN""#);
42    /// assert_eq!(Float::INFINITY.to_typst_string(), "infinity");
43    /// assert_eq!(Float::NEGATIVE_INFINITY.to_typst_string(), "-infinity");
44    /// assert_eq!(Float::ZERO.to_typst_string(), "0.0");
45    /// assert_eq!(Float::NEGATIVE_ZERO.to_typst_string(), "-0.0");
46    /// assert_eq!(Float::ONE.to_typst_string(), "1.0");
47    /// assert_eq!(Float::from(1.5).to_typst_string(), "1.5");
48    /// assert_eq!(
49    ///     Float::power_of_2(100u64).to_typst_string(),
50    ///     "1.3 times 10^(30)"
51    /// );
52    /// assert_eq!(
53    ///     Float::power_of_2(-100i64).to_typst_string(),
54    ///     "7.9 times 10^(-31)"
55    /// );
56    /// ```
57    ///
58    /// | value                       | fragment            |
59    /// |-----------------------------|---------------------|
60    /// | `Float::NAN`                | `"NaN"`             |
61    /// | `Float::INFINITY`           | `infinity`          |
62    /// | `Float::ONE`                | `1.0`               |
63    /// | `Float::power_of_2(100u64)` | `1.3 times 10^(30)` |
64    fn fmt_typst(&self, f: &mut Formatter) -> Result {
65        if self.is_nan() {
66            return f.write_str("\"NaN\"");
67        } else if self.is_infinite() {
68            return f.write_str(if self.is_sign_positive() {
69                "infinity"
70            } else {
71                "-infinity"
72            });
73        }
74        let s = self.to_string();
75        let Some(e_index) = s.find('e') else {
76            return f.write_str(&s);
77        };
78        let (mantissa, exponent) = s.split_at(e_index);
79        let exponent = &exponent[1..];
80        f.write_str(mantissa)?;
81        f.write_str(" times 10^")?;
82        f.write_char('(')?;
83        f.write_str(exponent)?;
84        f.write_char(')')
85    }
86}
87
88impl ToTypst for ComparableFloat {
89    /// Writes a [`ComparableFloat`] as a Typst math-mode fragment.
90    ///
91    /// The fragment is the wrapped [`Float`]'s own: the wrapper exists to give an equality and an
92    /// ordering that tell more [`Float`]s apart than the usual ones do, and does not change what
93    /// the value is.
94    ///
95    /// # Worst-case complexity
96    /// Same as the time and additional memory complexity of `fmt_typst` for [`Float`].
97    ///
98    /// # Examples
99    /// ```
100    /// use malachite_base::num::basic::traits::One;
101    /// use malachite_base::strings::typst::ToTypst;
102    /// use malachite_float::{ComparableFloat, Float};
103    ///
104    /// assert_eq!(ComparableFloat(Float::ONE).to_typst_string(), "1.0");
105    /// ```
106    #[inline]
107    fn fmt_typst(&self, f: &mut Formatter) -> Result {
108        self.0.fmt_typst(f)
109    }
110}
111
112impl ToTypst for ComparableFloatRef<'_> {
113    /// Writes a [`ComparableFloatRef`] as a Typst math-mode fragment.
114    ///
115    /// The fragment is the wrapped [`Float`]'s own: the wrapper exists to give an equality and an
116    /// ordering that tell more [`Float`]s apart than the usual ones do, and does not change what
117    /// the value is.
118    ///
119    /// # Worst-case complexity
120    /// Same as the time and additional memory complexity of `fmt_typst` for [`Float`].
121    ///
122    /// # Examples
123    /// ```
124    /// use malachite_base::num::basic::traits::One;
125    /// use malachite_base::strings::typst::ToTypst;
126    /// use malachite_float::{ComparableFloatRef, Float};
127    ///
128    /// let x = Float::ONE;
129    /// assert_eq!(ComparableFloatRef(&x).to_typst_string(), "1.0");
130    /// ```
131    #[inline]
132    fn fmt_typst(&self, f: &mut Formatter) -> Result {
133        self.0.fmt_typst(f)
134    }
135}