File indexing completed on 2025-12-13 10:32:15
0001
0002
0003
0004
0005
0006 #ifndef YODA_TRANSFORMATION_H
0007 #define YODA_TRANSFORMATION_H
0008
0009 #include "YODA/Exceptions.h"
0010 #include "YODA/Utils/MathUtils.h"
0011 #include "YODA/Utils/ndarray.h"
0012 #include <algorithm>
0013 #include <functional>
0014 #include <map>
0015 #include <utility>
0016
0017
0018 namespace YODA {
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 template<size_t N, typename... Args>
0029 class Transformation {
0030 public:
0031
0032
0033 using Pair = std::pair<double,double>;
0034 using NdVal = typename Utils::ndarray<double, N>;
0035 using NdValPair = typename Utils::ndarray<Pair, N>;
0036 using Breakdown = std::map<std::string,std::pair<double,double>>;
0037
0038
0039
0040
0041
0042
0043
0044 Transformation() = delete;
0045
0046
0047 Transformation(const std::function<double(double, Args...)>& fn) : _Fn(fn) { }
0048
0049
0050 Transformation(std::function<double(double, Args...)>&& fn) : _Fn(std::move(fn)) { }
0051
0052
0053
0054 double operator()(const double v, Args&&... args) const { return _Fn(v, std::forward<Args>(args)...); }
0055
0056
0057
0058
0059
0060
0061
0062
0063 void transform(double& val, Args&&... args) const { val = _Fn(val, std::forward<Args>(args)...); }
0064
0065
0066 void transform(NdVal& vals, Args&&... args) const {
0067 for (double& val : vals) {
0068 transform(val, std::forward<Args>(args)...);
0069 }
0070 }
0071
0072
0073
0074
0075 void transform(double& val, Breakdown& signed_errs, Args&&... args) const {
0076
0077 const double oldval = val;
0078
0079 transform(val, std::forward<Args>(args)...);
0080
0081 for (auto& item : signed_errs) {
0082 item.second.first = _Fn(oldval + item.second.first, std::forward<Args>(args)...) - val;
0083 item.second.second = _Fn(oldval + item.second.second, std::forward<Args>(args)...) - val;
0084 }
0085 }
0086
0087
0088 void transform(double& val, Pair& errs, Args&&... args) const {
0089
0090 const double trf_min = _Fn(val - errs.first, std::forward<Args>(args)...);
0091 const double trf_max = _Fn(val + errs.second, std::forward<Args>(args)...);
0092
0093 transform(val, std::forward<Args>(args)...);
0094
0095 const double new_min = std::min(trf_min, trf_max);
0096 const double new_max = std::max(trf_min, trf_max);
0097 errs = std::make_pair(val - new_min, new_max - val);
0098 }
0099
0100
0101 void transform(NdVal& vals, NdValPair& errs, Args&&... args) const {
0102 for (size_t i = 0; i < N; ++i) {
0103 transform(vals[i], errs[i], std::forward<Args>(args)...);
0104 }
0105 }
0106
0107
0108
0109 protected:
0110
0111
0112
0113
0114 std::function<double(double, Args...)> _Fn;
0115
0116
0117
0118 };
0119
0120
0121
0122
0123
0124
0125 template<size_t N>
0126 using Trf = Transformation<N>;
0127
0128
0129
0130 }
0131
0132 #endif