pub trait Scalar: Copy + Send + Sync + PartialEq + 'static {
type Acc: Scalar<Acc = Self::Acc>;
const ZERO: Self;
const ONE: Self;
}
impl Scalar for f32 {
type Acc = f32;
const ZERO: Self = 0.0;
const ONE: Self = 1.0;
}
impl Scalar for f64 {
type Acc = f64;
const ZERO: Self = 0.0;
const ONE: Self = 1.0;
}
#[cfg(feature = "half")]
impl Scalar for half::f16 {
type Acc = f32;
const ZERO: Self = half::f16::from_bits(0x0000);
const ONE: Self = half::f16::from_bits(0x3C00);
}
#[cfg(feature = "half")]
impl Scalar for half::bf16 {
type Acc = f32;
const ZERO: Self = half::bf16::from_bits(0x0000);
const ONE: Self = half::bf16::from_bits(0x3F80);
}
#[cfg(feature = "int8")]
impl Scalar for i8 {
type Acc = i32;
const ZERO: Self = 0;
const ONE: Self = 1;
}
#[cfg(feature = "int8")]
impl Scalar for i32 {
type Acc = i32;
const ZERO: Self = 0;
const ONE: Self = 1;
}
#[cfg(feature = "int8")]
impl Scalar for u8 {
type Acc = i32;
const ZERO: Self = 0;
const ONE: Self = 1;
}
#[cfg(feature = "complex")]
impl Scalar for num_complex::Complex<f32> {
type Acc = Self;
const ZERO: Self = num_complex::Complex::new(0.0, 0.0);
const ONE: Self = num_complex::Complex::new(1.0, 0.0);
}
#[cfg(feature = "complex")]
impl Scalar for num_complex::Complex<f64> {
type Acc = Self;
const ZERO: Self = num_complex::Complex::new(0.0, 0.0);
const ONE: Self = num_complex::Complex::new(1.0, 0.0);
}
#[cfg(feature = "complex")]
impl Float for num_complex::Complex<f32> {
#[inline(always)]
fn mul_add(self, b: Self, c: Self) -> Self {
self * b + c
}
}
#[cfg(feature = "complex")]
impl Float for num_complex::Complex<f64> {
#[inline(always)]
fn mul_add(self, b: Self, c: Self) -> Self {
self * b + c
}
}
#[cfg(feature = "complex")]
pub trait ComplexFloat: Float<Acc = Self> {
type Real: Float<Acc = Self::Real>;
fn re(self) -> Self::Real;
fn im(self) -> Self::Real;
fn new(re: Self::Real, im: Self::Real) -> Self;
}
#[cfg(feature = "complex")]
impl ComplexFloat for num_complex::Complex<f32> {
type Real = f32;
#[inline(always)]
fn re(self) -> f32 {
self.re
}
#[inline(always)]
fn im(self) -> f32 {
self.im
}
#[inline(always)]
fn new(re: f32, im: f32) -> Self {
num_complex::Complex::new(re, im)
}
}
#[cfg(feature = "complex")]
impl ComplexFloat for num_complex::Complex<f64> {
type Real = f64;
#[inline(always)]
fn re(self) -> f64 {
self.re
}
#[inline(always)]
fn im(self) -> f64 {
self.im
}
#[inline(always)]
fn new(re: f64, im: f64) -> Self {
num_complex::Complex::new(re, im)
}
}
#[cfg(feature = "half")]
pub trait NarrowFloat: Scalar<Acc = f32> {
fn widen(self) -> f32;
fn narrow(x: f32) -> Self;
}
#[cfg(feature = "half")]
impl NarrowFloat for half::f16 {
#[inline(always)]
fn widen(self) -> f32 {
#[cfg(not(miri))]
{
self.to_f32()
}
#[cfg(miri)]
{
self.to_f32_const()
}
}
#[inline(always)]
fn narrow(x: f32) -> Self {
#[cfg(not(miri))]
{
half::f16::from_f32(x)
}
#[cfg(miri)]
{
half::f16::from_f32_const(x)
}
}
}
#[cfg(feature = "half")]
impl NarrowFloat for half::bf16 {
#[inline(always)]
fn widen(self) -> f32 {
#[cfg(not(miri))]
{
self.to_f32()
}
#[cfg(miri)]
{
self.to_f32_const()
}
}
#[inline(always)]
fn narrow(x: f32) -> Self {
#[cfg(not(miri))]
{
half::bf16::from_f32(x)
}
#[cfg(miri)]
{
half::bf16::from_f32_const(x)
}
}
}
pub trait Float:
Scalar
+ core::ops::Add<Output = Self>
+ core::ops::Mul<Output = Self>
+ core::ops::Sub<Output = Self>
+ core::ops::Neg<Output = Self>
{
fn mul_add(self, b: Self, c: Self) -> Self;
}
impl Float for f32 {
#[inline(always)]
fn mul_add(self, b: Self, c: Self) -> Self {
self * b + c
}
}
impl Float for f64 {
#[inline(always)]
fn mul_add(self, b: Self, c: Self) -> Self {
self * b + c
}
}