CbmRoot
Loading...
Searching...
No Matches
KfSimdPseudo.h
Go to the documentation of this file.
1/* Copyright (C) 2010-2024 Frankfurt Institute for Advanced Studies, Goethe-Universität Frankfurt, Frankfurt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Igor Kulakov [committer] */
5#pragma once // include this header only once per compilation unit
7#include <boost/serialization/access.hpp>
9#include <cmath>
10#include <iomanip>
11#include <iostream>
12
13namespace cbm::algo::kf
14{
16 typedef float fscal;
17
18 /**********************************
19 *
20 * Pseudo SIMD vector
21 *
22 **********************************/
23
28
29
30 constexpr auto VcMemAlign = 16;
31
32 class fmask {
33
34 public:
35 static constexpr int Size{4};
37 static constexpr size_t size() { return Size; }
38
39 bool v[Size];
41 bool& operator[](size_t i) { return v[i]; }
42 bool operator[](size_t i) const { return v[i]; }
43
44 fmask() : fmask(0.f) {}
45
46 fmask(const fmask& a)
47 {
48 for (size_t i = 0; i < size(); i++) {
49 v[i] = a.v[i];
50 }
51 }
52
53 fmask(bool a)
54 {
55 for (size_t i = 0; i < size(); i++) {
56 v[i] = a;
57 }
58 }
59
60 static fmask One() { return fmask(true); }
61
62 static fmask Zero() { return fmask(false); }
63
64#define _op(A, B, F) \
65 fmask z; \
66 for (size_t i = 0; i < size(); i++) { \
67 z[i] = (A[i] F B[i]); \
68 } \
69 return z;
70
71 /* Logic */
72 friend fmask operator&&(const fmask& a, const fmask& b) { _op(a, b, &&) }
73 friend fmask operator||(const fmask& a, const fmask& b) { _op(a, b, ||) }
74 friend fmask operator&(const fmask& a, const fmask& b) { _op(a, b, &) }
75 friend fmask operator|(const fmask& a, const fmask& b) { _op(a, b, |) }
76 friend fmask operator^(const fmask& a, const fmask& b) { _op(a, b, ^) }
77
78#undef _op
80 friend fmask operator!(const fmask& a)
81 {
83 for (size_t i = 0; i < size(); i++) {
84 z[i] = !a[i];
85 }
86 return z;
87 }
89 bool isEmpty()
90 {
91 bool ret = true;
92 for (size_t i = 0; i < size(); i++) {
93 ret = ret && (!v[i]);
94 }
95 return ret;
96 }
97
98 bool isNotEmpty() { return !isEmpty(); }
99
101 friend std::ostream& operator<<(std::ostream& strm, const fmask& a)
102 {
103 strm << '[';
104 for (size_t i = 0; i < size(); i++) {
105 strm << std::setw(12) << std::setfill(' ') << a[i] << ' ';
106 }
107 return strm;
108 }
109
110 friend std::istream& operator>>(std::istream& strm, fmask& a)
112 for (size_t i = 0; i < size(); i++) {
113 strm >> a[i];
114 }
115 return strm;
117 };
119
120 class fvec {
122 public:
123 static constexpr size_t size() { return fmask::size(); }
125 fscal v[fmask::Size];
126
127 fvec() : fvec(0.) {}
128
129 fvec(const fvec& a)
130 {
131 for (size_t i = 0; i < size(); i++) {
132 v[i] = a.v[i];
134 }
138 for (size_t i = 0; i < size(); i++) {
139 v[i] = a;
141 }
142
145 template<class Archive>
146 void serialize(Archive& ar, const unsigned int)
147 {
148 for (size_t i = 0; i < size(); ++i) {
149 ar& v[i];
151 }
152
153 static fvec One() { return fvec(1.); }
154
155 static fvec Zero() { return fvec(0.); }
156
157 fscal& operator[](size_t i) { return v[i]; }
158
159 fscal operator[](size_t i) const { return v[i]; }
160
162 {
163 for (size_t i = 0; i < size(); i++) {
164 if (m[i]) {
165 v[i] = 0.;
166 }
167 }
168 }
169
170#define _f1(A, F) \
171 fvec z; \
172 for (size_t i = 0; i < size(); i++) { \
173 z[i] = F(A[i]); \
174 } \
175 return z;
176
177#define _f2(A, B, F) \
178 fvec z; \
179 for (size_t i = 0; i < size(); i++) { \
180 z[i] = F(A[i], B[i]); \
181 } \
182 return z;
183
184#define _op(A, B, F) \
185 fvec z; \
186 for (size_t i = 0; i < size(); i++) { \
187 z[i] = (A[i] F B[i]); \
188 } \
189 return z;
190
191#define _opComp(A, B, F) \
192 fmask z; \
193 for (size_t i = 0; i < size(); i++) { \
194 z[i] = (A[i] F B[i]); \
195 } \
196 return z;
197
198
199 /* Arithmetic Operators */
200 friend fvec operator+(const fvec& a, const fvec& b) { _op(a, b, +) }
201 friend fvec operator-(const fvec& a, const fvec& b) { _op(a, b, -) }
202 friend fvec operator*(const fvec& a, const fvec& b) { _op(a, b, *) }
203 friend fvec operator/(const fvec& a, const fvec& b) { _op(a, b, /) }
204
205 /* Comparison */
206 friend fmask operator<(const fvec& a, const fvec& b) { _opComp(a, b, <) }
207 friend fmask operator<=(const fvec& a, const fvec& b) { _opComp(a, b, <=) }
208 friend fmask operator>(const fvec& a, const fvec& b) { _opComp(a, b, >) }
209 friend fmask operator>=(const fvec& a, const fvec& b) { _opComp(a, b, >=) }
210 friend fmask operator==(const fvec& a, const fvec& b) { _opComp(a, b, ==) }
211
212 friend fmask isnan(const fvec& a)
213 {
214 fmask m;
215 for (size_t i = 0; i < size(); i++) {
216 m[i] = std::isnan(a[i]);
217 }
218 return m;
219 }
220
221 friend fvec iif(fmask a, fvec b, fvec c)
222 {
223 fvec z;
224 for (size_t i = 0; i < size(); i++) {
225 z[i] = a[i] ? b[i] : c[i];
226 }
227 return z;
228 }
229
230 /* Functions */
231 friend fscal min(fscal x, fscal y) { return x < y ? x : y; }
232 friend fscal max(fscal x, fscal y) { return x < y ? y : x; }
233 friend fscal asgnb(fscal x, fscal y) { return y >= 0.f ? fabs(x) : -fabs(x); }
234 friend fscal sgn(fscal x) { return x >= 0.f ? 1.f : -1.f; }
235
236 friend fvec min(const fvec& a, const fvec& b) { _f2(a, b, min) }
237 friend fvec max(const fvec& a, const fvec& b) { _f2(a, b, max) }
238 friend fvec asgnb(const fvec& a, const fvec& b) { _f2(a, b, asgnb) }
239 friend fvec sqrt(const fvec& a) { _f1(a, sqrt) }
240 // friend fvec abs(const fvec& a) { _f1(a, fabs) } // disabled to avoid confusions, use fabs() instead
241 friend fvec sgn(const fvec& a) { _f1(a, sgn) }
242 friend fvec exp(const fvec& a) { _f1(a, exp) }
243 friend fvec log(const fvec& a) { _f1(a, log) }
244 friend fvec sin(const fvec& a) { _f1(a, sin) }
245 friend fvec cos(const fvec& a) { _f1(a, cos) }
246#undef _f1
247#undef _f2
248#undef _op
249#undef _opComp
250
251 /* Define all operators for consistensy */
252
253 friend fvec operator-(const fvec& a) { return fvec(0) - a; }
254 friend fvec operator+(const fvec& a) { return a; }
255
256 friend void operator+=(fvec& a, const fvec& b) { a = a + b; }
257 friend void operator-=(fvec& a, const fvec& b) { a = a - b; }
258 friend void operator*=(fvec& a, const fvec& b) { a = a * b; }
259 friend void operator/=(fvec& a, const fvec& b) { a = a / b; }
260
261 friend std::ostream& operator<<(std::ostream& strm, const fvec& a)
262 {
263 //strm << "[" << a[0] << " " << a[1] << " " << a[2] << " " << a[3] << "]";
264 strm << '[';
265 for (size_t i = 0; i < size(); i++) {
266 strm << std::setw(12) << std::setfill(' ') << a[i] << ' ';
267 }
268 return strm;
269 }
270
271 friend std::istream& operator>>(std::istream& strm, fvec& a)
272 {
273 for (size_t i = 0; i < size(); i++) {
274 strm >> a[i];
275 }
276 return strm;
277 }
278
279 } __attribute__((aligned(16)));
280
281#define _fvecalignment __attribute__((aligned(fvec::size() * sizeof(fscal))))
282
283} // namespace cbm::algo::kf
#define _f2(A, B, F)
#define _opComp(A, B, F)
#define _op(A, B, F)
#define _f1(A, F)
friend fmask operator^(const fmask &a, const fmask &b)
friend std::ostream & operator<<(std::ostream &strm, const fmask &a)
friend fmask operator!(const fmask &a)
friend std::istream & operator>>(std::istream &strm, fmask &a)
bool & operator[](size_t i)
static fmask Zero()
static constexpr int Size
bool operator[](size_t i) const
friend fmask operator|(const fmask &a, const fmask &b)
fmask(const fmask &a)
static fmask One()
friend fmask operator||(const fmask &a, const fmask &b)
friend fmask operator&&(const fmask &a, const fmask &b)
static constexpr size_t size()
friend fmask operator&(const fmask &a, const fmask &b)
friend fvec min(const fvec &a, const fvec &b)
friend fmask operator>=(const fvec &a, const fvec &b)
friend fvec operator-(const fvec &a)
friend std::ostream & operator<<(std::ostream &strm, const fvec &a)
fscal v[fmask::Size]
fscal operator[](size_t i) const
friend std::istream & operator>>(std::istream &strm, fvec &a)
static constexpr size_t size()
friend fvec sin(const fvec &a)
friend fscal max(fscal x, fscal y)
friend fvec sqrt(const fvec &a)
fvec(const fvec &a)
friend fvec operator/(const fvec &a, const fvec &b)
friend fvec max(const fvec &a, const fvec &b)
friend void operator-=(fvec &a, const fvec &b)
friend fvec operator-(const fvec &a, const fvec &b)
friend fmask operator>(const fvec &a, const fvec &b)
void serialize(Archive &ar, const unsigned int)
friend fvec iif(fmask a, fvec b, fvec c)
static fvec One()
friend fvec sgn(const fvec &a)
friend fmask operator<(const fvec &a, const fvec &b)
friend fvec operator+(const fvec &a)
friend fvec exp(const fvec &a)
fscal & operator[](size_t i)
friend void operator/=(fvec &a, const fvec &b)
friend fvec operator+(const fvec &a, const fvec &b)
friend fvec cos(const fvec &a)
friend fmask isnan(const fvec &a)
friend void operator*=(fvec &a, const fvec &b)
friend void operator+=(fvec &a, const fvec &b)
friend class boost::serialization::access
Serialization block.
friend fscal asgnb(fscal x, fscal y)
friend fmask operator<=(const fvec &a, const fvec &b)
friend fscal min(fscal x, fscal y)
void setZero(fmask m)
friend fmask operator==(const fvec &a, const fvec &b)
static fvec Zero()
friend fvec operator*(const fvec &a, const fvec &b)
friend fvec asgnb(const fvec &a, const fvec &b)
friend fvec log(const fvec &a)
friend fscal sgn(fscal x)
class cbm::algo::kf::fvec __attribute__((aligned(16)))
constexpr auto VcMemAlign
fscal asgnb(fscal x, fscal y)
fscal min(fscal x, fscal y)
fscal max(fscal x, fscal y)
fscal sgn(fscal x)