diff --git a/library/stdarch/coresimd/ppsv/api/float_math.rs b/library/stdarch/coresimd/ppsv/api/float_math.rs index e0178b703cb9..32de85eb55c7 100644 --- a/library/stdarch/coresimd/ppsv/api/float_math.rs +++ b/library/stdarch/coresimd/ppsv/api/float_math.rs @@ -39,6 +39,20 @@ macro_rules! impl_float_math { use coresimd::ppsv::codegen::fma::FloatFma; FloatFma::fma(self, y, z) } + + /// Sin + #[inline(always)] + pub fn sin(self) -> Self { + use coresimd::ppsv::codegen::sin::FloatSin; + FloatSin::sin(self) + } + + /// Cos + #[inline] + pub fn cos(self) -> Self { + use coresimd::ppsv::codegen::cos::FloatCos; + FloatCos::cos(self) + } } }; } @@ -54,6 +68,14 @@ macro_rules! test_float_math { } } + fn pi() -> $elem_ty { + match ::mem::size_of::<$elem_ty>() { + 4 => ::std::f32::consts::PI as $elem_ty, + 8 => ::std::f64::consts::PI as $elem_ty, + _ => unreachable!(), + } + } + #[test] fn abs() { use coresimd::simd::*; @@ -126,7 +148,36 @@ macro_rules! test_float_math { assert_eq!(f, t.fma(t, z)); assert_eq!(f, t.fma(o, t)); - assert_eq!(t3, t.fma(t, o)); + assert_eq!(t3, t.fma(o, o)); + } + + #[test] + fn sin() { + use coresimd::simd::*; + let z = $id::splat(0 as $elem_ty); + let p = $id::splat(pi() as $elem_ty); + let ph = $id::splat(pi() as $elem_ty / 2.); + let o_r = $id::splat((pi() as $elem_ty / 2.).sin()); + let z_r = $id::splat((pi() as $elem_ty).sin()); + + assert_eq!(z, z.sin()); + assert_eq!(o_r, ph.sin()); + assert_eq!(z_r, p.sin()); + } + + #[test] + fn cos() { + use coresimd::simd::*; + let z = $id::splat(0 as $elem_ty); + let o = $id::splat(1 as $elem_ty); + let p = $id::splat(pi() as $elem_ty); + let ph = $id::splat(pi() as $elem_ty / 2.); + let z_r = $id::splat((pi() as $elem_ty / 2.).cos()); + let o_r = $id::splat((pi() as $elem_ty).cos()); + + assert_eq!(o, z.cos()); + assert_eq!(z_r, ph.cos()); + assert_eq!(o_r, p.cos()); } }; } diff --git a/library/stdarch/coresimd/ppsv/codegen/cos.rs b/library/stdarch/coresimd/ppsv/codegen/cos.rs new file mode 100644 index 000000000000..fdc61ea46425 --- /dev/null +++ b/library/stdarch/coresimd/ppsv/codegen/cos.rs @@ -0,0 +1,43 @@ +//! Exact vector cos + +use coresimd::simd::*; + +#[allow(improper_ctypes)] +extern "C" { + #[link_name = "llvm.cos.v2f32"] + fn cos_v2f32(x: f32x2) -> f32x2; + #[link_name = "llvm.cos.v4f32"] + fn cos_v4f32(x: f32x4) -> f32x4; + #[link_name = "llvm.cos.v8f32"] + fn cos_v8f32(x: f32x8) -> f32x8; + #[link_name = "llvm.cos.v16f32"] + fn cos_v16f32(x: f32x16) -> f32x16; + #[link_name = "llvm.cos.v2f64"] + fn cos_v2f64(x: f64x2) -> f64x2; + #[link_name = "llvm.cos.v4f64"] + fn cos_v4f64(x: f64x4) -> f64x4; + #[link_name = "llvm.cos.v8f64"] + fn cos_v8f64(x: f64x8) -> f64x8; +} + +pub(crate) trait FloatCos { + fn cos(self) -> Self; +} + +macro_rules! impl_fcos { + ($id:ident: $fn:ident) => { + impl FloatCos for $id { + fn cos(self) -> Self { + unsafe { $fn(self) } + } + } + } +} + +impl_fcos!(f32x2: cos_v2f32); +impl_fcos!(f32x4: cos_v4f32); +impl_fcos!(f32x8: cos_v8f32); +impl_fcos!(f32x16: cos_v16f32); +impl_fcos!(f64x2: cos_v2f64); +impl_fcos!(f64x4: cos_v4f64); +impl_fcos!(f64x8: cos_v8f64); diff --git a/library/stdarch/coresimd/ppsv/codegen/mod.rs b/library/stdarch/coresimd/ppsv/codegen/mod.rs index 2791e0670e2b..a1e8c24f6b03 100644 --- a/library/stdarch/coresimd/ppsv/codegen/mod.rs +++ b/library/stdarch/coresimd/ppsv/codegen/mod.rs @@ -8,3 +8,5 @@ pub mod masks_reductions; pub mod sqrt; pub mod abs; pub mod fma; +pub mod sin; +pub mod cos; diff --git a/library/stdarch/coresimd/ppsv/codegen/sin.rs b/library/stdarch/coresimd/ppsv/codegen/sin.rs new file mode 100644 index 000000000000..cf7f3dea2071 --- /dev/null +++ b/library/stdarch/coresimd/ppsv/codegen/sin.rs @@ -0,0 +1,43 @@ +//! Exact vector sin + +use coresimd::simd::*; + +#[allow(improper_ctypes)] +extern "C" { + #[link_name = "llvm.sin.v2f32"] + fn sin_v2f32(x: f32x2) -> f32x2; + #[link_name = "llvm.sin.v4f32"] + fn sin_v4f32(x: f32x4) -> f32x4; + #[link_name = "llvm.sin.v8f32"] + fn sin_v8f32(x: f32x8) -> f32x8; + #[link_name = "llvm.sin.v16f32"] + fn sin_v16f32(x: f32x16) -> f32x16; + #[link_name = "llvm.sin.v2f64"] + fn sin_v2f64(x: f64x2) -> f64x2; + #[link_name = "llvm.sin.v4f64"] + fn sin_v4f64(x: f64x4) -> f64x4; + #[link_name = "llvm.sin.v8f64"] + fn sin_v8f64(x: f64x8) -> f64x8; +} + +pub(crate) trait FloatSin { + fn sin(self) -> Self; +} + +macro_rules! impl_fsin { + ($id:ident: $fn:ident) => { + impl FloatSin for $id { + fn sin(self) -> Self { + unsafe { $fn(self) } + } + } + } +} + +impl_fsin!(f32x2: sin_v2f32); +impl_fsin!(f32x4: sin_v4f32); +impl_fsin!(f32x8: sin_v8f32); +impl_fsin!(f32x16: sin_v16f32); +impl_fsin!(f64x2: sin_v2f64); +impl_fsin!(f64x4: sin_v4f64); +impl_fsin!(f64x8: sin_v8f64);