Fix calc.inf, -calc.inf, and calc.nan reprs and displays (#4724)

This commit is contained in:
Malo 2024-08-11 22:18:57 +02:00 committed by GitHub
parent 70931ac1f6
commit 79fb2c3689
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 30 additions and 9 deletions

View File

@ -73,12 +73,15 @@ pub fn format_int_with_base(mut n: i64, base: i64) -> EcoString {
} }
/// Converts a float to a string representation with a specific precision and a /// Converts a float to a string representation with a specific precision and a
/// suffix, all with a single allocation. /// unit, all with a single allocation.
///
/// The returned string is always valid Typst code. As such, it might not be a
/// float literal. For example, it may return `"calc.inf"`.
pub fn format_float( pub fn format_float(
mut value: f64, mut value: f64,
precision: Option<u8>, precision: Option<u8>,
force_separator: bool, force_separator: bool,
suffix: &str, unit: &str,
) -> EcoString { ) -> EcoString {
if let Some(p) = precision { if let Some(p) = precision {
let offset = 10_f64.powi(p as i32); let offset = 10_f64.powi(p as i32);
@ -86,12 +89,16 @@ pub fn format_float(
} }
// Debug for f64 always prints a decimal separator, while Display only does // Debug for f64 always prints a decimal separator, while Display only does
// when necessary. // when necessary.
let unit_multiplication = if unit.is_empty() { "" } else { " * 1" };
if value.is_nan() { if value.is_nan() {
"NaN".into() eco_format!("calc.nan{unit_multiplication}{unit}")
} else if value.is_infinite() {
let sign = if value < 0.0 { "-" } else { "" };
eco_format!("{sign}calc.inf{unit_multiplication}{unit}")
} else if force_separator { } else if force_separator {
eco_format!("{:?}{}", value, suffix) eco_format!("{value:?}{unit}")
} else { } else {
eco_format!("{}{}", value, suffix) eco_format!("{value}{unit}")
} }
} }
@ -112,6 +119,9 @@ pub fn format_float_with_unit(value: f64, unit: &str) -> EcoString {
pub fn display_float(value: f64) -> EcoString { pub fn display_float(value: f64) -> EcoString {
if value.is_nan() { if value.is_nan() {
"NaN".into() "NaN".into()
} else if value.is_infinite() {
let sign = if value < 0.0 { MINUS_SIGN } else { "" };
eco_format!("{sign}∞")
} else if value < 0.0 { } else if value < 0.0 {
eco_format!("{}{}", MINUS_SIGN, value.abs()) eco_format!("{}{}", MINUS_SIGN, value.abs())
} else { } else {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -20,6 +20,8 @@
// Test float `is-nan()`. // Test float `is-nan()`.
#test(float(calc.nan).is-nan(), true) #test(float(calc.nan).is-nan(), true)
#test(float(10).is-nan(), false) #test(float(10).is-nan(), false)
#test(float(calc.inf).is-nan(), false)
#test(float(-calc.inf).is-nan(), false)
--- float-is-infinite --- --- float-is-infinite ---
// Test float `is-infinite()`. // Test float `is-infinite()`.
@ -27,6 +29,7 @@
#test(float(-calc.inf).is-infinite(), true) #test(float(-calc.inf).is-infinite(), true)
#test(float(10).is-infinite(), false) #test(float(10).is-infinite(), false)
#test(float(-10).is-infinite(), false) #test(float(-10).is-infinite(), false)
#test(float(calc.nan).is-infinite(), false)
--- float-signum --- --- float-signum ---
// Test float `signum()` // Test float `signum()`
@ -35,6 +38,8 @@
#test(float(-1.0).signum(), -1.0) #test(float(-1.0).signum(), -1.0)
#test(float(10.0).signum(), 1.0) #test(float(10.0).signum(), 1.0)
#test(float(-10.0).signum(), -1.0) #test(float(-10.0).signum(), -1.0)
#test(float(calc.inf).signum(), 1.0)
#test(float(-calc.inf).signum(), -1.0)
#test(float(calc.nan).signum().is-nan(), true) #test(float(calc.nan).signum().is-nan(), true)
--- float-repr --- --- float-repr ---
@ -49,7 +54,10 @@
#repr(-9876543210.0) \ #repr(-9876543210.0) \
#repr(-0987654321.0) \ #repr(-0987654321.0) \
#repr(-3.14) \ #repr(-3.14) \
#repr(4.0 - 8.0) #repr(4.0 - 8.0) \
#repr(calc.inf) \
#repr(-calc.inf) \
#repr(calc.nan)
--- float-display --- --- float-display ---
// Test floats. // Test floats.
@ -63,4 +71,7 @@
#(-9876543210.0) \ #(-9876543210.0) \
#(-0987654321.0) \ #(-0987654321.0) \
#(-3.14) \ #(-3.14) \
#(4.0 - 8.0) #(4.0 - 8.0) \
#calc.inf \
#(-calc.inf) \
#calc.nan

View File

@ -335,7 +335,7 @@
#(1em <= 10pt) #(1em <= 10pt)
--- ops-compare-normal-float-with-nan --- --- ops-compare-normal-float-with-nan ---
// Error: 3-22 cannot compare 2.2 with NaN // Error: 3-22 cannot compare 2.2 with calc.nan
#(2.2 <= float("nan")) #(2.2 <= float("nan"))
--- ops-compare-int-and-str --- --- ops-compare-int-and-str ---
@ -343,7 +343,7 @@
#((0, 1, 3) > (0, 1, "a")) #((0, 1, 3) > (0, 1, "a"))
--- ops-compare-array-nested-failure --- --- ops-compare-array-nested-failure ---
// Error: 3-42 cannot compare 3.5 with NaN // Error: 3-42 cannot compare 3.5 with calc.nan
#((0, "a", 3.5) <= (0, "a", float("nan"))) #((0, "a", 3.5) <= (0, "a", float("nan")))
--- ops-divide-by-zero-float --- --- ops-divide-by-zero-float ---