343 lines
8.2 KiB
Rust
343 lines
8.2 KiB
Rust
use std::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
|
|
|
|
pub use fallback::Float4;
|
|
mod fallback {
|
|
use std::ops::{Add, Div, Mul, Neg, Sub};
|
|
|
|
#[allow(non_camel_case_types)]
|
|
#[derive(Debug, Copy, Clone)]
|
|
#[repr(C, align(16))]
|
|
pub struct Float4 {
|
|
n: [f32; 4],
|
|
}
|
|
|
|
impl Float4 {
|
|
/// Create a new `Float4` with the given components.
|
|
#[inline(always)]
|
|
pub fn new(a: f32, b: f32, c: f32, d: f32) -> Self {
|
|
Self { n: [a, b, c, d] }
|
|
}
|
|
|
|
/// Create a new `Float4` with all elements set to `n`.
|
|
#[inline(always)]
|
|
pub fn splat(n: f32) -> Self {
|
|
Self { n: [n, n, n, n] }
|
|
}
|
|
|
|
/// Component-wise fused multiply-add.
|
|
///
|
|
/// `(self * a) + b` with only one rounding error.
|
|
#[inline(always)]
|
|
pub fn mul_add(self, a: Self, b: Self) -> Self {
|
|
Self {
|
|
n: [
|
|
self.n[0].mul_add(a.n[0], b.n[0]),
|
|
self.n[1].mul_add(a.n[1], b.n[1]),
|
|
self.n[2].mul_add(a.n[2], b.n[2]),
|
|
self.n[3].mul_add(a.n[3], b.n[3]),
|
|
],
|
|
}
|
|
}
|
|
|
|
/// Vertical minimum.
|
|
#[inline(always)]
|
|
pub fn min(self, a: Self) -> Self {
|
|
Self {
|
|
n: [
|
|
self.n[0].min(a.n[0]),
|
|
self.n[1].min(a.n[1]),
|
|
self.n[2].min(a.n[2]),
|
|
self.n[3].min(a.n[3]),
|
|
],
|
|
}
|
|
}
|
|
|
|
/// Vertical maximum.
|
|
#[inline(always)]
|
|
pub fn max(self, a: Self) -> Self {
|
|
Self {
|
|
n: [
|
|
self.n[0].max(a.n[0]),
|
|
self.n[1].max(a.n[1]),
|
|
self.n[2].max(a.n[2]),
|
|
self.n[3].max(a.n[3]),
|
|
],
|
|
}
|
|
}
|
|
|
|
// /// Horizontal minimum.
|
|
// #[inline(always)]
|
|
// pub fn hmin(self) -> f32 {
|
|
// let a = self.n[0].min(self.n[1]);
|
|
// let b = self.n[2].min(self.n[3]);
|
|
// a.min(b)
|
|
// }
|
|
|
|
// /// Horizontal maximum.
|
|
// #[inline(always)]
|
|
// pub fn hmax(self) -> f32 {
|
|
// let a = self.n[0].max(self.n[1]);
|
|
// let b = self.n[2].max(self.n[3]);
|
|
// a.max(b)
|
|
// }
|
|
|
|
//-----------------------------------------------------
|
|
// For matrix stuff.
|
|
|
|
#[inline(always)]
|
|
pub fn transpose_3x3(m: [Self; 3]) -> [Self; 3] {
|
|
[
|
|
// The fourth component in each row below is arbitrary,
|
|
// but in this case chosen so that it matches the
|
|
// behavior of the SSE version of transpose_3x3.
|
|
Self::new(m[0].a(), m[1].a(), m[2].a(), m[2].d()),
|
|
Self::new(m[0].b(), m[1].b(), m[2].b(), m[2].d()),
|
|
Self::new(m[0].c(), m[1].c(), m[2].c(), m[2].d()),
|
|
]
|
|
}
|
|
|
|
#[inline]
|
|
pub fn invert_3x3(_m: [Self; 3]) -> [Self; 3] {
|
|
todo!()
|
|
}
|
|
|
|
#[inline]
|
|
pub fn invert_3x3_precise(_m: [Self; 3]) -> [Self; 3] {
|
|
todo!()
|
|
}
|
|
|
|
//-----------------------------------------------------
|
|
// Individual components.
|
|
|
|
#[inline(always)]
|
|
pub fn a(self) -> f32 {
|
|
self.n[0]
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn b(self) -> f32 {
|
|
self.n[1]
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn c(self) -> f32 {
|
|
self.n[2]
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn d(self) -> f32 {
|
|
self.n[3]
|
|
}
|
|
|
|
#[inline(always)]
|
|
#[must_use]
|
|
pub fn set_a(self, n: f32) -> Self {
|
|
Self {
|
|
n: [n, self.n[1], self.n[2], self.n[3]],
|
|
}
|
|
}
|
|
|
|
#[inline(always)]
|
|
#[must_use]
|
|
pub fn set_b(self, n: f32) -> Self {
|
|
Self {
|
|
n: [self.n[0], n, self.n[2], self.n[3]],
|
|
}
|
|
}
|
|
|
|
#[inline(always)]
|
|
#[must_use]
|
|
pub fn set_c(self, n: f32) -> Self {
|
|
Self {
|
|
n: [self.n[0], self.n[1], n, self.n[3]],
|
|
}
|
|
}
|
|
|
|
#[inline(always)]
|
|
#[must_use]
|
|
pub fn set_d(self, n: f32) -> Self {
|
|
Self {
|
|
n: [self.n[0], self.n[1], self.n[2], n],
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------
|
|
// Shuffles.
|
|
|
|
#[inline(always)]
|
|
pub fn aaaa(self) -> Self {
|
|
let a = self.n[0];
|
|
Self { n: [a, a, a, a] }
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn bbbb(self) -> Self {
|
|
let b = self.n[1];
|
|
Self { n: [b, b, b, b] }
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn cccc(self) -> Self {
|
|
let c = self.n[2];
|
|
Self { n: [c, c, c, c] }
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn dddd(self) -> Self {
|
|
let d = self.n[3];
|
|
Self { n: [d, d, d, d] }
|
|
}
|
|
}
|
|
|
|
impl Add for Float4 {
|
|
type Output = Self;
|
|
|
|
#[inline(always)]
|
|
fn add(self, rhs: Self) -> Self {
|
|
Self {
|
|
n: [
|
|
self.n[0] + rhs.n[0],
|
|
self.n[1] + rhs.n[1],
|
|
self.n[2] + rhs.n[2],
|
|
self.n[3] + rhs.n[3],
|
|
],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Sub for Float4 {
|
|
type Output = Self;
|
|
|
|
#[inline(always)]
|
|
fn sub(self, rhs: Self) -> Self {
|
|
Self {
|
|
n: [
|
|
self.n[0] - rhs.n[0],
|
|
self.n[1] - rhs.n[1],
|
|
self.n[2] - rhs.n[2],
|
|
self.n[3] - rhs.n[3],
|
|
],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Mul for Float4 {
|
|
type Output = Self;
|
|
|
|
#[inline(always)]
|
|
fn mul(self, rhs: Self) -> Self {
|
|
Self {
|
|
n: [
|
|
self.n[0] * rhs.n[0],
|
|
self.n[1] * rhs.n[1],
|
|
self.n[2] * rhs.n[2],
|
|
self.n[3] * rhs.n[3],
|
|
],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Mul<f32> for Float4 {
|
|
type Output = Self;
|
|
|
|
#[inline(always)]
|
|
fn mul(self, rhs: f32) -> Self {
|
|
Self {
|
|
n: [
|
|
self.n[0] * rhs,
|
|
self.n[1] * rhs,
|
|
self.n[2] * rhs,
|
|
self.n[3] * rhs,
|
|
],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Div for Float4 {
|
|
type Output = Self;
|
|
|
|
#[inline(always)]
|
|
fn div(self, rhs: Self) -> Self {
|
|
Self {
|
|
n: [
|
|
self.n[0] / rhs.n[0],
|
|
self.n[1] / rhs.n[1],
|
|
self.n[2] / rhs.n[2],
|
|
self.n[3] / rhs.n[3],
|
|
],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Div<f32> for Float4 {
|
|
type Output = Self;
|
|
|
|
#[inline(always)]
|
|
fn div(self, rhs: f32) -> Self {
|
|
Self {
|
|
n: [
|
|
self.n[0] / rhs,
|
|
self.n[1] / rhs,
|
|
self.n[2] / rhs,
|
|
self.n[3] / rhs,
|
|
],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Neg for Float4 {
|
|
type Output = Self;
|
|
|
|
#[inline(always)]
|
|
fn neg(self) -> Self {
|
|
Self {
|
|
n: [-self.n[0], -self.n[1], -self.n[2], -self.n[3]],
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------
|
|
|
|
impl AddAssign for Float4 {
|
|
#[inline(always)]
|
|
fn add_assign(&mut self, rhs: Self) {
|
|
*self = *self + rhs;
|
|
}
|
|
}
|
|
|
|
impl SubAssign for Float4 {
|
|
#[inline(always)]
|
|
fn sub_assign(&mut self, rhs: Self) {
|
|
*self = *self - rhs;
|
|
}
|
|
}
|
|
|
|
impl MulAssign for Float4 {
|
|
#[inline(always)]
|
|
fn mul_assign(&mut self, rhs: Self) {
|
|
*self = *self * rhs;
|
|
}
|
|
}
|
|
|
|
impl MulAssign<f32> for Float4 {
|
|
#[inline(always)]
|
|
fn mul_assign(&mut self, rhs: f32) {
|
|
*self = *self * rhs;
|
|
}
|
|
}
|
|
|
|
impl DivAssign for Float4 {
|
|
#[inline(always)]
|
|
fn div_assign(&mut self, rhs: Self) {
|
|
*self = *self / rhs;
|
|
}
|
|
}
|
|
|
|
impl DivAssign<f32> for Float4 {
|
|
#[inline(always)]
|
|
fn div_assign(&mut self, rhs: f32) {
|
|
*self = *self / rhs;
|
|
}
|
|
}
|