MFEM  v4.6.0
Finite element discretization library
m128.hpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2023, Lawrence Livermore National Security, LLC. Produced
2 // at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3 // LICENSE and NOTICE for details. LLNL-CODE-806117.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability visit https://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the BSD-3 license. We welcome feedback and contributions, see file
10 // CONTRIBUTING.md for details.
11 
12 #ifndef MFEM_SIMD_M128_HPP
13 #define MFEM_SIMD_M128_HPP
14 
15 #ifdef __SSE2__
16 
17 #include "../../config/tconfig.hpp"
18 #if defined(__x86_64__)
19 #include <x86intrin.h>
20 #else // assuming MSVC with _M_X64 or _M_IX86
21 #include <intrin.h>
22 #endif
23 
24 namespace mfem
25 {
26 
27 template <typename, int, int> struct AutoSIMD;
28 
29 template <> struct AutoSIMD<double,2,16>
30 {
31  typedef double scalar_type;
32  static constexpr int size = 2;
33  static constexpr int align_bytes = 16;
34 
35  union
36  {
37  __m128d m128d;
38  double vec[size];
39  };
40 
41  AutoSIMD() = default;
42 
43  AutoSIMD(const AutoSIMD &) = default;
44 
45  inline MFEM_ALWAYS_INLINE double &operator[](int i)
46  {
47  return vec[i];
48  }
49 
50  inline MFEM_ALWAYS_INLINE const double &operator[](int i) const
51  {
52  return vec[i];
53  }
54 
55  inline MFEM_ALWAYS_INLINE AutoSIMD &operator=(const AutoSIMD &v)
56  {
57  m128d = v.m128d;
58  return *this;
59  }
60 
61  inline MFEM_ALWAYS_INLINE AutoSIMD &operator=(const double &e)
62  {
63  m128d = _mm_set1_pd(e);
64  return *this;
65  }
66 
67  inline MFEM_ALWAYS_INLINE AutoSIMD &operator+=(const AutoSIMD &v)
68  {
69  m128d = _mm_add_pd(m128d,v.m128d);
70  return *this;
71  }
72 
73  inline MFEM_ALWAYS_INLINE AutoSIMD &operator+=(const double &e)
74  {
75  m128d = _mm_add_pd(m128d,_mm_set1_pd(e));
76  return *this;
77  }
78 
79  inline MFEM_ALWAYS_INLINE AutoSIMD &operator-=(const AutoSIMD &v)
80  {
81  m128d = _mm_sub_pd(m128d,v.m128d);
82  return *this;
83  }
84 
85  inline MFEM_ALWAYS_INLINE AutoSIMD &operator-=(const double &e)
86  {
87  m128d = _mm_sub_pd(m128d,_mm_set1_pd(e));
88  return *this;
89  }
90 
91  inline MFEM_ALWAYS_INLINE AutoSIMD &operator*=(const AutoSIMD &v)
92  {
93  m128d = _mm_mul_pd(m128d,v.m128d);
94  return *this;
95  }
96 
97  inline MFEM_ALWAYS_INLINE AutoSIMD &operator*=(const double &e)
98  {
99  m128d = _mm_mul_pd(m128d,_mm_set1_pd(e));
100  return *this;
101  }
102 
103  inline MFEM_ALWAYS_INLINE AutoSIMD &operator/=(const AutoSIMD &v)
104  {
105  m128d = _mm_div_pd(m128d,v.m128d);
106  return *this;
107  }
108 
109  inline MFEM_ALWAYS_INLINE AutoSIMD &operator/=(const double &e)
110  {
111  m128d = _mm_div_pd(m128d,_mm_set1_pd(e));
112  return *this;
113  }
114 
115  inline MFEM_ALWAYS_INLINE AutoSIMD operator-() const
116  {
117  AutoSIMD r;
118  r.m128d = _mm_xor_pd(_mm_set1_pd(-0.0), m128d);
119  return r;
120  }
121 
122  inline MFEM_ALWAYS_INLINE AutoSIMD operator+() const
123  {
124  return *this;
125  }
126 
127  inline MFEM_ALWAYS_INLINE AutoSIMD operator+(const AutoSIMD &v) const
128  {
129  AutoSIMD r;
130  r.m128d = _mm_add_pd(m128d,v.m128d);
131  return r;
132  }
133 
134 
135  inline MFEM_ALWAYS_INLINE AutoSIMD operator+(const double &e) const
136  {
137  AutoSIMD r;
138  r.m128d = _mm_add_pd(m128d, _mm_set1_pd(e));
139  return r;
140  }
141 
142  inline MFEM_ALWAYS_INLINE AutoSIMD operator-(const AutoSIMD &v) const
143  {
144  AutoSIMD r;
145  r.m128d = _mm_sub_pd(m128d,v.m128d);
146  return r;
147  }
148 
149  inline MFEM_ALWAYS_INLINE AutoSIMD operator-(const double &e) const
150  {
151  AutoSIMD r;
152  r.m128d = _mm_sub_pd(m128d, _mm_set1_pd(e));
153  return r;
154  }
155 
156  inline MFEM_ALWAYS_INLINE AutoSIMD operator*(const AutoSIMD &v) const
157  {
158  AutoSIMD r;
159  r.m128d = _mm_mul_pd(m128d,v.m128d);
160  return r;
161  }
162 
163  inline MFEM_ALWAYS_INLINE AutoSIMD operator*(const double &e) const
164  {
165  AutoSIMD r;
166  r.m128d = _mm_mul_pd(m128d, _mm_set1_pd(e));
167  return r;
168  }
169 
170  inline MFEM_ALWAYS_INLINE AutoSIMD operator/(const AutoSIMD &v) const
171  {
172  AutoSIMD r;
173  r.m128d = _mm_div_pd(m128d,v.m128d);
174  return r;
175  }
176 
177  inline MFEM_ALWAYS_INLINE AutoSIMD operator/(const double &e) const
178  {
179  AutoSIMD r;
180  r.m128d = _mm_div_pd(m128d, _mm_set1_pd(e));
181  return r;
182  }
183 
184 
185  inline MFEM_ALWAYS_INLINE AutoSIMD &fma(const AutoSIMD &v, const AutoSIMD &w)
186  {
187  m128d = _mm_add_pd(_mm_mul_pd(w.m128d,v.m128d),m128d);
188  return *this;
189  }
190 
191  inline MFEM_ALWAYS_INLINE AutoSIMD &fma(const AutoSIMD &v, const double &e)
192  {
193  m128d = _mm_add_pd(_mm_mul_pd(_mm_set1_pd(e),v.m128d),m128d);
194  return *this;
195  }
196 
197  inline MFEM_ALWAYS_INLINE AutoSIMD &fma(const double &e, const AutoSIMD &v)
198  {
199  m128d = _mm_add_pd(_mm_mul_pd(v.m128d,_mm_set1_pd(e)),m128d);
200  return *this;
201  }
202 
203  inline MFEM_ALWAYS_INLINE AutoSIMD &mul(const AutoSIMD &v, const AutoSIMD &w)
204  {
205  m128d = _mm_mul_pd(v.m128d,w.m128d);
206  return *this;
207  }
208 
209  inline MFEM_ALWAYS_INLINE AutoSIMD &mul(const AutoSIMD &v, const double &e)
210  {
211  m128d = _mm_mul_pd(v.m128d,_mm_set1_pd(e));
212  return *this;
213  }
214 
215  inline MFEM_ALWAYS_INLINE AutoSIMD &mul(const double &e, const AutoSIMD &v)
216  {
217  m128d = _mm_mul_pd(_mm_set1_pd(e),v.m128d);
218  return *this;
219  }
220 };
221 
222 inline MFEM_ALWAYS_INLINE
224  const AutoSIMD<double,2,16> &v)
225 {
227  r.m128d = _mm_add_pd(_mm_set1_pd(e),v.m128d);
228  return r;
229 }
230 
231 inline MFEM_ALWAYS_INLINE
233  const AutoSIMD<double,2,16> &v)
234 {
236  r.m128d = _mm_sub_pd(_mm_set1_pd(e),v.m128d);
237  return r;
238 }
239 
240 inline MFEM_ALWAYS_INLINE
242  const AutoSIMD<double,2,16> &v)
243 {
245  r.m128d = _mm_mul_pd(_mm_set1_pd(e),v.m128d);
246  return r;
247 }
248 
249 inline MFEM_ALWAYS_INLINE
251  const AutoSIMD<double,2,16> &v)
252 {
254  r.m128d = _mm_div_pd(_mm_set1_pd(e),v.m128d);
255  return r;
256 }
257 
258 } // namespace mfem
259 
260 #endif // __SSE2__
261 
262 #endif // MFEM_SIMD_M128_HPP
MFEM_ALWAYS_INLINE AutoSIMD operator*(const double &e) const
Definition: m128.hpp:163
MFEM_ALWAYS_INLINE AutoSIMD & mul(const AutoSIMD &v, const AutoSIMD &w)
Definition: m128.hpp:203
MFEM_ALWAYS_INLINE AutoSIMD operator/(const double &e) const
Definition: m128.hpp:177
MFEM_ALWAYS_INLINE AutoSIMD operator*(const AutoSIMD &v) const
Definition: m128.hpp:156
MFEM_ALWAYS_INLINE AutoSIMD & operator/=(const double &e)
Definition: m128.hpp:109
MFEM_ALWAYS_INLINE const double & operator[](int i) const
Definition: m128.hpp:50
MFEM_ALWAYS_INLINE AutoSIMD operator+(const double &e) const
Definition: m128.hpp:135
MFEM_ALWAYS_INLINE AutoSIMD & operator/=(const AutoSIMD &v)
Definition: m128.hpp:103
MFEM_ALWAYS_INLINE AutoSIMD & mul(const double &e, const AutoSIMD &v)
Definition: m128.hpp:215
MFEM_ALWAYS_INLINE AutoSIMD< scalar_t, S, A > operator/(const scalar_t &e, const AutoSIMD< scalar_t, S, A > &v)
Definition: auto.hpp:271
MFEM_ALWAYS_INLINE AutoSIMD & fma(const AutoSIMD &v, const AutoSIMD &w)
Definition: m128.hpp:185
static const int size
Definition: auto.hpp:27
MFEM_ALWAYS_INLINE AutoSIMD operator+(const AutoSIMD &v) const
Definition: m128.hpp:127
scalar_t vec[size]
Definition: auto.hpp:30
MFEM_ALWAYS_INLINE AutoSIMD< scalar_t, S, A > operator+(const scalar_t &e, const AutoSIMD< scalar_t, S, A > &v)
Definition: auto.hpp:238
MFEM_ALWAYS_INLINE AutoSIMD & operator=(const double &e)
Definition: m128.hpp:61
MFEM_ALWAYS_INLINE AutoSIMD & fma(const AutoSIMD &v, const double &e)
Definition: m128.hpp:191
MFEM_ALWAYS_INLINE AutoSIMD operator+() const
Definition: m128.hpp:122
static const int align_bytes
Definition: auto.hpp:28
MFEM_ALWAYS_INLINE AutoSIMD & fma(const double &e, const AutoSIMD &v)
Definition: m128.hpp:197
MFEM_ALWAYS_INLINE AutoSIMD operator-(const double &e) const
Definition: m128.hpp:149
MFEM_ALWAYS_INLINE AutoSIMD & operator*=(const double &e)
Definition: m128.hpp:97
MFEM_ALWAYS_INLINE double & operator[](int i)
Definition: m128.hpp:45
MFEM_ALWAYS_INLINE AutoSIMD operator-() const
Definition: m128.hpp:115
MFEM_ALWAYS_INLINE AutoSIMD & operator+=(const AutoSIMD &v)
Definition: m128.hpp:67
MFEM_ALWAYS_INLINE AutoSIMD & operator*=(const AutoSIMD &v)
Definition: m128.hpp:91
MFEM_ALWAYS_INLINE AutoSIMD & operator-=(const double &e)
Definition: m128.hpp:85
MFEM_ALWAYS_INLINE AutoSIMD operator-(const AutoSIMD &v) const
Definition: m128.hpp:142
MFEM_ALWAYS_INLINE AutoSIMD & operator=(const AutoSIMD &v)
Definition: m128.hpp:55
MFEM_ALWAYS_INLINE AutoSIMD operator/(const AutoSIMD &v) const
Definition: m128.hpp:170
MFEM_ALWAYS_INLINE AutoSIMD & operator-=(const AutoSIMD &v)
Definition: m128.hpp:79
AutoSIMD()=default
MemoryClass operator*(MemoryClass mc1, MemoryClass mc2)
Return a suitable MemoryClass from a pair of MemoryClasses.
MFEM_ALWAYS_INLINE AutoSIMD< scalar_t, S, A > operator-(const scalar_t &e, const AutoSIMD< scalar_t, S, A > &v)
Definition: auto.hpp:249
MFEM_ALWAYS_INLINE AutoSIMD & operator+=(const double &e)
Definition: m128.hpp:73
MFEM_ALWAYS_INLINE AutoSIMD & mul(const AutoSIMD &v, const double &e)
Definition: m128.hpp:209