#[cfg(feature = "burn")]
mod burn_tensor;
#[cfg(feature = "candle")]
mod candle_tensor;
use std::fmt::Debug;
use serde::{Deserialize, Serialize};
use crate::error::TensorError;
type Result<T> = std::result::Result<T, TensorError>;
pub trait R2lTensor: Clone + Send + Sync + Debug + 'static {
fn to_vec(&self) -> Result<Vec<f32>>;
fn to_shape(&self) -> Vec<usize>;
fn to_vec_and_shape(&self) -> Result<(Vec<f32>, Vec<usize>)> {
let vec = self.to_vec()?;
let shape = self.to_shape();
Ok((vec, shape))
}
fn from_slice_and_shape(data: &[f32], shape: Vec<usize>) -> Result<Self>;
fn from_vec_and_shape(data: Vec<f32>, shape: Vec<usize>) -> Result<Self> {
Self::from_slice_and_shape(&data, shape)
}
fn convert<S: R2lTensor>(s: &S) -> Result<Self> {
let (data, shape) = s.to_vec_and_shape()?;
Self::from_vec_and_shape(data, shape)
}
fn size(&self) -> usize {
self.to_shape().iter().product()
}
fn is_empty(&self) -> bool {
self.size() == 0
}
fn add(&self, other: &Self) -> Result<Self>;
fn sub(&self, other: &Self) -> Result<Self>;
fn mul(&self, other: &Self) -> Result<Self>;
fn exp(&self) -> Result<Self>;
fn clamp(&self, min: f32, max: f32) -> Result<Self>;
fn minimum(&self, other: &Self) -> Result<Self>;
fn neg(&self) -> Result<Self>;
fn mean(&self) -> Result<Self>;
fn sqr(&self) -> Result<Self>;
fn zeros(shape: Vec<usize>) -> Result<Self> {
let data = vec![0f32; shape.iter().product()];
Self::from_vec_and_shape(data, shape)
}
fn mul_scalar(&self, scalar: f32) -> Result<Self>;
fn add_multiple(tensors: &[Self]) -> Result<Self> {
if tensors.is_empty() {
return Err(TensorError::EmptyInput {
operation: "add multiple".into(),
});
}
let shape = tensors[0].to_shape();
let init = Self::zeros(shape)?;
tensors.iter().try_fold(init, |acc, elem| acc.add(elem))
}
fn mean_tensors(tensors: &[Self]) -> Result<Self> {
if tensors.is_empty() {
return Err(TensorError::EmptyInput {
operation: "mean tensors".into(),
});
}
let sum = Self::add_multiple(tensors)?;
sum.mul_scalar(1f32 / tensors.len() as f32)
}
fn var_tensors(tensors: &[Self]) -> Result<Self> {
if tensors.is_empty() {
return Err(TensorError::EmptyInput {
operation: "variance".into(),
});
}
let mean = Self::mean_tensors(tensors)?;
let diffs_sqr = tensors
.iter()
.map(|tensor| tensor.sub(&mean)?.sqr())
.collect::<Result<Vec<_>>>()?;
let diffs_sqr_sum = Self::add_multiple(&diffs_sqr)?;
diffs_sqr_sum.mul_scalar(1f32 / tensors.len() as f32)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VecTensor {
data: Vec<f32>,
shape: Vec<usize>,
}
impl VecTensor {
fn ensure_same_shape(&self, other: &Self, operation: &str) -> Result<()> {
if self.shape != other.shape {
return Err(TensorError::ShapeMismatch {
operation: operation.into(),
left: self.shape.clone(),
right: other.shape.clone(),
});
}
Ok(())
}
#[must_use]
pub fn from_vec(data: Vec<f32>) -> Self {
let shape = vec![data.len()];
Self { data, shape }
}
pub fn new(data: Vec<f32>, shape: Vec<usize>) -> Result<Self> {
let expected = shape.iter().product();
if expected != data.len() {
return Err(TensorError::InvalidShape {
shape,
expected,
actual: data.len(),
});
}
Ok(Self { data, shape })
}
#[must_use]
pub fn into_vec(self) -> Vec<f32> {
self.data
}
}
impl R2lTensor for VecTensor {
fn to_vec(&self) -> Result<Vec<f32>> {
Ok(self.data.clone())
}
fn to_shape(&self) -> Vec<usize> {
self.shape.clone()
}
fn from_slice_and_shape(data: &[f32], shape: Vec<usize>) -> Result<Self> {
Self::new(data.to_vec(), shape)
}
fn from_vec_and_shape(data: Vec<f32>, shape: Vec<usize>) -> Result<Self> {
Self::new(data, shape)
}
fn add(&self, other: &Self) -> Result<Self> {
self.ensure_same_shape(other, "add")?;
let data = self
.data
.iter()
.zip(other.data.iter())
.map(|(a, b)| a + b)
.collect();
Self::new(data, self.shape.clone())
}
fn sub(&self, other: &Self) -> Result<Self> {
self.ensure_same_shape(other, "subtract")?;
let data = self
.data
.iter()
.zip(other.data.iter())
.map(|(a, b)| a - b)
.collect();
Self::new(data, self.shape.clone())
}
fn mul(&self, other: &Self) -> Result<Self> {
self.ensure_same_shape(other, "multiply")?;
let data = self
.data
.iter()
.zip(other.data.iter())
.map(|(a, b)| a * b)
.collect();
Self::new(data, self.shape.clone())
}
fn exp(&self) -> Result<Self> {
Self::new(
self.data.iter().map(|value| value.exp()).collect(),
self.shape.clone(),
)
}
fn clamp(&self, min: f32, max: f32) -> Result<Self> {
Self::new(
self.data
.iter()
.map(|value| value.clamp(min, max))
.collect(),
self.shape.clone(),
)
}
fn minimum(&self, other: &Self) -> Result<Self> {
self.ensure_same_shape(other, "minimum")?;
let data = self
.data
.iter()
.zip(other.data.iter())
.map(|(a, b)| a.min(*b))
.collect();
Self::new(data, self.shape.clone())
}
fn neg(&self) -> Result<Self> {
Self::new(
self.data.iter().map(|value| -value).collect(),
self.shape.clone(),
)
}
fn mean(&self) -> Result<Self> {
if self.data.is_empty() {
return Err(TensorError::EmptyInput {
operation: "mean".into(),
});
}
let mean = self.data.iter().sum::<f32>() / self.data.len() as f32;
Ok(Self::from_vec(vec![mean]))
}
fn sqr(&self) -> Result<Self> {
Self::new(
self.data.iter().map(|value| value * value).collect(),
self.shape.clone(),
)
}
fn zeros(shape: Vec<usize>) -> Result<Self> {
let len = shape.iter().product();
Self::new(vec![0.0; len], shape)
}
fn mul_scalar(&self, scalar: f32) -> Result<Self> {
Self::new(
self.data.iter().map(|value| value * scalar).collect(),
self.shape.clone(),
)
}
}