Nektar++
Loading...
Searching...
No Matches
scalar.hpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: scalar.hpp
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 "allocator.hpp"
40#include "traits.hpp"
41#include <cmath>
42#include <cstdint>
43#include <type_traits>
44#include <vector>
45
46namespace tinysimd
47{
48
49namespace abi
50{
51
52template <typename scalarType> struct scalar
53{
54 using type = void;
55};
56
57} // namespace abi
58
59// forward declaration of concrete types
60// makes default type available for all arithmetic types
61template <typename T,
62 typename = typename std::enable_if<std::is_arithmetic_v<T>>::type>
63struct scalarT;
64struct scalarMask;
65
66namespace abi
67{
68
69// mapping between abstract types and concrete types
70template <> struct scalar<double>
71{
73};
74template <> struct scalar<float>
75{
77};
78template <> struct scalar<std::int64_t>
79{
81};
82template <> struct scalar<std::uint64_t>
83{
85};
86template <> struct scalar<std::int32_t>
87{
89};
90template <> struct scalar<std::uint32_t>
91{
93};
94template <> struct scalar<bool>
95{
97};
98
99#ifdef __APPLE__ // for apple size_t is recognised as uint64_t
100template <> struct scalar<size_t>
101{
102 using type = scalarT<size_t>;
103};
104#endif
105
106} // namespace abi
107
108// concrete types
109template <typename T, typename> struct scalarT
110{
111 static constexpr unsigned int width = 1;
112 static constexpr unsigned int alignment = sizeof(T);
113
114 using scalarType = T;
117
118 // storage
120
121 // ctors
122 inline scalarT() = default;
123 inline scalarT(const scalarT &rhs) = default;
124 inline scalarT(const vectorType &rhs) : _data(rhs)
125 {
126 }
127
128 // copy assignment
129 inline scalarT &operator=(const scalarT &) = default;
130
131 // store
132 inline void store(scalarType *p) const
133 {
134 *p = _data;
135 }
136
137 template <class flag> inline void store(scalarType *p, flag) const
138 {
139 *p = _data;
140 }
141
142 // load
143 inline void load(const scalarType *p)
144 {
145 _data = *p;
146 }
147
148 template <class flag> inline void load(const scalarType *p, flag)
149 {
150 _data = *p;
151 }
152
153 inline void broadcast(const scalarType rhs)
154 {
155 _data = rhs;
156 }
157
158 template <typename U,
159 typename = typename std::enable_if<std::is_integral_v<U>>::type>
160 inline void gather(const scalarType *p, const scalarT<U> &indices)
161 {
162 _data = *(p + indices._data);
163 }
164
165 template <typename U,
166 typename = typename std::enable_if<std::is_integral_v<U>>::type>
167 inline void scatter(scalarType *p, const scalarT<U> &indices) const
168 {
169 p += indices._data;
170 *p = _data;
171 }
172
173 // fma
174 // this = this + a * b
175 inline void fma(const scalarT<T> &a, const scalarT<T> &b)
176 {
177 _data += a._data * b._data;
178 }
179
180 // subscript
181 inline scalarType operator[](size_t) const
182 {
183 return _data;
184 }
185
186 inline scalarType &operator[](size_t)
187 {
188 return _data;
189 }
190
191 // unary ops
192 inline void operator+=(scalarT<T> rhs)
193 {
194 _data += rhs._data;
195 }
196
197 inline void operator-=(scalarT<T> rhs)
198 {
199 _data -= rhs._data;
200 }
201
202 inline void operator*=(scalarT<T> rhs)
203 {
204 _data *= rhs._data;
205 }
206
207 inline void operator/=(scalarT<T> rhs)
208 {
209 _data /= rhs._data;
210 }
211};
212
213template <typename T>
215{
216 return lhs._data + rhs._data;
217}
218template <typename T, typename U,
219 typename = typename std::enable_if<std::is_arithmetic_v<U>>::type>
221{
222 return lhs + rhs._data;
223}
224template <typename T, typename U,
225 typename = typename std::enable_if<std::is_arithmetic_v<U>>::type>
227{
228 return lhs._data + rhs;
229}
230
231template <typename T>
233{
234 return lhs._data - rhs._data;
235}
236template <typename T, typename U,
237 typename = typename std::enable_if<std::is_arithmetic_v<U>>::type>
239{
240 return lhs - rhs._data;
241}
242template <typename T, typename U,
243 typename = typename std::enable_if<std::is_arithmetic_v<U>>::type>
245{
246 return lhs._data - rhs;
247}
248
249template <typename T> inline scalarT<T> operator-(scalarT<T> in)
250{
251 return -in._data;
252}
253
254template <typename T>
256{
257 return lhs._data * rhs._data;
258}
259template <typename T, typename U,
260 typename = typename std::enable_if<std::is_arithmetic_v<U>>::type>
262{
263 return lhs * rhs._data;
264}
265template <typename T, typename U,
266 typename = typename std::enable_if<std::is_arithmetic_v<U>>::type>
268{
269 return lhs._data * rhs;
270}
271
272template <typename T>
274{
275 return lhs._data / rhs._data;
276}
277template <typename T, typename U,
278 typename = typename std::enable_if<std::is_arithmetic_v<U>>::type>
280{
281 return lhs / rhs._data;
282}
283template <typename T, typename U,
284 typename = typename std::enable_if<std::is_arithmetic_v<U>>::type>
286{
287 return lhs._data / rhs;
288}
289
290template <typename T> inline scalarT<T> sqrt(scalarT<T> in)
291{
292 return std::sqrt(in._data);
293}
294
295template <typename T> inline scalarT<T> abs(scalarT<T> in)
296{
297 return std::abs(in._data);
298}
299
300template <typename T> inline scalarT<T> min(scalarT<T> lhs, scalarT<T> rhs)
301{
302 return std::min(lhs._data, rhs._data);
303}
304
305template <typename T> inline scalarT<T> max(scalarT<T> lhs, scalarT<T> rhs)
306{
307 return std::max(lhs._data, rhs._data);
308}
309
310template <typename T> inline scalarT<T> log(scalarT<T> in)
311{
312 return std::log(in._data);
313}
314
315template <typename T>
317 const T *in, const size_t dataLen,
318 std::vector<scalarT<T>, allocator<scalarT<T>>> &out)
319{
320 for (size_t i = 0; i < dataLen; ++i)
321 {
322 out[i] = in[i];
323 }
324}
325
326template <typename T>
327inline void load_interleave(const T *in, const size_t dataLen,
328 std::vector<scalarT<T>, allocator<scalarT<T>>> &out)
329{
330 for (size_t i = 0; i < dataLen; ++i)
331 {
332 out[i] = in[i];
333 }
334}
335
336template <typename T>
338 const std::vector<scalarT<T>, allocator<scalarT<T>>> &in,
339 const size_t dataLen, T *out)
340{
341 for (size_t i = 0; i < dataLen; ++i)
342 {
343 out[i] = in[i]._data;
344 }
345}
346
347template <typename T>
349 const std::vector<scalarT<T>, allocator<scalarT<T>>> &in,
350 const size_t dataLen, T *out)
351{
352 for (size_t i = 0; i < dataLen; ++i)
353 {
354 out[i] = in[i]._data;
355 }
356}
357
358////////////////////////////////////////////////////////////////////////////////
359
360// mask type
361// mask is a int type that uses boolean promotion
362//
363// VERY LIMITED SUPPORT...just enough to make cubic eos work...
364//
365struct scalarMask : public scalarT<std::uint64_t>
366{
367 // bring in ctors
368 using scalarT::scalarT;
369
370 static constexpr scalarType true_v = true;
371 static constexpr scalarType false_v = false;
372
373 // needs to be able to work with std::uint32_t
374 // for single precision overload
375 // usually using 32 or 64 bits would result in a different number of lanes
376 // this is not the case for a scalar
377
378 // store
379 inline void store(std::uint32_t *p) const
380 {
381 *p = static_cast<std::uint32_t>(_data);
382 }
383
384 // load
385 inline void load(const std::uint32_t *p)
386 {
387 _data = static_cast<std::uint32_t>(*p);
388 }
389
390 // make base implementations visible
391 using scalarT<std::uint64_t>::store;
392 using scalarT<std::uint64_t>::load;
393};
394
396{
397 return lhs._data > rhs._data;
398}
399
401{
402 return lhs._data > rhs._data;
403}
404
405inline bool operator&&(scalarMask lhs, bool rhs)
406{
407 return lhs._data && rhs;
408}
409
410} // namespace tinysimd
411#endif
STL namespace.
void load_interleave(const T *in, const size_t dataLen, std::vector< scalarT< T >, allocator< scalarT< T > > > &out)
Definition scalar.hpp:327
scalarT< T > abs(scalarT< T > in)
Definition scalar.hpp:295
void deinterleave_unalign_store(const std::vector< scalarT< T >, allocator< scalarT< T > > > &in, const size_t dataLen, T *out)
Definition scalar.hpp:337
scalarT< T > operator-(scalarT< T > lhs, scalarT< T > rhs)
Definition scalar.hpp:232
scalarT< T > operator/(scalarT< T > lhs, scalarT< T > rhs)
Definition scalar.hpp:273
scalarT< T > max(scalarT< T > lhs, scalarT< T > rhs)
Definition scalar.hpp:305
boost::alignment::aligned_allocator< T, T::alignment > allocator
Definition allocator.hpp:48
scalarT< T > log(scalarT< T > in)
Definition scalar.hpp:310
scalarT< T > operator*(scalarT< T > lhs, scalarT< T > rhs)
Definition scalar.hpp:255
scalarMask operator>(scalarT< double > lhs, scalarT< double > rhs)
Definition scalar.hpp:395
bool operator&&(scalarMask lhs, bool rhs)
Definition scalar.hpp:405
void load_unalign_interleave(const T *in, const size_t dataLen, std::vector< scalarT< T >, allocator< scalarT< T > > > &out)
Definition scalar.hpp:316
void deinterleave_store(const std::vector< scalarT< T >, allocator< scalarT< T > > > &in, const size_t dataLen, T *out)
Definition scalar.hpp:348
scalarT< T > min(scalarT< T > lhs, scalarT< T > rhs)
Definition scalar.hpp:300
scalarT< T > sqrt(scalarT< T > in)
Definition scalar.hpp:290
scalarT< T > operator+(scalarT< T > lhs, scalarT< T > rhs)
Definition scalar.hpp:214
static constexpr scalarType false_v
Definition scalar.hpp:371
void load(const std::uint32_t *p)
Definition scalar.hpp:385
void store(std::uint32_t *p) const
Definition scalar.hpp:379
static constexpr scalarType true_v
Definition scalar.hpp:370
void store(scalarType *p) const
Definition scalar.hpp:132
scalarT(const scalarT &rhs)=default
void gather(const scalarType *p, const scalarT< U > &indices)
Definition scalar.hpp:160
vectorType _data
Definition scalar.hpp:119
static constexpr unsigned int alignment
Definition scalar.hpp:112
void broadcast(const scalarType rhs)
Definition scalar.hpp:153
scalarType operator[](size_t) const
Definition scalar.hpp:181
void operator/=(scalarT< T > rhs)
Definition scalar.hpp:207
scalarType[width] scalarArray
Definition scalar.hpp:116
void load(const scalarType *p, flag)
Definition scalar.hpp:148
void operator+=(scalarT< T > rhs)
Definition scalar.hpp:192
scalarType & operator[](size_t)
Definition scalar.hpp:186
scalarT(const vectorType &rhs)
Definition scalar.hpp:124
static constexpr unsigned int width
Definition scalar.hpp:111
scalarType vectorType
Definition scalar.hpp:115
void fma(const scalarT< T > &a, const scalarT< T > &b)
Definition scalar.hpp:175
void operator-=(scalarT< T > rhs)
Definition scalar.hpp:197
void load(const scalarType *p)
Definition scalar.hpp:143
void operator*=(scalarT< T > rhs)
Definition scalar.hpp:202
void store(scalarType *p, flag) const
Definition scalar.hpp:137
scalarT & operator=(const scalarT &)=default
void scatter(scalarType *p, const scalarT< U > &indices) const
Definition scalar.hpp:167