17#ifndef ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINE1DSPEC_H
18#define ALICEO2_GPUCOMMON_TPCFASTTRANSFORMATION_SPLINE1DSPEC_H
24#if !defined(GPUCA_GPUCODE)
36template <
typename DataT>
41 GPUd() int32_t getU()
const {
return (int32_t)(
u + 0.1f); }
57template <
typename DataT,
class FlatBase = FlatObject>
64 GPUd() static constexpr int32_t getVersion() {
return 1; }
83 GPUd() int32_t getYdimensions()
const {
return mYdim; }
86 GPUd() size_t getParameterAlignmentBytes()
const
88 size_t s = 2 *
sizeof(DataT) *
mYdim;
89 return (s < 16) ? s : 16;
93 GPUd() int32_t getNumberOfParameters()
const {
return calcNumberOfParameters(
mYdim); }
96 GPUd() size_t getSizeOfParameters()
const {
return sizeof(DataT) * getNumberOfParameters(); }
124 GPUd() int32_t calcNumberOfParameters(int32_t nYdim)
const {
return (2 * nYdim) * getNumberOfKnots(); }
134template <
typename DataT,
typename FlatBase = FlatObject>
137template <
typename DataT>
142 GPUd() const int32_t* getUtoKnotMap()
const {
return mUtoKnotMap; }
145 GPUd() const
Knot<DataT>* getKnots()
const {
return reinterpret_cast<const Knot<DataT>*
>(this->mFlatBufferPtr); }
148 template <SafetyLevel SafeT = SafetyLevel::kSafe>
152 i = (
i < 0) ? 0 : (
i >= this->getNumberOfKnots() ? this->getNumberOfKnots() - 1 :
i);
154 return getKnots()[
i];
158 template <SafetyLevel SafeT = SafetyLevel::kSafe>
159 GPUd() int32_t getLeftKnotIndexForU(DataT u) const;
162 GPUd() DataT* getParameters() {
return mParameters; }
165 GPUd() const DataT* getParameters()
const {
return mParameters; }
167#if !defined(GPUCA_GPUCODE) && !defined(GPUCA_STANDALONE)
169 void approximateFunction(
double xMin,
double xMax, std::function<
void(
double x,
double f[])> F, int32_t nAuxiliaryDataPoints = 4);
184#if !defined(GPUCA_GPUCODE)
190 template <
class OtherFlatBase>
199#if !defined(GPUCA_GPUCODE)
200 void recreate(int32_t nYdim, int32_t numberOfKnots);
201 void recreate(int32_t nYdim, int32_t numberOfKnots,
const int32_t knotU[]);
210 int32_t* mUtoKnotMap =
nullptr;
211 DataT* mParameters =
nullptr;
216template <
typename DataT>
221 GPUd() const int32_t* getUtoKnotMapFromBuffer(const
char* flatBuf)
const
223 return reinterpret_cast<const int32_t*
>(flatBuf + this->getNumberOfKnots() *
sizeof(
Knot<DataT>));
228 template <SafetyLevel SafeT = SafetyLevel::kSafe>
229 GPUd() int32_t getLeftKnotIndexForUFromBuffer(const
char* flatBuf, DataT u)
const
231 int32_t iu = u < 0 ? 0 : (u > (
float)this->mUmax ? this->mUmax : (int32_t)u);
233 iu = (iu < 0) ? 0 : (iu > this->mUmax ? this->mUmax : iu);
241 GPUd() const
Knot<DataT>* getKnotsFromBuffer(const
char* flatBuf)
const {
return reinterpret_cast<const Knot<DataT>*
>(flatBuf); }
245 template <SafetyLevel SafeT = SafetyLevel::kSafe>
246 GPUd() const
Knot<DataT>& getKnotFromBuffer(const
char* flatBuf, int32_t
i)
const
249 i = (
i < 0) ? 0 : (
i >= this->getNumberOfKnots() ? this->getNumberOfKnots() - 1 :
i);
251 return getKnotsFromBuffer(flatBuf)[
i];
257 this->mNumberOfKnots = 0;
261 this->mXtoUscale = 1.;
262 this->mFlatBufferSize = 0;
267#if !defined(GPUCA_GPUCODE)
269 template <
class OtherFlatBase>
272 this->mYdim =
src.getYdimensions();
273 this->mNumberOfKnots =
src.getNumberOfKnots();
274 this->mUmax =
src.getUmax();
275 this->mXmin =
src.getXmin();
276 this->mXtoUscale =
src.getXtoUscale();
277 this->mFlatBufferSize =
src.getFlatBufferSize();
282template <
typename DataT>
283template <SafetyLevel SafeT>
284GPUdi() int32_t Spline1DContainer<DataT, FlatObject>::getLeftKnotIndexForU(DataT u)
const
288 int32_t iu = u < 0 ? 0 : (u > (
float)this->mUmax ? this->mUmax : (int32_t)u);
290 iu = (iu < 0) ? 0 : (iu > this->mUmax ? this->mUmax : iu);
292 return getUtoKnotMap()[iu];
295template <
typename DataT,
class FlatBase>
296GPUdi()
void Spline1DContainerBase<DataT, FlatBase>::setXrange(DataT xMin, DataT xMax)
299 double l = ((double)xMax) - xMin;
303 mXtoUscale = this->mUmax / l;
326template <
typename DataT,
int32_t YdimT,
int32_t SpecT,
class FlatBase = FlatObject>
333template <
typename DataT,
int32_t YdimT,
class FlatBase>
346 if constexpr (std::is_same_v<FlatBase, FlatObject>) {
347 interpolateAtU<SafetyLevel::kSafe>(this->mYdim, this->mParameters, this->convXtoU(
x),
S);
352 template <SafetyLevel SafeT = SafetyLevel::kSafe>
355 if constexpr (std::is_same_v<FlatBase, FlatObject>) {
356 const auto nYdimTmp = SplineUtil::getNdim<YdimT>(inpYdim);
357 const auto nYdim = nYdimTmp.get();
358 int32_t iknot = this->
template getLeftKnotIndexForU<SafeT>(u);
359 const DataT* d =
Parameters + (2 * nYdim) * iknot;
360 interpolateAtU(nYdim, this->getKnots()[iknot], &(d[0]), &(d[nYdim]), &(d[2 * nYdim]), &(d[3 * nYdim]), u,
S);
367 template <
typename T>
373 const auto nYdimTmp = SplineUtil::getNdim<YdimT>(inpYdim);
374 const auto nYdim = nYdimTmp.get();
376 T dSdSl, dSdDl, dSdSr, dSdDr;
377 getSderivativesOverParsAtU<T>(knotL, u, dSdSl, dSdDl, dSdSr, dSdDr);
379 for (int32_t dim = 0; dim < nYdim; ++dim) {
380 S[dim] = dSdSr * Sr[dim] + dSdSl * Sl[dim] + dSdDl * Dl[dim] + dSdDr * Dr[dim];
405 template <
typename T>
406 GPUd()
void getSderivativesOverParsAtU(const
KnotType& knotL, DataT u, T& dSdSl, T& dSdDl, T& dSdSr, T& dSdDr)
const
414 if (u > (DataT)Container::getUmax()) {
415 u = (DataT)Container::getUmax();
419 T
v = u * T(knotL.Li);
424 dSdSl = T(1.) - dSdSr;
430 template <
typename T>
431 GPUd()
void getSDderivativesOverParsAtU(const
KnotType& knotL, DataT u, T& dSdSl, T& dSdDl, T& dSdSr, T& dSdDr, T& dDdSl, T& dDdDl, T& dDdSr, T& dDdDr)
const
439 if (u > (DataT)Container::getUmax()) {
440 u = (DataT)Container::getUmax();
444 T
v = u * T(knotL.Li);
448 dSdSr =
v2 * (T(3.) -
v -
v);
449 dSdSl = T(1.) - dSdSr;
454 dDdSr = T(6.) *
v * (T(1.) -
v) * dv;
456 dDdDl = vm1 * (
v +
v + vm1);
457 dDdDr =
v * (
v + vm1 + vm1);
467template <
typename DataT,
int32_t YdimT,
class FlatBase>
473#if !defined(GPUCA_GPUCODE)
477 if constexpr (!std::is_same_v<FlatBase, NoFlatObject>) {
492 void recreate(int32_t numberOfKnots) { ParentSpec::recreate(YdimT, numberOfKnots); }
495 void recreate(int32_t numberOfKnots,
const int32_t knotU[]) { ParentSpec::recreate(YdimT, numberOfKnots, knotU); }
499 GPUd() constexpr int32_t getYdimensions()
const {
return YdimT; }
502 GPUd() constexpr
size_t getParameterAlignmentBytes()
const
504 size_t s = 2 *
sizeof(DataT) * YdimT;
505 return (s < 16) ? s : 16;
509 GPUd() int32_t getNumberOfParameters()
const {
return (2 * YdimT) * this->getNumberOfKnots(); }
512 GPUd() size_t getSizeOfParameters()
const {
return (
sizeof(DataT) * 2 * YdimT) * this->getNumberOfKnots(); }
517 template <SafetyLevel SafeT = SafetyLevel::kSafe>
520 ParentSpec::template interpolateAtU<SafeT>(YdimT,
Parameters, u,
S);
525 template <
typename T>
526 GPUd()
void interpolateAtU(const typename ParentSpec::KnotType& knotL,
531 ParentSpec::interpolateAtU(YdimT, knotL, Sl, Dl, Sr, Dr, u,
S);
539template <
typename DataT,
int32_t YdimT,
class FlatBase>
546#if !defined(GPUCA_GPUCODE)
550 if constexpr (!std::is_same_v<FlatBase, NoFlatObject>) {
551 ParentSpec::recreate(0, 2);
558 ParentSpec::recreate(nYdim, numberOfKnots);
564 ParentSpec::recreate(nYdim, numberOfKnots, knotU);
570 Container::cloneFromObject(
v,
nullptr);
574 void recreate(int32_t nYdim, int32_t numberOfKnots) { ParentSpec::recreate(nYdim, numberOfKnots); }
577 void recreate(int32_t nYdim, int32_t numberOfKnots,
const int32_t knotU[]) { ParentSpec::recreate(nYdim, numberOfKnots, knotU); }
584template <
typename DataT,
class FlatBase>
591 GPUd() DataT interpolate(DataT
x)
const
594 ParentSpec::interpolate(
x, &
S);
Definition of FlatObject class.
GPUd() int32_t getNumberOfParameters() const
Number of parameters.
GPUd() DataT convXtoU(DataT x) const
_______________ Technical stuff ________________________
GPUd() size_t getSizeOfParameters() const
Size of the parameter array in bytes.
GPUd() DataT getXmin() const
Get Xmin.
GPUd() int32_t getUmax() const
_______________ Getters ________________________
DataT mXtoUscale
a scaling factor to convert X to U
int32_t mYdim
_____________ Data members ____________
GPUd() static const expr int32_t getVersion()
_____________ Version control __________________________
Spline1DContainerBase(const Spline1DContainerBase &)=delete
Disable all other constructors.
~Spline1DContainerBase()=default
Destructor.
GPUd() DataT convUtoX(DataT u) const
Convert U coordinate to X.
GPUd() int32_t getNumberOfKnots() const
Get a number of knots.
DataT mXmin
X of the first knot.
GPUd() size_t getParameterAlignmentBytes() const
Get minimal required alignment for the spline parameters.
int32_t mNumberOfKnots
n knots on the grid
GPUd() DataT getXmax() const
Get Xmax.
GPUd() DataT getXtoUscale() const
Get XtoUscale.
GPUd() void setXrange(DataT xMin
Set X range.
GPUd() int32_t getYdimensions() const
Get number of Y dimensions.
Spline1DContainerBase()=default
_____________ C++ constructors / destructors __________________________
int32_t mUmax
U of the last knot.
void setFutureBufferAddress(char *futureFlatBufferPtr)
void importFrom(const Spline1DContainerBase< DataT, OtherFlatBase > &src)
Knot< DataT > * getKnots()
Non-const accessor to the knots array.
static Spline1DContainer * readFromFile(TFile &inpf, const char *name)
read a class object from the file
void recreate(int32_t nYdim, int32_t numberOfKnots, const int32_t knotU[])
ClassDefNV(Spline1DContainer, 1)
(transient!!) pointer to F-dependent parameters inside the mFlatBufferPtr array
void print() const
Print method.
GPUd() int32_t getLeftKnotIndexForU(DataT u) const
Get index of an associated knot for a given U coordinate. Performs a boundary check.
void moveBufferTo(char *newBufferPtr)
void setActualBufferAddress(char *actualFlatBufferPtr)
void recreate(int32_t nYdim, int32_t numberOfKnots)
GPUd() const Knot< DataT > *getKnots() const
Get the array of knots.
void approximateFunction(double xMin, double xMax, std::function< void(double x, double f[])> F, int32_t nAuxiliaryDataPoints=4)
approximate a function F with this spline
GPUd() const int32_t *getUtoKnotMap() const
Get a map (integer U -> corresponding knot index)
GPUd() const Knot< DataT > &getKnot(int32_t i) const
Get i-th knot.
int32_t writeToFile(TFile &outf, const char *name)
write a class object to the file
GPUd() const DataT *getParameters() const
Get spline parameters const.
int32_t * getUtoKnotMap()
Non-const accessor to U->knots map.
static int32_t test(const bool draw=0, const bool drawDataPoints=1)
Test the class functionality.
void cloneFromObject(const Spline1DContainer &obj, char *newFlatBufferPtr)
return getUtoKnotMapFromBuffer(flatBuf)[iu]
GPUdi() void setActualBufferAddress(char *)
void importFrom(const Spline1DContainerBase< DataT, OtherFlatBase > &src)
Copy schema fields from a spline with a different FlatBase (no pointer members to copy).
GPUd() const int32_t *getUtoKnotMapFromBuffer(const char *flatBuf) const
Get the U->knot-index map from an explicit flat buffer pointer.
GPUdi() void setFutureBufferAddress(char *)
GPUd() const Knot< DataT > *getKnotsFromBuffer(const char *flatBuf) const
GPUd() DataT interpolate(DataT x) const
Simplified interface for 1D: return the interpolated value.
GPUd() void interpolateAtU(int32_t inpYdim
Get interpolated value for an nYdim-dimensional S(u) using spline parameters Parameters.
GPUd() void interpolate(DataT x
_______________ Interpolation math ________________________
GPUd() size_t getSizeOfParameters() const
Size of the parameter array in bytes.
Spline1DSpec(int32_t numberOfKnots, const int32_t knotU[])
Constructor for an irregular spline.
void recreate(int32_t numberOfKnots)
Constructor for a regular spline.
void recreate(int32_t numberOfKnots, const int32_t knotU[])
Constructor for an irregular spline.
GPUd() void interpolateAtU(GPUgeneric() const DataT Parameters[]
_______ Expert tools: interpolation with given nYdim and external Parameters _______
Spline1DSpec()
Default constructor — skips recreate for NoFlatObject (no owned buffer)
GPUd() int32_t getNumberOfParameters() const
Number of parameters.
Spline1DSpec(int32_t numberOfKnots)
Constructor for a regular spline.
GPUd() const expr int32_t getYdimensions() const
Get number of Y dimensions.
Spline1DSpec(const Spline1DSpec &v)
Copy constructor.
GPUd() const expr size_t getParameterAlignmentBytes() const
Get minimal required alignment for the spline parameters.
Spline1DSpec(const Spline1DSpec &v)
Copy constructor.
void recreate(int32_t nYdim, int32_t numberOfKnots)
Constructor for a regular spline.
void recreate(int32_t nYdim, int32_t numberOfKnots, const int32_t knotU[])
Constructor for an irregular spline.
Spline1DSpec()
Default constructor — skips recreate for NoFlatObject (no owned buffer)
Spline1DSpec(int32_t nYdim, int32_t numberOfKnots, const int32_t knotU[])
Constructor for an irregular spline.
Spline1DSpec(int32_t nYdim, int32_t numberOfKnots)
Constructor for a regular spline.
static constexpr int32_t getSpec(int32_t nXdim, int32_t nYdim)
GLuint const GLchar * name
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLboolean GLboolean GLboolean GLboolean a
GLfloat GLfloat GLfloat v2
SafetyLevel
Named enumeration for the safety level used by some methods.
GPUd() const expr uint32_t MultivariatePolynomialHelper< Dim
TCanvas * drawDataPoints(TMultiGraph *mg, double min, double max)
GPUd() int32_t getU() const
Get u as an integer.
DataT u
u coordinate of the knot i (an integer number in float format)