hpt 0.1.3

High Performance Tensor (HPT) - A fast, efficient, and user-friendly tensor computation library for Rust
Documentation
use crate::backend::Cpu;
use crate::ops::Random;
use crate::tensor_base::_Tensor;
use hpt_allocator::traits::Allocator;
use hpt_allocator::traits::AllocatorOutputRetrive;
use hpt_common::{error::base::TensorError, shape::shape::Shape};
use hpt_traits::ops::creation::TensorCreator;
use hpt_traits::ops::random::RandomInt;
use hpt_traits::tensor::TensorLike;
use hpt_traits::tensor::{CommonBounds, TensorInfo};
use hpt_types::into_scalar::Cast;
use rand_distr::{
    uniform::SampleUniform, Distribution, Exp1, Normal, NormalInverseGaussian, Open01,
    OpenClosed01, StandardNormal, StandardUniform, Uniform,
};
use rayon::iter::{IntoParallelIterator, ParallelIterator};

impl<T, const DEVICE: usize, A> Random for _Tensor<T, Cpu, DEVICE, A>
where
    T: CommonBounds + SampleUniform + num::Float + rand_distr::num_traits::FloatConst,
    <T as SampleUniform>::Sampler: Sync,
    StandardNormal: Distribution<T>,
    Open01: Distribution<T>,
    Exp1: Distribution<T>,
    OpenClosed01: Distribution<T>,
    StandardUniform: Distribution<T>,
    A: Allocator,
    A::Output: AllocatorOutputRetrive,
{
    type Meta = T;
    fn randn<S: Into<Shape>>(shape: S) -> Result<Self, TensorError> {
        let res_shape = Shape::from(shape.into());
        let mut ret = Self::empty(res_shape)?;
        let normal = Normal::new(T::from(0.0).unwrap(), T::from(1.0).unwrap())?;
        ret.as_raw_mut().into_par_iter().for_each_init(
            || rand::rng(),
            |rng, x| {
                let rand_num = normal.sample(rng);
                *x = rand_num;
            },
        );
        Ok(ret)
    }

    fn randn_like(&self) -> Result<Self, TensorError> {
        Self::randn(self.shape())
    }

    fn rand<S: Into<Shape>>(
        shape: S,
        low: Self::Meta,
        high: Self::Meta,
    ) -> Result<Self, TensorError> {
        let res_shape = Shape::from(shape.into());
        let mut ret = Self::empty(res_shape)?;
        let normal = Uniform::new(low, high)?;
        ret.as_raw_mut().into_par_iter().for_each_init(
            || rand::rng(),
            |rng, x| {
                let rand_num = normal.sample(rng);
                *x = rand_num;
            },
        );
        Ok(ret)
    }

    fn rand_like(&self, low: Self::Meta, high: Self::Meta) -> Result<Self, TensorError> {
        _Tensor::rand(self.shape().clone(), low, high)
    }

    fn beta<S: Into<Shape>>(a: Self::Meta, b: Self::Meta, shape: S) -> Result<Self, TensorError> {
        let res_shape = Shape::from(shape.into());
        let mut ret = Self::empty(res_shape)?;
        let normal = rand_distr::Beta::new(a, b)?;
        ret.as_raw_mut().into_par_iter().for_each_init(
            || rand::rng(),
            |rng, x| {
                let rand_num = normal.sample(rng);
                *x = rand_num;
            },
        );
        Ok(ret)
    }

    fn beta_like(&self, a: Self::Meta, b: Self::Meta) -> Result<Self, TensorError> {
        _Tensor::beta(a, b, self.shape().clone())
    }

    fn chisquare<S: Into<Shape>>(df: Self::Meta, shape: S) -> Result<Self, TensorError> {
        let res_shape = Shape::from(shape.into());
        let mut ret = Self::empty(res_shape)?;
        let normal = rand_distr::ChiSquared::new(df)?;
        ret.as_raw_mut().into_par_iter().for_each_init(
            || rand::rng(),
            |rng, x| {
                let rand_num = normal.sample(rng);
                *x = rand_num;
            },
        );
        Ok(ret)
    }

    fn chisquare_like(&self, df: Self::Meta) -> Result<Self, TensorError> {
        _Tensor::chisquare(df, self.shape().clone())
    }

    fn exponential<S: Into<Shape>>(lambda: Self::Meta, shape: S) -> Result<Self, TensorError> {
        let res_shape = Shape::from(shape.into());
        let mut ret = Self::empty(res_shape)?;
        let normal = rand_distr::Exp::new(lambda)?;
        ret.as_raw_mut().into_par_iter().for_each_init(
            || rand::rng(),
            |rng, x| {
                let rand_num = normal.sample(rng);
                *x = rand_num;
            },
        );
        Ok(ret)
    }

    fn exponential_like(&self, lambda: Self::Meta) -> Result<Self, TensorError> {
        _Tensor::exponential(lambda, self.shape().clone())
    }

    fn gamma<S: Into<Shape>>(
        gamma_shape: Self::Meta,
        scale: Self::Meta,
        shape: S,
    ) -> Result<Self, TensorError> {
        let res_shape = Shape::from(shape.into());
        let mut ret = Self::empty(res_shape)?;
        let normal = rand_distr::Gamma::new(gamma_shape, scale)?;
        ret.as_raw_mut().into_par_iter().for_each_init(
            || rand::rng(),
            |rng, x| {
                let rand_num = normal.sample(rng);
                *x = rand_num;
            },
        );
        Ok(ret)
    }

    fn gamma_like(&self, gamma_shape: Self::Meta, scale: Self::Meta) -> Result<Self, TensorError> {
        _Tensor::gamma(gamma_shape, scale, self.shape().clone())
    }

    fn gumbel<S: Into<Shape>>(
        mu: Self::Meta,
        beta: Self::Meta,
        shape: S,
    ) -> Result<Self, TensorError> {
        let res_shape = Shape::from(shape.into());
        let mut ret = Self::empty(res_shape)?;
        let normal = rand_distr::Gumbel::new(mu, beta)?;
        ret.as_raw_mut().into_par_iter().for_each_init(
            || rand::rng(),
            |rng, x| {
                let rand_num = normal.sample(rng);
                *x = rand_num;
            },
        );
        Ok(ret)
    }

    fn gumbel_like(&self, mu: Self::Meta, beta: Self::Meta) -> Result<Self, TensorError> {
        _Tensor::gumbel(mu, beta, self.shape().clone())
    }

    fn lognormal<S: Into<Shape>>(
        mean: Self::Meta,
        std: Self::Meta,
        shape: S,
    ) -> Result<Self, TensorError> {
        let res_shape = Shape::from(shape.into());
        let mut ret = Self::empty(res_shape)?;
        let normal = rand_distr::LogNormal::new(mean, std)?;
        ret.as_raw_mut().into_par_iter().for_each_init(
            || rand::rng(),
            |rng, x| {
                let rand_num = normal.sample(rng);
                *x = rand_num;
            },
        );
        Ok(ret)
    }

    fn lognormal_like(&self, mean: Self::Meta, std: Self::Meta) -> Result<Self, TensorError> {
        _Tensor::lognormal(mean, std, self.shape().clone())
    }

    fn normal_gaussian<S: Into<Shape>>(
        mean: Self::Meta,
        std: Self::Meta,
        shape: S,
    ) -> Result<Self, TensorError> {
        let res_shape = Shape::from(shape.into());
        let mut ret = Self::empty(res_shape)?;
        let normal = NormalInverseGaussian::new(mean, std)?;
        ret.as_raw_mut().into_par_iter().for_each_init(
            || rand::rng(),
            |rng, x| {
                *x = normal.sample(rng);
            },
        );
        Ok(ret)
    }

    fn normal_gaussian_like(&self, mean: Self::Meta, std: Self::Meta) -> Result<Self, TensorError> {
        _Tensor::normal_gaussian(mean, std, self.shape().clone())
    }

    fn pareto<S: Into<Shape>>(
        pareto_shape: Self::Meta,
        a: Self::Meta,
        shape: S,
    ) -> Result<Self, TensorError> {
        let res_shape = Shape::from(shape.into());
        let mut ret = Self::empty(res_shape)?;
        let pareto = rand_distr::Pareto::new(a, pareto_shape)?;
        ret.as_raw_mut().into_par_iter().for_each_init(
            || rand::rng(),
            |rng, x| {
                *x = pareto.sample(rng);
            },
        );
        Ok(ret)
    }

    fn pareto_like(&self, pareto_shape: Self::Meta, a: Self::Meta) -> Result<Self, TensorError> {
        _Tensor::pareto(pareto_shape, a, self.shape().clone())
    }

    fn poisson<S: Into<Shape>>(lambda: Self::Meta, shape: S) -> Result<Self, TensorError> {
        let res_shape = Shape::from(shape.into());
        let mut ret = Self::empty(res_shape)?;
        let poisson = rand_distr::Poisson::new(lambda)?;
        ret.as_raw_mut().into_par_iter().for_each_init(
            || rand::rng(),
            |rng, x| {
                *x = poisson.sample(rng);
            },
        );
        Ok(ret)
    }

    fn poisson_like(&self, lambda: Self::Meta) -> Result<Self, TensorError> {
        _Tensor::poisson(lambda, self.shape().clone())
    }

    fn weibull<S: Into<Shape>>(
        a: Self::Meta,
        b: Self::Meta,
        shape: S,
    ) -> Result<Self, TensorError> {
        let res_shape = Shape::from(shape.into());
        let mut ret = Self::empty(res_shape)?;
        let weibull = rand_distr::Weibull::new(a, b)?;
        ret.as_raw_mut().into_par_iter().for_each_init(
            || rand::rng(),
            |rng, x| {
                *x = weibull.sample(rng);
            },
        );
        Ok(ret)
    }

    fn weibull_like(&self, a: Self::Meta, b: Self::Meta) -> Result<Self, TensorError> {
        _Tensor::weibull(a, b, self.shape().clone())
    }

    fn zipf<S: Into<Shape>>(n: Self::Meta, a: Self::Meta, shape: S) -> Result<Self, TensorError> {
        let res_shape = Shape::from(shape.into());
        let mut ret = Self::empty(res_shape)?;
        let zipf = rand_distr::Zipf::new(n, a)?;
        ret.as_raw_mut().into_par_iter().for_each_init(
            || rand::rng(),
            |rng, x| {
                *x = zipf.sample(rng);
            },
        );
        Ok(ret)
    }

    fn zipf_like(&self, n: Self::Meta, a: Self::Meta) -> Result<Self, TensorError> {
        _Tensor::zipf(n, a, self.shape().clone())
    }

    fn triangular<S: Into<Shape>>(
        low: Self::Meta,
        high: Self::Meta,
        mode: Self::Meta,
        shape: S,
    ) -> Result<Self, TensorError> {
        let res_shape = Shape::from(shape.into());
        let mut ret = Self::empty(res_shape)?;
        let triangular = rand_distr::Triangular::new(low, high, mode)?;
        ret.as_raw_mut().into_par_iter().for_each_init(
            || rand::rng(),
            |rng, x| {
                *x = triangular.sample(rng);
            },
        );
        Ok(ret)
    }

    fn triangular_like(
        &self,
        low: Self::Meta,
        high: Self::Meta,
        mode: Self::Meta,
    ) -> Result<Self, TensorError> {
        _Tensor::triangular(low, high, mode, self.shape().clone())
    }

    fn bernoulli<S: Into<Shape>>(shape: S, p: Self::Meta) -> Result<Self, TensorError>
    where
        T: Cast<f64>,
        bool: Cast<T>,
    {
        let res_shape = Shape::from(shape.into());
        let mut ret = Self::empty(res_shape)?;
        let bernoulli = rand_distr::Bernoulli::new(p.cast())?;
        ret.as_raw_mut().into_par_iter().for_each_init(
            || rand::rng(),
            |rng, x| {
                *x = bernoulli.sample(rng).cast();
            },
        );
        Ok(ret)
    }
}

impl<T, const DEVICE: usize, A> RandomInt for _Tensor<T, Cpu, DEVICE, A>
where
    T: CommonBounds + SampleUniform,
    A: Allocator,
    A::Output: AllocatorOutputRetrive,
{
    type Meta = T;
    fn randint<S: Into<Shape>>(
        low: Self::Meta,
        high: Self::Meta,
        shape: S,
    ) -> Result<Self, TensorError>
    where
        <T as SampleUniform>::Sampler: Sync,
    {
        let res_shape = Shape::from(shape.into());
        let mut ret = Self::empty(res_shape)?;
        let normal = Uniform::new(low, high)?;
        ret.as_raw_mut().into_par_iter().for_each_init(
            || rand::rng(),
            |rng, x| {
                let rand_num = normal.sample(rng);
                *x = rand_num;
            },
        );
        Ok(ret)
    }

    fn randint_like(&self, low: Self::Meta, high: Self::Meta) -> Result<Self, TensorError>
    where
        <T as SampleUniform>::Sampler: Sync,
    {
        _Tensor::randint(low, high, self.shape().clone())
    }
}