ATLAS Offline Software
Loading...
Searching...
No Matches
vec_fb.h
Go to the documentation of this file.
1// This file's extension implies that it's C, but it's really -*- C++ -*-.
2/*
3 * Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration.
4 */
15
16#ifndef CXXUTILS_VEC_FB_H
17#define CXXUTILS_VEC_FB_H
18
19#include <initializer_list>
20#include <type_traits>
21#include <algorithm>
22#include <cstdint>
23#include "CxxUtils/bit_int.h"
24
25namespace CxxUtils {
28template<typename T, size_t N>
29struct alignas(N*sizeof(T)) vec_fb
30{
31 static_assert(std::is_arithmetic_v<T>, "Element type is not arithmetic");
32 static_assert(N > 0 && (N & (N - 1)) == 0, "Size not a power or 2");
33 // cppcheck-suppress uninitMemberVar; deliberate
34 vec_fb() = default;
35 vec_fb(const vec_fb&) = default;
36 vec_fb& operator=(const vec_fb&) = default;
37 vec_fb(std::initializer_list<T> init)
38 {
39 std::copy(init.begin(), init.end(), m_arr);
40 std::fill(m_arr + init.size(), m_arr + N, T());
41 }
42
43 T operator[](size_t n) const { return m_arr[n]; }
44 T& operator[](size_t n) { return m_arr[n]; }
45
46 T m_arr[N];
47};
48
49// Helper: Given a vectorized class, find another vectorized class
50// that uses integers of the same size as the original class.
51template <typename T, size_t N>
52using ivec = vec_fb<CxxUtils::bit_int_t<sizeof(T) * 8>, N>;
53
54// Define binary operations.
55// For each operation, define
56// V1 OP V2
57// V OP S
58// S OP V
59// V1 OP= V2
60// V OP= S
61
62#define BINOP(op) \
63 template<typename T, size_t N> \
64 inline vec_fb<T, N> operator op(const vec_fb<T, N>& a, \
65 const vec_fb<T, N>& b) \
66 { \
67 vec_fb<T, N> c; \
68 for (size_t i = 0; i < N; ++i) \
69 c.m_arr[i] = a.m_arr[i] op b.m_arr[i]; \
70 return c; \
71 } \
72 template<typename T, size_t N, typename U> \
73 inline vec_fb<T, N> operator op(const vec_fb<T, N>& a, U b) \
74 { \
75 vec_fb<T, N> c; \
76 for (size_t i = 0; i < N; ++i) \
77 c.m_arr[i] = a.m_arr[i] op b; \
78 return c; \
79 } \
80 template<typename T, size_t N, typename U> \
81 inline vec_fb<T, N> operator op(U a, const vec_fb<T, N>& b) \
82 { \
83 vec_fb<T, N> c; \
84 for (size_t i = 0; i < N; ++i) \
85 c.m_arr[i] = a op b.m_arr[i]; \
86 return c; \
87 } \
88 template<typename T, size_t N> \
89 inline vec_fb<T, N>& operator op##=(vec_fb<T, N>& a, const vec_fb<T, N>& b) \
90 { \
91 for (size_t i = 0; i < N; ++i) \
92 a.m_arr[i] op## = b.m_arr[i]; \
93 return a; \
94 } \
95 template<typename T, size_t N, typename U> \
96 inline vec_fb<T, N>& operator op##=(vec_fb<T, N>& a, U b) \
97 { \
98 for (size_t i = 0; i < N; ++i) \
99 a.m_arr[i] op## = b; \
100 return a; \
101 }
102
103BINOP(+)
104BINOP(-)
105BINOP(*)
106BINOP(/)
107BINOP(^)
108BINOP(|)
109BINOP(&)
110BINOP(%)
111BINOP(>>)
112BINOP(<<)
113
114#undef BINOP
115
116// Define unary operations.
117
118#define UNOP(op) \
119 template<typename T, size_t N> \
120 inline vec_fb<T, N> operator op(const vec_fb<T, N>& a) \
121 { \
122 vec_fb<T, N> c; \
123 for (size_t i = 0; i < N; ++i) \
124 c.m_arr[i] = op a.m_arr[i]; \
125 return c; \
126 }
127
128UNOP(-)
129UNOP(~)
130
131#undef UNOP
132
133// Define relational operations.
134
135#define RELOP(op) \
136 template<typename T, size_t N> \
137 inline ivec<T, N> operator op(const vec_fb<T, N>& a, const vec_fb<T, N>& b) \
138 { \
139 ivec<T, N> c; \
140 for (size_t i = 0; i < N; ++i) \
141 c.m_arr[i] = a.m_arr[i] op b.m_arr[i]; \
142 return c; \
143 }
144
145RELOP(==)
146RELOP(!=)
147RELOP(<)
148RELOP(<=)
149RELOP(>)
150RELOP(>=)
151
152#undef RELOP
153
155template<typename T, size_t N>
156inline ivec<T, N>
158{
159 ivec<T, N> c;
160 for (size_t i = 0; i < N; ++i)
161 c.m_arr[i] = a.m_arr[i] == 0;
162 return c;
163}
164
166template<typename T, size_t N>
167inline ivec<T, N>
169{
170 ivec<T, N> c;
171 for (size_t i = 0; i < N; ++i)
172 c.m_arr[i] = (a.m_arr[i] != 0) & (b.m_arr[i] != 0);
173 return c;
174}
175
177template<typename T, size_t N, class U>
178inline ivec<T, N>
180{
181 ivec<T, N> c;
182 for (size_t i = 0; i < N; ++i)
183 c.m_arr[i] = a ? b.m_arr[i] != 0 : 0;
184 return c;
185}
186
188template<typename T, size_t N, class U>
189inline ivec<T, N>
191{
192 ivec<T, N> c;
193 for (size_t i = 0; i < N; ++i)
194 c.m_arr[i] = (a.m_arr[i] != 0) & (b ? -1 : 0);
195 return c;
196}
197
199template<typename T, size_t N>
200inline ivec<T, N>
202{
203 ivec<T, N> c;
204 for (size_t i = 0; i < N; ++i)
205 c.m_arr[i] = (a.m_arr[i] != 0) | (b.m_arr[i] != 0);
206 return c;
207}
208
209} // namespace CxxUtils
210
211#endif // CXXUTILS_VEC_FB_H
static Double_t a
Ispired by std::bit_int is proposed for a future C++ standard (P3666R2).
typename bit_int< Bits >::type bit_int_t
Definition bit_int.h:25
vec_fb< CxxUtils::bit_int_t< sizeof(T) *8 >, N > ivec
Definition vec_fb.h:52
ivec< T, N > operator||(const vec_fb< T, N > &a, const vec_fb< T, N > &b)
V1 || V2.
Definition vec_fb.h:201
ivec< T, N > operator&&(const vec_fb< T, N > &a, const vec_fb< T, N > &b)
V1 && V2.
Definition vec_fb.h:168
vec_fb & operator=(const vec_fb &)=default
T operator[](size_t n) const
Definition vec_fb.h:43
vec_fb(std::initializer_list< T > init)
Definition vec_fb.h:37
vec_fb()=default
T & operator[](size_t n)
Definition vec_fb.h:44
vec_fb(const vec_fb &)=default
#define RELOP(op)
Definition vec_fb.h:135
#define UNOP(op)
Definition vec_fb.h:118
#define BINOP(op)
Definition vec_fb.h:62