use crate::std::{Vec2f, Vec2i, Vec2u, Vec3f, Vec3i, Vec3u, Vec4f, Vec4i, Vec4u};
pub trait Bitcast<T> {
fn bitcast(self) -> T;
}
pub fn bitcast_f32(e: impl Bitcast<f32>) -> f32 {
e.bitcast()
}
pub fn bitcast_u32(e: impl Bitcast<u32>) -> u32 {
e.bitcast()
}
pub fn bitcast_i32(e: impl Bitcast<i32>) -> i32 {
e.bitcast()
}
pub fn bitcast_vec2f(e: impl Bitcast<Vec2f>) -> Vec2f {
e.bitcast()
}
pub fn bitcast_vec2u(e: impl Bitcast<Vec2u>) -> Vec2u {
e.bitcast()
}
pub fn bitcast_vec2i(e: impl Bitcast<Vec2i>) -> Vec2i {
e.bitcast()
}
pub fn bitcast_vec3f(e: impl Bitcast<Vec3f>) -> Vec3f {
e.bitcast()
}
pub fn bitcast_vec3u(e: impl Bitcast<Vec3u>) -> Vec3u {
e.bitcast()
}
pub fn bitcast_vec3i(e: impl Bitcast<Vec3i>) -> Vec3i {
e.bitcast()
}
pub fn bitcast_vec4f(e: impl Bitcast<Vec4f>) -> Vec4f {
e.bitcast()
}
pub fn bitcast_vec4u(e: impl Bitcast<Vec4u>) -> Vec4u {
e.bitcast()
}
pub fn bitcast_vec4i(e: impl Bitcast<Vec4i>) -> Vec4i {
e.bitcast()
}
mod bitcast_impls {
use crate::std::*;
impl Bitcast<f32> for f32 {
fn bitcast(self) -> f32 {
self
}
}
impl Bitcast<u32> for u32 {
fn bitcast(self) -> u32 {
self
}
}
impl Bitcast<i32> for i32 {
fn bitcast(self) -> i32 {
self
}
}
impl Bitcast<f32> for u32 {
fn bitcast(self) -> f32 {
f32::from_bits(self)
}
}
impl Bitcast<f32> for i32 {
fn bitcast(self) -> f32 {
f32::from_ne_bytes(self.to_ne_bytes())
}
}
impl Bitcast<u32> for f32 {
fn bitcast(self) -> u32 {
self.to_bits()
}
}
impl Bitcast<u32> for i32 {
fn bitcast(self) -> u32 {
u32::from_ne_bytes(self.to_ne_bytes())
}
}
impl Bitcast<i32> for f32 {
fn bitcast(self) -> i32 {
i32::from_ne_bytes(self.to_ne_bytes())
}
}
impl Bitcast<i32> for u32 {
fn bitcast(self) -> i32 {
i32::from_ne_bytes(self.to_ne_bytes())
}
}
macro_rules! impl_vec_bitcast {
($n:literal, $src_vec:ty, $dst_vec:ty, $src_scalar:ty, $dst_scalar:ty) => {
impl Bitcast<$dst_vec> for $src_vec {
fn bitcast(self) -> $dst_vec {
let src: [$src_scalar; $n] = self.to_array();
let dst: [$dst_scalar; $n] = src.map(|s| Bitcast::<$dst_scalar>::bitcast(s));
<$dst_vec>::from_array(dst)
}
}
};
}
macro_rules! impl_vec_bitcast_identity {
($vec:ty) => {
impl Bitcast<$vec> for $vec {
fn bitcast(self) -> $vec {
self
}
}
};
}
impl_vec_bitcast_identity!(Vec2f);
impl_vec_bitcast_identity!(Vec2u);
impl_vec_bitcast_identity!(Vec2i);
impl_vec_bitcast_identity!(Vec3f);
impl_vec_bitcast_identity!(Vec3u);
impl_vec_bitcast_identity!(Vec3i);
impl_vec_bitcast_identity!(Vec4f);
impl_vec_bitcast_identity!(Vec4u);
impl_vec_bitcast_identity!(Vec4i);
impl_vec_bitcast!(2, Vec2u, Vec2f, u32, f32);
impl_vec_bitcast!(2, Vec2i, Vec2f, i32, f32);
impl_vec_bitcast!(2, Vec2f, Vec2u, f32, u32);
impl_vec_bitcast!(2, Vec2i, Vec2u, i32, u32);
impl_vec_bitcast!(2, Vec2f, Vec2i, f32, i32);
impl_vec_bitcast!(2, Vec2u, Vec2i, u32, i32);
impl_vec_bitcast!(3, Vec3u, Vec3f, u32, f32);
impl_vec_bitcast!(3, Vec3i, Vec3f, i32, f32);
impl_vec_bitcast!(3, Vec3f, Vec3u, f32, u32);
impl_vec_bitcast!(3, Vec3i, Vec3u, i32, u32);
impl_vec_bitcast!(3, Vec3f, Vec3i, f32, i32);
impl_vec_bitcast!(3, Vec3u, Vec3i, u32, i32);
impl_vec_bitcast!(4, Vec4u, Vec4f, u32, f32);
impl_vec_bitcast!(4, Vec4i, Vec4f, i32, f32);
impl_vec_bitcast!(4, Vec4f, Vec4u, f32, u32);
impl_vec_bitcast!(4, Vec4i, Vec4u, i32, u32);
impl_vec_bitcast!(4, Vec4f, Vec4i, f32, i32);
impl_vec_bitcast!(4, Vec4u, Vec4i, u32, i32);
}
#[cfg(test)]
mod bitcast_tests {
use crate::std::*;
#[test]
fn bitcast_f32_identity() {
assert_eq!(bitcast_f32(1.0f32), 1.0f32);
assert_eq!(bitcast_f32(0.0f32), 0.0f32);
assert_eq!(bitcast_f32(-1.0f32), -1.0f32);
}
#[test]
fn bitcast_u32_identity() {
assert_eq!(bitcast_u32(42u32), 42u32);
assert_eq!(bitcast_u32(0u32), 0u32);
}
#[test]
fn bitcast_i32_identity() {
assert_eq!(bitcast_i32(42i32), 42i32);
assert_eq!(bitcast_i32(-1i32), -1i32);
}
#[test]
fn bitcast_u32_to_f32() {
assert_eq!(bitcast_f32(0x3F800000u32), 1.0f32);
assert_eq!(bitcast_f32(0u32), 0.0f32);
}
#[test]
fn bitcast_f32_to_u32() {
assert_eq!(bitcast_u32(1.0f32), 0x3F800000u32);
assert_eq!(bitcast_u32(0.0f32), 0u32);
}
#[test]
fn bitcast_i32_to_f32() {
assert_eq!(bitcast_f32(0x3F800000i32), 1.0f32);
}
#[test]
fn bitcast_f32_to_i32() {
assert_eq!(bitcast_i32(1.0f32), 0x3F800000i32);
}
#[test]
fn bitcast_u32_to_i32() {
assert_eq!(bitcast_i32(0xFFFFFFFFu32), -1i32);
assert_eq!(bitcast_i32(0u32), 0i32);
}
#[test]
fn bitcast_i32_to_u32() {
assert_eq!(bitcast_u32(-1i32), 0xFFFFFFFFu32);
assert_eq!(bitcast_u32(0i32), 0u32);
}
#[test]
fn bitcast_f32_u32_roundtrip() {
let original = std::f32::consts::PI;
let through_u32: u32 = bitcast_u32(original);
let back: f32 = bitcast_f32(through_u32);
assert_eq!(original, back);
}
#[test]
fn bitcast_f32_i32_roundtrip() {
let original = -std::f32::consts::E;
let through_i32: i32 = bitcast_i32(original);
let back: f32 = bitcast_f32(through_i32);
assert_eq!(original, back);
}
#[test]
fn bitcast_vec2u_to_vec2f() {
let v = vec2u(0x3F800000, 0x40000000); let result: Vec2f = bitcast_vec2f(v);
assert_eq!(result, vec2f(1.0, 2.0));
}
#[test]
fn bitcast_vec2f_to_vec2u() {
let v = vec2f(1.0, 2.0);
let result: Vec2u = bitcast_vec2u(v);
assert_eq!(result, vec2u(0x3F800000, 0x40000000));
}
#[test]
fn bitcast_vec3i_to_vec3f() {
let v = vec3i(0x3F800000, 0x40000000, 0x40400000); let result: Vec3f = bitcast_vec3f(v);
assert_eq!(result, vec3f(1.0, 2.0, 3.0));
}
#[test]
fn bitcast_vec4f_to_vec4u() {
let v = vec4f(1.0, 2.0, 3.0, 4.0);
let result: Vec4u = bitcast_vec4u(v);
assert_eq!(
result,
vec4u(0x3F800000, 0x40000000, 0x40400000, 0x40800000)
);
}
#[test]
fn bitcast_vec4u_to_vec4i() {
let v = vec4u(0xFFFFFFFF, 0, 1, 0x80000000);
let result: Vec4i = bitcast_vec4i(v);
assert_eq!(result, vec4i(-1, 0, 1, i32::MIN));
}
#[test]
fn bitcast_vec3f_identity() {
let v = vec3f(1.0, 2.0, 3.0);
assert_eq!(bitcast_vec3f(v), v);
}
#[test]
fn bitcast_vec4f_u32_roundtrip() {
let original = vec4f(1.0, -2.0, 3.1, 0.0);
let through_u: Vec4u = bitcast_vec4u(original);
let back: Vec4f = bitcast_vec4f(through_u);
assert_eq!(original, back);
}
}