use half::prelude::HalfFloatSliceExt;
use crate::prelude::*;
#[derive(Copy, Clone, Debug)]
pub enum Sample {
F16(f16),
F32(f32),
U32(u32),
}
impl Sample {
pub fn f32(f32: f32) -> Self {
Sample::F32(f32)
}
pub fn f16(f16: f16) -> Self {
Sample::F16(f16)
}
pub fn u32(u32: u32) -> Self {
Sample::U32(u32)
}
#[inline]
pub fn to_f16(self) -> f16 {
match self {
Sample::F16(sample) => sample,
Sample::F32(sample) => f16::from_f32(sample),
Sample::U32(sample) => f16::from_f32(sample as f32),
}
}
#[inline]
pub fn to_f32(self) -> f32 {
match self {
Sample::F32(sample) => sample,
Sample::F16(sample) => sample.to_f32(),
Sample::U32(sample) => sample as f32,
}
}
#[inline]
pub fn to_u32(self) -> u32 {
match self {
Sample::F16(sample) => sample.to_f32() as u32,
Sample::F32(sample) => sample as u32,
Sample::U32(sample) => sample,
}
}
#[inline]
pub fn is_nan(self) -> bool {
match self {
Sample::F16(value) => value.is_nan(),
Sample::F32(value) => value.is_nan(),
Sample::U32(_) => false,
}
}
#[inline]
pub fn is_zero(&self) -> bool {
match *self {
Sample::F16(value) => value == f16::ZERO || value == f16::NEG_ZERO,
Sample::F32(value) => value == 0.0,
Sample::U32(value) => value == 0,
}
}
}
impl PartialEq for Sample {
fn eq(&self, other: &Self) -> bool {
match *self {
Self::F16(num) => num == other.to_f16(),
Self::F32(num) => num == other.to_f32(),
Self::U32(num) => num == other.to_u32(),
}
}
}
impl Default for Sample {
fn default() -> Self {
Self::F32(0.0)
}
}
impl From<f16> for Sample {
#[inline]
fn from(f: f16) -> Self {
Self::F16(f)
}
}
impl From<f32> for Sample {
#[inline]
fn from(f: f32) -> Self {
Self::F32(f)
}
}
impl From<u32> for Sample {
#[inline]
fn from(f: u32) -> Self {
Self::U32(f)
}
}
impl<T> From<Option<T>> for Sample
where
T: Into<Self> + Default,
{
#[inline]
fn from(num: Option<T>) -> Self {
num.unwrap_or_default().into()
}
}
impl From<Sample> for f16 {
#[inline]
fn from(s: Sample) -> Self {
s.to_f16()
}
}
impl From<Sample> for f32 {
#[inline]
fn from(s: Sample) -> Self {
s.to_f32()
}
}
impl From<Sample> for u32 {
#[inline]
fn from(s: Sample) -> Self {
s.to_u32()
}
}
pub trait FromNativeSample: Sized + Copy + Default + 'static {
fn from_f16(value: f16) -> Self;
fn from_f32(value: f32) -> Self;
fn from_u32(value: u32) -> Self;
#[inline]
fn from_f16s(from: &[f16], to: &mut [Self]) {
assert_eq!(from.len(), to.len(), "slices must have the same length");
for (from, to) in from.iter().zip(to.iter_mut()) {
*to = Self::from_f16(*from);
}
}
#[inline]
fn from_f32s(from: &[f32], to: &mut [Self]) {
assert_eq!(from.len(), to.len(), "slices must have the same length");
for (from, to) in from.iter().zip(to.iter_mut()) {
*to = Self::from_f32(*from);
}
}
#[inline]
fn from_u32s(from: &[u32], to: &mut [Self]) {
assert_eq!(from.len(), to.len(), "slices must have the same length");
for (from, to) in from.iter().zip(to.iter_mut()) {
*to = Self::from_u32(*from);
}
}
}
impl FromNativeSample for f32 {
#[inline]
fn from_f16(value: f16) -> Self {
value.to_f32()
}
#[inline]
fn from_f32(value: f32) -> Self {
value
}
#[inline]
fn from_u32(value: u32) -> Self {
value as Self
}
#[inline]
fn from_f16s(from: &[f16], to: &mut [Self]) {
from.convert_to_f32_slice(to);
}
}
impl FromNativeSample for u32 {
#[inline]
fn from_f16(value: f16) -> Self {
value.to_f32() as Self
}
#[inline]
fn from_f32(value: f32) -> Self {
value as Self
}
#[inline]
fn from_u32(value: u32) -> Self {
value
}
}
impl FromNativeSample for f16 {
#[inline]
fn from_f16(value: f16) -> Self {
value
}
#[inline]
fn from_f32(value: f32) -> Self {
Self::from_f32(value)
}
#[inline]
fn from_u32(value: u32) -> Self {
Self::from_f32(value as f32)
}
#[inline]
fn from_f32s(from: &[f32], to: &mut [Self]) {
to.convert_from_f32_slice(from);
}
}
impl FromNativeSample for Sample {
#[inline]
fn from_f16(value: f16) -> Self {
Self::from(value)
}
#[inline]
fn from_f32(value: f32) -> Self {
Self::from(value)
}
#[inline]
fn from_u32(value: u32) -> Self {
Self::from(value)
}
}
pub trait IntoNativeSample: Copy + Default + Sync + 'static {
fn to_f16(&self) -> f16;
fn to_f32(&self) -> f32;
fn to_u32(&self) -> u32;
}
impl IntoNativeSample for f16 {
fn to_f16(&self) -> f16 {
Self::from_f16(*self)
}
fn to_f32(&self) -> f32 {
f32::from_f16(*self)
}
fn to_u32(&self) -> u32 {
u32::from_f16(*self)
}
}
impl IntoNativeSample for f32 {
fn to_f16(&self) -> f16 {
f16::from_f32(*self)
}
fn to_f32(&self) -> f32 {
Self::from_f32(*self)
}
fn to_u32(&self) -> u32 {
u32::from_f32(*self)
}
}
impl IntoNativeSample for u32 {
fn to_f16(&self) -> f16 {
f16::from_u32(*self)
}
fn to_f32(&self) -> f32 {
f32::from_u32(*self)
}
fn to_u32(&self) -> u32 {
Self::from_u32(*self)
}
}
impl IntoNativeSample for Sample {
fn to_f16(&self) -> f16 {
Self::to_f16(*self)
}
fn to_f32(&self) -> f32 {
Self::to_f32(*self)
}
fn to_u32(&self) -> u32 {
Self::to_u32(*self)
}
}