158 DataT* Fparameters,
const double xMin[],
const double xMax[],
159 std::function<
void(
const std::vector<double>
x[],
double f[])> F,
160 uint32_t batchsize)
const
166 double scaleX[mXdimensions];
167 for (int32_t
i = 0;
i < mXdimensions;
i++) {
168 scaleX[
i] = (xMax[
i] - xMin[
i]) / ((
double)(mHelpers[
i].getSpline().getUmax()));
171 const int32_t nrOfAllPoints = getNumberOfDataPoints();
172 std::vector<double> dataPointF(nrOfAllPoints * mFdimensions);
174 int32_t nrOfPoints[mXdimensions];
175 for (int32_t
i = 0;
i < mXdimensions;
i++) {
176 nrOfPoints[
i] = mHelpers[
i].getNumberOfDataPoints();
179 std::vector<double>
x[mXdimensions];
180 for (int32_t iDim = 0; iDim < mXdimensions; ++iDim) {
181 x[iDim].reserve(batchsize);
186 for (int32_t d = 0; d < nrOfAllPoints; d++) {
188 int32_t modoperand = 1;
192 for (int32_t
i = 0;
i < mXdimensions;
i++) {
193 modoperand *= nrOfPoints[
i];
197 x[
i].emplace_back(xMin[
i] + mHelpers[
i].getDataPoint(
indices[
i]).u * scaleX[
i]);
201 if (ibatch == batchsize || d == nrOfAllPoints - 1) {
205 index = (d + 1) * mFdimensions;
207 for (int32_t iDim = 0; iDim < mXdimensions; ++iDim) {
213 approximateFunction(Fparameters, dataPointF.data());
218 DataT* Fparameters,
const double DataPointF[])
const
222 int32_t numberOfKnots[mXdimensions];
223 for (int32_t
i = 0;
i < mXdimensions;
i++) {
224 numberOfKnots[
i] = mHelpers[
i].getSpline().getNumberOfKnots();
227 int32_t numberOfDataPoints[mXdimensions];
228 for (int32_t
i = 0;
i < mXdimensions;
i++) {
229 numberOfDataPoints[
i] = mHelpers[
i].getNumberOfDataPoints();
232 int32_t numberOfAllKnots = 1;
233 for (int32_t
i = 0;
i < mXdimensions;
i++) {
234 numberOfAllKnots *= numberOfKnots[
i];
237 LOG(info) <<
"total number of knots: " << numberOfAllKnots <<
", ";
239 int32_t numberOfAllDataPoints = 1;
240 for (int32_t
i = 0;
i < mXdimensions;
i++) {
241 numberOfAllDataPoints *= numberOfDataPoints[
i];
248 int32_t numberOfParameterTypes = (int32_t)(pow(2.0, mXdimensions));
253 std::unique_ptr<double[]> allParameters[numberOfParameterTypes];
254 for (int32_t
i = 0;
i < numberOfParameterTypes;
i++) {
255 allParameters[
i] = std::unique_ptr<double[]>(
new double[numberOfAllDataPoints * mFdimensions]);
258 for (int32_t
i = 0;
i < numberOfAllDataPoints;
i++) {
259 for (int32_t
f = 0;
f < mFdimensions;
f++) {
260 allParameters[0][
i * mFdimensions +
f] = DataPointF[
i * mFdimensions +
f];
262 int32_t p0indices[mXdimensions];
263 arraytopoints(
i, p0indices, numberOfDataPoints, mXdimensions);
265 for (int32_t
j = 0;
j < mXdimensions;
j++) {
266 if (!mHelpers[
j].getDataPoint(p0indices[
j]).isKnot) {
272 int32_t knotindices[mXdimensions];
273 for (int32_t
j = 0;
j < mXdimensions;
j++) {
275 knotindices[
j] = p0indices[
j] / ((numberOfDataPoints[
j] - 1) / (numberOfKnots[
j] - 1));
279 int32_t knotind = pointstoarray(knotindices, numberOfKnots, mXdimensions);
281 for (int32_t
f = 0;
f < mFdimensions;
f++) {
282 Fparameters[knotind * numberOfParameterTypes * mFdimensions +
f] = DataPointF[
i * mFdimensions +
f];
289 std::unique_ptr<double[]> dataPointF1D[mXdimensions];
290 for (int32_t
i = 0;
i < mXdimensions;
i++) {
291 dataPointF1D[
i] = std::unique_ptr<double[]>(
new double[numberOfDataPoints[
i] * mFdimensions]);
294 std::unique_ptr<DataT[]> par[mXdimensions];
295 std::unique_ptr<double[]> parD[mXdimensions];
297 for (int32_t
i = 0;
i < mXdimensions;
i++) {
298 par[
i] = std::unique_ptr<DataT[]>(
new DataT[numberOfKnots[
i] * mFdimensions * 2]);
299 parD[
i] = std::unique_ptr<double[]>(
new double[numberOfKnots[
i] * mFdimensions * 2]);
305 for (int32_t p = 1; p < numberOfParameterTypes; p++) {
306 int32_t dimension = 0;
307 for (int32_t
i = (int32_t)(log2f((
float)p));
i >= 0;
i--) {
308 if (p % (int32_t)(pow(2.0,
i)) == 0) {
314 int32_t currentDataPointF = p - (int32_t)(pow(2.0, dimension));
317 int32_t nrOf1DSplines = (numberOfAllDataPoints / numberOfDataPoints[dimension]);
321 int32_t currentNumbers[mXdimensions - 1];
322 for (int32_t
i = 0;
i < dimension;
i++) {
323 currentNumbers[
i] = numberOfDataPoints[
i];
325 for (int32_t
i = dimension;
i < mXdimensions - 1;
i++) {
326 currentNumbers[
i] = numberOfDataPoints[
i + 1];
329 for (int32_t
i = 0;
i < mXdimensions - 1;
i++) {
335 for (int32_t s = 0; s < nrOf1DSplines; s++) {
336 int32_t
indices[mXdimensions - 1];
337 arraytopoints(s,
indices, currentNumbers, mXdimensions - 1);
338 int32_t startpoint[mXdimensions];
339 for (int32_t
i = 0;
i < dimension;
i++) {
342 startpoint[dimension] = 0;
343 for (int32_t
i = dimension + 1;
i < mXdimensions;
i++) {
347 int32_t startdatapoint = pointstoarray(startpoint, numberOfDataPoints, mXdimensions);
349 for (int32_t
i = 0;
i < dimension;
i++) {
354 for (int32_t
i = 0;
i < numberOfDataPoints[dimension];
i++) {
355 for (int32_t
f = 0;
f < mFdimensions;
f++) {
356 dataPointF1D[dimension][
i * mFdimensions +
f] = allParameters[currentDataPointF][startdatapoint * mFdimensions + (
i *
distance +
f)];
359 mHelpers[dimension].approximateFunction(par[dimension].get(), dataPointF1D[dimension].get());
360 for (int32_t
i = 0;
i < numberOfKnots[dimension] * mFdimensions * 2;
i++) {
361 parD[dimension][
i] = par[dimension][
i];
365 int32_t redistributionindex[mXdimensions];
366 for (int32_t
i = 0;
i < mXdimensions;
i++) {
367 redistributionindex[
i] = startpoint[
i];
370 for (int32_t
i = 0;
i < numberOfKnots[dimension];
i++) {
371 redistributionindex[dimension] = mHelpers[dimension].getKnotDataPoint(
i);
372 int32_t finalposition = pointstoarray(redistributionindex, numberOfDataPoints, mXdimensions);
374 for (int32_t
f = 0;
f < mFdimensions;
f++) {
375 allParameters[p][finalposition * mFdimensions +
f] = par[dimension][2 *
i * mFdimensions + mFdimensions +
f];
379 for (int32_t
j = 0;
j < mXdimensions;
j++) {
380 if (!mHelpers[
j].getDataPoint(redistributionindex[
j]).isKnot) {
387 int32_t knotindices[mXdimensions];
389 for (int32_t
j = 0;
j < mXdimensions;
j++) {
390 knotindices[
j] = redistributionindex[
j] / ((numberOfDataPoints[
j] - 1) / (numberOfKnots[
j] - 1));
394 int32_t knotind = pointstoarray(knotindices, numberOfKnots, mXdimensions);
395 for (int32_t
f = 0;
f < mFdimensions;
f++) {
396 Fparameters[knotind * numberOfParameterTypes * mFdimensions + p * mFdimensions +
f] = par[dimension][2 *
i * mFdimensions + mFdimensions +
f];
402 for (int32_t
i = 0;
i < numberOfDataPoints[dimension];
i++) {
403 redistributionindex[dimension] =
i;
405 for (int32_t
j = 0;
j < mXdimensions;
j++) {
406 if (!mHelpers[
j].getDataPoint(redistributionindex[
j]).isKnot) {
411 double splineF[mFdimensions];
412 double u = mHelpers[dimension].getDataPoint(
i).u;
413 mHelpers[dimension].getSpline().interpolateU(mFdimensions, parD[dimension].get(), u, splineF);
414 for (int32_t dim = 0; dim < mFdimensions; dim++) {
416 allParameters[p - (int32_t)(pow(2.0, dimension))][(int32_t)(startdatapoint * mFdimensions +
i *
distance + dim)] = splineF[dim];
421 int32_t knotindices[mXdimensions];
423 for (int32_t
j = 0;
j < mXdimensions;
j++) {
424 knotindices[
j] = redistributionindex[
j] / ((numberOfDataPoints[
j] - 1) / (numberOfKnots[
j] - 1));
427 int32_t currentknotarrayindex = pointstoarray(knotindices, numberOfKnots, mXdimensions);
429 for (int32_t
f = 0;
f < mFdimensions;
f++) {
430 Fparameters[currentknotarrayindex * numberOfParameterTypes * mFdimensions + (p - (int32_t)(pow(2.0, dimension))) * mFdimensions +
f] = splineF[
f];
445 constexpr int32_t nDimX = 2;
446 constexpr int32_t nDimY = 2;
447 constexpr int32_t Fdegree = 4;
451 int32_t nKnots[nDimX];
452 int32_t* knotsU[nDimX];
453 int32_t nAxiliaryDatapoints[nDimX];
455 for (int32_t
i = 0;
i < nDimX;
i++) {
459 knotsU[
i] =
new int32_t[nKnots[
i]];
460 nAxiliaryDatapoints[
i] = 4;
464 const int32_t nTerms1D = 2 * (Fdegree + 1);
465 int32_t nFcoeff = nDimY;
466 for (int32_t
i = 0;
i < nDimX;
i++) {
470 double Fcoeff[nFcoeff];
472 auto F = [&](
const double x[nDimX],
double f[nDimY]) {
476 for (int32_t d = 0; d < nDimX; d++) {
479 double t = (
x[d] - xMin[d]) * TMath::Pi() / (xMax[d] - xMin[d]);
480 for (int32_t
i = 0;
i < nTerms1D;
i++) {
481 double c = (
i % 2) ? cos((
i / 2) * t) : cos((
i / 2) * t);
482 for (int32_t
j = 0;
j < na;
j++) {
484 assert(nb <= nFcoeff);
488 for (int32_t
i = 0;
i < nb;
i++) {
494 for (int32_t dim = 0; dim < nDimY; dim++) {
496 for (int32_t
i = 0;
i < na;
i++) {
497 f[dim] +=
a[
i] * (*
c++);
502 auto F2D = [&](
double x1,
double x2,
double f[nDimY]) {
503 double x[2] = {
x1, x2};
507 for (int32_t seed = 1; seed < 10; seed++) {
509 gRandom->SetSeed(seed);
512 for (int32_t
i = 0;
i < nFcoeff;
i++) {
513 Fcoeff[
i] = gRandom->Uniform(-1, 1);
516 for (int32_t
i = 0;
i < nDimX;
i++) {
518 for (int32_t
j = 1;
j < nKnots[
i];
j++) {
519 knotsU[
i][
j] =
j * 4;
526 spline.approximateFunction(xMin, xMax, F, nAxiliaryDatapoints);
527 spline2D.approximateFunction(xMin[0], xMax[0], xMin[1], xMax[1],
528 F2D, nAxiliaryDatapoints[0], nAxiliaryDatapoints[0]);
536 for (int32_t
i = 0;
i < nDimX;
i++) {
544 for (int32_t
i = 0;
i < nDimX;
i++) {
548 spline.interpolate(xf, s);
549 spline2D.interpolate(xf[0], xf[1], s2D);
551 for (int32_t dim = 0; dim < nDimY; dim++) {
552 statDf += (s[dim] -
f[dim]) * (s[dim] -
f[dim]);
553 statDf2D += (s2D[dim] -
f[dim]) * (s2D[dim] -
f[dim]);
557 for (; dim < nDimX; dim++) {
559 if (
x[dim] <= xMax[dim]) {
569 LOG(info) <<
"\n std dev for SplineND : " << sqrt(statDf / statN);
570 LOG(info) <<
"\n std dev for Spline2D : " << sqrt(statDf2D / statN);
574 for (int32_t
i = 0;
i < nDimX;
i++) {