use half::f16;
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
#[cfg(feature = "std")]
use std::vec::Vec;
#[cfg(all(not(feature = "std"), feature = "alloc"))]
use alloc::vec::Vec;
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default)]
#[repr(transparent)] pub struct Half(pub f16);
impl Half {
#[inline]
pub fn new(value: f16) -> Self {
Self(value)
}
#[inline]
pub fn from_f32(value: f32) -> Self {
Self(f16::from_f32(value))
}
#[inline]
pub fn to_f32(self) -> f32 {
self.0.to_f32()
}
}
impl From<f32> for Half {
#[inline]
fn from(value: f32) -> Self {
Half::from_f32(value)
}
}
impl From<Half> for f32 {
#[inline]
fn from(value: Half) -> Self {
value.to_f32()
}
}
impl From<f16> for Half {
#[inline]
fn from(value: f16) -> Self {
Half::new(value)
}
}
impl From<Half> for f16 {
#[inline]
fn from(value: Half) -> Self {
value.0
}
}
impl Add for Half {
type Output = Self;
#[inline]
fn add(self, rhs: Self) -> Self::Output {
Self(self.0 + rhs.0)
}
}
impl AddAssign for Half {
#[inline]
fn add_assign(&mut self, rhs: Self) {
self.0 = self.0 + rhs.0;
}
}
impl Sub for Half {
type Output = Self;
#[inline]
fn sub(self, rhs: Self) -> Self::Output {
Self(self.0 - rhs.0)
}
}
impl SubAssign for Half {
#[inline]
fn sub_assign(&mut self, rhs: Self) {
self.0 = self.0 - rhs.0;
}
}
impl Mul for Half {
type Output = Self;
#[inline]
fn mul(self, rhs: Self) -> Self::Output {
Self(self.0 * rhs.0)
}
}
impl MulAssign for Half {
#[inline]
fn mul_assign(&mut self, rhs: Self) {
self.0 = self.0 * rhs.0;
}
}
impl Div for Half {
type Output = Self;
#[inline]
fn div(self, rhs: Self) -> Self::Output {
Self(self.0 / rhs.0)
}
}
impl DivAssign for Half {
#[inline]
fn div_assign(&mut self, rhs: Self) {
self.0 = self.0 / rhs.0;
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn halfs_from_f32_slice(slice: &[f32]) -> Vec<Half> {
slice.iter().map(|&v| Half::from_f32(v)).collect()
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn f32s_from_half_slice(slice: &[Half]) -> Vec<f32> {
slice.iter().map(|&h| h.to_f32()).collect()
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn halfs_from_f16_slice(slice: &[f16]) -> Vec<Half> {
slice.iter().map(|&v| Half::new(v)).collect()
}
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn f16s_from_half_slice(slice: &[Half]) -> Vec<f16> {
slice.iter().map(|&h| h.0).collect()
}
pub fn halfs_from_f32_array<const N: usize>(arr: [f32; N]) -> [Half; N] {
let mut out: [Half; N] = [Half::from_f32(0.0); N];
for (i, v) in arr.iter().enumerate() {
out[i] = Half::from_f32(*v);
}
out
}
pub fn f32s_from_half_array<const N: usize>(arr: [Half; N]) -> [f32; N] {
let mut out: [f32; N] = [0.0; N];
for (i, h) in arr.iter().enumerate() {
out[i] = h.to_f32();
}
out
}
pub fn halfs_from_f16_array<const N: usize>(arr: [f16; N]) -> [Half; N] {
let mut out: [Half; N] = [Half::from_f32(0.0); N];
for (i, v) in arr.iter().enumerate() {
out[i] = Half::new(*v);
}
out
}
pub fn f16s_from_half_array<const N: usize>(arr: [Half; N]) -> [f16; N] {
let mut out: [f16; N] = [f16::from_f32(0.0); N];
for (i, h) in arr.iter().enumerate() {
out[i] = h.0;
}
out
}