IntpAkimaNonuniform1.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.08.13
  7. #pragma once
  8. #include <Mathematics/IntpAkima1.h>
  9. namespace WwiseGTE
  10. {
  11. template <typename Real>
  12. class IntpAkimaNonuniform1 : public IntpAkima1<Real>
  13. {
  14. public:
  15. // Construction. The interpolator is for arbitrarily spaced x-values.
  16. // The input arrays must have 'quantity' elements and the X[] array
  17. // must store increasing values: X[i + 1] > X[i] for all i.
  18. IntpAkimaNonuniform1(int quantity, Real const* X, Real const* F)
  19. :
  20. IntpAkima1<Real>(quantity, F),
  21. mX(X)
  22. {
  23. LogAssert(X != nullptr, "Invalid input.");
  24. for (int j0 = 0, j1 = 1; j1 < quantity; ++j0, ++j1)
  25. {
  26. LogAssert(X[j1] > X[j0], "Invalid input.");
  27. }
  28. // Compute slopes.
  29. std::vector<Real> slope(quantity + 3);
  30. int i, ip1, ip2;
  31. for (i = 0, ip1 = 1, ip2 = 2; i < quantity - 1; ++i, ++ip1, ++ip2)
  32. {
  33. Real dx = X[ip1] - X[i];
  34. Real df = F[ip1] - F[i];
  35. slope[ip2] = df / dx;
  36. }
  37. slope[1] = (Real)2 * slope[2] - slope[3];
  38. slope[0] = (Real)2 * slope[1] - slope[2];
  39. slope[quantity + 1] = (Real)2 * slope[quantity] - slope[quantity - 1];
  40. slope[quantity + 2] = (Real)2 * slope[quantity + 1] - slope[quantity];
  41. // Construct derivatives.
  42. std::vector<Real> FDer(quantity);
  43. for (i = 0; i < quantity; ++i)
  44. {
  45. FDer[i] = this->ComputeDerivative(&slope[i]);
  46. }
  47. // Construct polynomials.
  48. for (i = 0, ip1 = 1; i < quantity - 1; ++i, ++ip1)
  49. {
  50. auto& poly = this->mPoly[i];
  51. Real F0 = F[i];
  52. Real F1 = F[ip1];
  53. Real FDer0 = FDer[i];
  54. Real FDer1 = FDer[ip1];
  55. Real df = F1 - F0;
  56. Real dx = X[ip1] - X[i];
  57. Real dx2 = dx * dx;
  58. Real dx3 = dx2 * dx;
  59. poly[0] = F0;
  60. poly[1] = FDer0;
  61. poly[2] = ((Real)3 * df - dx * (FDer1 + (Real)2 * FDer0)) / dx2;
  62. poly[3] = (dx * (FDer0 + FDer1) - (Real)2 * df) / dx3;
  63. }
  64. }
  65. virtual ~IntpAkimaNonuniform1() = default;
  66. // Member access.
  67. Real const* GetX() const
  68. {
  69. return mX;
  70. }
  71. virtual Real GetXMin() const override
  72. {
  73. return mX[0];
  74. }
  75. virtual Real GetXMax() const override
  76. {
  77. return mX[this->mQuantity - 1];
  78. }
  79. protected:
  80. virtual void Lookup(Real x, int& index, Real& dx) const override
  81. {
  82. // The caller has ensured that mXMin <= x <= mXMax.
  83. for (index = 0; index + 1 < this->mQuantity; ++index)
  84. {
  85. if (x < mX[index + 1])
  86. {
  87. dx = x - mX[index];
  88. return;
  89. }
  90. }
  91. --index;
  92. dx = x - mX[index];
  93. }
  94. Real const* mX;
  95. };
  96. }