style: format Rust workspace

This commit is contained in:
2026-06-18 18:11:58 +08:00
parent 013465fc06
commit 531cd3fe08
57 changed files with 4045 additions and 1204 deletions

View File

@@ -43,18 +43,30 @@ pub trait TensorDType: Copy + Send + Sync + 'static {
impl TensorDType for f32 {
const DTYPE: DType = DType::F32;
fn to_f64(self) -> f64 { self as f64 }
fn from_f64(v: f64) -> Self { v as f32 }
fn to_f64(self) -> f64 {
self as f64
}
fn from_f64(v: f64) -> Self {
v as f32
}
}
impl TensorDType for f16 {
const DTYPE: DType = DType::F16;
fn to_f64(self) -> f64 { self.to_f32() as f64 }
fn from_f64(v: f64) -> Self { f16::from_f32(v as f32) }
fn to_f64(self) -> f64 {
self.to_f32() as f64
}
fn from_f64(v: f64) -> Self {
f16::from_f32(v as f32)
}
}
impl TensorDType for bf16 {
const DTYPE: DType = DType::BF16;
fn to_f64(self) -> f64 { self.to_f32() as f64 }
fn from_f64(v: f64) -> Self { bf16::from_f32(v as f32) }
fn to_f64(self) -> f64 {
self.to_f32() as f64
}
fn from_f64(v: f64) -> Self {
bf16::from_f32(v as f32)
}
}

View File

@@ -6,4 +6,4 @@ pub mod tensor;
pub use dtype::{DType, TensorDType};
pub use shape::Dims;
pub use storage::{Device, Storage};
pub use tensor::{register_gpu_contiguous, Tensor};
pub use tensor::{Tensor, register_gpu_contiguous};

View File

@@ -46,8 +46,16 @@ pub fn broadcast_shape(a: &[usize], b: &[usize]) -> Option<Dims> {
let ndim = a.len().max(b.len());
let mut result = SmallVec::with_capacity(ndim);
for i in 0..ndim {
let da = if i < ndim - a.len() { 1 } else { a[i - (ndim - a.len())] };
let db = if i < ndim - b.len() { 1 } else { b[i - (ndim - b.len())] };
let da = if i < ndim - a.len() {
1
} else {
a[i - (ndim - a.len())]
};
let db = if i < ndim - b.len() {
1
} else {
b[i - (ndim - b.len())]
};
if da == db {
result.push(da);
} else if da == 1 {
@@ -100,8 +108,14 @@ mod tests {
#[test]
fn test_broadcast_shape() {
assert_eq!(broadcast_shape(&[3, 1], &[1, 4]).unwrap().as_slice(), &[3, 4]);
assert_eq!(broadcast_shape(&[2, 3, 4], &[4]).unwrap().as_slice(), &[2, 3, 4]);
assert_eq!(
broadcast_shape(&[3, 1], &[1, 4]).unwrap().as_slice(),
&[3, 4]
);
assert_eq!(
broadcast_shape(&[2, 3, 4], &[4]).unwrap().as_slice(),
&[2, 3, 4]
);
assert_eq!(broadcast_shape(&[1], &[5, 3]).unwrap().as_slice(), &[5, 3]);
assert!(broadcast_shape(&[3], &[4]).is_none());
}
@@ -109,6 +123,9 @@ mod tests {
#[test]
fn test_broadcast_strides() {
// [3,1] with strides [1,1] broadcast to [3,4]
assert_eq!(broadcast_strides(&[3, 1], &[1, 1], &[3, 4]).as_slice(), &[1, 0]);
assert_eq!(
broadcast_strides(&[3, 1], &[1, 1], &[3, 4]).as_slice(),
&[1, 0]
);
}
}

View File

@@ -33,8 +33,20 @@ impl Tensor {
// --- Creation ---
/// Create a tensor from raw components (for advanced use like GPU KV cache).
pub fn from_storage(storage: Storage, shape: Dims, strides: Dims, offset: usize, dtype: DType) -> Self {
Self { storage, shape, strides, offset, dtype }
pub fn from_storage(
storage: Storage,
shape: Dims,
strides: Dims,
offset: usize,
dtype: DType,
) -> Self {
Self {
storage,
shape,
strides,
offset,
dtype,
}
}
pub fn from_slice<T: TensorDType>(data: &[T], shape: &[usize]) -> Self {
@@ -60,7 +72,10 @@ impl Tensor {
data.len(),
numel * dtype.size_bytes(),
"raw bytes length {} != expected {} (numel={} * elem_size={})",
data.len(), numel * dtype.size_bytes(), numel, dtype.size_bytes()
data.len(),
numel * dtype.size_bytes(),
numel,
dtype.size_bytes()
);
Self {
storage: Storage::cpu(data.to_vec()),
@@ -112,14 +127,28 @@ impl Tensor {
// --- Properties ---
pub fn shape(&self) -> &[usize] { &self.shape }
pub fn strides(&self) -> &[usize] { &self.strides }
pub fn dtype(&self) -> DType { self.dtype }
pub fn ndim(&self) -> usize { self.shape.len() }
pub fn numel(&self) -> usize { shape::num_elements(&self.shape) }
pub fn offset(&self) -> usize { self.offset }
pub fn shape(&self) -> &[usize] {
&self.shape
}
pub fn strides(&self) -> &[usize] {
&self.strides
}
pub fn dtype(&self) -> DType {
self.dtype
}
pub fn ndim(&self) -> usize {
self.shape.len()
}
pub fn numel(&self) -> usize {
shape::num_elements(&self.shape)
}
pub fn offset(&self) -> usize {
self.offset
}
pub fn device(&self) -> Device { self.storage.device() }
pub fn device(&self) -> Device {
self.storage.device()
}
pub fn is_contiguous(&self) -> bool {
shape::is_contiguous(&self.shape, &self.strides)
@@ -193,7 +222,11 @@ impl Tensor {
shape::contiguous_strides(&new_shape)
} else {
let mut s = self.strides.clone();
let stride_val = if dim < self.strides.len() { self.strides[dim] } else { 1 };
let stride_val = if dim < self.strides.len() {
self.strides[dim]
} else {
1
};
s.insert(dim, stride_val);
s
};
@@ -230,7 +263,12 @@ impl Tensor {
let ndim = self.ndim();
let mut idx = vec![0usize; ndim];
for flat in 0..numel {
let src_offset = self.offset + idx.iter().zip(self.strides.iter()).map(|(i, s)| i * s).sum::<usize>();
let src_offset = self.offset
+ idx
.iter()
.zip(self.strides.iter())
.map(|(i, s)| i * s)
.sum::<usize>();
let src_byte_offset = src_offset * elem_size;
let dst_byte_offset = flat * elem_size;
dst[dst_byte_offset..dst_byte_offset + elem_size]
@@ -261,7 +299,10 @@ impl Tensor {
}
// Transfer the raw storage (preserving strides/offset).
// Non-contiguous layout is preserved — the user can call contiguous() after.
let new_storage = self.storage.to_device(device).expect("device transfer failed");
let new_storage = self
.storage
.to_device(device)
.expect("device transfer failed");
Self {
storage: new_storage,
shape: self.shape.clone(),
@@ -310,14 +351,20 @@ impl Tensor {
}
}
pub fn storage(&self) -> &Storage { &self.storage }
pub fn storage(&self) -> &Storage {
&self.storage
}
}
impl std::fmt::Debug for Tensor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f, "Tensor(shape={:?}, dtype={}, device={}, contiguous={})",
self.shape.as_slice(), self.dtype, self.device(), self.is_contiguous()
f,
"Tensor(shape={:?}, dtype={}, device={}, contiguous={})",
self.shape.as_slice(),
self.dtype,
self.device(),
self.is_contiguous()
)
}
}

View File

@@ -32,7 +32,11 @@ fn test_zeros_and_ones() {
#[test]
fn test_bf16_tensor() {
let data: Vec<bf16> = vec![bf16::from_f32(1.0), bf16::from_f32(2.5), bf16::from_f32(-3.0)];
let data: Vec<bf16> = vec![
bf16::from_f32(1.0),
bf16::from_f32(2.5),
bf16::from_f32(-3.0),
];
let t = Tensor::from_slice(&data, &[3]);
assert_eq!(t.dtype(), DType::BF16);
let out = t.as_slice::<bf16>();