|
| 1 | +//! Float math |
| 2 | +
|
| 3 | +macro_rules! impl_float_math { |
| 4 | + ($id:ident) => { |
| 5 | + impl $id { |
| 6 | + /// Absolute-value |
| 7 | + #[inline] |
| 8 | + pub fn abs(self) -> Self { |
| 9 | + use coresimd::ppsv::codegen::abs::FloatAbs; |
| 10 | + FloatAbs::abs(self) |
| 11 | + } |
| 12 | + |
| 13 | + /// Square-root |
| 14 | + #[inline] |
| 15 | + pub fn sqrt(self) -> Self { |
| 16 | + use coresimd::ppsv::codegen::sqrt::FloatSqrt; |
| 17 | + FloatSqrt::sqrt(self) |
| 18 | + } |
| 19 | + |
| 20 | + /// Square-root estimate |
| 21 | + #[inline] |
| 22 | + pub fn sqrte(self) -> Self { |
| 23 | + use coresimd::simd_llvm::simd_fsqrt; |
| 24 | + unsafe { simd_fsqrt(self) } |
| 25 | + } |
| 26 | + |
| 27 | + /// Reciprocal square-root estimate |
| 28 | + #[inline] |
| 29 | + pub fn rsqrte(self) -> Self { |
| 30 | + unsafe { |
| 31 | + use coresimd::simd_llvm::simd_fsqrt; |
| 32 | + $id::splat(1.) / simd_fsqrt(self) |
| 33 | + } |
| 34 | + } |
| 35 | + |
| 36 | + /// Fused multiply add: `self * y + z` |
| 37 | + #[inline] |
| 38 | + pub fn fma(self, y: Self, z: Self) -> Self { |
| 39 | + use coresimd::ppsv::codegen::fma::FloatFma; |
| 40 | + FloatFma::fma(self, y, z) |
| 41 | + } |
| 42 | + } |
| 43 | + }; |
| 44 | +} |
| 45 | + |
| 46 | +macro_rules! test_float_math { |
| 47 | + ($id:ident, $elem_ty:ident) => { |
| 48 | + |
| 49 | + fn sqrt2() -> $elem_ty { |
| 50 | + match ::mem::size_of::<$elem_ty>() { |
| 51 | + 4 => 1.4142135 as $elem_ty, |
| 52 | + 8 => 1.4142135623730951 as $elem_ty, |
| 53 | + _ => unreachable!(), |
| 54 | + } |
| 55 | + } |
| 56 | + |
| 57 | + #[test] |
| 58 | + fn abs() { |
| 59 | + use coresimd::simd::*; |
| 60 | + let o = $id::splat(1 as $elem_ty); |
| 61 | + assert_eq!(o, o.abs()); |
| 62 | + |
| 63 | + let mo = $id::splat(-1 as $elem_ty); |
| 64 | + assert_eq!(o, mo.abs()); |
| 65 | + } |
| 66 | + |
| 67 | + #[test] |
| 68 | + fn sqrt() { |
| 69 | + use coresimd::simd::*; |
| 70 | + let z = $id::splat(0 as $elem_ty); |
| 71 | + let o = $id::splat(1 as $elem_ty); |
| 72 | + assert_eq!(z, z.sqrt()); |
| 73 | + assert_eq!(o, o.sqrt()); |
| 74 | + |
| 75 | + let t = $id::splat(2 as $elem_ty); |
| 76 | + let e = $id::splat(sqrt2() as $elem_ty); |
| 77 | + assert_eq!(e, t.sqrt()); |
| 78 | + } |
| 79 | + |
| 80 | + #[test] |
| 81 | + fn sqrte() { |
| 82 | + use coresimd::simd::*; |
| 83 | + let z = $id::splat(0 as $elem_ty); |
| 84 | + let o = $id::splat(1 as $elem_ty); |
| 85 | + assert_eq!(z, z.sqrte()); |
| 86 | + assert_eq!(o, o.sqrte()); |
| 87 | + |
| 88 | + let t = $id::splat(2 as $elem_ty); |
| 89 | + let e = $id::splat(sqrt2() as $elem_ty); |
| 90 | + let error = (e - t.sqrte()).abs(); |
| 91 | + let tol = $id::splat(2.4e-4 as $elem_ty); |
| 92 | + |
| 93 | + assert!(error.le(tol).all()); |
| 94 | + } |
| 95 | + |
| 96 | + #[test] |
| 97 | + fn rsqrte() { |
| 98 | + use coresimd::simd::*; |
| 99 | + let o = $id::splat(1 as $elem_ty); |
| 100 | + assert_eq!(o, o.rsqrte()); |
| 101 | + |
| 102 | + let t = $id::splat(2 as $elem_ty); |
| 103 | + let e = 1. / sqrt2(); |
| 104 | + let error = (e - t.rsqrte()).abs(); |
| 105 | + let tol = $id::splat(2.4e-4 as $elem_ty); |
| 106 | + assert!(error.le(tol).all()); |
| 107 | + } |
| 108 | + |
| 109 | + #[test] |
| 110 | + fn fma() { |
| 111 | + use coresimd::simd::*; |
| 112 | + let z = $id::splat(0 as $elem_ty); |
| 113 | + let o = $id::splat(1 as $elem_ty); |
| 114 | + let t = $id::splat(2 as $elem_ty); |
| 115 | + let t3 = $id::splat(3 as $elem_ty); |
| 116 | + let f = $id::splat(4 as $elem_ty); |
| 117 | + |
| 118 | + assert_eq!(z, z.fma(z, z)); |
| 119 | + assert_eq!(o, o.fma(o, z)); |
| 120 | + assert_eq!(o, o.fma(z, o)); |
| 121 | + assert_eq!(o, z.fma(o, o)); |
| 122 | + |
| 123 | + assert_eq!(t, o.fma(o, o)); |
| 124 | + assert_eq!(t, o.fma(t, z)); |
| 125 | + assert_eq!(t, t.fma(o, z)); |
| 126 | + |
| 127 | + assert_eq!(f, t.fma(t, z)); |
| 128 | + assert_eq!(f, t.fma(o, t)); |
| 129 | + assert_eq!(t3, t.fma(t, o)); |
| 130 | + } |
| 131 | + }; |
| 132 | +} |
0 commit comments