add float math: sin, cos

This commit is contained in:
gnzlbg 2018-06-04 17:07:09 +02:00 committed by gnzlbg
parent c8491ea363
commit d62b7dbc64
4 changed files with 140 additions and 1 deletions

View file

@ -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());
}
};
}

View file

@ -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);

View file

@ -8,3 +8,5 @@ pub mod masks_reductions;
pub mod sqrt;
pub mod abs;
pub mod fma;
pub mod sin;
pub mod cos;

View file

@ -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);