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>
299 template <
class Axis>
308 template <
class Axis>
318 template <
class Axis>
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) {
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,
358 const Numeric* fromData = fromSlice.
data();
359 const unsigned fromLen = fromSlice.
length();
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();
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);
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)
430 if (leftInterpolationLinear_[
i] || rightInterpolationLinear_[
i])
435 template <
class Numeric,
class Axis>
439 for (
unsigned i = 0;
i < dim_; ++
i) {
440 if (leftInterpolationLinear_[
i] !=
r.leftInterpolationLinear_[
i])
442 if (rightInterpolationLinear_[
i] !=
r.rightInterpolationLinear_[
i])
445 return data_ ==
r.data_ && axes_ ==
r.axes_ && functionLabel_ ==
r.functionLabel_;
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>
456 const bool status = data_.classId().write(of) && data_.write(of) && gs::write_obj_vector(of, axes_);
458 gs::write_pod_array(of, leftInterpolationLinear_, dim_);
459 gs::write_pod_array(of, rightInterpolationLinear_, dim_);
460 gs::write_pod(of, functionLabel_);
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);
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");
498 return leftInterpolationLinear_[
i];
501 template <
typename Numeric,
class Axis>
505 "In npstat::LinInterpolatedTableND::rightInterpolationLinear: "
506 "index out of range");
507 return rightInterpolationLinear_[
i];
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)
523 vec.push_back(std::pair<bool, bool>(leftInterpolationLinear_[
i], rightInterpolationLinear_[
i]));
527 template <
typename Numeric,
class Axis>
529 const std::vector<Axis>& axes,
const std::vector<std::pair<bool, bool> >& interpolationType,
const char*
label)
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>
553 functionLabel_(
r.functionLabel_),
555 allConstInterpolated_(
r.allConstInterpolated_) {
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,
568 : data_(
data), axes_(axes), functionLabel_(
label), dim_(
data.rank()) {
569 for (
unsigned i = 0;
i <
dim_; ++
i) {
576 template <
typename Numeric,
class Axis>
600 axes_.push_back(tAxis);
601 axes_.push_back(vAxis);
619 template <
typename Numeric,
class Axis>
638 axes_.push_back(tAxis);
654 template <
typename Numeric,
class Axis>
683 template <
typename Numeric,
class Axis>
685 const Axis&
xAxis,
bool leftX,
bool rightX,
const Axis&
yAxis,
bool leftY,
bool rightY,
const char*
label)
701 template <
typename Numeric,
class Axis>
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,
723 const char* functionLabel)
const {
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;
735 std::vector<std::pair<bool, bool> > iType(interpolationType());
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) {
748 sliceIndex[
count] = data_.span(
i);
749 fixedIndices[
count++] =
i;
756 scan.getIndex(sliceIndex,
count);
757 data_.exportSlice(&parentSlice, fixedIndices, 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,
776 const char* functionLabel)
const {
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;
786 std::vector<std::pair<bool, bool> > iType(interpolationType());
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) {
831 sliceIndex[
count] = data_.span(
i);
832 fixedIndices[
count++] =
i;
839 scan.getIndex(sliceIndex,
count);
840 data_.exportSlice(&parentSlice, fixedIndices, sliceIndex,
count);
841 invert1DResponse(parentSlice,
851 pTable->data_.importSlice(dauSlice, fixedIndices, sliceIndex,
count);
854 invert1DResponse(data_,
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)];
877 data_.convertLinearIndex(linearIndex,
index, dim_);
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;
907 if (!allConstInterpolated_)
908 for (
unsigned i = 0;
i < dim_; ++
i)
909 if ((leftInterpolationLinear_[
i] &&
point[
i] < axes_[
i].
min()) ||
910 (rightInterpolationLinear_[
i] &&
point[
i] > axes_[
i].
max())) {
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;
923 return data_.interpolate1(
buf, dim_);
925 unsigned ix[CHAR_BIT *
sizeof(
unsigned long)];
926 double weight[CHAR_BIT *
sizeof(
unsigned long)];
927 for (
unsigned i = 0;
i < dim_; ++
i) {
928 const bool linear = (leftInterpolationLinear_[
i] &&
point[
i] < axes_[
i].min()) ||
929 (rightInterpolationLinear_[
i] &&
point[
i] > axes_[
i].
max());
930 const std::pair<unsigned, double>& pair =
936 Numeric sum = Numeric();
937 const unsigned long maxcycle = 1UL << dim_;
938 const unsigned long* strides = data_.strides();
939 const Numeric* dat = data_.data();
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");
967 return operator()(
tmp, nArgs);
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");
980 return operator()(
tmp, nArgs);
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");
996 return operator()(
tmp, nArgs);
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");
1014 return operator()(
tmp, nArgs);
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");
1031 return operator()(
tmp, nArgs);
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;
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;
1061 if (stepcount == maxSteps)
1063 "In LinInterpolatedTableND::solveForRatioArg: "
1064 "faled to bracket the root");
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,
1097 const Numeric
zero = Numeric();
1098 const Numeric* fromData = fromSlice.
data();
1099 const unsigned fromLen = fromSlice.
length();
1101 assert(fromLen == fromAxis.nCoords());
1102 Numeric* toD = const_cast<Numeric*>(toSlice->
data());
1103 const unsigned nAxisPoints = toAxis.nCoords();
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;
1139 const double x = solveForRatioArg(
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_