You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
2.4KB

  1. #include <x86intrin.h>
  2. #define ALIGN(n) __attribute__((aligned(n)))
  3. namespace simd {
  4. template <int N>
  5. struct f32;
  6. /** Wrapper for `__m128` representing a vector of 4 single-precision float values. */
  7. template <>
  8. struct f32<4> {
  9. __m128 v;
  10. f32<4>() {}
  11. f32<4>(__m128 v) : v(v) {}
  12. template <typename T>
  13. f32<4>(T x) {
  14. v = _mm_set_ps1((float) x);
  15. }
  16. /** Reads an array of 4 values */
  17. f32<4>(const float *x) {
  18. v = _mm_loadu_ps(x);
  19. }
  20. /** Writes an array of 4 values */
  21. void store(float *x) {
  22. _mm_storeu_ps(x, v);
  23. }
  24. };
  25. // Operator overloads
  26. #define DECLARE_F32_4_OPERATOR_INFIX(operator, func) \
  27. inline f32<4> operator(f32<4> a, f32<4> b) { \
  28. return f32<4>(func(a.v, b.v)); \
  29. } \
  30. template <typename T> \
  31. f32<4> operator(T a, f32<4> b) { \
  32. return operator(f32<4>(a), b); \
  33. } \
  34. template <typename T> \
  35. f32<4> operator(f32<4> a, T b) { \
  36. return operator(a, f32<4>(b)); \
  37. }
  38. DECLARE_F32_4_OPERATOR_INFIX(operator+, _mm_add_ps)
  39. DECLARE_F32_4_OPERATOR_INFIX(operator-, _mm_sub_ps)
  40. DECLARE_F32_4_OPERATOR_INFIX(operator*, _mm_mul_ps)
  41. DECLARE_F32_4_OPERATOR_INFIX(operator/, _mm_div_ps)
  42. DECLARE_F32_4_OPERATOR_INFIX(operator==, _mm_cmpeq_ps)
  43. DECLARE_F32_4_OPERATOR_INFIX(operator>=, _mm_cmpge_ps)
  44. DECLARE_F32_4_OPERATOR_INFIX(operator>, _mm_cmpgt_ps)
  45. DECLARE_F32_4_OPERATOR_INFIX(operator<=, _mm_cmple_ps)
  46. DECLARE_F32_4_OPERATOR_INFIX(operator<, _mm_cmplt_ps)
  47. DECLARE_F32_4_OPERATOR_INFIX(operator!=, _mm_cmpneq_ps)
  48. #define DECLARE_F32_4_OPERATOR_INCREMENT(operator, func) \
  49. inline f32<4> &operator(f32<4> &a, f32<4> b) { \
  50. a.v = func(a.v, b.v); \
  51. return a; \
  52. } \
  53. template <typename T> \
  54. f32<4> &operator(f32<4> &a, T b) { \
  55. return operator(a, f32<4>(b)); \
  56. }
  57. DECLARE_F32_4_OPERATOR_INCREMENT(operator+=, _mm_add_ps);
  58. DECLARE_F32_4_OPERATOR_INCREMENT(operator-=, _mm_sub_ps);
  59. DECLARE_F32_4_OPERATOR_INCREMENT(operator*=, _mm_mul_ps);
  60. DECLARE_F32_4_OPERATOR_INCREMENT(operator/=, _mm_div_ps);
  61. inline f32<4> rsqrt(f32<4> a) {
  62. return f32<4>(_mm_rsqrt_ps(a.v));
  63. }
  64. inline f32<4> rcp(f32<4> a) {
  65. return f32<4>(_mm_rcp_ps(a.v));
  66. }
  67. } // namespace simd
  68. namespace std {
  69. inline simd::f32<4> max(simd::f32<4> a, simd::f32<4> b) {
  70. return simd::f32<4>(_mm_max_ps(a.v, b.v));
  71. }
  72. inline simd::f32<4> min(simd::f32<4> a, simd::f32<4> b) {
  73. return simd::f32<4>(_mm_min_ps(a.v, b.v));
  74. }
  75. inline simd::f32<4> sqrt(simd::f32<4> a) {
  76. return simd::f32<4>(_mm_sqrt_ps(a.v));
  77. }
  78. } // namespace std