Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RVec.cxx
Go to the documentation of this file.
1// Author: Enrico Guiraud, Enric Tejedor, Danilo Piparo CERN 04/2021
2// Implementation adapted from from llvm::SmallVector.
3// See /math/vecops/ARCHITECTURE.md for more information.
4
5/*************************************************************************
6 * Copyright (C) 1995-2021, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13#include "ROOT/RVec.hxx"
14using namespace ROOT::VecOps;
15
16#ifdef R__HAS_VDT
17#include "vdt/vdtMath.h"
18#endif
19
20// Check that no bytes are wasted and everything is well-aligned.
21namespace {
22struct Struct16B {
23 alignas(16) void *X;
24};
25struct Struct32B {
26 alignas(32) void *X;
27};
28}
29static_assert(alignof(RVec<Struct16B>) >= alignof(Struct16B), "wrong alignment for 16-byte aligned T");
30static_assert(alignof(RVec<Struct32B>) >= alignof(Struct32B), "wrong alignment for 32-byte aligned T");
31static_assert(sizeof(RVec<Struct16B>) >= alignof(Struct16B), "missing padding for 16-byte aligned T");
32static_assert(sizeof(RVec<Struct32B>) >= alignof(Struct32B), "missing padding for 32-byte aligned T");
33static_assert(sizeof(RVecN<void *, 0>) == sizeof(int32_t) * 2 + sizeof(void *), "wasted space in RVec");
34static_assert(sizeof(RVecN<void *, 1>) == sizeof(int32_t) * 2 + sizeof(void *) * 2,
35 "wasted space in SmallVector size 1");
36static_assert(sizeof(RVec<void *>) ==
37 sizeof(int32_t) * 2 +
39 "wasted space in RVec");
40
42{
43 std::string Reason = "RVec unable to grow. Requested capacity (" + std::to_string(MinSize) +
44 ") is larger than maximum value for size type (" + std::to_string(SizeTypeMax()) + ")";
45 throw std::length_error(Reason);
46}
47
49{
50 std::string Reason = "RVec capacity unable to grow. Already at maximum size " + std::to_string(SizeTypeMax());
51 throw std::length_error(Reason);
52}
53
54// Note: Moving this function into the header may cause performance regression.
55void ROOT::Internal::VecOps::SmallVectorBase::grow_pod(void *FirstEl, size_t MinSize, size_t TSize)
56{
57 // Ensure we can fit the new capacity.
58 // This is only going to be applicable when the capacity is 32 bit.
59 if (MinSize > SizeTypeMax())
60 report_size_overflow(MinSize);
61
62 // Ensure we can meet the guarantee of space for at least one more element.
63 // The above check alone will not catch the case where grow is called with a
64 // default MinSize of 0, but the current capacity cannot be increased.
65 // This is only going to be applicable when the capacity is 32 bit.
66 if (capacity() == SizeTypeMax())
67 report_at_maximum_capacity();
68
69 // In theory 2*capacity can overflow if the capacity is 64 bit, but the
70 // original capacity would never be large enough for this to be a problem.
71 size_t NewCapacity = 2 * capacity() + 1; // Always grow.
72 NewCapacity = std::min(std::max(NewCapacity, MinSize), SizeTypeMax());
73
74 void *NewElts = ::operator new(NewCapacity * TSize, std::nothrow);
75 R__ASSERT(NewElts != nullptr);
76 // Copy the elements over. No need to run dtors on PODs.
77 memcpy(NewElts, this->fBeginX, size() * TSize);
78
79 if (fBeginX != FirstEl && this->Owns()) {
80 // If this wasn't grown from the inline copy, delete the previously allocated space.
81 ::operator delete(this->fBeginX);
82 }
83
84 this->fBeginX = NewElts;
85 this->fCapacity = NewCapacity;
86}
87
88#if (_VECOPS_USE_EXTERN_TEMPLATES)
89
90namespace ROOT {
91namespace VecOps {
92
93#define RVEC_DECLARE_UNARY_OPERATOR(T, OP) \
94 template RVec<T> operator OP(const RVec<T> &);
95
96#define RVEC_DECLARE_BINARY_OPERATOR(T, OP) \
97 template auto operator OP(const RVec<T> &v, const T &y) -> RVec<decltype(v[0] OP y)>; \
98 template auto operator OP(const T &x, const RVec<T> &v) -> RVec<decltype(x OP v[0])>; \
99 template auto operator OP(const RVec<T> &v0, const RVec<T> &v1) -> RVec<decltype(v0[0] OP v1[0])>;
100
101#define RVEC_DECLARE_LOGICAL_OPERATOR(T, OP) \
102 template RVec<int> operator OP(const RVec<T> &, const T &); \
103 template RVec<int> operator OP(const T &, const RVec<T> &); \
104 template RVec<int> operator OP(const RVec<T> &, const RVec<T> &);
105
106#define RVEC_DECLARE_ASSIGN_OPERATOR(T, OP) \
107 template RVec<T> &operator OP(RVec<T> &, const T &); \
108 template RVec<T> &operator OP(RVec<T> &, const RVec<T> &);
109
110#define RVEC_DECLARE_FLOAT_TEMPLATE(T) \
111 template class RVec<T>; \
112 RVEC_DECLARE_UNARY_OPERATOR(T, +) \
113 RVEC_DECLARE_UNARY_OPERATOR(T, -) \
114 RVEC_DECLARE_UNARY_OPERATOR(T, !) \
115 RVEC_DECLARE_BINARY_OPERATOR(T, +) \
116 RVEC_DECLARE_BINARY_OPERATOR(T, -) \
117 RVEC_DECLARE_BINARY_OPERATOR(T, *) \
118 RVEC_DECLARE_BINARY_OPERATOR(T, /) \
119 RVEC_DECLARE_ASSIGN_OPERATOR(T, +=) \
120 RVEC_DECLARE_ASSIGN_OPERATOR(T, -=) \
121 RVEC_DECLARE_ASSIGN_OPERATOR(T, *=) \
122 RVEC_DECLARE_ASSIGN_OPERATOR(T, /=) \
123 RVEC_DECLARE_LOGICAL_OPERATOR(T, <) \
124 RVEC_DECLARE_LOGICAL_OPERATOR(T, >) \
125 RVEC_DECLARE_LOGICAL_OPERATOR(T, ==) \
126 RVEC_DECLARE_LOGICAL_OPERATOR(T, !=) \
127 RVEC_DECLARE_LOGICAL_OPERATOR(T, <=) \
128 RVEC_DECLARE_LOGICAL_OPERATOR(T, >=) \
129 RVEC_DECLARE_LOGICAL_OPERATOR(T, &&) \
130 RVEC_DECLARE_LOGICAL_OPERATOR(T, ||)
131
132#define RVEC_DECLARE_INTEGER_TEMPLATE(T) \
133 template class RVec<T>; \
134 RVEC_DECLARE_UNARY_OPERATOR(T, +) \
135 RVEC_DECLARE_UNARY_OPERATOR(T, -) \
136 RVEC_DECLARE_UNARY_OPERATOR(T, ~) \
137 RVEC_DECLARE_UNARY_OPERATOR(T, !) \
138 RVEC_DECLARE_BINARY_OPERATOR(T, +) \
139 RVEC_DECLARE_BINARY_OPERATOR(T, -) \
140 RVEC_DECLARE_BINARY_OPERATOR(T, *) \
141 RVEC_DECLARE_BINARY_OPERATOR(T, /) \
142 RVEC_DECLARE_BINARY_OPERATOR(T, %) \
143 RVEC_DECLARE_BINARY_OPERATOR(T, &) \
144 RVEC_DECLARE_BINARY_OPERATOR(T, |) \
145 RVEC_DECLARE_BINARY_OPERATOR(T, ^) \
146 RVEC_DECLARE_ASSIGN_OPERATOR(T, +=) \
147 RVEC_DECLARE_ASSIGN_OPERATOR(T, -=) \
148 RVEC_DECLARE_ASSIGN_OPERATOR(T, *=) \
149 RVEC_DECLARE_ASSIGN_OPERATOR(T, /=) \
150 RVEC_DECLARE_ASSIGN_OPERATOR(T, %=) \
151 RVEC_DECLARE_ASSIGN_OPERATOR(T, &=) \
152 RVEC_DECLARE_ASSIGN_OPERATOR(T, |=) \
153 RVEC_DECLARE_ASSIGN_OPERATOR(T, ^=) \
154 RVEC_DECLARE_ASSIGN_OPERATOR(T, >>=) \
155 RVEC_DECLARE_ASSIGN_OPERATOR(T, <<=) \
156 RVEC_DECLARE_LOGICAL_OPERATOR(T, <) \
157 RVEC_DECLARE_LOGICAL_OPERATOR(T, >) \
158 RVEC_DECLARE_LOGICAL_OPERATOR(T, ==) \
159 RVEC_DECLARE_LOGICAL_OPERATOR(T, !=) \
160 RVEC_DECLARE_LOGICAL_OPERATOR(T, <=) \
161 RVEC_DECLARE_LOGICAL_OPERATOR(T, >=) \
162 RVEC_DECLARE_LOGICAL_OPERATOR(T, &&) \
163 RVEC_DECLARE_LOGICAL_OPERATOR(T, ||)
164
165RVEC_DECLARE_INTEGER_TEMPLATE(char)
166RVEC_DECLARE_INTEGER_TEMPLATE(short)
167RVEC_DECLARE_INTEGER_TEMPLATE(int)
168RVEC_DECLARE_INTEGER_TEMPLATE(long)
169RVEC_DECLARE_INTEGER_TEMPLATE(long long)
170
171RVEC_DECLARE_INTEGER_TEMPLATE(unsigned char)
172RVEC_DECLARE_INTEGER_TEMPLATE(unsigned short)
173RVEC_DECLARE_INTEGER_TEMPLATE(unsigned int)
174RVEC_DECLARE_INTEGER_TEMPLATE(unsigned long)
175RVEC_DECLARE_INTEGER_TEMPLATE(unsigned long long)
176
177RVEC_DECLARE_FLOAT_TEMPLATE(float)
178RVEC_DECLARE_FLOAT_TEMPLATE(double)
179
180#define RVEC_DECLARE_UNARY_FUNCTION(T, NAME, FUNC) \
181 template RVec<PromoteType<T>> NAME(const RVec<T> &);
182
183#define RVEC_DECLARE_STD_UNARY_FUNCTION(T, F) RVEC_DECLARE_UNARY_FUNCTION(T, F, ::std::F)
184
185#define RVEC_DECLARE_BINARY_FUNCTION(T0, T1, NAME, FUNC) \
186 template RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &v, const T1 &y); \
187 template RVec<PromoteTypes<T0, T1>> NAME(const T0 &x, const RVec<T1> &v); \
188 template RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &v0, const RVec<T1> &v1);
189
190#define RVEC_DECLARE_STD_BINARY_FUNCTION(T, F) RVEC_DECLARE_BINARY_FUNCTION(T, T, F, ::std::F)
191
192#define RVEC_DECLARE_STD_FUNCTIONS(T) \
193 RVEC_DECLARE_STD_UNARY_FUNCTION(T, abs) \
194 RVEC_DECLARE_STD_BINARY_FUNCTION(T, fdim) \
195 RVEC_DECLARE_STD_BINARY_FUNCTION(T, fmod) \
196 RVEC_DECLARE_STD_BINARY_FUNCTION(T, remainder) \
197 RVEC_DECLARE_STD_UNARY_FUNCTION(T, exp) \
198 RVEC_DECLARE_STD_UNARY_FUNCTION(T, exp2) \
199 RVEC_DECLARE_STD_UNARY_FUNCTION(T, expm1) \
200 RVEC_DECLARE_STD_UNARY_FUNCTION(T, log) \
201 RVEC_DECLARE_STD_UNARY_FUNCTION(T, log10) \
202 RVEC_DECLARE_STD_UNARY_FUNCTION(T, log2) \
203 RVEC_DECLARE_STD_UNARY_FUNCTION(T, log1p) \
204 RVEC_DECLARE_STD_BINARY_FUNCTION(T, pow) \
205 RVEC_DECLARE_STD_UNARY_FUNCTION(T, sqrt) \
206 RVEC_DECLARE_STD_UNARY_FUNCTION(T, cbrt) \
207 RVEC_DECLARE_STD_BINARY_FUNCTION(T, hypot) \
208 RVEC_DECLARE_STD_UNARY_FUNCTION(T, sin) \
209 RVEC_DECLARE_STD_UNARY_FUNCTION(T, cos) \
210 RVEC_DECLARE_STD_UNARY_FUNCTION(T, tan) \
211 RVEC_DECLARE_STD_UNARY_FUNCTION(T, asin) \
212 RVEC_DECLARE_STD_UNARY_FUNCTION(T, acos) \
213 RVEC_DECLARE_STD_UNARY_FUNCTION(T, atan) \
214 RVEC_DECLARE_STD_BINARY_FUNCTION(T, atan2) \
215 RVEC_DECLARE_STD_UNARY_FUNCTION(T, sinh) \
216 RVEC_DECLARE_STD_UNARY_FUNCTION(T, cosh) \
217 RVEC_DECLARE_STD_UNARY_FUNCTION(T, tanh) \
218 RVEC_DECLARE_STD_UNARY_FUNCTION(T, asinh) \
219 RVEC_DECLARE_STD_UNARY_FUNCTION(T, acosh) \
220 RVEC_DECLARE_STD_UNARY_FUNCTION(T, atanh) \
221 RVEC_DECLARE_STD_UNARY_FUNCTION(T, floor) \
222 RVEC_DECLARE_STD_UNARY_FUNCTION(T, ceil) \
223 RVEC_DECLARE_STD_UNARY_FUNCTION(T, trunc) \
224 RVEC_DECLARE_STD_UNARY_FUNCTION(T, round) \
225 RVEC_DECLARE_STD_UNARY_FUNCTION(T, lround) \
226 RVEC_DECLARE_STD_UNARY_FUNCTION(T, llround) \
227 RVEC_DECLARE_STD_UNARY_FUNCTION(T, erf) \
228 RVEC_DECLARE_STD_UNARY_FUNCTION(T, erfc) \
229 RVEC_DECLARE_STD_UNARY_FUNCTION(T, lgamma) \
230 RVEC_DECLARE_STD_UNARY_FUNCTION(T, tgamma) \
231
232RVEC_DECLARE_STD_FUNCTIONS(float)
233RVEC_DECLARE_STD_FUNCTIONS(double)
234#undef RVEC_DECLARE_STD_UNARY_FUNCTION
235#undef RVEC_DECLARE_STD_BINARY_FUNCTION
236#undef RVEC_DECLARE_STD_UNARY_FUNCTIONS
237
238#ifdef R__HAS_VDT
239
240#define RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(FP, FUNC) \
241 RVec<FP> FUNC(RVec<FP> const &in) \
242 { \
243 RVec<FP> out(in.size()); \
244 for (unsigned int i = 0; i < in.size(); ++i) { \
245 out[i] = vdt::FUNC(in[i]); \
246 } \
247 return out; \
248 }
249
250RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(float, fast_expf)
251RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(float, fast_logf)
252RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(float, fast_sinf)
253RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(float, fast_cosf)
254RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(float, fast_tanf)
255RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(float, fast_asinf)
256RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(float, fast_acosf)
257RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(float, fast_atanf)
258
259RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(double, fast_exp)
260RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(double, fast_log)
261RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(double, fast_sin)
262RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(double, fast_cos)
263RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(double, fast_tan)
264RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(double, fast_asin)
265RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(double, fast_acos)
266RVEC_IMPLEMENT_VDT_UNARY_FUNCTION(double, fast_atan)
267
268#endif // R__HAS_VDT
269
270} // namespace VecOps
271} // namespace ROOT
272
273#endif // _VECOPS_USE_EXTERN_TEMPLATES
std::size_t capacity
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define R__ASSERT(e)
Checks condition e and reports a fatal error if it's false.
Definition TError.h:139
static constexpr size_t SizeTypeMax()
The maximum value of the Size_T used.
Definition RVec.hxx:143
static void report_size_overflow(size_t MinSize)
Report that MinSize doesn't fit into this vector's size type.
Definition RVec.cxx:41
static void report_at_maximum_capacity()
Report that this vector is already at maximum capacity.
Definition RVec.cxx:48
void grow_pod(void *FirstEl, size_t MinSize, size_t TSize)
This is an implementation of the grow() method which only works on POD-like data types and is out of ...
Definition RVec.cxx:55
A "std::vector"-like collection of values implementing handy operation to analyse them.
Definition RVec.hxx:1509
The size of the inline storage of an RVec.
Definition RVec.hxx:509