#![cfg(all(feature = "half_float", any(feature = "std", feature = "alloc")))]
use gemath::*;
#[cfg(test)]
mod tests {
use super::*;
use half::f16;
const EPSILON: f32 = 1e-3;
#[test]
fn test_half_from_f32_to_f32() {
let f32_val: f32 = 0.123;
let h = Half::from_f32(f32_val);
let f32_back = h.to_f32();
assert!(
(f32_val - f32_back).abs() < EPSILON,
"Original: {}, Back: {}",
f32_val,
f32_back
);
let f32_val_neg: f32 = -3.14159;
let h_neg = Half::from_f32(f32_val_neg);
let f32_back_neg = h_neg.to_f32();
assert!(
(f32_val_neg - f32_back_neg).abs() < EPSILON,
"Original: {}, Back: {}",
f32_val_neg,
f32_back_neg
);
}
#[test]
fn test_half_from_trait_f32() {
let f32_val: f32 = 10.5;
let h: Half = f32_val.into();
let f32_back: f32 = h.into();
assert!((f32_val - f32_back).abs() < EPSILON);
}
#[test]
fn test_half_from_f16_to_f16() {
let f16_val = f16::from_f32(0.5);
let h = Half::new(f16_val);
assert_eq!(h.0, f16_val);
let f16_back: f16 = h.into();
assert_eq!(f16_back, f16_val);
}
#[test]
fn test_half_default() {
let h_def: Half = Default::default();
assert_eq!(h_def.to_f32(), 0.0);
assert_eq!(h_def.0, f16::ZERO);
}
#[test]
fn test_half_arithmetic() {
let a = Half::from_f32(1.5);
let b = Half::from_f32(2.0);
let c = Half::from_f32(-0.5);
assert!(((a + b).to_f32() - 3.5).abs() < EPSILON);
assert!(((b - a).to_f32() - 0.5).abs() < EPSILON);
assert!(((a * b).to_f32() - 3.0).abs() < EPSILON);
assert!(((b / a).to_f32() - (2.0 / 1.5)).abs() < EPSILON);
let mut x = a;
x += b;
assert!((x.to_f32() - 3.5).abs() < EPSILON);
let mut y = b;
y -= a;
assert!((y.to_f32() - 0.5).abs() < EPSILON);
let mut z = a;
z *= b;
assert!((z.to_f32() - 3.0).abs() < EPSILON);
let mut w = b;
w /= a;
assert!((w.to_f32() - (2.0 / 1.5)).abs() < EPSILON);
assert!(((a + c).to_f32() - 1.0).abs() < EPSILON);
}
#[test]
fn test_half_array_slice_conversions() {
use gemath::{
f16s_from_half_array, f16s_from_half_slice, f32s_from_half_array, f32s_from_half_slice,
halfs_from_f16_array, halfs_from_f16_slice, halfs_from_f32_array, halfs_from_f32_slice,
};
use half::f16;
let f32s = [1.0f32, -2.0, 3.5, 0.0];
let halfs = halfs_from_f32_slice(&f32s);
for (i, h) in halfs.iter().enumerate() {
assert!((h.to_f32() - f32s[i]).abs() < EPSILON);
}
let f32s_back = f32s_from_half_slice(&halfs);
for (a, b) in f32s.iter().zip(f32s_back.iter()) {
assert!((*a - *b).abs() < EPSILON);
}
let f16s: Vec<f16> = f32s.iter().map(|&v| f16::from_f32(v)).collect();
let halfs2 = halfs_from_f16_slice(&f16s);
for (i, h) in halfs2.iter().enumerate() {
assert_eq!(h.0, f16s[i]);
}
let f16s_back = f16s_from_half_slice(&halfs2);
for (a, b) in f16s.iter().zip(f16s_back.iter()) {
assert_eq!(*a, *b);
}
let arr_halfs = halfs_from_f32_array(f32s);
for (i, h) in arr_halfs.iter().enumerate() {
assert!((h.to_f32() - f32s[i]).abs() < EPSILON);
}
let arr_f32s = f32s_from_half_array(arr_halfs);
for (a, b) in f32s.iter().zip(arr_f32s.iter()) {
assert!((*a - *b).abs() < EPSILON);
}
let arr_f16s: [f16; 4] = [
f16::from_f32(1.0),
f16::from_f32(-2.0),
f16::from_f32(3.5),
f16::from_f32(0.0),
];
let arr_halfs2 = halfs_from_f16_array(arr_f16s);
for (i, h) in arr_halfs2.iter().enumerate() {
assert_eq!(h.0, arr_f16s[i]);
}
let arr_f16s_back = f16s_from_half_array(arr_halfs2);
for (a, b) in arr_f16s.iter().zip(arr_f16s_back.iter()) {
assert_eq!(*a, *b);
}
}
}