use std::{
fmt::Debug,
ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub, SubAssign},
};
pub trait Scalar: Copy + Send + Sync + Debug + 'static {
const ZERO: Self;
}
pub trait Real:
Scalar
+ PartialOrd
+ Add<Output = Self>
+ Sub<Output = Self>
+ Mul<Output = Self>
+ Div<Output = Self>
+ Neg<Output = Self>
+ AddAssign
+ SubAssign
+ MulAssign
{
const ONE: Self;
#[must_use]
fn from_f64(x: f64) -> Self;
fn to_f64(self) -> f64;
#[must_use]
fn sqrt(self) -> Self;
#[must_use]
fn abs(self) -> Self;
#[must_use]
fn tanh(self) -> Self;
#[must_use]
fn powi(self, n: i32) -> Self;
#[must_use]
fn max(self, other: Self) -> Self;
#[must_use]
fn min(self, other: Self) -> Self;
}
macro_rules! impl_real {
($t:ty) => {
impl Scalar for $t {
const ZERO: Self = 0.0;
}
impl Real for $t {
const ONE: Self = 1.0;
#[inline(always)]
fn from_f64(x: f64) -> Self {
x as $t
}
#[inline(always)]
fn to_f64(self) -> f64 {
self as f64
}
#[inline(always)]
fn sqrt(self) -> Self {
self.sqrt()
}
#[inline(always)]
fn abs(self) -> Self {
self.abs()
}
#[inline(always)]
fn tanh(self) -> Self {
self.tanh()
}
#[inline(always)]
fn powi(self, n: i32) -> Self {
self.powi(n)
}
#[inline(always)]
fn max(self, other: Self) -> Self {
<$t>::max(self, other)
}
#[inline(always)]
fn min(self, other: Self) -> Self {
<$t>::min(self, other)
}
}
};
}
impl_real!(f32);
impl_real!(f64);
pub trait StorageBackend<T: Scalar>: Send + Sync {
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn as_slice(&self) -> &[T];
fn as_mut_slice(&mut self) -> &mut [T];
}
pub trait Allocator<T: Scalar>: Send + Sync {
type Storage: StorageBackend<T>;
fn allocate(&self, len: usize) -> Self::Storage;
}
#[derive(Debug, Clone)]
pub struct DenseStorage<T: Scalar> {
data: Box<[T]>,
}
impl<T: Scalar> StorageBackend<T> for DenseStorage<T> {
#[inline(always)]
fn len(&self) -> usize {
self.data.len()
}
#[inline(always)]
fn as_slice(&self) -> &[T] {
&self.data
}
#[inline(always)]
fn as_mut_slice(&mut self) -> &mut [T] {
&mut self.data
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct SystemAllocator;
impl<T: Scalar> Allocator<T> for SystemAllocator {
type Storage = DenseStorage<T>;
fn allocate(&self, len: usize) -> Self::Storage {
DenseStorage {
data: vec![T::ZERO; len].into_boxed_slice(),
}
}
}