#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum ComplexToRealStrategy {
RealPart,
ImaginaryPart,
Magnitude,
Phase,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum M0Interpretation {
Signed,
Unsigned,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum Mode {
Int8 = 0,
Int16 = 1,
Float32 = 2,
Int16Complex = 3,
Float32Complex = 4,
Uint16 = 6,
Float16 = 12,
Packed4Bit = 101,
}
impl Mode {
#[inline]
pub const fn as_i32(self) -> i32 {
self as i32
}
#[inline]
pub fn from_i32(mode: i32) -> Option<Self> {
match mode {
0 => Some(Self::Int8),
1 => Some(Self::Int16),
2 => Some(Self::Float32),
3 => Some(Self::Int16Complex),
4 => Some(Self::Float32Complex),
6 => Some(Self::Uint16),
12 => Some(Self::Float16),
101 => Some(Self::Packed4Bit),
_ => None,
}
}
#[inline]
pub fn byte_size(&self) -> usize {
match self {
Self::Int8 => 1,
Self::Int16 => 2,
Self::Float32 => 4,
Self::Int16Complex => 4, Self::Float32Complex => 8, Self::Uint16 => 2,
Self::Float16 => 2,
Self::Packed4Bit => 1, }
}
#[inline]
pub fn is_complex(&self) -> bool {
matches!(self, Self::Int16Complex | Self::Float32Complex)
}
#[inline]
pub fn is_integer(&self) -> bool {
matches!(
self,
Self::Int8 | Self::Int16 | Self::Int16Complex | Self::Uint16 | Self::Packed4Bit
)
}
#[inline]
pub fn is_float(&self) -> bool {
matches!(self, Self::Float32 | Self::Float32Complex | Self::Float16)
}
#[inline]
pub fn byte_size_for_count(&self, n: usize) -> usize {
match self {
Self::Packed4Bit => n.div_ceil(2),
_ => n * self.byte_size(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
#[repr(C)]
pub struct Int16Complex {
pub real: i16,
pub imag: i16,
}
impl Int16Complex {
#[inline]
pub fn to_real(&self, strategy: ComplexToRealStrategy) -> f32 {
match strategy {
ComplexToRealStrategy::RealPart => self.real as f32,
ComplexToRealStrategy::ImaginaryPart => self.imag as f32,
ComplexToRealStrategy::Magnitude => {
let r = self.real as f32;
let i = self.imag as f32;
(r * r + i * i).sqrt()
}
ComplexToRealStrategy::Phase => (self.imag as f32).atan2(self.real as f32),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[repr(C)]
pub struct Float32Complex {
pub real: f32,
pub imag: f32,
}
impl Default for Float32Complex {
fn default() -> Self {
Self {
real: 0.0,
imag: 0.0,
}
}
}
impl Float32Complex {
#[inline]
pub fn to_real(&self, strategy: ComplexToRealStrategy) -> f32 {
match strategy {
ComplexToRealStrategy::RealPart => self.real,
ComplexToRealStrategy::ImaginaryPart => self.imag,
ComplexToRealStrategy::Magnitude => {
(self.real * self.real + self.imag * self.imag).sqrt()
}
ComplexToRealStrategy::Phase => self.imag.atan2(self.real),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct Packed4Bit(pub(crate) u8);
impl Packed4Bit {
pub fn new(value: u8) -> Self {
Self(value)
}
pub fn first(&self) -> u8 {
self.0 & 0x0F
}
pub fn second(&self) -> u8 {
(self.0 >> 4) & 0x0F
}
}
pub trait Voxel:
crate::engine::codec::EndianCodec + Copy + Send + Sync + Default + 'static
{
const MODE: Mode;
}
impl Voxel for i8 {
const MODE: Mode = Mode::Int8;
}
impl Voxel for i16 {
const MODE: Mode = Mode::Int16;
}
impl Voxel for f32 {
const MODE: Mode = Mode::Float32;
}
impl Voxel for Int16Complex {
const MODE: Mode = Mode::Int16Complex;
}
impl Voxel for Float32Complex {
const MODE: Mode = Mode::Float32Complex;
}
impl Voxel for u16 {
const MODE: Mode = Mode::Uint16;
}
#[cfg(feature = "f16")]
impl Voxel for crate::f16 {
const MODE: Mode = Mode::Float16;
}