Add alternate Display for concise matrix printing

Add format option for concise printing of matrices
as semicolon-delimited rows. e.g. println!("{:#}", matrix);
This commit is contained in:
Owen Brooks 2022-06-15 13:48:46 +10:00
parent 807e4c153a
commit 49e3633c1c
1 changed files with 82 additions and 58 deletions

View File

@ -1893,68 +1893,92 @@ macro_rules! impl_fmt {
S: RawStorage<T, R, C>, S: RawStorage<T, R, C>,
{ {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[cfg(feature = "std")] if !f.alternate() { // pretty print in 2D layout
fn val_width<T: Scalar + $trait>(val: &T, f: &mut fmt::Formatter<'_>) -> usize { #[cfg(feature = "std")]
match f.precision() { fn val_width<T: Scalar + $trait>(val: &T, f: &mut fmt::Formatter<'_>) -> usize {
Some(precision) => format!($fmt_str_with_precision, val, precision)
.chars()
.count(),
None => format!($fmt_str_without_precision, val).chars().count(),
}
}
#[cfg(not(feature = "std"))]
fn val_width<T: Scalar + $trait>(_: &T, _: &mut fmt::Formatter<'_>) -> usize {
4
}
let (nrows, ncols) = self.shape();
if nrows == 0 || ncols == 0 {
return write!(f, "[ ]");
}
let mut max_length = 0;
for i in 0..nrows {
for j in 0..ncols {
max_length = crate::max(max_length, val_width(&self[(i, j)], f));
}
}
let max_length_with_space = max_length + 1;
writeln!(f)?;
writeln!(
f,
" ┌ {:>width$} ┐",
"",
width = max_length_with_space * ncols - 1
)?;
for i in 0..nrows {
write!(f, "")?;
for j in 0..ncols {
let number_length = val_width(&self[(i, j)], f) + 1;
let pad = max_length_with_space - number_length;
write!(f, " {:>thepad$}", "", thepad = pad)?;
match f.precision() { match f.precision() {
Some(precision) => { Some(precision) => format!($fmt_str_with_precision, val, precision)
write!(f, $fmt_str_with_precision, (*self)[(i, j)], precision)? .chars()
} .count(),
None => write!(f, $fmt_str_without_precision, (*self)[(i, j)])?, None => format!($fmt_str_without_precision, val).chars().count(),
} }
} }
writeln!(f, "")?;
}
writeln!( #[cfg(not(feature = "std"))]
f, fn val_width<T: Scalar + $trait>(_: &T, _: &mut fmt::Formatter<'_>) -> usize {
" └ {:>width$} ┘", 4
"", }
width = max_length_with_space * ncols - 1
)?; let (nrows, ncols) = self.shape();
writeln!(f)
if nrows == 0 || ncols == 0 {
return write!(f, "[ ]");
}
let mut max_length = 0;
for i in 0..nrows {
for j in 0..ncols {
max_length = crate::max(max_length, val_width(&self[(i, j)], f));
}
}
let max_length_with_space = max_length + 1;
writeln!(f)?; // leading newline to ensure no offset from previous prints
writeln!(
f,
" ┌ {:>width$} ┐",
"",
width = max_length_with_space * ncols - 1
)?;
for i in 0..nrows {
write!(f, "")?;
for j in 0..ncols {
let number_length = val_width(&self[(i, j)], f) + 1;
let pad = max_length_with_space - number_length;
write!(f, " {:>thepad$}", "", thepad = pad)?;
match f.precision() {
Some(precision) => {
write!(f, $fmt_str_with_precision, (*self)[(i, j)], precision)?
}
None => write!(f, $fmt_str_without_precision, (*self)[(i, j)])?,
}
}
writeln!(f, "")?;
}
write!(
f,
" └ {:>width$} ┘",
"",
width = max_length_with_space * ncols - 1
)
} else { // print on single line with semicolon-delimited rows and comma-delimited columns
let (nrows, ncols) = self.shape();
write!(f, "[")?;
for row in 0..nrows {
for col in 0..ncols {
if col != 0 {
write!(f, ", ")?;
}
match f.precision() {
Some(precision) => write!(
f,
$fmt_str_with_precision,
(*self)[(row, col)],
precision
)?,
None => write!(f, $fmt_str_without_precision, (*self)[(row, col)])?,
}
}
if row != nrows - 1 {
write!(f, "; ")?;
}
}
write!(f, "]")
}
} }
} }
}; };