15#ifndef ALICEO2_TPC_MULTIVARIATEPOLYNOMIALHELPER
16#define ALICEO2_TPC_MULTIVARIATEPOLYNOMIALHELPER
20#if !defined(GPUCA_GPUCODE)
24#if !defined(GPUCA_NO_FMT)
25#include <fmt/format.h>
34#if !defined(GPUCA_GPUCODE)
63 GPUd() static constexpr uint32_t getNParametersAllTerms(const uint32_t degree, const uint32_t
dim) {
return (degree == 0) ? binomialCoeff(
dim - 1, 0) : binomialCoeff(
dim - 1 + degree, degree) + getNParametersAllTerms(degree - 1,
dim); }
66 GPUd() static constexpr uint32_t getNParametersInteractionOnly(const uint32_t degree, const uint32_t
dim) {
return (degree == 0) ? binomialCoeff(
dim - 1, 0) : binomialCoeff(
dim, degree) + getNParametersInteractionOnly(degree - 1,
dim); }
68 GPUd() static constexpr uint32_t getNParameters(const uint32_t degree, const uint32_t
dim, const
bool interactionOnly)
70 if (interactionOnly) {
71 return getNParametersInteractionOnly(degree,
dim);
73 return getNParametersAllTerms(degree,
dim);
80 GPUd() static constexpr uint32_t factorial(const uint32_t
n) {
return (
n == 0) || (
n == 1) ? 1 :
n * factorial(
n - 1); }
84 GPUd() static constexpr uint32_t binomialCoeff(const uint32_t
n, const uint32_t k) {
return factorial(
n) / (factorial(k) * factorial(
n - k)); }
92template <u
int32_t Dim, u
int32_t Degree,
bool InteractionOnly>
95 static constexpr uint16_t FMaxdim = 10;
96 static constexpr uint16_t FMaxdegree = 9;
98#if !defined(GPUCA_GPUCODE)
99 static_assert(Dim <= MultivariatePolynomialHelper<Dim, Degree, InteractionOnly>::FMaxdim && Degree <= MultivariatePolynomialHelper<Dim, Degree, InteractionOnly>::FMaxdegree,
"Max. number of dimensions or degrees exceeded!");
106 GPUd() static constexpr
float evalPol(
GPUgeneric() const
float par[], const
float x[]) {
return par[0] + loopDegrees<1>(par,
x); }
109 GPUd() static constexpr uint32_t getDim() {
return Dim; }
112 GPUd() static constexpr uint32_t getDegree() {
return Degree; }
115 GPUd() static constexpr
bool isInteractionOnly() {
return InteractionOnly; }
119 GPUd() static constexpr uint32_t pow10(const uint32_t
n) {
return n == 0 ? 1 : 10 * pow10(
n - 1); }
122 GPUd() static constexpr uint32_t mod10(const uint32_t
a, const uint32_t
b) {
return (
a /
b) % 10; }
125 GPUd() static constexpr uint32_t resetIndices(const uint32_t degreePol, const uint32_t pos, const uint32_t leftDigit, const uint32_t iter, const uint32_t refDigit);
127 GPUd() static constexpr uint32_t getNewPos(const uint32_t degreePol, const uint32_t pos, const uint32_t digitPos);
132 template <uint32_t DegreePol>
133 GPUd() static constexpr
float prodTerm(const
float x[], const uint32_t pos);
136 template <uint32_t DegreePol, uint32_t posNew>
137 static constexpr
bool checkInteraction();
143 template <uint32_t DegreePol, uint32_t Pos, uint32_t Index>
144 GPUd() static constexpr
float sumTerms(
GPUgeneric() const
float par[], const
float x[]);
150 template <uint32_t DegreePol>
151 GPUd() static constexpr
float loopDegrees(
GPUgeneric() const
float par[], const
float x[]);
154#if !defined(GPUCA_GPUCODE)
163 MultivariatePolynomialHelper(
const uint32_t nDim,
const uint32_t degree,
const bool interactionOnly) : mDim{nDim}, mDegree{degree}, mInteractionOnly{interactionOnly} { assert(mDegree <= FMaxdegree); };
193 static std::vector<float>
fit(TLinearFitter& fitter, std::vector<double>&
x, std::vector<double>&
y, std::vector<double>& error,
const bool clearPoints);
201 std::vector<float>
fit(std::vector<double>&
x, std::vector<double>&
y, std::vector<double>& error,
const bool clearPoints)
const;
206 float evalPol(
const float par[],
const float x[])
const {
return evalPol(par,
x, mDegree, mDim, mInteractionOnly); }
209 float evalPol(
const float par[],
const float x[],
const uint32_t degree,
const uint32_t dim,
const bool interactionOnly)
const;
223 bool mInteractionOnly{};
226 static constexpr uint16_t FMaxdegree = 9;
229 template <
class Type>
230 Type combination_with_repetiton(
const uint32_t degree,
const uint32_t dim,
const float par[], int32_t& indexPar,
const float x[],
const bool interactionOnly)
const;
238template <u
int32_t Dim, u
int32_t Degree,
bool InteractionOnly>
239GPUd() constexpr uint32_t
MultivariatePolynomialHelper<Dim,
Degree, InteractionOnly>::resetIndices(const uint32_t degreePol, const uint32_t pos, const uint32_t leftDigit, const uint32_t iter, const uint32_t refDigit)
241 if (iter <= degreePol) {
242 const int32_t powTmp = pow10(leftDigit);
243 const int32_t rightDigit = mod10(
pos, powTmp);
244 const int32_t posTmp =
pos - (rightDigit - refDigit) * powTmp;
245 return resetIndices(degreePol, posTmp, leftDigit - 1, iter + 1, refDigit);
250template <u
int32_t Dim, u
int32_t Degree,
bool InteractionOnly>
251GPUd() constexpr uint32_t MultivariatePolynomialHelper<Dim,
Degree, InteractionOnly>::getNewPos(const uint32_t degreePol, const uint32_t pos, const uint32_t digitPos)
253 if (degreePol > digitPos) {
255 if (mod10(pos, pow10(digitPos)) == Dim) {
257 const uint32_t leftDigit = digitPos + 1;
258 const uint32_t posTmp =
pos + pow10(leftDigit);
259 const uint32_t refDigit = mod10(posTmp, pow10(digitPos + 1));
262 const uint32_t posReset = resetIndices(degreePol, posTmp, leftDigit - 1, degreePol - digitPos, refDigit);
265 return getNewPos(degreePol, posReset, digitPos + 1);
267 return getNewPos(degreePol, pos, digitPos + 1);
272template <u
int32_t Dim, u
int32_t Degree,
bool InteractionOnly>
273template <u
int32_t DegreePol>
276 if constexpr (DegreePol > 0) {
278 const uint32_t
index = mod10(
pos, pow10(DegreePol - 1));
279 return x[
index] * prodTerm<DegreePol - 1>(
x,
pos);
284template <u
int32_t Dim, u
int32_t Degree,
bool InteractionOnly>
285template <u
int32_t DegreePol, u
int32_t posNew>
286constexpr bool MultivariatePolynomialHelper<Dim, Degree, InteractionOnly>::checkInteraction()
288 if constexpr (DegreePol > 1) {
289 constexpr bool isInteraction = mod10(posNew, pow10(DegreePol - 1)) == mod10(posNew, pow10(DegreePol - 2));
290 if constexpr (isInteraction) {
293 return checkInteraction<DegreePol - 1, posNew>();
298template <u
int32_t Dim, u
int32_t Degree,
bool InteractionOnly>
299template <u
int32_t DegreePol, u
int32_t Pos, u
int32_t Index>
300GPUd() constexpr
float MultivariatePolynomialHelper<Dim,
Degree, InteractionOnly>::sumTerms(
GPUgeneric() const
float par[], const
float x[])
303 constexpr uint32_t posNew = getNewPos(DegreePol, Pos, 0);
304 if constexpr (mod10(posNew, pow10(DegreePol)) != 1) {
307 if constexpr (InteractionOnly && checkInteraction<DegreePol, posNew>()) {
308 return sumTerms<DegreePol, posNew + 1, Index>(par,
x);
312 return par[Index] * prodTerm<DegreePol>(
x, posNew) + sumTerms<DegreePol, posNew + 1, Index + 1>(par,
x);
317template <u
int32_t Dim, u
int32_t Degree,
bool InteractionOnly>
318template <u
int32_t DegreePol>
319GPUd() constexpr
float MultivariatePolynomialHelper<Dim,
Degree, InteractionOnly>::loopDegrees(
GPUgeneric() const
float par[], const
float x[])
321 if constexpr (DegreePol <=
Degree) {
322 constexpr uint32_t
index{getNParameters(DegreePol - 1, Dim, InteractionOnly)};
323 return sumTerms<DegreePol, 0, index>(par,
x) + loopDegrees<DegreePol + 1>(par,
x);
uint32_t getDegree() const
TLinearFitter getTLinearFitter() const
std::string getFormula() const
MultivariatePolynomialHelper(const uint32_t nDim, const uint32_t degree, const bool interactionOnly)
MultivariatePolynomialHelper()=default
default constructor
static std::vector< float > fit(TLinearFitter &fitter, std::vector< double > &x, std::vector< double > &y, std::vector< double > &error, const bool clearPoints)
std::vector< std::string > getTerms() const
std::vector< float > fit(std::vector< double > &x, std::vector< double > &y, std::vector< double > &error, const bool clearPoints) const
~MultivariatePolynomialHelper()=default
Destructor.
float evalPol(const float par[], const float x[], const uint32_t degree, const uint32_t dim, const bool interactionOnly) const
evalutes the polynomial
std::string getTLinearFitterFormula() const
float evalPol(const float par[], const float x[]) const
void print() const
printing the formula of the polynomial
bool isInteractionOnly() const
GPUd() static const expr uint32_t getDegree()
GPUd() static const expr float evalPol(GPUgeneric() const float par[]
GPUd() static const expr uint32_t getDim()
GPUd() static const expr bool isInteractionOnly()
Helper class for calculating the number of parameters for a multidimensional polynomial.
GPUd() static const expr uint32_t getNParametersInteractionOnly(const uint32_t degree
GPUd() static const expr uint32_t getNParameters(const uint32_t degree
GPUd() static const expr uint32_t getNParametersAllTerms(const uint32_t degree
GLboolean GLboolean GLboolean b
GLenum const GLfloat * params
GLboolean GLboolean GLboolean GLboolean a
simple struct to enable writing the MultivariatePolynomial to file
const uint32_t mDim
number of dimensions of the polynomial
const uint32_t mDegree
degree of the polynomials
MultivariatePolynomialContainer()=default
for ROOT I/O
const bool mInteractionOnly
consider only interaction terms
MultivariatePolynomialContainer(const uint32_t dim, const uint32_t degree, const uint32_t nParameters, const float params[], const bool interactionOnly)
const std::vector< float > mParams
parameters of the polynomial