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>
133 Numeric
operator()(
const double& x0,
const double&
x1)
const;
134 Numeric
operator()(
const double& x0,
const double&
x1,
const double&
x2)
const;
135 Numeric
operator()(
const double& x0,
const double&
x1,
const double&
x2,
const double& x3)
const;
136 Numeric
operator()(
const double& x0,
const double&
x1,
const double&
x2,
const double& x3,
const double& x4)
const;
142 inline const std::vector<Axis>&
axes()
const {
return axes_; }
143 inline const Axis&
axis(
const unsigned i)
const {
return axes_.at(
i); }
158 void getCoords(
unsigned long linearIndex,
double* coords,
unsigned coordsBufferSize)
const;
181 template <
typename ConvertibleToUn
signed>
182 CPP11_auto_ptr<LinInterpolatedTableND>
invertWRTAxis(ConvertibleToUnsigned axisNumber,
183 const Axis& replacementAxis,
184 bool newAxisLeftLinear,
185 bool newAxisRightLinear,
210 template <
class Functor1,
class Functor2>
212 const Axis& replacementAxis,
213 bool newAxisLeftLinear,
214 bool newAxisRightLinear,
227 inline gs::ClassId
classId()
const {
return gs::ClassId(*
this); }
228 bool write(std::ostream& of)
const;
232 static inline unsigned version() {
return 1; }
237 const std::vector<Axis>&
axes,
238 const char* leftInterpolation,
239 const char* rightInterpolation,
252 template <
class Functor1>
255 template <
class Functor1>
257 const Axis& fromAxis,
273 #include <functional>
275 #include "Alignment/Geners/interface/binaryIO.hh"
282 template <
class Axis>
284 const unsigned n = axes.size();
287 for (
unsigned i = 0;
i <
n; ++
i)
288 result.push_back(axes[
i].nCoords());
292 template <
class Axis>
300 template <
class Axis>
309 template <
class Axis>
319 template <
class Axis>
326 result.push_back(tAxis.nCoords());
330 template <
class Axis>
332 const Axis&
xAxis,
const Axis&
yAxis,
const Axis&
zAxis,
const Axis& tAxis,
const Axis& vAxis) {
338 result.push_back(tAxis.nCoords());
339 result.push_back(vAxis.nCoords());
344 const double x0,
const double x1,
const double y0,
const double y1,
const double x) {
345 return y0 + (
y1 - y0) * ((x - x0) / (
x1 - x0));
348 template <
typename Numeric,
class Axis>
350 const Axis& fromAxis,
352 const bool leftLinear,
353 const bool rightLinear,
359 const Numeric* fromData = fromSlice.
data();
360 const unsigned fromLen = fromSlice.
length();
362 assert(fromLen == fromAxis.nCoords());
363 const Numeric* fromDataEnd = fromData + fromLen;
366 "In npstat::Private::lind_invert1DSlice: "
367 "slice data is not monotonous and can not be inverted");
369 const Numeric yfirst = fromData[0];
370 const Numeric ylast = fromData[fromLen - 1
U];
371 const bool increasing = yfirst < ylast;
373 Numeric* toD = const_cast<Numeric*>(toSlice->
data());
374 const unsigned nAxisPoints = toAxis.nCoords();
377 for (
unsigned ipt = 0; ipt < nAxisPoints; ++ipt) {
378 const Numeric y = static_cast<Numeric>(toAxis.coordinate(ipt));
383 yfirst, fromData[1], fromAxis.coordinate(0), fromAxis.coordinate(1), y);
385 toD[ipt] = fromAxis.coordinate(0);
386 }
else if (y >= ylast) {
389 fromData[fromLen - 2
U],
390 fromAxis.coordinate(fromLen - 1
U),
391 fromAxis.coordinate(fromLen - 2
U),
394 toD[ipt] = fromAxis.coordinate(fromLen - 1
U);
398 fromData[
i - 1
U], fromData[
i], fromAxis.coordinate(
i - 1
U), fromAxis.coordinate(
i), y);
406 fromData[fromLen - 2
U],
407 fromAxis.coordinate(fromLen - 1
U),
408 fromAxis.coordinate(fromLen - 2
U),
411 toD[ipt] = fromAxis.coordinate(fromLen - 1
U);
412 }
else if (y >= yfirst) {
415 yfirst, fromData[1], fromAxis.coordinate(0), fromAxis.coordinate(1), y);
417 toD[ipt] = fromAxis.coordinate(0);
419 const unsigned i =
std::lower_bound(fromData, fromDataEnd, y, std::greater<Numeric>()) - fromData;
421 fromData[
i - 1
U], fromData[
i], fromAxis.coordinate(
i - 1
U), fromAxis.coordinate(
i), y);
428 template <
class Numeric,
class Axis>
430 for (
unsigned i = 0;
i < dim_; ++
i)
431 if (leftInterpolationLinear_[
i] || rightInterpolationLinear_[
i])
436 template <
class Numeric,
class Axis>
440 for (
unsigned i = 0;
i < dim_; ++
i) {
441 if (leftInterpolationLinear_[
i] !=
r.leftInterpolationLinear_[
i])
443 if (rightInterpolationLinear_[
i] !=
r.rightInterpolationLinear_[
i])
446 return data_ ==
r.data_ && axes_ ==
r.axes_ && functionLabel_ ==
r.functionLabel_;
449 template <
typename Numeric,
class Axis>
451 static const std::string myClass(gs::template_class_name<Numeric, Axis>(
"npstat::LinInterpolatedTableND"));
452 return myClass.c_str();
455 template <
typename Numeric,
class Axis>
457 const bool status = data_.classId().write(of) && data_.write(of) && gs::write_obj_vector(of, axes_);
459 gs::write_pod_array(of, leftInterpolationLinear_, dim_);
460 gs::write_pod_array(of, rightInterpolationLinear_, dim_);
461 gs::write_pod(of, functionLabel_);
463 return status && !of.fail();
466 template <
typename Numeric,
class Axis>
470 current.ensureSameId(
id);
472 gs::ClassId ida(
in, 1);
475 std::vector<Axis> axes;
476 gs::read_heap_obj_vector_as_placed(
in, &axes);
477 const unsigned dim = axes.size();
478 if (dim > CHAR_BIT *
sizeof(
unsigned long) ||
data.rank() != dim)
479 throw gs::IOInvalidData(
480 "In npstat::LinInterpolatedTableND::read: "
481 "read back invalid dimensionality");
482 char leftInterpolation[CHAR_BIT *
sizeof(
unsigned long)];
483 gs::read_pod_array(
in, leftInterpolation, dim);
484 char rightInterpolation[CHAR_BIT *
sizeof(
unsigned long)];
485 gs::read_pod_array(
in, rightInterpolation, dim);
489 throw gs::IOReadFailure(
"In npstat::LinInterpolatedTableND::read: input stream failure");
493 template <
typename Numeric,
class Axis>
497 "In npstat::LinInterpolatedTableND::leftInterpolationLinear: "
498 "index out of range");
499 return leftInterpolationLinear_[
i];
502 template <
typename Numeric,
class Axis>
506 "In npstat::LinInterpolatedTableND::rightInterpolationLinear: "
507 "index out of range");
508 return rightInterpolationLinear_[
i];
511 template <
typename Numeric,
class Axis>
513 for (
unsigned i = 0;
i < dim_; ++
i)
514 if (!axes_[
i].isUniform())
519 template <
typename Numeric,
class Axis>
521 std::vector<std::pair<bool, bool> > vec;
523 for (
unsigned i = 0;
i < dim_; ++
i)
524 vec.push_back(std::pair<bool, bool>(leftInterpolationLinear_[
i], rightInterpolationLinear_[
i]));
528 template <
typename Numeric,
class Axis>
530 const std::vector<Axis>& axes,
const std::vector<std::pair<bool, bool> >& interpolationType,
const char*
label)
532 if (
dim_ == 0 ||
dim_ >= CHAR_BIT *
sizeof(
unsigned long))
534 "In npstat::LinInterpolatedTableND constructor: requested "
535 "table dimensionality is not supported");
538 "In npstat::LinInterpolatedTableND constructor: "
539 "incompatible number of interpolation specifications");
540 for (
unsigned i = 0;
i <
dim_; ++
i) {
549 template <
typename Numeric,
class Axis>
550 template <
class Num2>
554 functionLabel_(
r.functionLabel_),
556 allConstInterpolated_(
r.allConstInterpolated_) {
557 for (
unsigned i = 0;
i <
dim_; ++
i) {
563 template <
typename Numeric,
class Axis>
565 const std::vector<Axis>& axes,
566 const char* leftInterpolation,
567 const char* rightInterpolation,
569 : data_(
data), axes_(axes), functionLabel_(
label), dim_(
data.rank()) {
570 for (
unsigned i = 0;
i <
dim_; ++
i) {
577 template <
typename Numeric,
class Axis>
601 axes_.push_back(tAxis);
602 axes_.push_back(vAxis);
620 template <
typename Numeric,
class Axis>
639 axes_.push_back(tAxis);
655 template <
typename Numeric,
class Axis>
684 template <
typename Numeric,
class Axis>
686 const Axis&
xAxis,
bool leftX,
bool rightX,
const Axis&
yAxis,
bool leftY,
bool rightY,
const char*
label)
702 template <
typename Numeric,
class Axis>
717 template <
typename Numeric,
class Axis>
718 template <
typename ConvertibleToUn
signed>
720 const ConvertibleToUnsigned axisNumC,
721 const Axis& replacementAxis,
722 const bool leftLinear,
723 const bool rightLinear,
724 const char* functionLabel)
const {
725 const unsigned axisNumber = static_cast<unsigned>(axisNumC);
727 if (axisNumber >= dim_)
729 "In npstat::LinInterpolatedTableND::invertAxis: "
730 "axis number is out of range");
733 std::vector<Axis> newAxes(axes_);
734 newAxes[axisNumber] = replacementAxis;
736 std::vector<std::pair<bool, bool> > iType(interpolationType());
737 iType[axisNumber] = std::pair<bool, bool>(leftLinear, rightLinear);
744 unsigned sliceIndex[CHAR_BIT *
sizeof(
unsigned long)];
745 unsigned fixedIndices[CHAR_BIT *
sizeof(
unsigned long)];
747 for (
unsigned i = 0;
i < dim_; ++
i)
748 if (
i != axisNumber) {
749 sliceIndex[
count] = data_.span(
i);
750 fixedIndices[
count++] =
i;
757 scan.getIndex(sliceIndex,
count);
758 data_.exportSlice(&parentSlice, fixedIndices, sliceIndex,
count);
760 parentSlice, axes_[axisNumber], replacementAxis, leftLinear, rightLinear, &dauSlice);
761 pTable->data_.importSlice(dauSlice, fixedIndices, sliceIndex,
count);
768 template <
typename Numeric,
class Axis>
769 template <
class Functor1,
class Functor2>
771 const unsigned axisNumber,
772 const Axis& replacementAxis,
773 const bool leftLinear,
774 const bool rightLinear,
777 const char* functionLabel)
const {
778 if (axisNumber >= dim_)
780 "In npstat::LinInterpolatedTableND::invertRatioResponse: "
781 "axis number is out of range");
784 std::vector<Axis> newAxes(axes_);
785 newAxes[axisNumber] = replacementAxis;
787 std::vector<std::pair<bool, bool> > iType(interpolationType());
788 iType[axisNumber] = std::pair<bool, bool>(leftLinear, rightLinear);
791 const Axis& oldAxis(axes_[axisNumber]);
792 std::vector<double> rawx;
793 const unsigned nCoords = oldAxis.nCoords();
794 rawx.reserve(nCoords);
795 for (
unsigned i = 0;
i < nCoords; ++
i) {
796 const double x = invg(oldAxis.coordinate(
i));
799 "In npstat::LinInterpolatedTableND::invertRatioResponse: "
800 "invalid original axis definition (negative transformed "
806 std::vector<double> rawf;
807 const unsigned nFuncs = replacementAxis.nCoords();
808 rawf.reserve(nFuncs);
809 for (
unsigned i = 0;
i < nFuncs; ++
i) {
810 const double f = invh(replacementAxis.coordinate(
i));
813 "In npstat::LinInterpolatedTableND::invertRatioResponse: "
814 "invalid new axis definition (negative transformed "
820 std::vector<double> workspace(nCoords);
827 unsigned sliceIndex[CHAR_BIT *
sizeof(
unsigned long)];
828 unsigned fixedIndices[CHAR_BIT *
sizeof(
unsigned long)];
830 for (
unsigned i = 0;
i < dim_; ++
i)
831 if (
i != axisNumber) {
832 sliceIndex[
count] = data_.span(
i);
833 fixedIndices[
count++] =
i;
840 scan.getIndex(sliceIndex,
count);
841 data_.exportSlice(&parentSlice, fixedIndices, sliceIndex,
count);
842 invert1DResponse(parentSlice,
852 pTable->data_.importSlice(dauSlice, fixedIndices, sliceIndex,
count);
855 invert1DResponse(data_,
868 template <
typename Numeric,
class Axis>
871 const unsigned coordsBufferSize)
const {
872 if (coordsBufferSize < dim_)
874 "In LinInterpolatedTableND::getCoords: "
875 "insufficient buffer size");
877 unsigned index[CHAR_BIT *
sizeof(
unsigned long)];
878 data_.convertLinearIndex(linearIndex,
index, dim_);
879 for (
unsigned i = 0;
i < dim_; ++
i)
883 template <
typename Numeric,
class Axis>
887 "In npstat::LinInterpolatedTableND::isWithinLimits: "
888 "incompatible point dimensionality");
891 for (
unsigned i = 0;
i < dim_; ++
i)
897 template <
typename Numeric,
class Axis>
903 "In npstat::LinInterpolatedTableND::operator(): "
904 "incompatible point dimensionality");
907 bool interpolateArray =
true;
908 if (!allConstInterpolated_)
909 for (
unsigned i = 0;
i < dim_; ++
i)
910 if ((leftInterpolationLinear_[
i] &&
point[
i] < axes_[
i].
min()) ||
911 (rightInterpolationLinear_[
i] &&
point[
i] > axes_[
i].
max())) {
912 interpolateArray =
false;
916 if (interpolateArray) {
919 double buf[CHAR_BIT *
sizeof(
unsigned long)];
920 for (
unsigned i = 0;
i < dim_; ++
i) {
921 const std::pair<unsigned, double>& pair = axes_[
i].getInterval(
point[
i]);
922 buf[
i] = pair.first + 1
U - pair.second;
924 return data_.interpolate1(
buf, dim_);
926 unsigned ix[CHAR_BIT *
sizeof(
unsigned long)];
927 double weight[CHAR_BIT *
sizeof(
unsigned long)];
928 for (
unsigned i = 0;
i < dim_; ++
i) {
929 const bool linear = (leftInterpolationLinear_[
i] &&
point[
i] < axes_[
i].min()) ||
930 (rightInterpolationLinear_[
i] &&
point[
i] > axes_[
i].
max());
931 const std::pair<unsigned, double>& pair =
937 Numeric sum = Numeric();
938 const unsigned long maxcycle = 1UL << dim_;
939 const unsigned long* strides = data_.strides();
940 const Numeric* dat = data_.data();
941 for (
unsigned long icycle = 0UL; icycle < maxcycle; ++icycle) {
943 unsigned long icell = 0UL;
944 for (
unsigned i = 0;
i < dim_; ++
i) {
945 if (icycle & (1UL <<
i)) {
947 icell += strides[
i] * (ix[
i] + 1
U);
950 icell += strides[
i] * ix[
i];
953 sum += dat[icell] * static_cast<proper_double>(
w);
959 template <
typename Numeric,
class Axis>
961 const unsigned nArgs = 1
U;
964 "In npstat::LinInterpolatedTableND::operator(): number of "
965 "arguments, 1, is incompatible with the interpolator dimensionality");
968 return operator()(
tmp, nArgs);
971 template <
typename Numeric,
class Axis>
973 const unsigned nArgs = 2
U;
976 "In npstat::LinInterpolatedTableND::operator(): number of "
977 "arguments, 2, is incompatible with the interpolator dimensionality");
981 return operator()(
tmp, nArgs);
984 template <
typename Numeric,
class Axis>
987 const double&
x2)
const {
988 const unsigned nArgs = 3
U;
991 "In npstat::LinInterpolatedTableND::operator(): number of "
992 "arguments, 3, is incompatible with the interpolator dimensionality");
997 return operator()(
tmp, nArgs);
1000 template <
typename Numeric,
class Axis>
1004 const double& x3)
const {
1005 const unsigned nArgs = 4
U;
1008 "In npstat::LinInterpolatedTableND::operator(): number of "
1009 "arguments, 4, is incompatible with the interpolator dimensionality");
1015 return operator()(
tmp, nArgs);
1018 template <
typename Numeric,
class Axis>
1020 const double& x0,
const double&
x1,
const double&
x2,
const double& x3,
const double& x4)
const {
1021 const unsigned nArgs = 5
U;
1024 "In npstat::LinInterpolatedTableND::operator(): number of "
1025 "arguments, 5, is incompatible with the interpolator dimensionality");
1032 return operator()(
tmp, nArgs);
1035 template <
typename Numeric,
class Axis>
1036 template <
class Functor1>
1038 const double xmin,
const double xmax,
const double rmin,
const double rmax,
const double fval,
Functor1 invg) {
1042 double fmin = invg(
xmin) * rmin;
1043 double fmax = invg(
xmax) * rmax;
1048 unsigned stepcount = 0;
1049 const unsigned maxSteps = 1000
U;
1050 for (
double stepfactor = 1.0; (fval < fmin || fval > fmax) && stepcount < maxSteps; stepfactor *= 2.0, ++stepcount)
1054 x0 -= stepfactor *
step;
1062 if (stepcount == maxSteps)
1064 "In LinInterpolatedTableND::solveForRatioArg: "
1065 "faled to bracket the root");
1069 const double xhalf = (
x1 + x0) / 2.0;
1079 return (
x1 + x0) / 2.0;
1082 template <
typename Numeric,
class Axis>
1083 template <
class Functor1>
1085 const Axis& fromAxis,
1087 const bool newLeftLinear,
1088 const bool newRightLinear,
1098 const Numeric
zero = Numeric();
1099 const Numeric* fromData = fromSlice.
data();
1100 const unsigned fromLen = fromSlice.
length();
1102 assert(fromLen == fromAxis.nCoords());
1103 Numeric* toD = const_cast<Numeric*>(toSlice->
data());
1104 const unsigned nAxisPoints = toAxis.nCoords();
1107 for (
unsigned i = 0;
i < fromLen; ++
i) {
1108 if (fromData[
i] <=
zero)
1110 "In LinInterpolatedTableND::invert1DResponse: "
1111 "non-positive response found. This ratio "
1112 "response table is not invertible.");
1113 workspace[
i] = rawx[
i] * fromData[
i];
1116 const double yfirst = workspace[0];
1117 const double ylast = workspace[fromLen - 1
U];
1119 bool adjustZero =
false;
1120 unsigned nBelow = 0;
1121 for (
unsigned ipt = 0; ipt < nAxisPoints; ++ipt) {
1122 const double y = rawf[ipt];
1129 }
else if (y <= yfirst) {
1131 solve = newLeftLinear;
1132 }
else if (y >= ylast) {
1133 solve = newRightLinear;
1134 i0 = solve ? fromLen - 2 : fromLen - 1;
1137 i0 = static_cast<unsigned>(
std::lower_bound(workspace, workspace + fromLen, y) - workspace) - 1
U;
1140 const double x = solveForRatioArg(
1141 fromAxis.coordinate(i0), fromAxis.coordinate(i0 + 1), fromData[i0], fromData[i0 + 1], y, invg);
1142 toD[ipt] = invg(x) / y;
1144 toD[ipt] = 1.0 / fromData[i0];
1146 if (adjustZero && nBelow)
1151 #endif // NPSTAT_LININTERPOLATEDTABLEND_HH_