This is the second of four short posts about matten. The first post explained the motivation. This one shows what the library looks like in practice.
Getting started
# Cargo.toml
[dependencies]
matten = "0.28"
The default feature set includes serde, json, and csv. If you want the smallest possible dependency footprint, you can turn them off:
matten = { version = "0.28", default-features = false }
Creating tensors
The whole import is use matten::Tensor;. No generic parameters, no lifetime annotations.
use matten::Tensor;
// From data and an explicit shape
let a = Tensor::new(vec![1.0, 2.0, 3.0, 4.0], &[2, 2]);
assert_eq!(a.shape(), &[2, 2]);
assert_eq!(a.ndim(), 2);
// Convenience constructors
let z = Tensor::zeros(&[3, 3]);
let o = Tensor::ones(&[3, 3]);
let f = Tensor::full(&[2, 4], 5.0);
Shape mismatches produce an actionable error rather than a panic when you use the boundary-style constructor:
use matten::{MattenError, Tensor};
let result = Tensor::try_new(vec![1.0, 2.0, 3.0], &[2, 2]);
assert!(matches!(result, Err(MattenError::Shape { .. })));
Arithmetic and broadcasting
The operators work on references, so you keep ownership of the originals. Shape broadcasting follows NumPy-style right-alignment rules.
use matten::Tensor;
let a = Tensor::new(vec![1.0, 2.0, 3.0, 4.0], &[2, 2]);
let b = Tensor::ones(&[2, 2]);
let c = &a + &b; // [2.0, 3.0, 4.0, 5.0]
let d = &a * 2.0; // scalar broadcast: [2.0, 4.0, 6.0, 8.0]
// Broadcasting a row across a matrix
let row = Tensor::new(vec![1.0, 2.0], &[1, 2]);
let mat = Tensor::ones(&[3, 2]);
let result = &mat + &row; // shape [3, 2]
Shape operations
use matten::Tensor;
let t = Tensor::new(vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0], &[2, 3]);
let flat = t.flatten(); // shape [6]
let reshaped = t.reshape(&[3, 2])?;
let transposed = t.transpose()?; // shape [3, 2]
// Reductions
let s = t.sum(); // scalar
let m = t.mean()?;
let col_sums = t.sum_axis(0)?; // shape [3]
JSON and CSV
Both are on by default. The API returns Result at the boundary, so a malformed input gives you an error rather than a panic.
use matten::Tensor;
// JSON — two accepted forms
let t = Tensor::from_json(r#"{"shape":[2,2],"data":[1.0,2.0,3.0,4.0]}"#)?;
let t = Tensor::from_json("[[1.0, 2.0], [3.0, 4.0]]")?;
// From a file
let t = Tensor::load_json("data/tensor.json")?;
// CSV
let t = Tensor::from_csv("1.0,2.0,3.0\n4.0,5.0,6.0\n")?;
let t = Tensor::load_csv("data/matrix.csv")?;
Serialisation goes through serde, so serde_json::to_string(&t) and serde_json::from_str(&json_str) round-trip correctly when the json or serde feature is active.
Error handling
matten has two deliberate error zones. Internal shape operations (constructing from new, reshaping, slicing) panic with an actionable message — useful during fast prototyping because you see the problem immediately. External boundary operations (from_json, from_csv, load_*) always return Result<Tensor, MattenError>, because real input data is not always clean.
MattenError is #[non_exhaustive], so match on the variant you care about and use a wildcard for the rest:
use matten::{MattenError, Tensor};
match Tensor::from_csv("1.0,not_a_number\n") {
Ok(t) => println!("got shape {:?}", t.shape()),
Err(MattenError::Parse { .. }) => println!("bad input"),
Err(e) => println!("other error: {e:?}"),
}
That covers the everyday numeric core. The next post covers something different:
what happens when the input data is not a clean f64 matrix — when it has mixed types, missing values, or integers alongside floats.
Links: crates.io · docs.rs · mdBook · repository
United States
NORTH AMERICA
Related News
Secret Claude Tracker Shocks Users After Anthropic's Anti-Surveillance Stance
12h ago
EV Batteries Defy Expectations, Last Hundreds of Thousands of Miles
1d ago
GBase 8a Performance Anomaly Case Study: How a Single Parameter Change Sparked a Chain Reaction
1d ago
Who Else Has Inherited a Codebase With Zero Comments and a Prayer?
1d ago
完美的平庸
3h ago