Nektar++
scalar.hpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: scalar.cpp
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: Scalar type used when a vector type is needed, but no SIMD
32 // extension is available.
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
36 #ifndef NEKTAR_LIB_LIBUTILITES_SIMDLIB_SCALAR_H
37 #define NEKTAR_LIB_LIBUTILITES_SIMDLIB_SCALAR_H
38 
39 #include <vector>
40 #include <cmath>
41 #include <cstdint>
42 #include <type_traits>
43 #include <cstdint>
44 #include "allocator.hpp"
45 #include "traits.hpp"
46 
47 namespace tinysimd
48 {
49 
50 namespace abi
51 {
52 
53 template <typename scalarType>
54 struct scalar
55 {
56  using type = void;
57 };
58 
59 } // namespace abi
60 
61 // forward declaration of concrete types
62 // makes default type available for all arithmetic types
63 template<typename T, typename = typename std::enable_if<
64  std::is_arithmetic<T>::value>::type>
65 struct scalarT;
66 struct scalarMask;
67 
68 namespace abi
69 {
70 
71  // mapping between abstract types and concrete types
72  template <> struct scalar<double>{ using type = scalarT<double>; };
73  template <> struct scalar<float> { using type = scalarT<float>; };
74  template <> struct scalar<std::int64_t>{ using type = scalarT<std::int64_t>; };
75  template <> struct scalar<std::uint64_t>{ using type = scalarT<std::uint64_t>; };
76  template <> struct scalar<std::int32_t>{ using type = scalarT<std::int32_t>; };
77  template <> struct scalar<std::uint32_t>{ using type = scalarT<std::uint32_t>; };
78  template <> struct scalar<bool>{ using type = scalarMask; };
79 
80 
81 #ifdef __APPLE__ // for apple size_t is recognised as uint64_t
82  template <> struct scalar<size_t>{ using type = scalarT<size_t>; };
83 #endif
84 
85 } // namespace abi
86 
87 // concrete types
88 template<typename T, typename>
89 struct scalarT
90 {
91  static constexpr unsigned int width = 1;
92  static constexpr unsigned int alignment = sizeof(T);
93 
94  using scalarType = T;
97 
98  // storage
100 
101  // ctors
102  inline scalarT() = default;
103  inline scalarT(const scalarT& rhs) = default;
104  inline scalarT(const vectorType& rhs) : _data(rhs){}
105 
106  // store
107  inline void store(scalarType* p) const
108  {
109  *p = _data;
110  }
111 
112  template<class flag>
113  inline void store(scalarType* p, flag) const
114  {
115  *p = _data;
116  }
117 
118  // load
119  inline void load(const scalarType* p)
120  {
121  _data = *p;
122  }
123 
124  template<class flag>
125  inline void load(const scalarType* p, flag)
126  {
127  _data = *p;
128  }
129 
130  inline void broadcast(const scalarType rhs)
131  {
132  _data = rhs;
133  }
134 
135  template<typename U, typename = typename std::enable_if<
136  std::is_integral<U>::value>::type>
137  inline void gather(const scalarType* p, const scalarT<U>& indices)
138  {
139  _data = *(p + indices._data);
140  }
141 
142  template<typename U, typename = typename std::enable_if<
143  std::is_integral<U>::value>::type>
144  inline void scatter(scalarType* p, const scalarT<U>& indices) const
145  {
146  p += indices._data;
147  *p = _data;
148  }
149 
150  // fma
151  // this = this + a * b
152  inline void fma(const scalarT<T>& a, const scalarT<T>& b)
153  {
154  _data += a._data * b._data;
155  }
156 
157  // subscript
158  inline scalarType operator[](size_t) const
159  {
160  return _data;
161  }
162 
163  inline scalarType& operator[](size_t)
164  {
165  return _data;
166  }
167 
168  // unary ops
169  inline void operator+=(scalarT<T> rhs)
170  {
171  _data += rhs._data;
172  }
173 
174  inline void operator-=(scalarT<T> rhs)
175  {
176  _data -= rhs._data;
177  }
178 
179  inline void operator*=(scalarT<T> rhs)
180  {
181  _data *= rhs._data;
182  }
183 
184  inline void operator/=(scalarT<T> rhs)
185  {
186  _data /= rhs._data;
187  }
188 
189 };
190 
191 template<typename T>
193 {
194  return lhs._data + rhs._data;
195 }
196 template<typename T, typename U, typename = typename std::enable_if<
197  std::is_arithmetic<U>::value>::type>
198 inline scalarT<T> operator+(U lhs, scalarT<T> rhs)
199 {
200  return lhs + rhs._data;
201 }
202 template<typename T, typename U, typename = typename std::enable_if<
203  std::is_arithmetic<U>::value>::type>
204 inline scalarT<T> operator+(scalarT<T> lhs, U rhs)
205 {
206  return lhs._data + rhs;
207 }
208 
209 
210 template<typename T>
212 {
213  return lhs._data - rhs._data;
214 }
215 template<typename T, typename U, typename = typename std::enable_if<
216  std::is_arithmetic<U>::value>::type>
217 inline scalarT<T> operator-(U lhs, scalarT<T> rhs)
218 {
219  return lhs - rhs._data;
220 }
221 template<typename T, typename U, typename = typename std::enable_if<
222  std::is_arithmetic<U>::value>::type>
223 inline scalarT<T> operator-(scalarT<T> lhs, U rhs)
224 {
225  return lhs._data - rhs;
226 }
227 
228 
229 template<typename T>
231 {
232  return lhs._data * rhs._data;
233 }
234 template<typename T, typename U, typename = typename std::enable_if<
235  std::is_arithmetic<U>::value>::type>
236 inline scalarT<T> operator*(U lhs, scalarT<T> rhs)
237 {
238  return lhs * rhs._data;
239 }
240 template<typename T, typename U, typename = typename std::enable_if<
241  std::is_arithmetic<U>::value>::type>
242 inline scalarT<T> operator*(scalarT<T> lhs, U rhs)
243 {
244  return lhs._data * rhs;
245 }
246 
247 
248 template<typename T>
250 {
251  return lhs._data / rhs._data;
252 }
253 template<typename T, typename U, typename = typename std::enable_if<
254  std::is_arithmetic<U>::value>::type>
255 inline scalarT<T> operator/(U lhs, scalarT<T> rhs)
256 {
257  return lhs / rhs._data;
258 }
259 template<typename T, typename U, typename = typename std::enable_if<
260  std::is_arithmetic<U>::value>::type>
261 inline scalarT<T> operator/(scalarT<T> lhs, U rhs)
262 {
263  return lhs._data / rhs;
264 }
265 
266 template<typename T>
268 {
269  return std::sqrt(in._data);
270 }
271 template<typename T>
273 {
274  return std::abs(in._data);
275 }
276 
277 template<typename T>
279 {
280  return std::log(in._data);
281 }
282 
283 template<typename T>
284 inline void load_interleave(
285  const T* in,
286  size_t dataLen,
287  std::vector<scalarT<T>, allocator<scalarT<T>>> &out)
288 {
289  for (size_t i = 0; i < dataLen; ++i)
290  {
291  out[i] = in[i];
292  }
293 }
294 
295 template<typename T>
296 inline void deinterleave_store(
297  const std::vector<scalarT<T>, allocator<scalarT<T>>> &in,
298  size_t dataLen,
299  T *out)
300 {
301  for (size_t i = 0; i < dataLen; ++i)
302  {
303  out[i] = in[i]._data;
304  }
305 }
306 
307 ////////////////////////////////////////////////////////////////////////////////
308 
309 // mask type
310 // mask is a int type that uses boolean promotion
311 //
312 // VERY LIMITED SUPPORT...just enough to make cubic eos work...
313 //
314 struct scalarMask : scalarT<std::uint64_t>
315 {
316  // bring in ctors
317  using scalarT::scalarT;
318 
319  static constexpr scalarType true_v = true;
320  static constexpr scalarType false_v = false;
321 };
322 
324 {
325 
326  return lhs._data > rhs._data;
327 }
328 
329 inline bool operator&&(scalarMask lhs, bool rhs)
330 {
331  return lhs._data && rhs;
332 }
333 
334 } // namespace tinysimd
335 #endif
scalarT< T > log(scalarT< T > in)
Definition: scalar.hpp:278
scalarT< T > operator+(scalarT< T > lhs, scalarT< T > rhs)
Definition: scalar.hpp:192
void deinterleave_store(const std::vector< scalarT< T >, allocator< scalarT< T >>> &in, size_t dataLen, T *out)
Definition: scalar.hpp:296
scalarT< T > operator-(scalarT< T > lhs, scalarT< T > rhs)
Definition: scalar.hpp:211
scalarT< T > abs(scalarT< T > in)
Definition: scalar.hpp:272
boost::alignment::aligned_allocator< T, T::alignment > allocator
Definition: allocator.hpp:48
scalarMask operator>(scalarT< double > lhs, scalarT< double > rhs)
Definition: scalar.hpp:323
void load_interleave(const T *in, size_t dataLen, std::vector< scalarT< T >, allocator< scalarT< T >>> &out)
Definition: scalar.hpp:284
bool operator&&(scalarMask lhs, bool rhs)
Definition: scalar.hpp:329
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:267
scalarT< T > operator/(scalarT< T > lhs, scalarT< T > rhs)
Definition: scalar.hpp:249
scalarT< T > operator*(scalarT< T > lhs, scalarT< T > rhs)
Definition: scalar.hpp:230
static constexpr scalarType false_v
Definition: scalar.hpp:320
static constexpr scalarType true_v
Definition: scalar.hpp:319
void store(scalarType *p) const
Definition: scalar.hpp:107
scalarT(const scalarT &rhs)=default
void gather(const scalarType *p, const scalarT< U > &indices)
Definition: scalar.hpp:137
vectorType _data
Definition: scalar.hpp:99
static constexpr unsigned int alignment
Definition: scalar.hpp:92
void broadcast(const scalarType rhs)
Definition: scalar.hpp:130
scalarType & operator[](size_t)
Definition: scalar.hpp:163
scalarType operator[](size_t) const
Definition: scalar.hpp:158
void operator/=(scalarT< T > rhs)
Definition: scalar.hpp:184
scalarType[width] scalarArray
Definition: scalar.hpp:96
void load(const scalarType *p, flag)
Definition: scalar.hpp:125
void operator+=(scalarT< T > rhs)
Definition: scalar.hpp:169
scalarT(const vectorType &rhs)
Definition: scalar.hpp:104
static constexpr unsigned int width
Definition: scalar.hpp:91
scalarType vectorType
Definition: scalar.hpp:95
void fma(const scalarT< T > &a, const scalarT< T > &b)
Definition: scalar.hpp:152
void operator-=(scalarT< T > rhs)
Definition: scalar.hpp:174
void load(const scalarType *p)
Definition: scalar.hpp:119
void operator*=(scalarT< T > rhs)
Definition: scalar.hpp:179
void store(scalarType *p, flag) const
Definition: scalar.hpp:113
void scatter(scalarType *p, const scalarT< U > &indices) const
Definition: scalar.hpp:144