Loading [MathJax]/jax/output/NativeMML/config.js
Isis 3 Programmer Reference
NumericalApproximation.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include "NumericalApproximation.h"
8 
9 #include <cmath>
10 #include <iostream>
11 #include <sstream>
12 #include <string>
13 #include <vector>
14 #include <algorithm>
15 
16 #include "SpecialPixel.h"
17 #include "IException.h"
18 #include "IString.h"
19 
20 using namespace std;
21 namespace Isis {
22  NumericalApproximation::FunctorList NumericalApproximation::p_interpFunctors;
23 
41  NumericalApproximation::NumericalApproximation(const NumericalApproximation::InterpType &itype) {
42  // Validate parameter and initialize class variables
43  try {
44  Init(itype);
45  p_dataValidated = false;
46  }
47  catch(IException &e) { // catch exception from Init()
48  throw IException(e, e.errorType(),
49  "NumericalApproximation() - Unable to construct NumericalApproximation object",
50  _FILEINFO_);
51  }
52  }
53 
87  NumericalApproximation::NumericalApproximation(unsigned int n, double *x, double *y,
89  try {
90  Init(itype);
91  AddData(n, x, y);
92  ValidateDataSet();
93  }
94  catch(IException &e) { // catch exception from Init(), AddData(), ValidateDataSet()
95  throw IException(e, e.errorType(),
96  "NumericalApproximation() - Unable to construct object using the given arrays, size and interpolation type",
97  _FILEINFO_);
98  }
99  }
100 
131  NumericalApproximation::NumericalApproximation(const vector <double> &x, const vector <double> &y,
132  const NumericalApproximation::InterpType &itype) {
133  try {
134  Init(itype);
135  AddData(x, y); // size of x = size of y validated in this method
136  ValidateDataSet();
137  }
138  catch(IException &e) { // catch exception from Init(), AddData(), ValidateDataSet()
139  throw IException(e, e.errorType(),
140  "NumericalApproximation() - Unable to construct an object using the given vectors and interpolation type",
141  _FILEINFO_);
142  }
143  }
144 
170  NumericalApproximation::NumericalApproximation(const NumericalApproximation &oldObject) {
171  try {
172  // initialize new object and set type to that of old object
173  Init(oldObject.p_itype);
174  // fill data set of new object
175  p_x = oldObject.p_x;
176  p_y = oldObject.p_y;
177  // if this data was previously validated, no need to do this again
178  p_dataValidated = oldObject.p_dataValidated;
179  // copy values for interpolation-specific variables
180  p_clampedComputed = oldObject.p_clampedComputed;
181  p_clampedEndptsSet = oldObject.p_clampedEndptsSet;
182  p_clampedSecondDerivs = oldObject.p_clampedSecondDerivs;
183  p_clampedDerivFirstPt = oldObject.p_clampedDerivFirstPt;
184  p_clampedDerivLastPt = oldObject.p_clampedDerivLastPt;
185  p_polyNevError = oldObject.p_polyNevError;
186  p_fprimeOfx = oldObject.p_fprimeOfx;
187  }
188  catch(IException &e) { // catch exception from Init()
189  throw IException(e,
190  e.errorType(),
191  "NumericalApproximation() - Unable to copy the given object",
192  _FILEINFO_);
193  }
194  }
195 
220  NumericalApproximation &NumericalApproximation::operator=(const NumericalApproximation &oldObject) {
221  try {
222  if(&oldObject != this) {
223  if(GslInterpType(p_itype)) GslDeallocation();
224  SetInterpType(oldObject.p_itype);
225  // set class variables
226  p_x = oldObject.p_x;
227  p_y = oldObject.p_y;
228  p_dataValidated = oldObject.p_dataValidated;
229  p_clampedSecondDerivs = oldObject.p_clampedSecondDerivs;
230  p_clampedDerivFirstPt = oldObject.p_clampedDerivFirstPt;
231  p_clampedDerivLastPt = oldObject.p_clampedDerivLastPt;
232  p_polyNevError = oldObject.p_polyNevError;
233  p_fprimeOfx = oldObject.p_fprimeOfx;
234  }
235  return (*this);
236  }
237  catch(IException &e) { // catch exception from SetInterpType()
238  throw IException(e,
239  e.errorType(),
240  "operator=() - Unable to copy the given object",
241  _FILEINFO_);
242  }
243 
244  }
245 
256  NumericalApproximation::~NumericalApproximation() {
257  if(GslInterpType(p_itype)) GslDeallocation();
258  }
259 
282  string NumericalApproximation::Name() const {
283  if(p_itype == NumericalApproximation::CubicNeighborhood) {
284  return "cspline-neighborhood";
285  }
286  else if(p_itype == NumericalApproximation::CubicClamped) {
287  return "cspline-clamped";
288  }
289  else if(p_itype == NumericalApproximation::PolynomialNeville) {
290  return "polynomial-Neville's";
291  }
292  else if(p_itype == NumericalApproximation::CubicHermite) {
293  return "cspline-Hermite";
294  }
295  try {
296  string name = (string(GslFunctor(p_itype)->name));
297  if(p_itype == NumericalApproximation::CubicNatural) {
298  return name + "-natural";
299  }
300  else return name;
301  }
302  catch(IException &e) { // catch exception from GslFunctor()
303  throw IException(e,
304  e.errorType(),
305  "Name() - GSL interpolation type not found",
306  _FILEINFO_);
307  }
308  }
309 
333  int NumericalApproximation::MinPoints() {
334  if(p_itype == NumericalApproximation::CubicNeighborhood) {
335  return 4;
336  }
337  else if(p_itype == NumericalApproximation::CubicClamped) {
338  return 3;
339  }
340  else if(p_itype == NumericalApproximation::PolynomialNeville) {
341  return 3;
342  }
343  else if(p_itype == NumericalApproximation::CubicHermite) {
344  return 2;
345  }
346  try {
347  return (GslFunctor(p_itype)->min_size);
348  }
349  catch(IException &e) { // catch exception from GslFunctor()
350  throw IException(e,
351  e.errorType(),
352  "MinPoints() - GSL interpolation not found",
353  _FILEINFO_);
354  }
355  }
356 
384  int NumericalApproximation::MinPoints(NumericalApproximation::InterpType itype) {
385  //Validates the parameter
386  if(GslInterpType(itype)) {
387  try {
388  //GslFunctor() Validates parameter for Gsl interp types
389  NumericalApproximation nam(itype);
390  return (nam.GslFunctor(itype)->min_size);
391  }
392  catch(IException &e) { // catch exception from GslFunctor()
393  throw IException(e,
394  e.errorType(),
395  "MinPoints() - GSL interpolation type not found",
396  _FILEINFO_);
397  }
398  }
399  else if(itype == NumericalApproximation::CubicNeighborhood) {
400  return 4;
401  }
402  else if(itype == NumericalApproximation::CubicClamped) {
403  return 3;
404  }
405  else if(itype == NumericalApproximation::PolynomialNeville) {
406  return 3;
407  }
408  else if(itype == NumericalApproximation::CubicHermite) {
409  return 2;
410  }
411  throw IException(IException::Programmer,
412  "MinPoints() - Invalid argument. Unknown interpolation type: "
414  _FILEINFO_);
415  }
416 
440  void NumericalApproximation::AddData(const double x, const double y) {
441  p_x.push_back(x);
442  p_y.push_back(y);
443  p_clampedComputed = false;
444  p_clampedEndptsSet = false;
445  p_dataValidated = false;
446  p_clampedSecondDerivs.clear();
447  p_clampedDerivFirstPt = 0;
448  p_clampedDerivLastPt = 0;
449  p_polyNevError.clear();
450  p_interp = 0;
451  p_acc = 0;
452  return;
453  }
454 
473  void NumericalApproximation::AddData(unsigned int n, double *x, double *y) {
474  for(unsigned int i = 0; i < n; i++) {
475  p_x.push_back(x[i]);
476  p_y.push_back(y[i]);
477  }
478  p_clampedComputed = false;
479  p_clampedEndptsSet = false;
480  p_dataValidated = false;
481  p_clampedSecondDerivs.clear();
482  p_clampedDerivFirstPt = 0;
483  p_clampedDerivLastPt = 0;
484  p_polyNevError.clear();
485  p_interp = 0;
486  p_acc = 0;
487  return;
488  }
489 
512  void NumericalApproximation::AddData(const vector <double> &x,
513  const vector <double> &y)
514  {
515  int n = x.size();
516  int m = y.size();
517  if(n != m) {
518  ReportException(IException::Programmer, "AddData()",
519  "Invalid arguments. The sizes of the input vectors do "
520  "not match",
521  _FILEINFO_);
522  }
523 
524  // Avoid push_back if at all possible. These calls were consuming 10% of
525  // cam2map's run time on a line scan camera.
526  if(!p_x.empty() || !p_y.empty()) {
527  for(int i = 0; i < n; i++) {
528  p_x.push_back(x[i]);
529  p_y.push_back(y[i]);
530  }
531  }
532  else {
533  p_x = x;
534  p_y = y;
535  }
536 
537  p_clampedComputed = false;
538  p_clampedEndptsSet = false;
539  p_dataValidated = false;
540  p_clampedSecondDerivs.clear();
541  p_clampedDerivFirstPt = 0;
542  p_clampedDerivLastPt = 0;
543  p_polyNevError.clear();
544  p_interp = 0;
545  p_acc = 0;
546  return;
547  }
548 
565  void NumericalApproximation::SetCubicClampedEndptDeriv(double yp1, double ypn) {
566  if(p_itype != NumericalApproximation::CubicClamped) {
567  ReportException(IException::Programmer, "SetCubicClampedEndptDeriv()",
568  "This method is only valid for cspline-clamped interpolation, may not be used for "
569  + Name() + " interpolation",
570  _FILEINFO_);
571  }
572  p_clampedDerivFirstPt = yp1;
573  p_clampedDerivLastPt = ypn;
574  p_clampedEndptsSet = true;
575  return;
576  }
577 
592  void NumericalApproximation::AddCubicHermiteDeriv(unsigned int n, double *fprimeOfx) {
593  if(p_itype != NumericalApproximation::CubicHermite) {
594  ReportException(IException::Programmer, "SetCubicHermiteDeriv()",
595  "This method is only valid for cspline-Hermite interpolation, may not be used for "
596  + Name() + " interpolation",
597  _FILEINFO_);
598  }
599  for(unsigned int i = 0; i < n; i++) {
600  p_fprimeOfx.push_back(fprimeOfx[i]);
601  }
602  return;
603  }
617  void NumericalApproximation::AddCubicHermiteDeriv(
618  const vector <double> &fprimeOfx) {
619  if(p_itype != NumericalApproximation::CubicHermite) {
620  ReportException(IException::Programmer, "SetCubicHermiteDeriv()",
621  "This method is only valid for cspline-Hermite interpolation, may not be used for "
622  + Name() + " interpolation",
623  _FILEINFO_);
624  }
625 
626  // Avoid push_back if at all possible.
627  if(!p_fprimeOfx.empty()) {
628  for(unsigned int i = 0; i < fprimeOfx.size(); i++) {
629  p_fprimeOfx.push_back(fprimeOfx[i]);
630  }
631  }
632  else {
633  p_fprimeOfx = fprimeOfx;
634  }
635 
636  return;
637  }
651  void NumericalApproximation::AddCubicHermiteDeriv(
652  double fprimeOfx) {
653  if(p_itype != NumericalApproximation::CubicHermite) {
654  ReportException(IException::Programmer, "SetCubicHermiteDeriv()",
655  "This method is only valid for cspline-Hermite interpolation, may not be used for "
656  + Name() + " interpolation",
657  _FILEINFO_);
658  }
659  p_fprimeOfx.push_back(fprimeOfx);
660  return;
661  }
662 
687  vector <double> NumericalApproximation::CubicClampedSecondDerivatives() {
688  try {
689  if(p_itype != NumericalApproximation::CubicClamped)
690  ReportException(IException::Programmer, "CubicClampedSecondDerivatives()",
691  "This method is only valid for cspline-clamped interpolation type may not be used for "
692  + Name() + " interpolation",
693  _FILEINFO_);
694  if(!p_clampedComputed) ComputeCubicClamped();
695  return p_clampedSecondDerivs;
696  }
697  catch(IException &e) { // catch exception from ComputeCubicClamped()
698  throw IException(e,
699  e.errorType(),
700  "CubicClampedSecondDerivatives() - Unable to compute clamped cubic spline interpolation",
701  _FILEINFO_);
702  }
703  }
704 
723  double NumericalApproximation::DomainMinimum() {
724  try {
725  if(GslInterpType(p_itype)) {
726  // if GSL interpolation type, we need to compute, if not already done
727  if(!GslComputed()) ComputeGsl();
728  return (p_interp->interp->xmin);
729  }
730  else {
731  if(!p_dataValidated) ValidateDataSet();
732  return *min_element(p_x.begin(), p_x.end());
733  }
734  }
735  catch(IException &e) { // catch exception from ComputeGsl() or ValidateDataSet()
736  throw IException(e,
737  e.errorType(),
738  "DomainMinimum() - Unable to calculate the domain minimum for the data set",
739  _FILEINFO_);
740  }
741  }
742 
760  double NumericalApproximation::DomainMaximum() {
761  try {
762  if(GslInterpType(p_itype)) {
763  // if GSL interpolation type, we need to compute, if not already done
764  if(!GslComputed()) ComputeGsl();
765  return (p_interp->interp->xmax);
766  }
767  else {
768  if(!p_dataValidated) ValidateDataSet();
769  return *max_element(p_x.begin(), p_x.end());
770  }
771  }
772  catch(IException &e) { // catch exception from ComputeGsl() or ValidateDataSet()
773  throw IException(e,
774  e.errorType(),
775  "DomainMaximum() - Unable to calculate the domain maximum for the data set",
776  _FILEINFO_);
777  }
778  }
779 
793  bool NumericalApproximation::Contains(double x) {
794  return binary_search(p_x.begin(), p_x.end(), x);
795  }
796 
836  double NumericalApproximation::Evaluate(const double a, const ExtrapType &etype) {
837  try {
838  // a is const, so we must set up temporary variable in case value needs to be changed
839  double a0;
840  if(InsideDomain(a)) // this will validate data set, if not already done
841  a0 = a;
842  else a0 = ValueToExtrapolate(a, etype);
843  // perform interpolation/extrapoltion
844  if(p_itype == NumericalApproximation::CubicNeighborhood) {
845  return EvaluateCubicNeighborhood(a0);
846  }
847  else if(p_itype == NumericalApproximation::PolynomialNeville) {
848  p_polyNevError.clear();
849  return EvaluatePolynomialNeville(a0);
850  }
851  else if(p_itype == NumericalApproximation::CubicClamped) {
852  // if cubic clamped, we need to compute, if not already done
853  if(!p_clampedComputed) ComputeCubicClamped();
854  return EvaluateCubicClamped(a0);
855  }
856  else if(p_itype == NumericalApproximation::CubicHermite) {
857  return EvaluateCubicHermite(a0);
858  }
859  // if GSL interpolation type we need to compute, if not already done
860  if(!GslComputed()) ComputeGsl();
861  double result;
862  GslIntegrityCheck(gsl_spline_eval_e(p_interp, a0, p_acc, &result), _FILEINFO_);
863  return (result);
864  }
865  catch(IException &e) { // catch exception from EvaluateCubicNeighborhood(), EvaluateCubicClamped(), EvaluatePolynomialNeville(), GslIntegrityCheck()
866  throw IException(e,
867  e.errorType(),
868  "Evaluate() - Unable to evaluate the function at the point a = "
869  + IString(a),
870  _FILEINFO_);
871  }
872  }
873 
912  vector <double> NumericalApproximation::Evaluate(const vector <double> &a, const ExtrapType &etype) {
913  try {
914  if(p_itype == NumericalApproximation::CubicNeighborhood) {
915  // cubic neighborhood has it's own method that will take entire vector
916  // this is faster than looping through values calling Evaluate(double)
917  // for each component of the passed in vector
918  return EvaluateCubicNeighborhood(a, etype);
919  }
920  vector <double> result(a.size());
921  if(p_itype == NumericalApproximation::PolynomialNeville) {
922  // cannot loop through values calling Evaluate(double)
923  // because it will clear the p_polyNevError vector each time
924  p_polyNevError.clear();
925  for(unsigned int i = 0; i < result.size(); i++) {
926  double a0;
927  if(InsideDomain(a[i]))
928  a0 = a[i];
929  else a0 = ValueToExtrapolate(a[i], etype);
930  result[i] = EvaluatePolynomialNeville(a0);
931  }
932  return result;
933  }
934  // cubic-clamped, cubic-Hermite and gsl types can be done by calling Evaluate(double)
935  // for each value of the passed in vector
936  for(unsigned int i = 0; i < result.size(); i++) {
937  result[i] = Evaluate(a[i], etype);
938  }
939  return result;
940  }
941  catch(IException &e) { // catch exception from EvaluateCubicNeighborhood(), EvaluateCubicClamped(), EvaluatePolynomialNeville(), GslIntegrityCheck()
942  throw IException(e,
943  e.errorType(),
944  "Evaluate() - Unable to evaluate the function at the given vector of points",
945  _FILEINFO_);
946  }
947  }
948 
970  vector <double> NumericalApproximation::PolynomialNevilleErrorEstimate() {
971  if(p_itype != NumericalApproximation::PolynomialNeville) {
972  ReportException(IException::Programmer, "PolynomialNevilleErrorEstimate()",
973  "This method is only valid for polynomial-Neville's, may not be used for "
974  + Name() + " interpolation",
975  _FILEINFO_);
976  }
977  if(p_polyNevError.empty()) {
978  ReportException(IException::Programmer, "PolynomialNevilleErrorEstimate()",
979  "Error not calculated. This method only valid after Evaluate() has been called",
980  _FILEINFO_);
981  }
982  return p_polyNevError;
983  }
984 
1020  double NumericalApproximation::GslFirstDerivative(const double a) {
1021  try { // we need to compute, if not already done
1022  if(!GslComputed()) ComputeGsl();
1023  }
1024  catch(IException &e) { // catch exception from ComputeGsl()
1025  throw IException(e,
1026  e.errorType(),
1027  "GslFirstDerivative() - Unable to compute the first derivative at a = "
1028  + IString(a) + " using the GSL interpolation",
1029  _FILEINFO_);
1030  }
1031  if(!InsideDomain(a)) {
1032  ReportException(IException::Programmer, "GslFirstDerivative()",
1033  "Invalid argument. Value entered, a = "
1034  + IString(a) + ", is outside of domain = ["
1035  + IString(DomainMinimum()) + ", "
1036  + IString(DomainMaximum()) + "]",
1037  _FILEINFO_);
1038  }
1039  if(!GslInterpType(p_itype)) {
1040  ReportException(IException::Programmer, "GslFirstDerivative()",
1041  "Method only valid for GSL interpolation types, may not be used for "
1042  + Name() + " interpolation",
1043  _FILEINFO_);
1044  }
1045  try {
1046  double value;
1047  GslIntegrityCheck(gsl_spline_eval_deriv_e(p_interp, a, p_acc, &value), _FILEINFO_);
1048  return (value);
1049  }
1050  catch(IException &e) { // catch exception from GslIntegrityCheck()
1051  throw IException(e,
1052  e.errorType(),
1053  "GslFirstDerivative() - Unable to compute the first derivative at a = "
1054  + IString(a) + ". GSL integrity check failed",
1055  _FILEINFO_);
1056  }
1057  }
1058 
1071  double NumericalApproximation::EvaluateCubicHermiteFirstDeriv(const double a) {
1072  if(p_itype != NumericalApproximation::CubicHermite) { //??? is this necessary??? create single derivative method with GSL?
1073  ReportException(IException::User, "EvaluateCubicHermiteFirstDeriv()",
1074  "This method is only valid for cspline-Hermite interpolation, may not be used for "
1075  + Name() + " interpolation",
1076  _FILEINFO_);
1077  }
1078  if(p_fprimeOfx.size() != Size()) {
1079  ReportException(IException::User, "EvaluateCubicHermiteFirstDeriv()",
1080  "Invalid arguments. The size of the first derivative vector does not match the number of (x,y) data points.",
1081  _FILEINFO_);
1082  }
1083  // find the interval in which "a" exists
1084  int lowerIndex = FindIntervalLowerIndex(a);
1085 
1086  // we know that "a" is within the domain since this is verified in
1087  // Evaluate() before this method is called, thus n <= Size()
1088  if(a == p_x[lowerIndex]) {
1089  return p_fprimeOfx[lowerIndex];
1090  }
1091  if(a == p_x[lowerIndex+1]) {
1092  return p_fprimeOfx[lowerIndex+1];
1093  }
1094 
1095  double x0, x1, y0, y1, m0, m1;
1096  // a is contained within the interval (x0,x1)
1097  x0 = p_x[lowerIndex];
1098  x1 = p_x[lowerIndex+1];
1099  // the corresponding known y-values for x0 and x1
1100  y0 = p_y[lowerIndex];
1101  y1 = p_y[lowerIndex+1];
1102  // the corresponding known tangents (slopes) at (x0,y0) and (x1,y1)
1103  m0 = p_fprimeOfx[lowerIndex];
1104  m1 = p_fprimeOfx[lowerIndex+1];
1105 
1106  double h, t;
1107  h = x1 - x0;
1108  t = (a - x0) / h;
1109  if(h != 0.) {
1110  return ((6 * t * t - 6 * t) * y0 + (3 * t * t - 4 * t + 1) * h * m0 + (-6 * t * t + 6 * t) * y1 + (3 * t * t - 2 * t) * h * m1) / h;
1111  }
1112  else {
1113  return 0; // Should never happen
1114  }
1115  }
1116 
1159  double NumericalApproximation::BackwardFirstDifference(const double a, const unsigned int n, const double h) {
1160  if(!InsideDomain(a)) {
1161  ReportException(IException::Programmer, "BackwardFirstDifference()",
1162  "Invalid argument. Value entered, a = "
1163  + IString(a) + ", is outside of domain = ["
1164  + IString(DomainMinimum()) + ", "
1165  + IString(DomainMaximum()) + "]",
1166  _FILEINFO_);
1167  }
1168  if(!InsideDomain(a - (n - 1)*h)) {
1169  ReportException(IException::Programmer, "BackwardFirstDifference()",
1170  "Formula steps outside of domain. For "
1171  + IString((int) n) + "-point backward difference, a-(n-1)h = "
1172  + IString(a - (n - 1)*h) + " is smaller than domain min = "
1173  + IString(DomainMinimum())
1174  + ". Try forward difference or use smaller value for h or n",
1175  _FILEINFO_);
1176  }
1177  if(!p_dataValidated) ValidateDataSet();
1178  vector <double> f;
1179  double xi;
1180  try {
1181  for(double i = 0; i < n; i++) {
1182  xi = a + h * (i - (n - 1));
1183  f.push_back(Evaluate(xi)); // allow ExtrapType = ThrowError (default)
1184  }
1185  }
1186  catch(IException &e) { // catch exception from Evaluate()
1187  throw IException(e,
1188  e.errorType(),
1189  "BackwardFirstDifference() - Unable to calculate backward first difference for (a, n, h) = ("
1190  + IString(a) + ", " + IString((int) n) + ", " + IString(h) + ")",
1191  _FILEINFO_);
1192  }
1193  switch(n) {
1194  case 2:
1195  return (-f[0] + f[1]) / h; //2pt backward
1196  case 3:
1197  return (3 * f[2] - 4 * f[1] + f[0]) / (2 * h); //3pt backward
1198  default:
1199  throw IException(IException::Programmer,
1200  "BackwardFirstDifference() - Invalid argument. There is no "
1201  + IString((int) n) + "-point backward difference formula in use",
1202  _FILEINFO_);
1203  }
1204  }
1205 
1206 
1248  double NumericalApproximation::ForwardFirstDifference(const double a, const unsigned int n, const double h) {
1249  if(!InsideDomain(a)) {
1250  ReportException(IException::Programmer, "ForwardFirstDifference()",
1251  "Invalid argument. Value entered, a = "
1252  + IString(a) + ", is outside of domain = ["
1253  + IString(DomainMinimum()) + ", "
1254  + IString(DomainMaximum()) + "]",
1255  _FILEINFO_);
1256  }
1257  if(!InsideDomain(a + (n - 1)*h)) {
1258  ReportException(IException::Programmer, "ForwardFirstDifference()",
1259  "Formula steps outside of domain. For "
1260  + IString((int) n) + "-point forward difference, a+(n-1)h = "
1261  + IString(a + (n - 1)*h) + " is greater than domain max = "
1262  + IString(DomainMaximum())
1263  + ". Try backward difference or use smaller value for h or n",
1264  _FILEINFO_);
1265  }
1266  if(!p_dataValidated) ValidateDataSet();
1267  vector <double> f;
1268  double xi;
1269  try {
1270  for(double i = 0; i < n; i++) {
1271  xi = a + h * i;
1272  f.push_back(Evaluate(xi));// allow ExtrapType = ThrowError (default)
1273  }
1274  }
1275  catch(IException &e) { // catch exception from Evaluate()
1276  throw IException(e,
1277  e.errorType(),
1278  "ForwardFirstDifference() - Unable to calculate forward first difference for (a, n, h) = ("
1279  + IString(a) + ", " + IString((int) n) + ", " + IString(h) + ")",
1280  _FILEINFO_);
1281  }
1282  switch(n) {
1283  case 2:
1284  return (-f[0] + f[1]) / h; //2pt forward
1285  case 3:
1286  return (-3 * f[0] + 4 * f[1] - f[2]) / (2 * h); //3pt forward
1287  default:
1288  throw IException(IException::Programmer,
1289  "ForwardFirstDifference() - Invalid argument. There is no "
1290  + IString((int) n) + "-point forward difference formula in use",
1291  _FILEINFO_);
1292  }
1293  }
1294 
1295 
1338  double NumericalApproximation::CenterFirstDifference(const double a, const unsigned int n, const double h) {
1339  if(!InsideDomain(a)) {
1340  ReportException(IException::Programmer, "CenterFirstDifference()",
1341  "Invalid argument. Value entered, a = "
1342  + IString(a) + ", is outside of domain = ["
1343  + IString(DomainMinimum()) + ", "
1344  + IString(DomainMaximum()) + "]",
1345  _FILEINFO_);
1346  }
1347  if(!InsideDomain(a + (n - 1)*h) || !InsideDomain(a - (n - 1)*h)) {
1348  ReportException(IException::Programmer, "CenterFirstDifference()",
1349  "Formula steps outside of domain. For "
1350  + IString((int) n) + "-point center difference, a-(n-1)h = "
1351  + IString(a - (n - 1)*h) + " or a+(n-1)h = "
1352  + IString(a + (n - 1)*h) + " is out of domain = ["
1353  + IString(DomainMinimum()) + ", " + IString(DomainMaximum())
1354  + "]. Use smaller value for h or n",
1355  _FILEINFO_);
1356  }
1357  if(!p_dataValidated) ValidateDataSet();
1358  vector <double> f;
1359  double xi;
1360  try {
1361  for(double i = 0; i < n; i++) {
1362  xi = a + h * (i - (n - 1) / 2);
1363  f.push_back(Evaluate(xi));// allow ExtrapType = ThrowError (default)
1364  }
1365  }
1366  catch(IException &e) { // catch exception from Evaluate()
1367  throw IException(e,
1368  e.errorType(),
1369  "CenterFirstDifference() - Unable to calculate center first difference for (a, n, h) = ("
1370  + IString(a) + ", " + IString((int) n) + ", " + IString(h) + ")",
1371  _FILEINFO_);
1372  }
1373  switch(n) {
1374  case 3:
1375  return (-f[0] + f[2]) / (2 * h); //3pt center
1376  case 5:
1377  return (f[0] - 8 * f[1] + 8 * f[3] - f[4]) / (12 * h); //5pt center
1378  default:
1379  throw IException(IException::Programmer,
1380  "CenterFirstDifference() - Invalid argument. There is no "
1381  + IString((int) n) + "-point center difference formula in use",
1382  _FILEINFO_);
1383  }
1384  }
1385 
1422  double NumericalApproximation::GslSecondDerivative(const double a) {
1423  try { // we need to compute, if not already done
1424  if(!GslComputed()) ComputeGsl();
1425  }
1426  catch(IException &e) { // catch exception from ComputeGsl()
1427  throw IException(e,
1428  e.errorType(),
1429  "GslSecondDerivative() - Unable to compute the second derivative at a = "
1430  + IString(a) + " using the GSL interpolation",
1431  _FILEINFO_);
1432  }
1433  if(!InsideDomain(a))
1434  ReportException(IException::Programmer, "GslSecondDerivative()",
1435  "Invalid argument. Value entered, a = "
1436  + IString(a) + ", is outside of domain = ["
1437  + IString(DomainMinimum()) + ", "
1438  + IString(DomainMaximum()) + "]",
1439  _FILEINFO_);
1440  if(!GslInterpType(p_itype))
1441  ReportException(IException::Programmer, "GslSecondDerivative()",
1442  "Method only valid for GSL interpolation types, may not be used for "
1443  + Name() + " interpolation",
1444  _FILEINFO_);
1445  try {
1446  // we need to compute, if not already done
1447  if(!GslComputed()) ComputeGsl();
1448  double value;
1449  GslIntegrityCheck(gsl_spline_eval_deriv2_e(p_interp, a, p_acc, &value), _FILEINFO_);
1450  return (value);
1451  }
1452  catch(IException &e) { // catch exception from GslIntegrityCheck()
1453  throw IException(e,
1454  e.errorType(),
1455  "GslSecondDerivative() - Unable to compute the second derivative at a = "
1456  + IString(a) + ". GSL integrity check failed",
1457  _FILEINFO_);
1458  }
1459  }
1460 
1461 
1474  double NumericalApproximation::EvaluateCubicHermiteSecDeriv(const double a) {
1475  if(p_itype != NumericalApproximation::CubicHermite) {
1476  ReportException(IException::User, "EvaluateCubicHermiteSecDeriv()",
1477  "This method is only valid for cspline-Hermite interpolation, may not be used for "
1478  + Name() + " interpolation",
1479  _FILEINFO_);
1480  }
1481  if(p_fprimeOfx.size() != Size()) {
1482  ReportException(IException::User, "EvaluateCubicHermiteSecDeriv()",
1483  "Invalid arguments. The size of the first derivative vector does not match the number of (x,y) data points.",
1484  _FILEINFO_);
1485  }
1486  // find the interval in which "a" exists
1487  int lowerIndex = FindIntervalLowerIndex(a);
1488  double x0, x1, y0, y1, m0, m1;
1489  // a is contained within the interval (x0,x1)
1490  x0 = p_x[lowerIndex];
1491  x1 = p_x[lowerIndex+1];
1492  // the corresponding known y-values for x0 and x1
1493  y0 = p_y[lowerIndex];
1494  y1 = p_y[lowerIndex+1];
1495  // the corresponding known tangents (slopes) at (x0,y0) and (x1,y1)
1496  m0 = p_fprimeOfx[lowerIndex];
1497  m1 = p_fprimeOfx[lowerIndex+1];
1498 
1499  double h, t;
1500  h = x1 - x0;
1501  t = (a - x0) / h;
1502  if(h != 0.) {
1503  return ((12 * t - 6) * y0 + (6 * t - 4) * h * m0 + (-12 * t + 6) * y1 + (6 * t - 2) * h * m1) / h;
1504  }
1505  else {
1506  return 0; // Should never happen
1507  }
1508  }
1509 
1546  double NumericalApproximation::BackwardSecondDifference(const double a, const unsigned int n, const double h) {
1547  if(!InsideDomain(a)) {
1548  ReportException(IException::Programmer, "BackwardSecondDifference()",
1549  "Invalid argument. Value entered, a = "
1550  + IString(a) + ", is outside of domain = ["
1551  + IString(DomainMinimum()) + ", "
1552  + IString(DomainMaximum()) + "]",
1553  _FILEINFO_);
1554  }
1555  if(!InsideDomain(a - (n - 1)*h)) {
1556  ReportException(IException::Programmer, "BackwardSecondDifference()",
1557  "Formula steps outside of domain. For "
1558  + IString((int) n) + "-point backward difference, a-(n-1)h = "
1559  + IString(a - (n - 1)*h) + " is smaller than domain min = "
1560  + IString(DomainMinimum())
1561  + ". Try forward difference or use smaller value for h or n",
1562  _FILEINFO_);
1563  }
1564  if(!p_dataValidated) ValidateDataSet();
1565  vector <double> f;
1566  double xi;
1567  try {
1568  for(double i = 0; i < n; i++) {
1569  xi = a + h * (i - (n - 1));
1570  f.push_back(Evaluate(xi));// allow ExtrapType = ThrowError (default)
1571  }
1572  }
1573  catch(IException &e) { // catch exception from Evaluate()
1574  throw IException(e,
1575  e.errorType(),
1576  "BackwardSecondDifference() - Unable to calculate backward second difference for (a, n, h) = ("
1577  + IString(a) + ", " + IString((int) n) + ", " + IString(h) + ")",
1578  _FILEINFO_);
1579  }
1580  switch(n) {
1581  case 3:
1582  return (f[0] - 2 * f[1] + f[2]) / (h * h); //3pt backward
1583  default:
1584  throw IException(IException::Programmer,
1585  "BackwardSecondDifference() - Invalid argument. There is no "
1586  + IString((int) n) + "-point backward second difference formula in use",
1587  _FILEINFO_);
1588  }
1589  }
1590 
1591 
1628  double NumericalApproximation::ForwardSecondDifference(const double a, const unsigned int n, const double h) {
1629  if(!InsideDomain(a)) {
1630  ReportException(IException::Programmer, "ForwardSecondDifference()",
1631  "Invalid argument. Value entered, a = "
1632  + IString(a) + ", is outside of domain = ["
1633  + IString(DomainMinimum()) + ", "
1634  + IString(DomainMaximum()) + "]",
1635  _FILEINFO_);
1636  }
1637  if(!InsideDomain(a + (n - 1)*h)) {
1638  ReportException(IException::Programmer, "ForwardSecondDifference()",
1639  "Formula steps outside of domain. For "
1640  + IString((int) n) + "-point forward difference, a+(n-1)h = "
1641  + IString(a + (n - 1)*h) + " is greater than domain max = "
1642  + IString(DomainMaximum())
1643  + ". Try backward difference or use smaller value for h or n",
1644  _FILEINFO_);
1645  }
1646  if(!p_dataValidated) ValidateDataSet();
1647  vector <double> f;
1648  double xi;
1649  try {
1650  for(double i = 0; i < n; i++) {
1651  xi = a + h * i;
1652  f.push_back(Evaluate(xi));// allow ExtrapType = ThrowError (default)
1653  }
1654  }
1655  catch(IException &e) { // catch exception from Evaluate()
1656  throw IException(e,
1657  e.errorType(),
1658  "ForwardSecondDifference() - Unable to calculate forward second difference for (a, n, h) = ("
1659  + IString(a) + ", " + IString((int) n) + ", " + IString(h) + ")",
1660  _FILEINFO_);
1661  }
1662  switch(n) {
1663  case 3:
1664  return (f[0] - 2 * f[1] + f[2]) / (h * h); //3pt forward
1665  default:
1666  throw IException(IException::Programmer,
1667  "ForwardSecondDifference() - Invalid argument. There is no "
1668  + IString((int) n) + "-point forward second difference formula in use",
1669  _FILEINFO_);
1670  }
1671  }
1672 
1673 
1716  double NumericalApproximation::CenterSecondDifference(const double a, const unsigned int n, const double h) {
1717  if(!InsideDomain(a)) {
1718  ReportException(IException::Programmer, "CenterSecondDifference()",
1719  "Invalid argument. Value entered, a = "
1720  + IString(a) + ", is outside of domain = ["
1721  + IString(DomainMinimum()) + ", "
1722  + IString(DomainMaximum()) + "]",
1723  _FILEINFO_);
1724  }
1725  if(!InsideDomain(a + (n - 1)*h) || !InsideDomain(a - (n - 1)*h)) {
1726  ReportException(IException::Programmer, "CenterSecondDifference()",
1727  "Formula steps outside of domain. For "
1728  + IString((int) n) + "-point center difference, a-(n-1)h = "
1729  + IString(a - (n - 1)*h) + " or a+(n-1)h = "
1730  + IString(a + (n - 1)*h) + " is out of domain = ["
1731  + IString(DomainMinimum()) + ", " + IString(DomainMaximum())
1732  + "]. Use smaller value for h or n",
1733  _FILEINFO_);
1734  }
1735  if(!p_dataValidated) ValidateDataSet();
1736  vector <double> f;
1737  double xi;
1738  try {
1739  for(double i = 0; i < n; i++) {
1740  xi = a + h * (i - (n - 1) / 2);
1741  f.push_back(Evaluate(xi));// allow ExtrapType = ThrowError (default)
1742  }
1743  }
1744  catch(IException &e) { // catch exception from Evaluate()
1745  throw IException(e,
1746  e.errorType(),
1747  "CenterSecondDifference() - Unable to calculate center second difference for (a, n, h) = ("
1748  + IString(a) + ", " + IString((int) n) + ", " + IString(h) + ")",
1749  _FILEINFO_);
1750  }
1751  switch(n) {
1752  case 3:
1753  return (f[0] - 2 * f[1] + f[2]) / (h * h); //3pt center
1754  case 5:
1755  return (-f[0] + 16 * f[1] - 30 * f[2] + 16 * f[3] - f[4]) / (12 * h * h); //5pt center
1756  default:
1757  throw IException(IException::Programmer,
1758  "CenterSecondDifference() - Invalid argument. There is no "
1759  + IString((int) n) + "-point center second difference formula in use",
1760  _FILEINFO_);
1761  }
1762  }
1763 
1797  double NumericalApproximation::GslIntegral(const double a, const double b) {
1798  try { // we need to compute, if not already done
1799  if(!GslComputed()) ComputeGsl();
1800  }
1801  catch(IException &e) { // catch exception from ComputeGsl()
1802  throw IException(e,
1803  e.errorType(),
1804  "GslIntegral() - Unable to compute the integral on the interval (a,b) = ("
1805  + IString(a) + ", " + IString(b)
1806  + ") using the GSL interpolation",
1807  _FILEINFO_);
1808  }
1809  if(a > b) {
1810  ReportException(IException::Programmer, "GslIntegral()",
1811  "Invalid interval entered: [a,b] = ["
1812  + IString(a) + ", " + IString(b) + "]",
1813  _FILEINFO_);
1814  }
1815  if(!InsideDomain(a) || !InsideDomain(b)) {
1816  ReportException(IException::Programmer, "GslIntegral()",
1817  "Invalid arguments. Interval entered ["
1818  + IString(a) + ", " + IString(b)
1819  + "] is not contained within domain ["
1820  + IString(DomainMinimum()) + ", "
1821  + IString(DomainMaximum()) + "]",
1822  _FILEINFO_);
1823  }
1824  if(!GslInterpType(p_itype)) {
1825  ReportException(IException::Programmer, "GslIntegral()",
1826  "Method only valid for GSL interpolation types, may not be used for "
1827  + Name() + " interpolation",
1828  _FILEINFO_);
1829  }
1830  try {
1831  double value;
1832  GslIntegrityCheck(gsl_spline_eval_integ_e(p_interp, a, b, p_acc, &value), _FILEINFO_);
1833  return (value);
1834  }
1835  catch(IException &e) { // catch exception from GslIntegrityCheck()
1836  throw IException(e,
1837  e.errorType(),
1838  "GslIntegral() - Unable to compute the integral on the interval (a,b) = ("
1839  + IString(a) + ", " + IString(b)
1840  + "). GSL integrity check failed",
1841  _FILEINFO_);
1842  }
1843  }
1844 
1868  double NumericalApproximation::TrapezoidalRule(const double a, const double b) {
1869  try {
1870  //n is the number of points used in the formula of the integration type chosen
1871  unsigned int n = 2;
1872  double result = 0;
1873  vector <double> f = EvaluateForIntegration(a, b, n);
1874  double h = f.back();
1875  f.pop_back();
1876  //Compute the integral using composite trapezoid formula
1877  int ii;
1878  for(unsigned int i = 0; i < (f.size() - 1) / (n - 1); i++) {
1879  ii = (i + 1) * (n - 1);
1880  result += (f[ii-1] + f[ii]) * h / 2;
1881  }
1882  return result;
1883  }
1884  catch(IException &e) { // catch exception from EvaluateForIntegration()
1885  throw IException(e,
1886  e.errorType(),
1887  "TrapezoidalRule() - Unable to calculate the integral on the interval (a,b) = ("
1888  + IString(a) + ", " + IString(b)
1889  + ") using the trapeziodal rule",
1890  _FILEINFO_);
1891  }
1892  }
1893 
1920  double NumericalApproximation::Simpsons3PointRule(const double a, const double b) {
1921  try {
1922  //n is the number of points used in the formula of the integration type chosen
1923  unsigned int n = 3;
1924  double result = 0;
1925  vector <double> f = EvaluateForIntegration(a, b, n);
1926  double h = f.back();
1927  f.pop_back();
1928  int ii;
1929  for(unsigned int i = 0; i < (f.size() - 1) / (n - 1); i++) {
1930  ii = (i + 1) * (n - 1);
1931  result += (f[ii-2] + 4 * f[ii-1] + f[ii]) * h / 3;
1932  }
1933  return result;
1934  }
1935  catch(IException &e) { // catch exception from EvaluateForIntegration()
1936  throw IException(e,
1937  e.errorType(),
1938  "Simpsons3PointRule() - Unable to calculate the integral on the interval (a,b) = ("
1939  + IString(a) + ", " + IString(b)
1940  + ") using Simpson's 3 point rule",
1941  _FILEINFO_);
1942  }
1943  }
1944 
1945 
1972  double NumericalApproximation::Simpsons4PointRule(const double a, const double b) {
1973  try {
1974  //n is the number of points used in the formula of the integration type chosen
1975  unsigned int n = 4;
1976  double result = 0;
1977  vector <double> f = EvaluateForIntegration(a, b, n);
1978  double h = f.back();
1979  f.pop_back();
1980  int ii;
1981  for(unsigned int i = 0; i < (f.size() - 1) / (n - 1); i++) {
1982  ii = (i + 1) * (n - 1);
1983  result += (f[ii-3] + 3 * f[ii-2] + 3 * f[ii-1] + f[ii]) * h * 3 / 8;
1984  }
1985  return result;
1986  }
1987  catch(IException &e) { // catch exception from EvaluateForIntegration()
1988  throw IException(e,
1989  e.errorType(),
1990  "Simpsons4PointRule() - Unable to calculate the integral on the interval (a,b) = ("
1991  + IString(a) + ", " + IString(b)
1992  + ") using Simpson's 4 point rule",
1993  _FILEINFO_);
1994  }
1995  }
1996 
1997 
2027  double NumericalApproximation::BoolesRule(const double a, const double b) {
2028  try {
2029  //n is the number of points used in the formula of the integration type chosen
2030  unsigned int n = 5;
2031  double result = 0;
2032  vector <double> f = EvaluateForIntegration(a, b, n);
2033  double h = f.back();
2034  f.pop_back();
2035  int ii;
2036  for(unsigned int i = 0; i < (f.size() - 1) / (n - 1); i++) {
2037  ii = (i + 1) * (n - 1);
2038  result += (7 * f[ii-4] + 32 * f[ii-3] + 12 * f[ii-2] + 32 * f[ii-1] + 7 * f[ii]) * h * 2 / 45;
2039  }
2040  return result;
2041  }
2042  catch(IException &e) { // catch exception from EvaluateForIntegration()
2043  throw IException(e,
2044  e.errorType(),
2045  "BoolesRule() - Unable to calculate the integral on the interval (a,b) = ("
2046  + IString(a) + ", " + IString(b)
2047  + ") using Boole's rule",
2048  _FILEINFO_);
2049  }
2050  }
2051 
2096  double NumericalApproximation::RefineExtendedTrap(double a, double b, double s, unsigned int n) {
2097  // This method was derived from an algorithm in the text
2098  // Numerical Recipes in C: The Art of Scientific Computing
2099  // Section 4.2 by Flannery, Press, Teukolsky, and Vetterling
2100  try {
2101  if(n == 1) {
2102  double begin, end;
2103  if(GslInterpType(p_itype) || p_itype == NumericalApproximation::CubicNeighborhood) {
2104  // if a or b are outside the domain, return y-value of nearest endpoint
2105  begin = Evaluate(a, NumericalApproximation::NearestEndpoint);
2106  end = Evaluate(b, NumericalApproximation::NearestEndpoint);
2107  }
2108  else {
2109  // if a or b are outside the domain, return extrapolated y-value
2110  begin = Evaluate(a, NumericalApproximation::Extrapolate);
2111  end = Evaluate(b, NumericalApproximation::Extrapolate);
2112  }
2113  return (0.5 * (b - a) * (begin + end));
2114  }
2115  else {
2116  int it;
2117  double delta, tnm, x, sum;
2118  it = (int)(pow(2.0, (double)(n - 2)));
2119  tnm = it;
2120  delta = (b - a) / tnm; // spacing of the points to be added
2121  x = a + 0.5 * delta;
2122  sum = 0.0;
2123  for(int i = 0; i < it; i++) {
2124  if(GslInterpType(p_itype) || p_itype == NumericalApproximation::CubicNeighborhood) {
2125  sum = sum + Evaluate(x, NumericalApproximation::NearestEndpoint);
2126  }
2127  else {
2128  sum = sum + Evaluate(x, NumericalApproximation::Extrapolate);
2129  }
2130  x = x + delta;
2131  }
2132  return (0.5 * (s + (b - a) * sum / tnm));// return refined value of s
2133  }
2134  }
2135  catch(IException &e) { // catch exception from Evaluate()
2136  throw IException(e,
2137  e.errorType(),
2138  "RefineExtendedTrap() - Unable to calculate the integral on the interval (a,b) = ("
2139  + IString(a) + ", " + IString(b)
2140  + ") using the extended trapeziodal rule",
2141  _FILEINFO_);
2142  }
2143  }
2144 
2179  double NumericalApproximation::RombergsMethod(double a, double b) {
2180  // This method was derived from an algorithm in the text
2181  // Numerical Recipes in C: The Art of Scientific Computing
2182  // Section 4.3 by Flannery, Press, Teukolsky, and Vetterling
2183  int maxits = 20;
2184  double dss = 0; // error estimate for
2185  double h[maxits+1]; // relative stepsizes for trap
2186  double trap[maxits+1]; // successive trapeziodal approximations
2187  double epsilon; // desired fractional accuracy
2188  double epsilon2;// desired fractional accuracy
2189  double ss; // result
2190 
2191  epsilon = 1.0e-4;
2192  epsilon2 = 1.0e-6;
2193 
2194  h[0] = 1.0;
2195  try {
2196  NumericalApproximation interp(NumericalApproximation::PolynomialNeville);
2197  for(int i = 0; i < maxits; i++) {
2198  // i will determine number of trapezoidal partitions of area
2199  // under curve for "integration" using refined trapezoidal rule
2200  trap[i] = RefineExtendedTrap(a, b, trap[i], i + 1); // validates data here
2201  if(i >= 4) {
2202  interp.AddData(5, &h[i-4], &trap[i-4]);
2203  // PolynomialNeville can extrapolate data outside of domain
2204  ss = interp.Evaluate(0.0, NumericalApproximation::Extrapolate);
2205  dss = interp.PolynomialNevilleErrorEstimate()[0];
2206  interp.Reset();
2207  // we work only until our necessary accuracy is achieved
2208  if(fabs(dss) <= epsilon * fabs(ss)) return ss;
2209  if(fabs(dss) <= epsilon2) return ss;
2210  }
2211  trap[i+1] = trap[i];
2212  h[i+1] = 0.25 * h[i];
2213  // This is a key step: the factor is 0.25d0 even though
2214  // the stepsize is decreased by 0.5d0. This makes the
2215  // extraplolation a polynomial in h-squared as allowed
2216  // by the equation from Numerical Recipes 4.2.1 pg.132,
2217  // not just a polynomial in h.
2218  }
2219  }
2220  catch(IException &e) { // catch error from RefineExtendedTrap, Constructor, Evaluate, PolynomialNevilleErrorEstimate
2221  throw IException(e,
2222  e.errorType(),
2223  "RombergsMethod() - Unable to calculate the integral on the interval (a,b) = ("
2224  + IString(a) + ", " + IString(b)
2225  + ") using Romberg's method",
2226  _FILEINFO_);
2227  }
2228  throw IException(IException::Programmer,
2229  "RombergsMethod() - Unable to calculate the integral using RombergsMethod() - Failed to converge in "
2230  + IString(maxits) + " iterations",
2231  _FILEINFO_);
2232  }
2233 
2251  void NumericalApproximation::Reset() {
2252  if(GslInterpType(p_itype)) GslDeallocation();
2253  p_clampedComputed = false;
2254  p_clampedEndptsSet = false;
2255  p_dataValidated = false;
2256  p_x.clear();
2257  p_y.clear();
2258  p_clampedSecondDerivs.clear();
2259  p_clampedDerivFirstPt = 0;
2260  p_clampedDerivLastPt = 0;
2261  p_polyNevError.clear();
2262  p_fprimeOfx.clear();
2263  return;
2264  }
2265 
2283  void NumericalApproximation::Reset(NumericalApproximation::InterpType itype) {
2284  try {
2285  Reset();
2286  SetInterpType(itype);
2287  return;
2288  }
2289  catch(IException &e) { // catch exception from SetInterpType()
2290  throw IException(e,
2291  e.errorType(),
2292  "Reset() - Unable to reset interpolation type",
2293  _FILEINFO_);
2294  }
2295  }
2296 
2319  void NumericalApproximation::SetInterpType(NumericalApproximation::InterpType itype) {
2320  // Validates the parameter
2321  if(GslInterpType(itype)) {
2322  try {
2323  GslFunctor(itype);
2324  }
2325  catch(IException &e) { // catch exception from GslFunctor()
2326  throw IException(e,
2327  e.errorType(),
2328  "SetInterpType() - Unable to set interpolation type",
2329  _FILEINFO_);
2330  }
2331  }
2332  else if(itype > 9) { // there are currently 9 interpolation types
2333  ReportException(IException::Programmer, "SetInterpType()",
2334  "Invalid argument. Unknown interpolation type: "
2336  _FILEINFO_);
2337  }
2338  // p_x, p_y are kept and p_itype is replaced
2339  p_itype = itype;
2340  // reset state of class variables that are InterpType dependent //??? should we keep some of this info?
2341  p_dataValidated = false;
2342  p_clampedComputed = false;
2343  p_clampedEndptsSet = false;
2344  p_clampedSecondDerivs.clear();
2345  p_clampedDerivFirstPt = 0;
2346  p_clampedDerivLastPt = 0;
2347  p_polyNevError.clear();
2348  p_fprimeOfx.clear();
2349  }
2350 
2375  void NumericalApproximation::Init(NumericalApproximation::InterpType itype) {
2376  if(p_interpFunctors.empty()) {
2377  p_interpFunctors.insert(make_pair(Linear, gsl_interp_linear));
2378  p_interpFunctors.insert(make_pair(Polynomial, gsl_interp_polynomial));
2379  p_interpFunctors.insert(make_pair(CubicNatural, gsl_interp_cspline));
2380  p_interpFunctors.insert(make_pair(CubicNatPeriodic, gsl_interp_cspline_periodic));
2381  p_interpFunctors.insert(make_pair(Akima, gsl_interp_akima));
2382  p_interpFunctors.insert(make_pair(AkimaPeriodic, gsl_interp_akima_periodic));
2383  }
2384 
2385  p_acc = 0;
2386  p_interp = 0;
2387  try {
2388  SetInterpType(itype);
2389  }
2390  catch(IException &e) { // catch exception from SetInterpType()
2391  throw IException(e,
2392  e.errorType(),
2393  "Init() - Unable to initialize NumericalApproximation object",
2394  _FILEINFO_);
2395  }
2396  // Turn all GSL error handling off...repeatedly, every time this routine is
2397  // called.
2398  gsl_set_error_handler_off();
2399  }
2400 
2418  bool NumericalApproximation::GslInterpType(NumericalApproximation::InterpType itype) const {
2419  if(itype == NumericalApproximation::Linear) return true;
2420  if(itype == NumericalApproximation::Polynomial) return true;
2421  if(itype == NumericalApproximation::CubicNatural) return true;
2422  if(itype == NumericalApproximation::CubicNatPeriodic) return true;
2423  if(itype == NumericalApproximation::Akima) return true;
2424  if(itype == NumericalApproximation::AkimaPeriodic) return true;
2425  return false;
2426  }
2427 
2444  void NumericalApproximation::GslAllocation(unsigned int npoints) {
2445  GslDeallocation();
2446  //get pointer to accelerator object (iterator for interpolation lookups)
2447  p_acc = gsl_interp_accel_alloc();
2448  //get pointer to interpolation object of interp type given for npoints datapoints
2449  p_interp = gsl_spline_alloc(GslFunctor(p_itype), npoints);
2450  return;
2451  }
2452 
2466  void NumericalApproximation::GslDeallocation() {
2467  if(p_interp) gsl_spline_free(p_interp);
2468  if(p_acc) gsl_interp_accel_free(p_acc);
2469  p_acc = 0;
2470  p_interp = 0;
2471  return;
2472  }
2473 
2493  const {
2494  FunctorConstIter fItr = p_interpFunctors.find(itype);
2495  if(fItr == p_interpFunctors.end()) {
2496  ReportException(IException::Programmer, "GslFunctor()",
2497  "Invalid argument. Unable to find GSL interpolator with id = "
2499  _FILEINFO_);
2500  }
2501  return (fItr->second);
2502  }
2503 
2523  void NumericalApproximation::GslIntegrityCheck(int gsl_status, const char *src, int line)
2524  {
2525  if(gsl_status != GSL_SUCCESS) {
2526  if(gsl_status != GSL_EDOM) {
2527  ReportException(IException::Programmer, "GslIntegrityCheck(int,char,int)",
2528  "GslIntegrityCheck(): GSL error occured: "
2529  + string(gsl_strerror(gsl_status)), src, line);
2530  }
2531  }
2532  return;
2533  }
2534 
2563  void NumericalApproximation::ValidateDataSet() {
2564  if((int) Size() < MinPoints()) {
2565  ReportException(IException::Programmer, "ValidateDataSet()",
2566  Name() + " interpolation requires a minimum of "
2567  + IString(MinPoints()) + " data points - currently have "
2568  + IString((int) Size()),
2569  _FILEINFO_);
2570  }
2571  for(unsigned int i = 1; i < Size(); i++) {
2572  // Check for uniqueness -- this applies to all interpolation types
2573  if(p_x[i-1] == p_x[i]) {
2574  ReportException(IException::Programmer, "ValidateDataSet()",
2575  "Invalid data set, x-values must be unique: \n\t\tp_x["
2576  + IString((int) i - 1) + "] = " + IString(p_x[i-1])
2577  + " = p_x[" + IString((int) i) + "]",
2578  _FILEINFO_);
2579  }
2580  if(p_x[i-1] > p_x[i]) {
2581  // Verify that data set is in ascending order --
2582  // this does not apply to PolynomialNeville, which appears to get the same results with unsorted data
2583  if(p_itype != NumericalApproximation::PolynomialNeville) {
2584  ReportException(IException::Programmer, "ValidateDataSet()",
2585  "Invalid data set, x-values must be in ascending order for "
2586  + Name() + " interpolation: \n\t\tx["
2587  + IString((int) i - 1) + "] = " + IString(p_x[i-1]) + " > x["
2588  + IString((int) i) + "] = " + IString(p_x[i]),
2589  _FILEINFO_);
2590  }
2591  }
2592  }
2593  if(p_itype == NumericalApproximation::CubicNatPeriodic) {
2594  if(p_y[0] != p_y[Size()-1]) {
2595  ReportException(IException::Programmer, "ValidateDataSet()",
2596  "First and last points of the data set must have the same y-value for "
2597  + Name() + "interpolation to prevent discontinuity at the boundary",
2598  _FILEINFO_);
2599  }
2600  }
2601  p_dataValidated = true;
2602  return;
2603  }
2604 
2605 
2619  bool NumericalApproximation::InsideDomain(const double a) {
2620  try {
2621  if(a + DBL_EPSILON < DomainMinimum()) {
2622  return false;
2623  }
2624  if(a - DBL_EPSILON > DomainMaximum()) {
2625  return false;
2626  }
2627  }
2628  catch(IException &e) { // catch exception from DomainMinimum(), DomainMaximum()
2629  throw IException(e,
2630  e.errorType(),
2631  "InsideDomain() - Unable to compute domain boundaries",
2632  _FILEINFO_);
2633  }
2634  return true;
2635  }
2636 
2653  bool NumericalApproximation::GslComputed() const {
2654  if(GslInterpType(p_itype)) return ((p_interp) && (p_acc));
2655  else
2656  throw IException(IException::Programmer,
2657  "GslComputed() - Method only valid for GSL interpolation types, may not be used for "
2658  + Name() + " interpolation",
2659  _FILEINFO_);
2660  }
2661 
2683  void NumericalApproximation::ComputeGsl() {
2684  try {
2685  if(GslComputed()) return;
2686  if(!p_dataValidated) ValidateDataSet();
2687  GslAllocation(Size());
2688  GslIntegrityCheck(gsl_spline_init(p_interp, &p_x[0], &p_y[0], Size()), _FILEINFO_);
2689  return;
2690  }
2691  catch(IException &e) { // catch exception from ValidateDataSet(), GslIntegrityCheck()
2692  throw IException(e,
2693  e.errorType(),
2694  "ComputeGsl() - Unable to compute GSL interpolation",
2695  _FILEINFO_);
2696  }
2697  }
2698 
2735  void NumericalApproximation::ComputeCubicClamped() {
2736  // This method was derived from an algorithm in the text
2737  // Numerical Recipes in C: The Art of Scientific Computing
2738  // Section 3.3 by Flannery, Press, Teukolsky, and Vetterling
2739 
2740  if(!p_dataValidated) {
2741  try {
2742  ValidateDataSet();
2743  }
2744  catch(IException &e) { // catch exception from ValidateDataSet()
2745  throw IException(e,
2746  e.errorType(),
2747  "ComputeCubicClamped() - Unable to compute cubic clamped interpolation",
2748  _FILEINFO_);
2749  }
2750  }
2751  if(!p_clampedEndptsSet) {
2752  ReportException(IException::Programmer, "ComputeCubicClamped()",
2753  "Must set endpoint derivative values after adding data in order to compute cubic spline with clamped boundary conditions",
2754  _FILEINFO_);
2755  }
2756  int n = Size();
2757  p_clampedSecondDerivs.resize(n);
2758  double u[n];
2759  double p, sig, qn, un;
2760 
2761  if(p_clampedDerivFirstPt > 0.99e30) {
2762  p_clampedSecondDerivs[0] = 0.0;//natural boundary conditions are used if deriv of first value is greater than 10^30
2763  u[0] = 0.0;
2764  }
2765  else {
2766  p_clampedSecondDerivs[0] = -0.5;// clamped conditions are used
2767  u[0] = (3.0 / (p_x[1] - p_x[0])) * ((p_y[1] - p_y[0]) / (p_x[1] - p_x[0]) - p_clampedDerivFirstPt);
2768  }
2769  for(int i = 1; i < n - 1; i++) { // decomposition loop of the tridiagonal algorithm
2770  sig = (p_x[i] - p_x[i-1]) / (p_x[i+1] - p_x[i-1]);
2771  p = sig * p_clampedSecondDerivs[i-1] + 2.0;
2772  p_clampedSecondDerivs[i] = (sig - 1.0) / p;
2773  u[i] = (6.0 * ((p_y[i+1] - p_y[i]) / (p_x[i+1] - p_x[i]) - (p_y[i] - p_y[i-1]) /
2774  (p_x[i] - p_x[i-1])) / (p_x[i+1] - p_x[i-1]) - sig * u[i-1]) / p;
2775  }
2776  if(p_clampedDerivLastPt > 0.99e30) { // upper boundary is natural
2777  qn = 0.0;
2778  un = 0.0;
2779  }
2780  else {// upper boundary is clamped
2781  qn = 0.5;
2782  un = (3.0 / (p_x[n-1] - p_x[n-2])) * (p_clampedDerivLastPt - (p_y[n-1] - p_y[n-2]) /
2783  (p_x[n-1] - p_x[n-2]));
2784  }
2785  p_clampedSecondDerivs[n-1] = (un - qn * u[n-2]) / (qn * p_clampedSecondDerivs[n-2] + 1.0);
2786  for(int i = n - 2; i >= 0; i--) { // backsubstitution loop of the tridiagonal algorithm
2787  p_clampedSecondDerivs[i] = p_clampedSecondDerivs[i] * p_clampedSecondDerivs[i+1] + u[i];
2788  }
2789  p_clampedComputed = true;
2790  return;
2791  }
2792 
2830  double NumericalApproximation::ValueToExtrapolate(const double a, const ExtrapType &etype) {
2831  if(etype == NumericalApproximation::ThrowError) {
2832  ReportException(IException::Programmer, "Evaluate()",
2833  "Invalid argument. Value entered, a = "
2834  + IString(a) + ", is outside of domain = ["
2835  + IString(DomainMinimum()) + ", "
2836  + IString(DomainMaximum()) + "]",
2837  _FILEINFO_);
2838  }
2839  if(etype == NumericalApproximation::NearestEndpoint) {
2840  if(a + DBL_EPSILON < DomainMinimum()) {
2841  return DomainMinimum();
2842  }
2843  else {
2844  return DomainMaximum(); // (a > DomainMaximum())
2845  }
2846  }
2847  else { // gsl interpolations and CubicNeighborhood cannot extrapolate
2848  if(GslInterpType(p_itype)
2849  || p_itype == NumericalApproximation::CubicNeighborhood) {
2850  ReportException(IException::Programmer, "Evaluate()",
2851  "Invalid argument. Cannot extrapolate for type "
2852  + Name() + ", must choose to throw error or return nearest neighbor",
2853  _FILEINFO_);
2854  }
2855  return a;
2856  }
2857  }
2858 
2893  double NumericalApproximation::EvaluateCubicNeighborhood(const double a) {
2894  try {
2895  int s = 0, s_old, s0;
2896  vector <double> x0(4), y0(4);
2897  NumericalApproximation spline(NumericalApproximation::CubicNatural);
2898  for(unsigned int n = 0; n < Size(); n++) {
2899  if(p_x[n] < a) s = n;
2900  else break;
2901  }
2902  if(s < 1) s = 1;
2903  else if(s > (int) Size() - 3) s = Size() - 3;
2904  s_old = -1;
2905  s0 = s - 1;
2906  if(s_old != s0) {
2907  for(int n = 0; n < 4; n++) {
2908  x0[n] = p_x[n+s0];
2909  y0[n] = p_y[n+s0];
2910  spline.AddData(x0[n], y0[n]);
2911  }
2912  s_old = s0;
2913  }
2914  // use nearest endpoint extrapolation method for neighborhood spline
2915  // since CubicNatural can do no other
2916  return spline.Evaluate(a, NumericalApproximation::NearestEndpoint);
2917  }
2918  catch(IException &e) { // catch exception from Constructor, ComputeGsl(), Evaluate()
2919  throw IException(e,
2920  e.errorType(),
2921  "EvaluateCubicNeighborhood() - Unable to evaluate cubic neighborhood interpolation at a = "
2922  + IString(a),
2923  _FILEINFO_);
2924  }
2925  }
2926 
2973  vector <double> NumericalApproximation::EvaluateCubicNeighborhood(const vector <double> &a,
2974  const NumericalApproximation::ExtrapType &etype) {
2975  vector <double> result(a.size());
2976  int s_old, s0;
2977  vector <double> x0(4), y0(4);
2978  vector <int> s;
2979  s.clear();
2980  s.resize(a.size());
2981  for(unsigned int i = 0; i < a.size(); i++) {
2982  for(unsigned int n = 0; n < Size(); n++) {
2983  if(p_x[n] < a[i]) {
2984  s[i] = n;
2985  }
2986  }
2987  if(s[i] < 1) {
2988  s[i] = 1;
2989  }
2990  if(s[i] > ((int) Size()) - 3) {
2991  s[i] = Size() - 3;
2992  }
2993  }
2994  s_old = -1;
2995  try {
2996  NumericalApproximation spline(NumericalApproximation::CubicNatural);
2997  for(unsigned int i = 0; i < a.size(); i++) {
2998  s0 = s[i] - 1;
2999  if(s_old != s0) {
3000  spline.Reset();
3001  for(int n = 0; n < 4; n++) {
3002  x0[n] = p_x[n+s0];
3003  y0[n] = p_y[n+s0];
3004  spline.AddData(x0[n], y0[n]);
3005  }
3006  s_old = s0;
3007  }
3008  double a0;
3009  // checks whether this value is in domain of the main spline
3010  if(InsideDomain(a[i]))
3011  a0 = a[i];
3012  else a0 = ValueToExtrapolate(a[i], etype);
3013  // since neighborhood spline is CubicNatural, the only extrapolation possible is NearestEndpoint
3014  result[i] = spline.Evaluate(a0, NumericalApproximation::NearestEndpoint);
3015  }
3016  return result;
3017  }
3018  catch(IException &e) { // catch exception from Constructor, ComputeGsl(), Evaluate()
3019  throw IException(e,
3020  e.errorType(),
3021  "EvaluateCubicNeighborhood() - Unable to evaluate the function at the given vector of points using cubic neighborhood interpolation",
3022  _FILEINFO_);
3023  }
3024  }
3025 
3060  double NumericalApproximation::EvaluateCubicClamped(double a) {
3061  // This method was derived from an algorithm in the text
3062  // Numerical Recipes in C: The Art of Scientific Computing
3063  // Section 3.3 by Flannery, Press, Teukolsky, and Vetterling
3064  int n = Size();
3065  double result = 0;
3066 
3067  int k;
3068  int k_Lo;
3069  int k_Hi;
3070  double h;
3071  double A;
3072  double B;
3073 
3074  k_Lo = 0;
3075  k_Hi = n - 1;
3076  while(k_Hi - k_Lo > 1) {
3077  k = (k_Hi + k_Lo) / 2;
3078  if(p_x[k] > a) {
3079  k_Hi = k;
3080  }
3081  else {
3082  k_Lo = k;
3083  }
3084  }
3085 
3086  h = p_x[k_Hi] - p_x[k_Lo];
3087  A = (p_x[k_Hi] - a) / h;
3088  B = (a - p_x[k_Lo]) / h;
3089  result = A * p_y[k_Lo] + B * p_y[k_Hi] + ((pow(A, 3.0) - A) *
3090  p_clampedSecondDerivs[k_Lo] + (pow(B, 3.0) - B) * p_clampedSecondDerivs[k_Hi]) * pow(h, 2.0) / 6.0;
3091  return result;
3092  }
3093 
3121  double NumericalApproximation::EvaluateCubicHermite(const double a) {
3122  // algorithm was found at en.wikipedia.org/wiki/Cubic_Hermite_spline
3123  // it seems to produce same answers, as the NumericalAnalysis book
3124 
3125  if(p_fprimeOfx.size() != Size()) {
3126  ReportException(IException::User, "EvaluateCubicHermite()",
3127  "Invalid arguments. The size of the first derivative vector does not match the number of (x,y) data points.",
3128  _FILEINFO_);
3129  }
3130  // find the interval in which "a" exists
3131  int lowerIndex = FindIntervalLowerIndex(a);
3132 
3133  // we know that "a" is within the domain since this is verified in
3134  // Evaluate() before this method is called, thus n <= Size()
3135  if(a == p_x[lowerIndex]) {
3136  return p_y[lowerIndex];
3137  }
3138  if(a == p_x[lowerIndex+1]) {
3139  return p_y[lowerIndex+1];
3140  }
3141 
3142  double x0, x1, y0, y1, m0, m1;
3143  // a is contained within the interval (x0,x1)
3144  x0 = p_x[lowerIndex];
3145  x1 = p_x[lowerIndex+1];
3146  // the corresponding known y-values for x0 and x1
3147  y0 = p_y[lowerIndex];
3148  y1 = p_y[lowerIndex+1];
3149  // the corresponding known tangents (slopes) at (x0,y0) and (x1,y1)
3150  m0 = p_fprimeOfx[lowerIndex];
3151  m1 = p_fprimeOfx[lowerIndex+1];
3152 
3153 
3154  // following algorithm found at en.wikipedia.org/wiki/Cubic_Hermite_spline
3155  // seems to produce same answers, is it faster?
3156 
3157  double h, t;
3158  h = x1 - x0;
3159  t = (a - x0) / h;
3160  return (2 * t * t * t - 3 * t * t + 1) * y0 + (t * t * t - 2 * t * t + t) * h * m0 + (-2 * t * t * t + 3 * t * t) * y1 + (t * t * t - t * t) * h * m1;
3161  }
3162 
3183  int NumericalApproximation::FindIntervalLowerIndex(const double a) {
3184  if(InsideDomain(a)) {
3185  // find the interval in which "a" exists
3186  std::vector<double>::iterator pos;
3187  // find position in vector that is greater than or equal to "a"
3188  pos = upper_bound(p_x.begin(), p_x.end(), a);
3189  int upperIndex = 0;
3190  if(pos != p_x.end()) {
3191  upperIndex = distance(p_x.begin(), pos);
3192  }
3193  else {
3194  upperIndex = Size() - 1;
3195  }
3196  return upperIndex - 1;
3197  }
3198  else if((a + DBL_EPSILON) < DomainMinimum()) {
3199  return 0;
3200  }
3201  else {
3202  return Size() - 2;
3203  }
3204  }
3205 
3206 
3242  double NumericalApproximation::EvaluatePolynomialNeville(const double a) {
3243  // This method was derived from an algorithm in the text
3244  // Numerical Recipes in C: The Art of Scientific Computing
3245  // Section 3.1 by Flannery, Press, Teukolsky, and Vetterling
3246  int n = Size();
3247  double y;
3248 
3249  int ns;
3250  double den, dif, dift, c[n], d[n], ho, hp, w;
3251  double *err = 0;
3252  ns = 1;
3253  dif = fabs(a - p_x[0]);
3254  for(int i = 0; i < n; i++) { // Get the index ns of the closest table entry
3255  dift = fabs(a - p_x[i]);
3256  if(dift < dif) {
3257  ns = i + 1;
3258  dif = dift;
3259  }
3260  c[i] = p_y[i]; // initialize c and d
3261  d[i] = p_y[i];
3262  }
3263  ns = ns - 1;
3264  y = p_y[ns]; // initial approximation for y
3265  for(int m = 1; m < n; m++) {
3266  for(int i = 1; i <= n - m; i++) { // loop over c and d and update them
3267  ho = p_x[i-1] - a;
3268  hp = p_x[i+m-1] - a;
3269  w = c[i] - d[i-1];
3270  den = ho - hp;
3271  den = w / den;
3272  d[i-1] = hp * den; // update c and d
3273  c[i-1] = ho * den;
3274  }
3275  if(2 * ns < n - m) { // After each column in the tableau is completed, we decide
3276  err = &c[ns]; // which correction, c or d, we want to add to our accumulating
3277  } // value of y, i.e., which path to take through the tableau|
3278  else { // forking up or down. We do this in such a way as to take the
3279  ns = ns - 1; // most "straight line" route through the tableau to its apex,
3280  err = &d[ns]; // updating ns accordingly to keep track of where we are. This
3281  } // route keeps the partial approximations centered (insofar as possible)
3282  y = y + *err; // on the target x. The last err added is thus the error indication.
3283  }
3284  p_polyNevError.push_back(*err);
3285  return y;
3286  }
3287 
3306  vector <double> NumericalApproximation::EvaluateForIntegration(const double a, const double b, const unsigned int n) {
3307  if(a > b) {
3308  ReportException(IException::Programmer, "EvaluatedForIntegration()",
3309  "Invalid interval entered: [a,b] = ["
3310  + IString(a) + ", " + IString(b) + "]",
3311  _FILEINFO_);
3312  }
3313  if(!InsideDomain(a) || !InsideDomain(b)) {
3314  ReportException(IException::Programmer, "EvaluateForIntegration()",
3315  "Invalid arguments. Interval entered ["
3316  + IString(a) + ", " + IString(b)
3317  + "] is not contained within domain ["
3318  + IString(DomainMinimum()) + ", "
3319  + IString(DomainMaximum()) + "]",
3320  _FILEINFO_);
3321  }
3322  vector <double> f;
3323  //need total number of segments to be divisible by n-1
3324  // This way we can use the formula for each interval: 0 to n, n to 2n, 2n to 3n, etc.
3325  // Notice interval endpoints will overlap for these composite formulas
3326  int xSegments = Size() - 1;
3327  while(xSegments % (n - 1) != 0) {
3328  xSegments++;
3329  }
3330  // x must be sorted and unique
3331  double xMin = a;
3332  double xMax = b;
3333  //Uniform step size.
3334  double h = (xMax - xMin) / xSegments;
3335  //Compute the interpolates using spline.
3336  try {
3337  for(double i = 0; i < (xSegments + 1); i++) {
3338  double xi = h * i + xMin;
3339  f.push_back(Evaluate(xi)); // validate data set here, allow default ThrowError extrap type
3340  }
3341  f.push_back(h);
3342  return f;
3343  }
3344  catch(IException &e) { // catch exception from Evaluate()
3345  throw IException(e,
3346  e.errorType(),
3347  "EvaluateForIntegration() - Unable to evaluate the data set for integration",
3348  _FILEINFO_);
3349  }
3350  }// for integration using composite of spline (creates evenly spaced points)
3351 
3372  void NumericalApproximation::ReportException(IException::ErrorType type, const string &methodName, const string &message,
3373  const char *filesrc, int lineno)
3374  const {
3375  string msg = methodName + " - " + message;
3376  throw IException(type, msg.c_str(), filesrc, lineno);
3377  return;
3378  }
3379 
3380 }
Isis::NumericalApproximation::p_fprimeOfx
vector< double > p_fprimeOfx
List of first derivatives corresponding to each x value in the data set (i.e. each value in p_x)
Definition: NumericalApproximation.h:881
Isis::NumericalApproximation::PolynomialNevilleErrorEstimate
vector< double > PolynomialNevilleErrorEstimate()
Retrieves the error estimate for the Neville's polynomial interpolation type.
Definition: NumericalApproximation.cpp:970
Isis::NumericalApproximation::ExtrapType
ExtrapType
This enum defines the manner in which a value outside of the domain should be handled if passed to th...
Definition: NumericalApproximation.h:813
Isis::NumericalApproximation::InterpFunctor
const gsl_interp_type * InterpFunctor
GSL Interpolation specs.
Definition: NumericalApproximation.h:866
Isis::NumericalApproximation::p_clampedComputed
bool p_clampedComputed
Flag variable to determine whether ComputeCubicClamped() has been called.
Definition: NumericalApproximation.h:874
Isis::NumericalApproximation::p_y
vector< double > p_y
List of Y values.
Definition: NumericalApproximation.h:863
Isis::NumericalApproximation::p_clampedDerivFirstPt
double p_clampedDerivFirstPt
First derivative of first x-value, p_x[0]. This is only used for the CubicClamped interpolation type.
Definition: NumericalApproximation.h:875
Isis::NumericalApproximation::p_clampedDerivLastPt
double p_clampedDerivLastPt
First derivative of last x-value, p_x[n-1]. This is only used for the CubicClamped interpolation type...
Definition: NumericalApproximation.h:876
Isis::NumericalApproximation::p_clampedEndptsSet
bool p_clampedEndptsSet
Flag variable to determine whether SetCubicClampedEndptDeriv() has been called after all data was add...
Definition: NumericalApproximation.h:873
Isis::NumericalApproximation::p_dataValidated
bool p_dataValidated
Flag variable to determine whether ValidateDataSet() has been called.
Definition: NumericalApproximation.h:864
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::IException::errorType
ErrorType errorType() const
Returns the source of the error for this exception.
Definition: IException.cpp:430
Isis::NumericalApproximation::p_polyNevError
vector< double > p_polyNevError
Estimate of error for interpolation evaluated at x. This is only used for the PolynomialNeville inter...
Definition: NumericalApproximation.h:879
Isis::NumericalApproximation::p_clampedSecondDerivs
vector< double > p_clampedSecondDerivs
List of second derivatives evaluated at p_x values. This is only used for the CubicClamped interpolat...
Definition: NumericalApproximation.h:877
std
Namespace for the standard library.
Isis::NumericalApproximation::AddData
void AddData(const double x, const double y)
Add a datapoint to the set.
Definition: NumericalApproximation.cpp:440
Isis::NumericalApproximation::p_x
vector< double > p_x
List of X values.
Definition: NumericalApproximation.h:862
Isis::NumericalApproximation::Evaluate
double Evaluate(const double a, const ExtrapType &etype=ThrowError)
Calculates interpolated or extrapolated value of tabulated data set for given domain value.
Definition: NumericalApproximation.cpp:836
Isis::NumericalApproximation::p_itype
InterpType p_itype
Interpolation type.
Definition: NumericalApproximation.h:861
Isis::NumericalApproximation::InterpType
InterpType
This enum defines the types of interpolation supported in this class.
Definition: NumericalApproximation.h:731
Isis::IString
Adds specific functionality to C++ strings.
Definition: IString.h:165
Isis::NumericalApproximation::GslFunctor
InterpFunctor GslFunctor(NumericalApproximation::InterpType itype) const
Search for a GSL interpolation function.
Definition: NumericalApproximation.cpp:2492
Isis::NumericalApproximation::Reset
void Reset()
Resets the state of the object.
Definition: NumericalApproximation.cpp:2251
Isis::NumericalApproximation::FunctorConstIter
FunctorList::const_iterator FunctorConstIter
GSL Iterator.
Definition: NumericalApproximation.h:868
Isis::IException::ErrorType
ErrorType
Contains a set of exception error types.
Definition: IException.h:111
Isis::NumericalApproximation
NumericalApproximation provides various numerical analysis methods of interpolation,...
Definition: NumericalApproximation.h:726
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the USGS Astrogeology Discussion Board
To report a bug, or suggest a feature go to: ISIS Github
File Modified: 07/13/2023 15:16:57