psychopath/sub_crates/rmath/src/wide4.rs

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;
}
}