Theoretica
Scientific Computing
Loading...
Searching...
No Matches
dataset.h
Go to the documentation of this file.
1
6
7#ifndef THEORETICA_DATASET_H
8#define THEORETICA_DATASET_H
9
10#ifndef THEORETICA_NO_PRINT
11#include <sstream>
12#include <ostream>
13#endif
14
15#include "./core_traits.h"
16#include "./constants.h"
17#include "./error.h"
18
19
20namespace theoretica {
21
22
24 template<typename Vector, enable_vector<Vector> = true>
25 inline auto product(const Vector& X) {
26
27 if(!X.size()) {
28 TH_MATH_ERROR("product", X.size(), MathError::InvalidArgument);
30 }
31
32 auto res = X[0];
33 for(unsigned int i = 1; i < X.size(); i++)
34 res *= X[i];
35
36 return res;
37 }
38
39
41 template<typename Vector>
42 inline auto product_sum(const Vector& X, const Vector& Y) {
43
44 if(X.size() != Y.size() || !X.size()) {
45 TH_MATH_ERROR("product_sum", X.size(), MathError::InvalidArgument);
46 return nan();
47 }
48
49 auto res = X[0] * Y[0];
50 for(unsigned int i = 1; i < X.size(); i++)
51 res += X[i] * Y[i];
52
53 return res;
54 }
55
56
58 template<typename Vector>
59 inline auto product_sum_squares(const Vector& X, const Vector& Y) {
60
61 if(X.size() != Y.size() || !X.size()) {
62 TH_MATH_ERROR("product_sum_squares", X.size(), MathError::InvalidArgument);
63 return nan();
64 }
65
66 auto res = (X[0] * X[0]) * (Y[0] * Y[0]);
67
68 for(unsigned int i = 1; i < X.size(); i++)
69 res += (X[i] * X[i]) * (Y[i] * Y[i]);
70
71 return res;
72 }
73
74
76 template<typename Vector>
77 inline auto product_sum(const Vector& X, const Vector& Y, const Vector& Z) {
78
79 if(X.size() != Y.size() || X.size() != Z.size() || !X.size()) {
80 TH_MATH_ERROR("product_sum", X.size(), MathError::InvalidArgument);
81 return nan();
82 }
83
84 auto res = X[0] * Y[0] * Z[0];
85 for(unsigned int i = 1; i < X.size(); i++)
86 res += X[i] * Y[i] * Z[i];
87
88 return res;
89 }
90
91
93 template<typename Vector>
94 inline auto quotient_sum(const Vector& X, const Vector& Y) {
95
96 if(X.size() != Y.size()) {
97 TH_MATH_ERROR("quotient_sum", X.size(), MathError::InvalidArgument);
98 return nan();
99 }
100
101 if(abs(Y[0]) < MACH_EPSILON) {
102 TH_MATH_ERROR("quotient_sum", Y[0], MathError::DivByZero);
103 return nan();
104 }
105
106 auto res = X[0] / Y[0];
107 for(unsigned int i = 1; i < X.size(); i++) {
108
109 if(abs(Y[i]) < MACH_EPSILON) {
110 TH_MATH_ERROR("quotient_sum", Y[i], MathError::DivByZero);
111 return nan();
112 }
113
114 res += X[i] / Y[i];
115 }
116
117 return res;
118 }
119
120
122 template<typename Vector>
123 inline auto sum_squares(const Vector& X) {
124
125 if(!X.size()) {
126 TH_MATH_ERROR("sum_squares", X.size(), MathError::InvalidArgument);
127 return nan();
128 }
129
130 auto res = X[0] * X[0];
131 for(unsigned int i = 1; i < X.size(); i++)
132 res += X[i] * X[i];
133
134 return res;
135 }
136
137
143 template<typename Vector>
144 inline real sum_compensated(const Vector& X) {
145
146 // Total sum
147 real sum = 0;
148
149 // Correction term
150 real corr = 0;
151
152 for (unsigned int i = 0; i < X.size(); i++) {
153
154 const real temp = sum + X[i];
155
156 // Sort the two addends to preserve bits
157 corr += (abs(sum) >= abs(X[i]))
158 ? ((sum - temp) + X[i])
159 : ((X[i] - temp) + sum);
160
161 sum = temp;
162 }
163
164 // Apply correction
165 return sum + corr;
166 }
167
168
177 template<typename Vector>
179 const Vector& X, size_t begin = 0,
180 size_t end = 0, size_t base_size = 128) {
181
182 if(end == 0)
183 end = X.size();
184
185 real sum = 0;
186
187 // Base case with given size (defaults to 128)
188 if((end - begin) <= base_size) {
189
190 for (size_t i = begin; i < end; ++i)
191 sum += X[i];
192
193 } else {
194
195 // Recursive sum of two halves
196 const size_t m = (end - begin) / 2;
197 const size_t cutoff = begin + m;
198
199 sum = sum_pairwise(X, begin, cutoff, base_size)
200 + sum_pairwise(X, cutoff, end, base_size);
201 }
202
203 return sum;
204 }
205
206
211 template <
212 typename Vector,
213 std::enable_if_t<has_real_elements<Vector>::value> = true
214 >
215 inline auto sum(const Vector& X) {
216 return sum_pairwise(X);
217 }
218
219
223 template<typename Vector>
224 inline auto sum(const Vector& X) {
225
226 // Use pairwise sum to reduce floating point errors.
227 if TH_CONSTIF (has_real_elements<Vector>())
228 return sum_pairwise(X);
229
230 auto res = X[0];
231 for(unsigned int i = 1; i < X.size(); i++)
232 res += X[i];
233
234 return res;
235 }
236
237
245 template<typename Vector, typename Function>
247
248 for (unsigned int i = 0; i < X.size(); i++)
249 X[i] = f(X[i]);
250
251 return X;
252 }
253
254
262 template<typename Vector1, typename Vector2 = Vector1, typename Function>
263 inline Vector2& map(Function f, const Vector1& src, Vector2& dest) {
264
265 if(src.size() != dest.size()) {
267 return algebra::vec_error(dest);
268 }
269
270 for (unsigned int i = 0; i < src.size(); i++)
271 dest[i] = f(src[i]);
272
273 return dest;
274 }
275
276
282 template<typename Vector2, typename Vector1, typename Function>
283 inline Vector2 map(Function f, const Vector1& X) {
284
285 Vector2 res;
286 res.resize(X.size());
287
288 for (unsigned int i = 0; i < X.size(); i++)
289 res[i] = f(X[i]);
290
291 return res;
292 }
293
294
300 template<typename Vector, typename Function>
301 inline Vector map(Function f, const Vector& X) {
303 }
304
305
307 template<typename Vector1, typename Vector2, typename Vector3 = Vector1>
308 inline Vector3 concatenate(const Vector1& v1, const Vector2& v2) {
309
310 Vector3 res;
311 res.resize(v1.size() + v2.size());
312 const unsigned int offset = v1.size();
313
314 for (unsigned int i = 0; i < offset; ++i)
315 res[i] = v1[i];
316
317 for (unsigned int i = 0; i < v2.size(); ++i)
318 res[i + offset] = v2[i];
319
320 return res;
321 }
322
323
325 template<typename Vector>
326 inline auto max(const Vector& X) {
327
328 using Type = vector_element_t<Vector>;
329
330 if(!X.size()) {
332 return make_error<Type>();
333 }
334
335 auto curr = X[0];
336
337 for (unsigned int i = 1; i < X.size(); ++i)
338 if(X[i] > curr)
339 curr = X[i];
340
341 return curr;
342 }
343
344
346 template<typename Vector>
347 inline auto min(const Vector& X) {
348
349 using Type = vector_element_t<Vector>;
350
351 if(!X.size()) {
353 return make_error<Type>();
354 }
355
356 auto curr = X[0];
357
358 for (unsigned int i = 1; i < X.size(); ++i)
359 if(X[i] < curr)
360 curr = X[i];
361
362 return curr;
363 }
364
365
366 // Different types of means
367
368
370 template<typename Dataset>
371 inline real arithmetic_mean(const Dataset& data) {
372
373 if(!data.size()) {
374 TH_MATH_ERROR("arithmetic_mean", data.size(), MathError::DivByZero);
375 return nan();
376 }
377
378 // Sum of x_i / N
379 return sum(data) / (real) data.size();
380 }
381
382
384 template<typename Dataset>
385 inline real harmonic_mean(const Dataset& data) {
386
387 if(!data.size()) {
388 TH_MATH_ERROR("harmonic_mean", data.size(), MathError::DivByZero);
389 return nan();
390 }
391
392 real res = 0;
393
394 for (unsigned int i = 0; i < data.size(); ++i) {
395
396 if(data[i] == 0) {
397 TH_MATH_ERROR("harmonic_mean", data[i], MathError::DivByZero);
398 return nan();
399 }
400
401 res += 1.0 / data[i];
402 }
403
404 return static_cast<real>(data.size()) / res;
405 }
406
407
410 template<typename Dataset>
411 inline real geometric_mean(const Dataset& data) {
412 return root(product(data), data.size());
413 }
414
415
418 template<typename Dataset1, typename Dataset2>
419 inline real weighted_mean(const Dataset1& data, const Dataset2& weights) {
420
421 // Sum of x_i * w_i / Sum of w_i
422 return product_sum(data, weights) / sum(weights);
423 }
424
425
428 template<typename Dataset>
429 inline real quadratic_mean(const Dataset& data) {
430
431 if(!data.size()) {
432 TH_MATH_ERROR("quadratic_mean", data.size(), MathError::InvalidArgument);
433 return nan();
434 }
435
436 return sqrt(sum_squares(data) / data.size());
437 }
438}
439
440#endif
Mathematical constants and default algorithm parameters.
#define TH_CONSTIF
Enable constexpr in if statements if C++17 is supported.
Definition constants.h:178
#define TH_MATH_ERROR(F_NAME, VALUE, EXCEPTION)
TH_MATH_ERROR is a macro which throws exceptions or modifies errno (depending on which compilation op...
Definition error.h:219
Fundamental type traits.
Error handling for IO operations.
Vector & vec_error(Vector &v)
Overwrite the given vector with the error vector with NaN values.
Definition algebra.h:58
Main namespace of the library which contains all functions and objects.
Definition algebra.h:27
double real
A real number, defined as a floating point type.
Definition constants.h:207
Vector & transform(Function f, Vector &X)
Transform a vector by applying a function to each of its elements.
Definition dataset.h:246
real weighted_mean(const Dataset1 &data, const Dataset2 &weights)
Compute the weighted mean of a set of values <data> and <weights> must have the same size.
Definition dataset.h:419
real arithmetic_mean(const Dataset &data)
Compute the arithmetic mean of a set of values.
Definition dataset.h:371
auto min(const Vector &X)
Finds the minimum value inside a dataset.
Definition dataset.h:347
real harmonic_mean(const Dataset &data)
Compute the harmonic mean of a set of values.
Definition dataset.h:385
real sum_compensated(const Vector &X)
Compute the sum of a set of values using the compensated Neumaier-Kahan-Babushka summation algorithm ...
Definition dataset.h:144
dual2 sqrt(dual2 x)
Compute the square root of a second order dual number.
Definition dual2_functions.h:54
Vector3 concatenate(const Vector1 &v1, const Vector2 &v2)
Concatenate two datasets to form a single one.
Definition dataset.h:308
Vector2 & map(Function f, const Vector1 &src, Vector2 &dest)
Overwrite a vector by applying a function to the elements of another vector.
Definition dataset.h:263
dual2 abs(dual2 x)
Compute the absolute value of a second order dual number.
Definition dual2_functions.h:242
real sum_pairwise(const Vector &X, size_t begin=0, size_t end=0, size_t base_size=128)
Compute the sum of a set of values using pairwise summation to reduce round-off error.
Definition dataset.h:178
Vector make_error()
Create a vector representing an error state, with all NaN values.
Definition algebra.h:103
auto sum(const Vector &X)
Compute the sum of a vector of real values using pairwise summation to reduce round-off error.
Definition dataset.h:215
real geometric_mean(const Dataset &data)
Compute the geometric mean of a set of values as .
Definition dataset.h:411
auto max(const Vector &X)
Finds the maximum value inside a dataset.
Definition dataset.h:326
auto product_sum(const Vector &X, const Vector &Y)
Sum the products of two sets of values.
Definition dataset.h:42
auto product_sum_squares(const Vector &X, const Vector &Y)
Sum the products of the squares of two sets of data.
Definition dataset.h:59
TH_CONSTEXPR real nan()
Return a quiet NaN number in floating point representation.
Definition error.h:74
real quadratic_mean(const Dataset &data)
Compute the quadratic mean (Root Mean Square) of a set of values .
Definition dataset.h:429
@ InvalidArgument
Invalid argument.
@ DivByZero
Division by zero.
auto quotient_sum(const Vector &X, const Vector &Y)
Sum the quotients of two sets of values.
Definition dataset.h:94
constexpr real MACH_EPSILON
Machine epsilon for the real type.
Definition constants.h:216
real root(real x, int n)
Compute the n-th root of x.
Definition real_analysis.h:812
auto product(const Vector &X)
Compute the product of a set of values.
Definition dataset.h:25
auto sum_squares(const Vector &X)
Sum the squares of a set of values.
Definition dataset.h:123