Skip to content

Commit 8935a61

Browse files
drinkcatsylvestre
authored andcommitted
od: Add printer for ExtendedBigDecimal (for f80/f128)
1 parent 778b3ff commit 8935a61

2 files changed

Lines changed: 114 additions & 5 deletions

File tree

src/uu/od/Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,11 @@ bigdecimal = { workspace = true }
2424
byteorder = { workspace = true }
2525
clap = { workspace = true }
2626
half = { workspace = true }
27-
uucore = { workspace = true, features = ["extendedbigdecimal", "parser"] }
27+
uucore = { workspace = true, features = [
28+
"extendedbigdecimal",
29+
"format",
30+
"parser",
31+
] }
2832
fluent = { workspace = true }
2933

3034
[[bin]]

src/uu/od/src/prn_float.rs

Lines changed: 109 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22
//
33
// For the full copyright and license information, please view the LICENSE
44
// file that was distributed with this source code.
5-
// spell-checker:ignore (ToDO) extendedbigdecimal
5+
// spell-checker:ignore (ToDO) bigdecimal extendedbigdecimal
66

77
use half::f16;
88
use std::num::FpCategory;
99
use uucore::extendedbigdecimal::ExtendedBigDecimal;
10+
use uucore::format::num_format;
11+
use uucore::format::num_format::Formatter;
1012

1113
use crate::formatter_item_info::{FormatWriter, FormatterItemInfo};
1214

@@ -36,7 +38,7 @@ pub static FORMAT_ITEM_BF16: FormatterItemInfo = FormatterItemInfo {
3638

3739
pub static FORMAT_ITEM_F128: FormatterItemInfo = FormatterItemInfo {
3840
byte_size: 16,
39-
print_width: 25, //TODO
41+
print_width: 30,
4042
formatter: FormatWriter::ExtendedBigDecimalWriter(format_item_f128),
4143
};
4244

@@ -137,8 +139,22 @@ fn format_float(f: f64, width: usize, precision: usize) -> String {
137139
}
138140
}
139141

140-
fn format_f128(_ebd: &ExtendedBigDecimal) -> String {
141-
"TODO".to_string()
142+
fn format_f128(ebd: &ExtendedBigDecimal) -> String {
143+
format_extended_big_decimal(ebd, 29, 20)
144+
}
145+
146+
fn format_extended_big_decimal(ebd: &ExtendedBigDecimal, width: usize, precision: usize) -> String {
147+
let float = num_format::Float {
148+
variant: num_format::FloatVariant::Shortest,
149+
width,
150+
alignment: num_format::NumberAlignment::RightSpace,
151+
precision: Some(precision),
152+
..Default::default()
153+
};
154+
// TODO: For performance, it'd be best if `od` directly collected and printed Vec<u8>.
155+
let mut v = Vec::new();
156+
float.fmt(&mut v, ebd).unwrap();
157+
String::from_utf8(v).unwrap()
142158
}
143159

144160
#[test]
@@ -277,3 +293,92 @@ fn test_format_f16() {
277293
assert_eq!(format_f16(f16::NEG_ZERO), " -0");
278294
assert_eq!(format_f16(f16::ZERO), " 0");
279295
}
296+
297+
#[test]
298+
#[allow(clippy::cognitive_complexity)]
299+
fn test_format_f128() {
300+
use bigdecimal::BigDecimal;
301+
302+
// Note: These tests print exact ExtendedBigDecimal values, so the results
303+
// maybe be different from an end-to-end test with a "native" f80/f128 input.
304+
// Padding and format is tested, though.
305+
306+
assert_eq!(format_f128(&1.0.into()), " 1");
307+
assert_eq!(format_f128(&10.0.into()), " 10");
308+
assert_eq!(
309+
format_f128(&1_000_000_000_000_000.0.into()),
310+
" 1000000000000000"
311+
);
312+
assert_eq!(
313+
format_f128(&10_000_000_000_000_000.0.into()),
314+
" 10000000000000000"
315+
);
316+
// BigDecimal scale is -exponent
317+
assert_eq!(
318+
format_f128(&ExtendedBigDecimal::BigDecimal(BigDecimal::new(
319+
1.into(),
320+
-100
321+
))),
322+
" 1e+100"
323+
);
324+
325+
assert_eq!(
326+
format_f128(&ExtendedBigDecimal::BigDecimal(BigDecimal::new(
327+
(-10_000_000_000_000_000_001i128).into(),
328+
20
329+
))),
330+
" -0.10000000000000000001"
331+
);
332+
assert_eq!(
333+
format_f128(&ExtendedBigDecimal::BigDecimal(BigDecimal::new(
334+
(-100_000_000_000_000_000_001i128).into(),
335+
21
336+
))),
337+
" -0.1"
338+
);
339+
340+
// BigDecimal scale is -exponent
341+
assert_eq!(
342+
format_f128(&ExtendedBigDecimal::BigDecimal(BigDecimal::new(
343+
12_345_678_901_234_567_890u128.into(),
344+
0
345+
))),
346+
" 12345678901234567890"
347+
);
348+
assert_eq!(
349+
format_f128(&ExtendedBigDecimal::BigDecimal(BigDecimal::new(
350+
12_345_678_901_234_567_890u128.into(),
351+
1100
352+
))),
353+
" 1.234567890123456789e-1081"
354+
);
355+
assert_eq!(
356+
format_f128(&ExtendedBigDecimal::BigDecimal(BigDecimal::new(
357+
12_345_678_901_234_567_890u128.into(),
358+
-1100
359+
))),
360+
" 1.234567890123456789e+1119"
361+
);
362+
363+
assert_eq!(
364+
format_f128(&ExtendedBigDecimal::BigDecimal(BigDecimal::new(
365+
4.into(),
366+
320
367+
))),
368+
" 4e-320"
369+
);
370+
assert_eq!(
371+
format_f128(&f64::NAN.into()),
372+
" nan"
373+
);
374+
assert_eq!(
375+
format_f128(&f64::INFINITY.into()),
376+
" inf"
377+
);
378+
assert_eq!(
379+
format_f128(&f64::NEG_INFINITY.into()),
380+
" -inf"
381+
);
382+
assert_eq!(format_f128(&(-0.0).into()), " -0");
383+
assert_eq!(format_f128(&0.0.into()), " 0");
384+
}

0 commit comments

Comments
 (0)