use serde::{Deserialize, Serialize};
use trustformers_core::TrustformersError as CoreError;
pub type Result<T> = std::result::Result<T, CoreError>;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Tensor<T> {
data: Vec<T>,
shape: Vec<usize>,
}
impl<T: Clone> Tensor<T> {
pub fn from_slice(data: &[T], shape: &[usize]) -> Result<Self> {
Ok(Self {
data: data.to_vec(),
shape: shape.to_vec(),
})
}
pub fn data(&self) -> &[T] {
&self.data
}
pub fn shape(&self) -> &[usize] {
&self.shape
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
}
impl Tensor<f32> {
pub fn gt_scalar(&self, scalar: f32) -> Result<Tensor<f32>> {
let result_data: Vec<f32> =
self.data.iter().map(|x| if *x > scalar { 1.0 } else { 0.0 }).collect();
Tensor::from_slice(&result_data, &self.shape)
}
pub fn gt_scalar_bool(&self, scalar: f32) -> Vec<bool> {
self.data.iter().map(|x| *x > scalar).collect()
}
pub fn data_cloned(&self) -> Vec<f32> {
self.data.clone()
}
}
pub struct SimdOps {
vector_width: usize,
}
impl SimdOps {
pub fn new_with_width(_width: usize) -> Result<Self> {
Ok(Self { vector_width: 256 })
}
pub fn vector_width(&self) -> usize {
self.vector_width
}
pub fn correlation(&self, _a: &Tensor<f32>, _b: &Tensor<f32>) -> Result<f32> {
Ok(0.5) }
pub fn abs(&self, tensor: &Tensor<f32>) -> Result<Tensor<f32>> {
let abs_data: Vec<f32> = tensor.data.iter().map(|x| x.abs()).collect();
Tensor::from_slice(&abs_data, &tensor.shape)
}
pub fn add(&self, a: &Tensor<f32>, b: &Tensor<f32>) -> Result<Tensor<f32>> {
let result_data: Vec<f32> = a.data.iter().zip(b.data.iter()).map(|(x, y)| x + y).collect();
Tensor::from_slice(&result_data, &a.shape)
}
pub fn sub(&self, a: &Tensor<f32>, b: &Tensor<f32>) -> Result<Tensor<f32>> {
let result_data: Vec<f32> = a.data.iter().zip(b.data.iter()).map(|(x, y)| x - y).collect();
Tensor::from_slice(&result_data, &a.shape)
}
pub fn mul(&self, a: &Tensor<f32>, b: &Tensor<f32>) -> Result<Tensor<f32>> {
let result_data: Vec<f32> = a.data.iter().zip(b.data.iter()).map(|(x, y)| x * y).collect();
Tensor::from_slice(&result_data, &a.shape)
}
pub fn sub_scalar(&self, tensor: &Tensor<f32>, scalar: f32) -> Result<Tensor<f32>> {
let result_data: Vec<f32> = tensor.data.iter().map(|x| x - scalar).collect();
Tensor::from_slice(&result_data, &tensor.shape)
}
pub fn add_scalar(&self, tensor: &Tensor<f32>, scalar: f32) -> Result<Tensor<f32>> {
let result_data: Vec<f32> = tensor.data.iter().map(|x| x + scalar).collect();
Tensor::from_slice(&result_data, &tensor.shape)
}
pub fn mul_scalar(&self, tensor: &Tensor<f32>, scalar: f32) -> Result<Tensor<f32>> {
let result_data: Vec<f32> = tensor.data.iter().map(|x| x * scalar).collect();
Tensor::from_slice(&result_data, &tensor.shape)
}
pub fn div_scalar(&self, tensor: &Tensor<f32>, scalar: f32) -> Result<Tensor<f32>> {
let result_data: Vec<f32> = tensor.data.iter().map(|x| x / scalar).collect();
Tensor::from_slice(&result_data, &tensor.shape)
}
pub fn pow_scalar(&self, tensor: &Tensor<f32>, exponent: f32) -> Result<Tensor<f32>> {
let result_data: Vec<f32> = tensor.data.iter().map(|x| x.powf(exponent)).collect();
Tensor::from_slice(&result_data, &tensor.shape)
}
}
pub struct LinalgOps;
impl LinalgOps {
pub fn new() -> Self {
Self
}
}
impl Default for LinalgOps {
fn default() -> Self {
Self::new()
}
}
pub struct StatisticalOps;
impl StatisticalOps {
pub fn new() -> Self {
Self
}
pub fn simd_mean(&self, tensor: &Tensor<f32>) -> Result<f32> {
let sum: f32 = tensor.data.iter().sum();
Ok(sum / tensor.data.len() as f32)
}
pub fn simd_variance(&self, tensor: &Tensor<f32>) -> Result<f32> {
let mean = self.simd_mean(tensor)?;
let variance =
tensor.data.iter().map(|x| (x - mean).powi(2)).sum::<f32>() / tensor.data.len() as f32;
Ok(variance)
}
pub fn simd_std(&self, tensor: &Tensor<f32>) -> Result<f32> {
Ok(self.simd_variance(tensor)?.sqrt())
}
pub fn simd_sum(&self, tensor: &Tensor<f32>) -> Result<f32> {
Ok(tensor.data.iter().sum())
}
pub fn simd_minmax(&self, tensor: &Tensor<f32>) -> Result<(f32, f32)> {
let min = tensor.data.iter().fold(f32::INFINITY, |a, &b| a.min(b));
let max = tensor.data.iter().fold(f32::NEG_INFINITY, |a, &b| a.max(b));
Ok((min, max))
}
pub fn simd_quantile(&self, tensor: &Tensor<f32>, quantile: f32) -> Result<f32> {
let mut sorted_data = tensor.data.clone();
sorted_data.sort_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal));
let index = ((sorted_data.len() - 1) as f32 * quantile) as usize;
Ok(sorted_data[index.min(sorted_data.len() - 1)])
}
}
impl Default for StatisticalOps {
fn default() -> Self {
Self::new()
}
}
pub struct DistributionOps;
impl DistributionOps {
pub fn new() -> Self {
Self
}
}
impl Default for DistributionOps {
fn default() -> Self {
Self::new()
}
}
pub struct DefaultRng;
impl DefaultRng {
pub fn new() -> Self {
Self
}
pub fn gen<T>(&mut self) -> T
where
T: RandomGenerate,
{
T::generate()
}
pub fn random<T>(&mut self) -> T
where
T: RandomGenerate,
{
T::generate()
}
}
impl Default for DefaultRng {
fn default() -> Self {
Self::new()
}
}
pub trait RandomGenerate {
fn generate() -> Self;
}
impl RandomGenerate for f32 {
fn generate() -> Self {
fastrand::f32()
}
}
impl RandomGenerate for f64 {
fn generate() -> Self {
fastrand::f64()
}
}
impl RandomGenerate for u32 {
fn generate() -> Self {
fastrand::u32(..)
}
}
impl RandomGenerate for u64 {
fn generate() -> Self {
fastrand::u64(..)
}
}
impl RandomGenerate for usize {
fn generate() -> Self {
fastrand::usize(..)
}
}
impl<T> Tensor<T> {
pub fn to_vec(&self) -> &Vec<T> {
&self.data
}
}
pub mod random {
pub mod legacy {
pub fn f32() -> f32 {
fastrand::f32()
}
pub fn f64() -> f64 {
fastrand::f64()
}
pub fn usize_range(min: usize, max: usize) -> usize {
if max <= min {
min
} else {
fastrand::usize(min..max)
}
}
}
}