Logo ROOT  
Reference Guide
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// Check that no bytes are wasted and everything is well-aligned.
17namespace {
18struct Struct16B {
19 alignas(16) void *X;
20};
21struct Struct32B {
22 alignas(32) void *X;
23};
24}
25static_assert(alignof(RVec<Struct16B>) >= alignof(Struct16B), "wrong alignment for 16-byte aligned T");
26static_assert(alignof(RVec<Struct32B>) >= alignof(Struct32B), "wrong alignment for 32-byte aligned T");
27static_assert(sizeof(RVec<Struct16B>) >= alignof(Struct16B), "missing padding for 16-byte aligned T");
28static_assert(sizeof(RVec<Struct32B>) >= alignof(Struct32B), "missing padding for 32-byte aligned T");
29static_assert(sizeof(RVecN<void *, 0>) == sizeof(int32_t) * 2 + sizeof(void *), "wasted space in RVec");
30static_assert(sizeof(RVecN<void *, 1>) == sizeof(int32_t) * 2 + sizeof(void *) * 2,
31 "wasted space in SmallVector size 1");
32static_assert(sizeof(RVec<void *>) ==
33 sizeof(int32_t) * 2 +
35 "wasted space in RVec");
36
38{
39 std::string Reason = "RVec unable to grow. Requested capacity (" + std::to_string(MinSize) +
40 ") is larger than maximum value for size type (" + std::to_string(SizeTypeMax()) + ")";
41 throw std::length_error(Reason);
42}
43
45{
46 std::string Reason = "RVec capacity unable to grow. Already at maximum size " + std::to_string(SizeTypeMax());
47 throw std::length_error(Reason);
48}
49
50// Note: Moving this function into the header may cause performance regression.
51void ROOT::Internal::VecOps::SmallVectorBase::grow_pod(void *FirstEl, size_t MinSize, size_t TSize)
52{
53 // Ensure we can fit the new capacity.
54 // This is only going to be applicable when the capacity is 32 bit.
55 if (MinSize > SizeTypeMax())
56 report_size_overflow(MinSize);
57
58 // Ensure we can meet the guarantee of space for at least one more element.
59 // The above check alone will not catch the case where grow is called with a
60 // default MinSize of 0, but the current capacity cannot be increased.
61 // This is only going to be applicable when the capacity is 32 bit.
62 if (capacity() == SizeTypeMax())
63 report_at_maximum_capacity();
64
65 // In theory 2*capacity can overflow if the capacity is 64 bit, but the
66 // original capacity would never be large enough for this to be a problem.
67 size_t NewCapacity = 2 * capacity() + 1; // Always grow.
68 NewCapacity = std::min(std::max(NewCapacity, MinSize), SizeTypeMax());
69
70 void *NewElts;
71 if (fBeginX == FirstEl || !this->Owns()) {
72 NewElts = malloc(NewCapacity * TSize);
73 R__ASSERT(NewElts != nullptr);
74
75 // Copy the elements over. No need to run dtors on PODs.
76 memcpy(NewElts, this->fBeginX, size() * TSize);
77 } else {
78 // If this wasn't grown from the inline copy, grow the allocated space.
79 NewElts = realloc(this->fBeginX, NewCapacity * TSize);
80 R__ASSERT(NewElts != nullptr);
81 }
82
83 this->fBeginX = NewElts;
84 this->fCapacity = NewCapacity;
85}
86
87#if (_VECOPS_USE_EXTERN_TEMPLATES)
88
89namespace ROOT {
90namespace VecOps {
91
92#define RVEC_DECLARE_UNARY_OPERATOR(T, OP) \
93 template RVec<T> operator OP(const RVec<T> &);
94
95#define RVEC_DECLARE_BINARY_OPERATOR(T, OP) \
96 template auto operator OP(const RVec<T> &v, const T &y) -> RVec<decltype(v[0] OP y)>; \
97 template auto operator OP(const T &x, const RVec<T> &v) -> RVec<decltype(x OP v[0])>; \
98 template auto operator OP(const RVec<T> &v0, const RVec<T> &v1) -> RVec<decltype(v0[0] OP v1[0])>;
99
100#define RVEC_DECLARE_LOGICAL_OPERATOR(T, OP) \
101 template RVec<int> operator OP(const RVec<T> &, const T &); \
102 template RVec<int> operator OP(const T &, const RVec<T> &); \
103 template RVec<int> operator OP(const RVec<T> &, const RVec<T> &);
104
105#define RVEC_DECLARE_ASSIGN_OPERATOR(T, OP) \
106 template RVec<T> &operator OP(RVec<T> &, const T &); \
107 template RVec<T> &operator OP(RVec<T> &, const RVec<T> &);
108
109#define RVEC_DECLARE_FLOAT_TEMPLATE(T) \
110 template class RVec<T>; \
111 RVEC_DECLARE_UNARY_OPERATOR(T, +) \
112 RVEC_DECLARE_UNARY_OPERATOR(T, -) \
113 RVEC_DECLARE_UNARY_OPERATOR(T, !) \
114 RVEC_DECLARE_BINARY_OPERATOR(T, +) \
115 RVEC_DECLARE_BINARY_OPERATOR(T, -) \
116 RVEC_DECLARE_BINARY_OPERATOR(T, *) \
117 RVEC_DECLARE_BINARY_OPERATOR(T, /) \
118 RVEC_DECLARE_ASSIGN_OPERATOR(T, +=) \
119 RVEC_DECLARE_ASSIGN_OPERATOR(T, -=) \
120 RVEC_DECLARE_ASSIGN_OPERATOR(T, *=) \
121 RVEC_DECLARE_ASSIGN_OPERATOR(T, /=) \
122 RVEC_DECLARE_LOGICAL_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
131#define RVEC_DECLARE_INTEGER_TEMPLATE(T) \
132 template class RVec<T>; \
133 RVEC_DECLARE_UNARY_OPERATOR(T, +) \
134 RVEC_DECLARE_UNARY_OPERATOR(T, -) \
135 RVEC_DECLARE_UNARY_OPERATOR(T, ~) \
136 RVEC_DECLARE_UNARY_OPERATOR(T, !) \
137 RVEC_DECLARE_BINARY_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_ASSIGN_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_LOGICAL_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
164RVEC_DECLARE_INTEGER_TEMPLATE(char)
165RVEC_DECLARE_INTEGER_TEMPLATE(short)
166RVEC_DECLARE_INTEGER_TEMPLATE(int)
167RVEC_DECLARE_INTEGER_TEMPLATE(long)
168RVEC_DECLARE_INTEGER_TEMPLATE(long long)
169
170RVEC_DECLARE_INTEGER_TEMPLATE(unsigned char)
171RVEC_DECLARE_INTEGER_TEMPLATE(unsigned short)
172RVEC_DECLARE_INTEGER_TEMPLATE(unsigned int)
173RVEC_DECLARE_INTEGER_TEMPLATE(unsigned long)
174RVEC_DECLARE_INTEGER_TEMPLATE(unsigned long long)
175
176RVEC_DECLARE_FLOAT_TEMPLATE(float)
177RVEC_DECLARE_FLOAT_TEMPLATE(double)
178
179#define RVEC_DECLARE_UNARY_FUNCTION(T, NAME, FUNC) \
180 template RVec<PromoteType<T>> NAME(const RVec<T> &);
181
182#define RVEC_DECLARE_STD_UNARY_FUNCTION(T, F) RVEC_DECLARE_UNARY_FUNCTION(T, F, ::std::F)
183
184#define RVEC_DECLARE_BINARY_FUNCTION(T0, T1, NAME, FUNC) \
185 template RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &v, const T1 &y); \
186 template RVec<PromoteTypes<T0, T1>> NAME(const T0 &x, const RVec<T1> &v); \
187 template RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &v0, const RVec<T1> &v1);
188
189#define RVEC_DECLARE_STD_BINARY_FUNCTION(T, F) RVEC_DECLARE_BINARY_FUNCTION(T, T, F, ::std::F)
190
191#define RVEC_DECLARE_STD_FUNCTIONS(T) \
192 RVEC_DECLARE_STD_UNARY_FUNCTION(T, abs) \
193 RVEC_DECLARE_STD_BINARY_FUNCTION(T, fdim) \
194 RVEC_DECLARE_STD_BINARY_FUNCTION(T, fmod) \
195 RVEC_DECLARE_STD_BINARY_FUNCTION(T, remainder) \
196 RVEC_DECLARE_STD_UNARY_FUNCTION(T, exp) \
197 RVEC_DECLARE_STD_UNARY_FUNCTION(T, exp2) \
198 RVEC_DECLARE_STD_UNARY_FUNCTION(T, expm1) \
199 RVEC_DECLARE_STD_UNARY_FUNCTION(T, log) \
200 RVEC_DECLARE_STD_UNARY_FUNCTION(T, log10) \
201 RVEC_DECLARE_STD_UNARY_FUNCTION(T, log2) \
202 RVEC_DECLARE_STD_UNARY_FUNCTION(T, log1p) \
203 RVEC_DECLARE_STD_BINARY_FUNCTION(T, pow) \
204 RVEC_DECLARE_STD_UNARY_FUNCTION(T, sqrt) \
205 RVEC_DECLARE_STD_UNARY_FUNCTION(T, cbrt) \
206 RVEC_DECLARE_STD_BINARY_FUNCTION(T, hypot) \
207 RVEC_DECLARE_STD_UNARY_FUNCTION(T, sin) \
208 RVEC_DECLARE_STD_UNARY_FUNCTION(T, cos) \
209 RVEC_DECLARE_STD_UNARY_FUNCTION(T, tan) \
210 RVEC_DECLARE_STD_UNARY_FUNCTION(T, asin) \
211 RVEC_DECLARE_STD_UNARY_FUNCTION(T, acos) \
212 RVEC_DECLARE_STD_UNARY_FUNCTION(T, atan) \
213 RVEC_DECLARE_STD_BINARY_FUNCTION(T, atan2) \
214 RVEC_DECLARE_STD_UNARY_FUNCTION(T, sinh) \
215 RVEC_DECLARE_STD_UNARY_FUNCTION(T, cosh) \
216 RVEC_DECLARE_STD_UNARY_FUNCTION(T, tanh) \
217 RVEC_DECLARE_STD_UNARY_FUNCTION(T, asinh) \
218 RVEC_DECLARE_STD_UNARY_FUNCTION(T, acosh) \
219 RVEC_DECLARE_STD_UNARY_FUNCTION(T, atanh) \
220 RVEC_DECLARE_STD_UNARY_FUNCTION(T, floor) \
221 RVEC_DECLARE_STD_UNARY_FUNCTION(T, ceil) \
222 RVEC_DECLARE_STD_UNARY_FUNCTION(T, trunc) \
223 RVEC_DECLARE_STD_UNARY_FUNCTION(T, round) \
224 RVEC_DECLARE_STD_UNARY_FUNCTION(T, lround) \
225 RVEC_DECLARE_STD_UNARY_FUNCTION(T, llround) \
226 RVEC_DECLARE_STD_UNARY_FUNCTION(T, erf) \
227 RVEC_DECLARE_STD_UNARY_FUNCTION(T, erfc) \
228 RVEC_DECLARE_STD_UNARY_FUNCTION(T, lgamma) \
229 RVEC_DECLARE_STD_UNARY_FUNCTION(T, tgamma) \
230
231RVEC_DECLARE_STD_FUNCTIONS(float)
232RVEC_DECLARE_STD_FUNCTIONS(double)
233#undef RVEC_DECLARE_STD_UNARY_FUNCTION
234#undef RVEC_DECLARE_STD_BINARY_FUNCTION
235#undef RVEC_DECLARE_STD_UNARY_FUNCTIONS
236
237#ifdef R__HAS_VDT
238
239#define RVEC_DECLARE_VDT_UNARY_FUNCTION(T, F) \
240 RVEC_DECLARE_UNARY_FUNCTION(T, F, vdt::F)
241
242RVEC_DECLARE_VDT_UNARY_FUNCTION(float, fast_expf)
243RVEC_DECLARE_VDT_UNARY_FUNCTION(float, fast_logf)
244RVEC_DECLARE_VDT_UNARY_FUNCTION(float, fast_sinf)
245RVEC_DECLARE_VDT_UNARY_FUNCTION(float, fast_cosf)
246RVEC_DECLARE_VDT_UNARY_FUNCTION(float, fast_tanf)
247RVEC_DECLARE_VDT_UNARY_FUNCTION(float, fast_asinf)
248RVEC_DECLARE_VDT_UNARY_FUNCTION(float, fast_acosf)
249RVEC_DECLARE_VDT_UNARY_FUNCTION(float, fast_atanf)
250
251RVEC_DECLARE_VDT_UNARY_FUNCTION(double, fast_exp)
252RVEC_DECLARE_VDT_UNARY_FUNCTION(double, fast_log)
253RVEC_DECLARE_VDT_UNARY_FUNCTION(double, fast_sin)
254RVEC_DECLARE_VDT_UNARY_FUNCTION(double, fast_cos)
255RVEC_DECLARE_VDT_UNARY_FUNCTION(double, fast_tan)
256RVEC_DECLARE_VDT_UNARY_FUNCTION(double, fast_asin)
257RVEC_DECLARE_VDT_UNARY_FUNCTION(double, fast_acos)
258RVEC_DECLARE_VDT_UNARY_FUNCTION(double, fast_atan)
259
260#endif // R__HAS_VDT
261
262} // namespace VecOps
263} // namespace ROOT
264
265#endif // _VECOPS_USE_EXTERN_TEMPLATES
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
#define R__ASSERT(e)
Definition: TError.h:118
#define realloc
Definition: civetweb.c:1538
#define malloc
Definition: civetweb.c:1536
static constexpr size_t SizeTypeMax()
The maximum value of the Size_T used.
Definition: RVec.hxx:135
static void report_size_overflow(size_t MinSize)
Report that MinSize doesn't fit into this vector's size type.
Definition: RVec.cxx:37
static void report_at_maximum_capacity()
Report that this vector is already at maximum capacity.
Definition: RVec.cxx:44
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:51
A "std::vector"-like collection of values implementing handy operation to analyse them.
Definition: RVec.hxx:1439
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
__roodevice__ double fast_exp(double x)
Definition: RooVDTHeaders.h:53
__roodevice__ double fast_log(double x)
Definition: RooVDTHeaders.h:57
The size of the inline storage of an RVec.
Definition: RVec.hxx:494