#[cfg(target_arch = "x86")]
use core::arch::x86::{__m128d, _mm_cvtsd_f64, _mm_dp_pd, _mm_set_pd};
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::{__m128d, _mm_cvtsd_f64, _mm_dp_pd, _mm_set_pd};
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[target_feature(enable = "sse4.2")]
#[inline]
#[must_use]
pub unsafe fn dot2d(a: __m128d, b: __m128d) -> f64 {
let c = _mm_dp_pd(a, b, 0x33);
_mm_cvtsd_f64(c)
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[target_feature(enable = "sse4.2")]
#[inline]
#[must_use]
pub unsafe fn dot_product(a_0: f64, a_1: f64, b_0: f64, b_1: f64) -> f64 {
unsafe { dot2d(_mm_set_pd(a_1, a_0), _mm_set_pd(b_1, b_0)) }
}
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
#[target_feature(enable = "sse4.2")]
#[inline]
#[must_use]
pub unsafe fn perp_product(a_0: f64, a_1: f64, b_0: f64, b_1: f64) -> f64 {
unsafe { dot2d(_mm_set_pd(a_1, a_0), _mm_set_pd(-b_0, b_1)) }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_dot_product() {
unsafe {
assert_eq!(1.0, dot_product(1.0, 0.0, 1.0, 0.0));
assert_eq!(0.0, dot_product(1.0, 0.0, 0.0, 1.0));
assert_eq!(0.0, dot_product(0.0, 1.0, 1.0, 0.0));
}
}
#[test]
fn test_perp_product() {
unsafe {
assert_eq!(0.0, perp_product(1.0, 0.0, 1.0, 0.0));
assert_eq!(1.0, perp_product(1.0, 0.0, 0.0, 1.0));
assert_eq!(-1.0, perp_product(0.0, 1.0, 1.0, 0.0));
}
}
}