Skip to content

Commit 0a74db7

Browse files
committed
General-precision zmij for printing in ASCII when precision is None
1 parent 1bf75d4 commit 0a74db7

3 files changed

Lines changed: 27 additions & 10 deletions

File tree

cli/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66

77
- New `webgraph-rank` CLI supporting centrality measures.
88

9+
### Improved
10+
11+
- Floats without a specified precision are now printed using the `zmij` crate,
12+
which brings a 3-4x speed improvement.
13+
914
## [0.4.0] - 2026-02-18
1015

1116
### New

cli/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ zstd.workspace = true
4343

4444
jiff = "0.2.5"
4545
clap_complete = { version = "4.4.11" }
46+
zmij = "1.0.21"
4647

4748
[dev-dependencies]
4849
serde_json.workspace = true

cli/src/lib.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -210,20 +210,20 @@ impl FloatVectorFormat {
210210
/// Stores float values in the specified `path` using the format defined by
211211
/// `self`.
212212
///
213-
/// If the result is a textual format, i.e., ASCII or JSON, `precision`
213+
/// If the result is a textual format, that is, ASCII or JSON, `precision`
214214
/// will be used to truncate the float values to the specified number of
215-
/// decimal digits.
215+
/// decimal digits. If `None`, [zmij](https://crates.io/crates/zmij)
216+
/// formatting will be used.
216217
pub fn store<F>(
217218
&self,
218219
path: impl AsRef<Path>,
219220
values: &[F],
220221
precision: Option<usize>,
221222
) -> Result<()>
222223
where
223-
F: ToBytes + core::fmt::Display + epserde::ser::Serialize + Copy,
224+
F: ToBytes + core::fmt::Display + epserde::ser::Serialize + Copy + zmij::Float,
224225
for<'a> &'a [F]: epserde::ser::Serialize,
225226
{
226-
let precision = precision.unwrap_or(f64::DIGITS as usize);
227227
create_parent_dir(&path)?;
228228
let path_display = path.as_ref().display();
229229
let mut file = std::fs::File::create(&path)
@@ -247,21 +247,32 @@ impl FloatVectorFormat {
247247
}
248248
FloatVectorFormat::Ascii => {
249249
log::info!("Storing in ASCII format at {}", path_display);
250+
let mut buf = zmij::Buffer::new();
250251
for word in values.iter() {
251-
writeln!(file, "{word:.precision$}")
252-
.with_context(|| format!("Could not write vector to {}", path_display))?;
252+
match precision {
253+
None => writeln!(file, "{}", buf.format(*word)),
254+
Some(precision) => writeln!(file, "{word:.precision$}"),
255+
}
256+
.with_context(|| format!("Could not write vector to {}", path_display))?;
253257
}
254258
}
255259
FloatVectorFormat::Json => {
256260
log::info!("Storing in JSON format at {}", path_display);
261+
let mut buf = zmij::Buffer::new();
257262
write!(file, "[")?;
258263
for word in values.iter().take(values.len().saturating_sub(1)) {
259-
write!(file, "{word:.precision$}, ")
260-
.with_context(|| format!("Could not write vector to {}", path_display))?;
264+
match precision {
265+
None => write!(file, "{}, ", buf.format(*word)),
266+
Some(precision) => write!(file, "{word:.precision$}, "),
267+
}
268+
.with_context(|| format!("Could not write vector to {}", path_display))?;
261269
}
262270
if let Some(last) = values.last() {
263-
write!(file, "{last:.precision$}")
264-
.with_context(|| format!("Could not write vector to {}", path_display))?;
271+
match precision {
272+
None => write!(file, "{}", buf.format(*last)),
273+
Some(precision) => write!(file, "{last:.precision$}"),
274+
}
275+
.with_context(|| format!("Could not write vector to {}", path_display))?;
265276
}
266277
write!(file, "]")?;
267278
}

0 commit comments

Comments
 (0)