1 #ifndef NPSTAT_LININTERPOLATEDTABLEND_HH_ 2 #define NPSTAT_LININTERPOLATEDTABLEND_HH_ 18 #include "Alignment/Geners/interface/CPP11_auto_ptr.hh" 30 template <
class Numeric,
class Axis = UniformAxis>
32 template <
typename Num2,
typename Axis2>
54 const std::vector<std::pair<bool, bool> >& extrapolationType,
118 template <
class Num2>
130 Numeric
operator()(
const double& x0,
const double&
x1)
const;
131 Numeric
operator()(
const double& x0,
const double&
x1,
const double&
x2)
const;
132 Numeric
operator()(
const double& x0,
const double&
x1,
const double&
x2,
const double& x3)
const;
133 Numeric
operator()(
const double& x0,
const double&
x1,
const double&
x2,
const double& x3,
const double& x4)
const;
139 inline const std::vector<Axis>&
axes()
const {
return axes_; }
140 inline const Axis&
axis(
const unsigned i)
const {
return axes_.at(i); }
155 void getCoords(
unsigned long linearIndex,
double* coords,
unsigned coordsBufferSize)
const;
178 template <
typename ConvertibleToUn
signed>
179 CPP11_auto_ptr<LinInterpolatedTableND>
invertWRTAxis(ConvertibleToUnsigned axisNumber,
180 const Axis& replacementAxis,
181 bool newAxisLeftLinear,
182 bool newAxisRightLinear,
207 template <
class Functor1,
class Functor2>
209 const Axis& replacementAxis,
210 bool newAxisLeftLinear,
211 bool newAxisRightLinear,
224 inline gs::ClassId
classId()
const {
return gs::ClassId(*
this); }
225 bool write(std::ostream& of)
const;
229 static inline unsigned version() {
return 1; }
236 const std::vector<Axis>&
axes,
237 const char* leftInterpolation,
238 const char* rightInterpolation,
251 template <
class Functor1>
254 template <
class Functor1>
256 const Axis& fromAxis,
272 #include <functional> 274 #include "Alignment/Geners/interface/binaryIO.hh" 281 template <
class Axis>
283 const unsigned n = axes.size();
286 for (
unsigned i = 0;
i <
n; ++
i)
287 result.push_back(axes[
i].nCoords());
291 template <
class Axis>
295 result.push_back(xAxis.nCoords());
299 template <
class Axis>
303 result.push_back(xAxis.nCoords());
304 result.push_back(yAxis.nCoords());
308 template <
class Axis>
312 result.push_back(xAxis.nCoords());
313 result.push_back(yAxis.nCoords());
314 result.push_back(zAxis.nCoords());
318 template <
class Axis>
322 result.push_back(xAxis.nCoords());
323 result.push_back(yAxis.nCoords());
324 result.push_back(zAxis.nCoords());
325 result.push_back(tAxis.nCoords());
329 template <
class Axis>
331 const Axis&
xAxis,
const Axis&
yAxis,
const Axis&
zAxis,
const Axis& tAxis,
const Axis& vAxis) {
334 result.push_back(xAxis.nCoords());
335 result.push_back(yAxis.nCoords());
336 result.push_back(zAxis.nCoords());
337 result.push_back(tAxis.nCoords());
338 result.push_back(vAxis.nCoords());
343 const double x0,
const double x1,
const double y0,
const double y1,
const double x) {
344 return y0 + (y1 - y0) * ((x - x0) / (x1 - x0));
347 template <
typename Numeric,
class Axis>
349 const Axis& fromAxis,
351 const bool leftLinear,
352 const bool rightLinear,
355 assert(fromSlice.
rank() == 1
U);
356 assert(toSlice->
rank() == 1
U);
358 const Numeric* fromData = fromSlice.
data();
359 const unsigned fromLen = fromSlice.
length();
360 assert(fromLen > 1
U);
361 assert(fromLen == fromAxis.nCoords());
362 const Numeric* fromDataEnd = fromData + fromLen;
365 "In npstat::Private::lind_invert1DSlice: " 366 "slice data is not monotonous and can not be inverted");
368 const Numeric yfirst = fromData[0];
369 const Numeric ylast = fromData[fromLen - 1
U];
370 const bool increasing = yfirst < ylast;
372 Numeric* toD =
const_cast<Numeric*
>(toSlice->
data());
373 const unsigned nAxisPoints = toAxis.nCoords();
374 assert(toSlice->
length() == nAxisPoints);
376 for (
unsigned ipt = 0; ipt < nAxisPoints; ++ipt) {
377 const Numeric y =
static_cast<Numeric
>(toAxis.coordinate(ipt));
382 yfirst, fromData[1], fromAxis.coordinate(0), fromAxis.coordinate(1), y);
384 toD[ipt] = fromAxis.coordinate(0);
385 }
else if (y >= ylast) {
388 fromData[fromLen - 2
U],
389 fromAxis.coordinate(fromLen - 1
U),
390 fromAxis.coordinate(fromLen - 2
U),
393 toD[ipt] = fromAxis.coordinate(fromLen - 1
U);
395 const unsigned i = std::lower_bound(fromData, fromDataEnd, y) - fromData;
397 fromData[i - 1
U], fromData[i], fromAxis.coordinate(i - 1
U), fromAxis.coordinate(i), y);
405 fromData[fromLen - 2
U],
406 fromAxis.coordinate(fromLen - 1
U),
407 fromAxis.coordinate(fromLen - 2
U),
410 toD[ipt] = fromAxis.coordinate(fromLen - 1
U);
411 }
else if (y >= yfirst) {
414 yfirst, fromData[1], fromAxis.coordinate(0), fromAxis.coordinate(1), y);
416 toD[ipt] = fromAxis.coordinate(0);
418 const unsigned i = std::lower_bound(fromData, fromDataEnd, y, std::greater<Numeric>()) - fromData;
420 fromData[i - 1
U], fromData[i], fromAxis.coordinate(i - 1
U), fromAxis.coordinate(i), y);
427 template <
class Numeric,
class Axis>
429 for (
unsigned i = 0;
i <
dim_; ++
i)
435 template <
class Numeric,
class Axis>
439 for (
unsigned i = 0;
i <
dim_; ++
i) {
448 template <
typename Numeric,
class Axis>
450 static const std::string myClass(gs::template_class_name<Numeric, Axis>(
"npstat::LinInterpolatedTableND"));
451 return myClass.c_str();
454 template <
typename Numeric,
class Axis>
462 return status && !of.fail();
465 template <
typename Numeric,
class Axis>
469 current.ensureSameId(
id);
471 gs::ClassId ida(in, 1);
474 std::vector<Axis>
axes;
475 gs::read_heap_obj_vector_as_placed(in, &axes);
476 const unsigned dim = axes.size();
477 if (dim > CHAR_BIT *
sizeof(
unsigned long) || data.
rank() !=
dim)
478 throw gs::IOInvalidData(
479 "In npstat::LinInterpolatedTableND::read: " 480 "read back invalid dimensionality");
481 char leftInterpolation[CHAR_BIT *
sizeof(
unsigned long)];
482 gs::read_pod_array(in, leftInterpolation, dim);
483 char rightInterpolation[CHAR_BIT *
sizeof(
unsigned long)];
484 gs::read_pod_array(in, rightInterpolation, dim);
486 gs::read_pod(in, &label);
488 throw gs::IOReadFailure(
"In npstat::LinInterpolatedTableND::read: input stream failure");
492 template <
typename Numeric,
class Axis>
496 "In npstat::LinInterpolatedTableND::leftInterpolationLinear: " 497 "index out of range");
501 template <
typename Numeric,
class Axis>
505 "In npstat::LinInterpolatedTableND::rightInterpolationLinear: " 506 "index out of range");
510 template <
typename Numeric,
class Axis>
512 for (
unsigned i = 0;
i <
dim_; ++
i)
513 if (!
axes_[
i].isUniform())
518 template <
typename Numeric,
class Axis>
520 std::vector<std::pair<bool, bool> > vec;
522 for (
unsigned i = 0;
i <
dim_; ++
i)
527 template <
typename Numeric,
class Axis>
531 if (
dim_ == 0 ||
dim_ >= CHAR_BIT *
sizeof(
unsigned long))
533 "In npstat::LinInterpolatedTableND constructor: requested " 534 "table dimensionality is not supported");
537 "In npstat::LinInterpolatedTableND constructor: " 538 "incompatible number of interpolation specifications");
539 for (
unsigned i = 0;
i <
dim_; ++
i) {
548 template <
typename Numeric,
class Axis>
549 template <
class Num2>
556 for (
unsigned i = 0;
i <
dim_; ++
i) {
562 template <
typename Numeric,
class Axis>
564 const std::vector<Axis>&
axes,
565 const char* leftInterpolation,
566 const char* rightInterpolation,
569 for (
unsigned i = 0;
i <
dim_; ++
i) {
576 template <
typename Numeric,
class Axis>
597 axes_.push_back(xAxis);
598 axes_.push_back(yAxis);
599 axes_.push_back(zAxis);
600 axes_.push_back(tAxis);
601 axes_.push_back(vAxis);
619 template <
typename Numeric,
class Axis>
635 axes_.push_back(xAxis);
636 axes_.push_back(yAxis);
637 axes_.push_back(zAxis);
638 axes_.push_back(tAxis);
654 template <
typename Numeric,
class Axis>
667 axes_.push_back(xAxis);
668 axes_.push_back(yAxis);
669 axes_.push_back(zAxis);
683 template <
typename Numeric,
class Axis>
685 const Axis&
xAxis,
bool leftX,
bool rightX,
const Axis&
yAxis,
bool leftY,
bool rightY,
const char*
label)
688 axes_.push_back(xAxis);
689 axes_.push_back(yAxis);
701 template <
typename Numeric,
class Axis>
708 axes_.push_back(xAxis);
716 template <
typename Numeric,
class Axis>
717 template <
typename ConvertibleToUn
signed>
719 const ConvertibleToUnsigned axisNumC,
720 const Axis& replacementAxis,
721 const bool leftLinear,
722 const bool rightLinear,
724 const unsigned axisNumber =
static_cast<unsigned>(axisNumC);
726 if (axisNumber >=
dim_)
728 "In npstat::LinInterpolatedTableND::invertAxis: " 729 "axis number is out of range");
732 std::vector<Axis> newAxes(
axes_);
733 newAxes[axisNumber] = replacementAxis;
736 iType[axisNumber] = std::pair<bool, bool>(leftLinear, rightLinear);
743 unsigned sliceIndex[CHAR_BIT *
sizeof(
unsigned long)];
744 unsigned fixedIndices[CHAR_BIT *
sizeof(
unsigned long)];
746 for (
unsigned i = 0;
i <
dim_; ++
i)
747 if (
i != axisNumber) {
749 fixedIndices[count++] =
i;
756 scan.getIndex(sliceIndex, count);
759 parentSlice,
axes_[axisNumber], replacementAxis, leftLinear, rightLinear, &dauSlice);
760 pTable->data_.importSlice(dauSlice, fixedIndices, sliceIndex, count);
767 template <
typename Numeric,
class Axis>
768 template <
class Functor1,
class Functor2>
770 const unsigned axisNumber,
771 const Axis& replacementAxis,
772 const bool leftLinear,
773 const bool rightLinear,
777 if (axisNumber >=
dim_)
779 "In npstat::LinInterpolatedTableND::invertRatioResponse: " 780 "axis number is out of range");
783 std::vector<Axis> newAxes(
axes_);
784 newAxes[axisNumber] = replacementAxis;
787 iType[axisNumber] = std::pair<bool, bool>(leftLinear, rightLinear);
790 const Axis& oldAxis(
axes_[axisNumber]);
791 std::vector<double> rawx;
792 const unsigned nCoords = oldAxis.nCoords();
793 rawx.reserve(nCoords);
794 for (
unsigned i = 0;
i < nCoords; ++
i) {
795 const double x = invg(oldAxis.coordinate(
i));
798 "In npstat::LinInterpolatedTableND::invertRatioResponse: " 799 "invalid original axis definition (negative transformed " 805 std::vector<double> rawf;
806 const unsigned nFuncs = replacementAxis.nCoords();
807 rawf.reserve(nFuncs);
808 for (
unsigned i = 0;
i < nFuncs; ++
i) {
809 const double f = invh(replacementAxis.coordinate(
i));
812 "In npstat::LinInterpolatedTableND::invertRatioResponse: " 813 "invalid new axis definition (negative transformed " 819 std::vector<double> workspace(nCoords);
826 unsigned sliceIndex[CHAR_BIT *
sizeof(
unsigned long)];
827 unsigned fixedIndices[CHAR_BIT *
sizeof(
unsigned long)];
829 for (
unsigned i = 0;
i <
dim_; ++
i)
830 if (
i != axisNumber) {
832 fixedIndices[count++] =
i;
839 scan.getIndex(sliceIndex, count);
851 pTable->data_.importSlice(dauSlice, fixedIndices, sliceIndex, count);
867 template <
typename Numeric,
class Axis>
870 const unsigned coordsBufferSize)
const {
871 if (coordsBufferSize <
dim_)
873 "In LinInterpolatedTableND::getCoords: " 874 "insufficient buffer size");
876 unsigned index[CHAR_BIT *
sizeof(
unsigned long)];
878 for (
unsigned i = 0;
i <
dim_; ++
i)
882 template <
typename Numeric,
class Axis>
886 "In npstat::LinInterpolatedTableND::isWithinLimits: " 887 "incompatible point dimensionality");
890 for (
unsigned i = 0;
i <
dim_; ++
i)
896 template <
typename Numeric,
class Axis>
902 "In npstat::LinInterpolatedTableND::operator(): " 903 "incompatible point dimensionality");
906 bool interpolateArray =
true;
908 for (
unsigned i = 0;
i <
dim_; ++
i)
911 interpolateArray =
false;
915 if (interpolateArray) {
918 double buf[CHAR_BIT *
sizeof(
unsigned long)];
919 for (
unsigned i = 0;
i <
dim_; ++
i) {
920 const std::pair<unsigned, double>& pair =
axes_[
i].getInterval(point[
i]);
921 buf[
i] = pair.first + 1
U - pair.second;
925 unsigned ix[CHAR_BIT *
sizeof(
unsigned long)];
926 double weight[CHAR_BIT *
sizeof(
unsigned long)];
927 for (
unsigned i = 0;
i <
dim_; ++
i) {
930 const std::pair<unsigned, double>& pair =
931 linear ?
axes_[
i].linearInterval(point[
i]) :
axes_[
i].getInterval(point[i]);
936 Numeric sum = Numeric();
937 const unsigned long maxcycle = 1UL <<
dim_;
940 for (
unsigned long icycle = 0UL; icycle < maxcycle; ++icycle) {
942 unsigned long icell = 0UL;
943 for (
unsigned i = 0;
i <
dim_; ++
i) {
944 if (icycle & (1UL <<
i)) {
946 icell += strides[
i] * (ix[
i] + 1
U);
949 icell += strides[
i] * ix[
i];
952 sum += dat[icell] *
static_cast<proper_double
>(
w);
958 template <
typename Numeric,
class Axis>
960 const unsigned nArgs = 1
U;
963 "In npstat::LinInterpolatedTableND::operator(): number of " 964 "arguments, 1, is incompatible with the interpolator dimensionality");
970 template <
typename Numeric,
class Axis>
972 const unsigned nArgs = 2
U;
975 "In npstat::LinInterpolatedTableND::operator(): number of " 976 "arguments, 2, is incompatible with the interpolator dimensionality");
983 template <
typename Numeric,
class Axis>
986 const double&
x2)
const {
987 const unsigned nArgs = 3
U;
990 "In npstat::LinInterpolatedTableND::operator(): number of " 991 "arguments, 3, is incompatible with the interpolator dimensionality");
999 template <
typename Numeric,
class Axis>
1003 const double& x3)
const {
1004 const unsigned nArgs = 4
U;
1007 "In npstat::LinInterpolatedTableND::operator(): number of " 1008 "arguments, 4, is incompatible with the interpolator dimensionality");
1017 template <
typename Numeric,
class Axis>
1019 const double& x0,
const double&
x1,
const double&
x2,
const double& x3,
const double& x4)
const {
1020 const unsigned nArgs = 5
U;
1023 "In npstat::LinInterpolatedTableND::operator(): number of " 1024 "arguments, 5, is incompatible with the interpolator dimensionality");
1034 template <
typename Numeric,
class Axis>
1035 template <
class Functor1>
1037 const double xmin,
const double xmax,
const double rmin,
const double rmax,
const double fval,
Functor1 invg) {
1041 double fmin = invg(xmin) * rmin;
1042 double fmax = invg(xmax) * rmax;
1044 assert(fmin < fmax);
1047 unsigned stepcount = 0;
1048 const unsigned maxSteps = 1000
U;
1049 for (
double stepfactor = 1.0; (fval < fmin || fval > fmax) && stepcount < maxSteps; stepfactor *= 2.0, ++stepcount)
1053 x0 -= stepfactor *
step;
1058 x1 += stepfactor *
step;
1061 if (stepcount == maxSteps)
1063 "In LinInterpolatedTableND::solveForRatioArg: " 1064 "faled to bracket the root");
1067 while ((x1 - x0) / (
std::abs(x1) +
std::abs(x0) + DBL_EPSILON) > 4.0 * DBL_EPSILON) {
1068 const double xhalf = (x1 + x0) / 2.0;
1078 return (x1 + x0) / 2.0;
1081 template <
typename Numeric,
class Axis>
1082 template <
class Functor1>
1084 const Axis& fromAxis,
1086 const bool newLeftLinear,
1087 const bool newRightLinear,
1094 assert(fromSlice.
rank() == 1
U);
1095 assert(toSlice->
rank() == 1
U);
1097 const Numeric zero = Numeric();
1098 const Numeric* fromData = fromSlice.
data();
1099 const unsigned fromLen = fromSlice.
length();
1100 assert(fromLen > 1
U);
1101 assert(fromLen == fromAxis.nCoords());
1102 Numeric* toD =
const_cast<Numeric*
>(toSlice->
data());
1103 const unsigned nAxisPoints = toAxis.nCoords();
1104 assert(toSlice->
length() == nAxisPoints);
1106 for (
unsigned i = 0;
i < fromLen; ++
i) {
1107 if (fromData[
i] <= zero)
1109 "In LinInterpolatedTableND::invert1DResponse: " 1110 "non-positive response found. This ratio " 1111 "response table is not invertible.");
1112 workspace[
i] = rawx[
i] * fromData[
i];
1115 const double yfirst = workspace[0];
1116 const double ylast = workspace[fromLen - 1
U];
1118 bool adjustZero =
false;
1119 unsigned nBelow = 0;
1120 for (
unsigned ipt = 0; ipt < nAxisPoints; ++ipt) {
1121 const double y = rawf[ipt];
1128 }
else if (y <= yfirst) {
1130 solve = newLeftLinear;
1131 }
else if (y >= ylast) {
1132 solve = newRightLinear;
1133 i0 = solve ? fromLen - 2 : fromLen - 1;
1136 i0 =
static_cast<unsigned>(std::lower_bound(workspace, workspace + fromLen, y) - workspace) - 1
U;
1140 fromAxis.coordinate(i0), fromAxis.coordinate(i0 + 1), fromData[i0], fromData[i0 + 1], y, invg);
1141 toD[ipt] = invg(x) / y;
1143 toD[ipt] = 1.0 / fromData[i0];
1145 if (adjustZero && nBelow)
1150 #endif // NPSTAT_LININTERPOLATEDTABLEND_HH_
bool rightInterpolationLinear(unsigned i) const
static void invert1DResponse(const ArrayND< Numeric > &fromSlice, const Axis &fromAxis, const Axis &toAxis, bool newLeftLinear, bool newRightLinear, Functor1 invg, const double *rawx, const double *rawf, double *workspace, ArrayND< Numeric > *toSlice)
bool allConstInterpolated_
void convertLinearIndex(unsigned long l, unsigned *index, unsigned indexLen) const
bool write(std::ostream &of) const
void getCoords(unsigned long linearIndex, double *coords, unsigned coordsBufferSize) const
std::unique_ptr< LinInterpolatedTableND > invertRatioResponse(unsigned axisNumber, const Axis &replacementAxis, bool newAxisLeftLinear, bool newAxisRightLinear, Functor1 invg, Functor2 invh, const char *functionLabel=0) const
std::vector< unsigned > ArrayShape
unsigned long length() const
unsigned span(unsigned dim) const
std::string functionLabel_
Numeric interpolate1(const double *x, unsigned xDim) const
const ArrayND< Numeric > & table() const
static double solveForRatioArg(double xmin, double xmax, double rmin, double rmax, double fval, Functor1 invg)
Numeric operator()(const double *point, unsigned dim) const
unsigned long length() const
bool write(std::ostream &of) const
A few simple template functions for checking monotonicity of container values.
gs::ClassId classId() const
bool operator==(const LinInterpolatedTableND &) const
LinInterpolatedTableND()=delete
std::vector< std::pair< bool, bool > > interpolationType() const
const std::vector< Axis > & axes() const
static LinInterpolatedTableND * read(const gs::ClassId &id, std::istream &in)
bool operator!=(const LinInterpolatedTableND &r) const
std::vector< Axis > axes_
Abs< T >::type abs(const T &t)
const Numeric * data() const
void setFunctionLabel(const char *newlabel)
char rightInterpolationLinear_[CHAR_BIT *sizeof(unsigned long)]
static unsigned version()
ArrayShape makeTableShape(const Axis &xAxis, const Axis &yAxis, const Axis &zAxis, const Axis &tAxis, const Axis &vAxis)
bool isUniformlyBinned() const
std::unique_ptr< LinInterpolatedTableND > invertWRTAxis(ConvertibleToUnsigned axisNumber, const Axis &replacementAxis, bool newAxisLeftLinear, bool newAxisRightLinear, const char *functionLabel=0) const
char leftInterpolationLinear_[CHAR_BIT *sizeof(unsigned long)]
bool leftInterpolationLinear(unsigned i) const
double lind_interpolateSimple(const double x0, const double x1, const double y0, const double y1, const double x)
ArrayND< Numeric > & table()
bool isStrictlyMonotonous(Iter const begin, Iter const end)
static void restore(const gs::ClassId &id, std::istream &in, ArrayND *array)
bool allConstInterpolated() const
void lind_invert1DSlice(const ArrayND< Numeric > &fromSlice, const Axis &fromAxis, const Axis &toAxis, const bool leftLinear, const bool rightLinear, ArrayND< Numeric > *toSlice)
bool isWithinLimits(const double *point, unsigned dim) const
char data[epos_bytes_allocation]
const unsigned long * strides() const
const Axis & axis(const unsigned i) const
const std::string & functionLabel() const
Iteration over indices of a multidimensional array.
static const char * classname()
gs::ClassId classId() const
Arbitrary-dimensional array template.
*vegas h *****************************************************used in the default bin number in original ***version of VEGAS is ***a higher bin number might help to derive a more precise ***grade subtle point
void exportSlice(ArrayND< Num2, Len2, Dim2 > *slice, const unsigned *fixedIndices, const unsigned *fixedIndexValues, unsigned nFixedIndices) const