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 template <u
int32_t Degree, u
int32_t Dim>
64 GPUd() static constexpr uint32_t getNParametersAllTerms()
66 if constexpr (
Degree == 0) {
67 return binomialCoeff<Dim - 1, 0>();
69 return binomialCoeff<Dim - 1 +
Degree,
Degree>() + getNParametersAllTerms<Degree - 1, Dim>();
76 GPUd() static constexpr uint32_t getNParametersAllTerms(uint32_t degree, uint32_t dim)
79 return binomialCoeff(dim - 1, 0);
81 return binomialCoeff(dim - 1 + degree, degree) + getNParametersAllTerms(degree - 1, dim);
86 template <u
int32_t Degree, u
int32_t Dim>
87 GPUd() static constexpr uint32_t getNParametersInteractionOnly()
89 if constexpr (
Degree == 0) {
90 return binomialCoeff<Dim - 1, 0>();
92 return binomialCoeff<Dim, Degree>() + getNParametersInteractionOnly<
Degree - 1, Dim>();
97 GPUd() static constexpr uint32_t getNParametersInteractionOnly(uint32_t degree, uint32_t dim)
100 return binomialCoeff(dim - 1, 0);
102 return binomialCoeff(dim, degree) + getNParametersInteractionOnly(degree - 1, dim);
106 template <u
int32_t Degree, u
int32_t Dim,
bool InteractionOnly>
107 GPUd() static constexpr uint32_t getNParameters()
109 if constexpr (InteractionOnly) {
110 return getNParametersInteractionOnly<Degree, Dim>();
112 return getNParametersAllTerms<Degree, Dim>();
116 GPUd() static constexpr uint32_t getNParameters(uint32_t degree, uint32_t dim,
bool interactionOnly)
118 if (interactionOnly) {
119 return getNParametersInteractionOnly(degree, dim);
121 return getNParametersAllTerms(degree, dim);
128 template <u
int32_t N>
129 GPUd() static constexpr uint32_t factorial()
131 if constexpr (N == 0 || N == 1) {
134 return N * factorial<N - 1>();
140 GPUd() static constexpr uint32_t factorial(uint32_t
n) {
return n == 0 ||
n == 1 ? 1 :
n * factorial(
n - 1); }
144 template <u
int32_t N, u
int32_t K>
145 GPUd() static constexpr uint32_t binomialCoeff()
147 return factorial<N>() / (factorial<K>() * factorial<N - K>());
152 GPUd() static constexpr uint32_t binomialCoeff(uint32_t
n, uint32_t k)
154 return factorial(
n) / (factorial(k) * factorial(
n - k));
163template <u
int32_t Dim, u
int32_t Degree,
bool InteractionOnly>
166 static constexpr uint16_t FMaxdim = 10;
167 static constexpr uint16_t FMaxdegree = 9;
169#if !defined(GPUCA_GPUCODE)
170 static_assert(Dim <= MultivariatePolynomialHelper<Dim, Degree, InteractionOnly>::FMaxdim && Degree <= MultivariatePolynomialHelper<Dim, Degree, InteractionOnly>::FMaxdegree,
"Max. number of dimensions or degrees exceeded!");
177 GPUd() static constexpr
float evalPol(
GPUgeneric() const
float par[], const
float x[])
179 return par[0] + loopDegrees<1>(par,
x);
183 GPUd() static constexpr uint32_t getDim() {
return Dim; }
186 GPUd() static constexpr uint32_t getDegree() {
return Degree; }
189 GPUd() static constexpr
bool isInteractionOnly() {
return InteractionOnly; }
193 GPUd() static constexpr uint32_t pow10(const uint32_t
n) {
return n == 0 ? 1 : 10 * pow10(
n - 1); }
195 template <u
int32_t N>
196 GPUd() static constexpr uint32_t pow10()
198 if constexpr (N == 0) {
201 return 10 * pow10<N - 1>();
206 GPUd() static constexpr uint32_t mod10(const uint32_t
a, const uint32_t
b) {
return (
a /
b) % 10; }
208 template <u
int32_t A, u
int32_t B>
209 GPUd() static constexpr uint32_t mod10()
215 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);
217 template <uint32_t DegreePol, uint32_t Pos, uint32_t DigitPos>
218 GPUd() static constexpr uint32_t getNewPos();
223 template <uint32_t DegreePol, uint32_t Pos>
224 GPUd() static constexpr
float prodTerm(const
float x[]);
227 template <uint32_t DegreePol, uint32_t posNew>
228 static constexpr
bool checkInteraction();
234 template <uint32_t DegreePol, uint32_t Pos, uint32_t Index>
235 GPUd() static constexpr
float sumTerms(
GPUgeneric() const
float par[], const
float x[]);
241 template <uint32_t DegreePol>
242 GPUd() static constexpr
float loopDegrees(
GPUgeneric() const
float par[], const
float x[]);
245#if !defined(GPUCA_GPUCODE)
254 MultivariatePolynomialHelper(
const uint32_t nDim,
const uint32_t degree,
const bool interactionOnly) : mDim{nDim}, mDegree{degree}, mInteractionOnly{interactionOnly} { assert(mDegree <= FMaxdegree); };
284 static std::vector<float>
fit(TLinearFitter& fitter, std::vector<double>&
x, std::vector<double>&
y, std::vector<double>& error,
const bool clearPoints);
292 std::vector<float>
fit(std::vector<double>&
x, std::vector<double>&
y, std::vector<double>& error,
const bool clearPoints)
const;
297 float evalPol(
const float par[],
const float x[])
const
299 return evalPol(par,
x, mDegree, mDim, mInteractionOnly);
303 float evalPol(
const float par[],
const float x[],
const uint32_t degree,
const uint32_t dim,
const bool interactionOnly)
const;
317 bool mInteractionOnly{};
320 static constexpr uint16_t FMaxdegree = 9;
323 template <
class Type>
324 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;
332template <u
int32_t Dim, u
int32_t Degree,
bool InteractionOnly>
333GPUd() 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)
335 if (iter <= degreePol) {
336 const int32_t powTmp = pow10(leftDigit);
337 const int32_t rightDigit = mod10(
pos, powTmp);
338 const int32_t posTmp =
pos - (rightDigit - refDigit) * powTmp;
339 return resetIndices(degreePol, posTmp, leftDigit - 1, iter + 1, refDigit);
344template <u
int32_t Dim, u
int32_t Degree,
bool InteractionOnly>
345template <u
int32_t DegreePol, u
int32_t Pos, u
int32_t DigitPos>
346GPUd() constexpr uint32_t MultivariatePolynomialHelper<Dim,
Degree, InteractionOnly>::getNewPos()
348 if constexpr (DegreePol > DigitPos) {
350 if constexpr (mod10<Pos, pow10<DigitPos>()>() == Dim) {
352 constexpr uint32_t LeftDigit = DigitPos + 1;
353 constexpr uint32_t PowLeftDigit = pow10<LeftDigit>();
354 constexpr uint32_t PosTmp = Pos + PowLeftDigit;
355 constexpr uint32_t RefDigit = mod10<PosTmp, PowLeftDigit>();
358 constexpr uint32_t PosReset = resetIndices(DegreePol, PosTmp, LeftDigit - 1, DegreePol - DigitPos, RefDigit);
361 return getNewPos<DegreePol, PosReset, DigitPos + 1>();
363 return getNewPos<DegreePol, Pos, DigitPos + 1>();
370template <u
int32_t Dim, u
int32_t Degree,
bool InteractionOnly>
371template <u
int32_t DegreePol, u
int32_t Pos>
374 if constexpr (DegreePol > 0) {
376 const uint32_t
index = mod10<Pos, pow10<DegreePol - 1>()>();
377 return x[
index] * prodTerm<DegreePol - 1, Pos>(
x);
382template <u
int32_t Dim, u
int32_t Degree,
bool InteractionOnly>
383template <u
int32_t DegreePol, u
int32_t posNew>
384constexpr bool MultivariatePolynomialHelper<Dim, Degree, InteractionOnly>::checkInteraction()
386 if constexpr (DegreePol > 1) {
387 constexpr bool isInteraction = mod10<posNew, pow10<DegreePol - 1>()>() == mod10<posNew, pow10<DegreePol - 2>()>();
388 if constexpr (isInteraction) {
391 return checkInteraction<DegreePol - 1, posNew>();
396template <u
int32_t Dim, u
int32_t Degree,
bool InteractionOnly>
397template <u
int32_t DegreePol, u
int32_t Pos, u
int32_t Index>
398GPUd() constexpr
float MultivariatePolynomialHelper<Dim,
Degree, InteractionOnly>::sumTerms(
GPUgeneric() const
float par[], const
float x[])
401 constexpr uint32_t PosNew = getNewPos<DegreePol, Pos, 0>();
402 if constexpr (mod10<PosNew, pow10<DegreePol>()>() != 1) {
405 if constexpr (InteractionOnly && checkInteraction<DegreePol, PosNew>()) {
406 return sumTerms<DegreePol, PosNew + 1, Index>(par,
x);
409 return par[Index] * prodTerm<DegreePol, PosNew>(
x) + sumTerms<DegreePol, PosNew + 1, Index + 1>(par,
x);
415template <u
int32_t Dim, u
int32_t Degree,
bool InteractionOnly>
416template <u
int32_t DegreePol>
419 if constexpr (DegreePol <=
Degree) {
420 constexpr uint32_t
index{getNParameters<DegreePol - 1, Dim, InteractionOnly>()};
421 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 getNParametersAllTerms(uint32_t degree
GPUd() static const expr uint32_t getNParametersAllTerms()
GLboolean GLboolean GLboolean b
GLenum const GLfloat * params
GLboolean GLboolean GLboolean GLboolean a
Node par(int index)
Parameters.
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