File indexing completed on 2024-09-27 07:03:24
0001
0002
0003
0004 #ifndef Interpolate_
0005 #define Interpolate_
0006
0007 #include <array>
0008 #include <cmath>
0009 #include <cstddef>
0010 #include <limits>
0011 #include <stdexcept>
0012 #include <vector>
0013
0014
0015 template<typename T>
0016 inline T linear(T f1, T f2, T x) {
0017 return (1. - x) * f1 + x * f2;
0018 }
0019
0020
0021 template<typename T>
0022 inline T linear(T f1, T f2, T h, T x) {
0023 return ((h - x) / h) * f1 + (x / h) * f2;
0024 }
0025
0026
0027
0028 template<typename T>
0029 inline T cubic(T f0, T f1, T f2, T f3, T x) {
0030 return
0031 2. * (1. - x) * (1. - x) * (0.5 + x) * f1
0032 + 0.5 * (1. - x) * (1. - x) * x * (f2 - f0)
0033 + 2. * x * x * (1.5 - x) * f2
0034 - 0.5 * x * x * (1. - x) * (f3 - f1);
0035 }
0036
0037
0038 template<typename T>
0039 inline T cubic(T f0, T f1, T f2, T f3, T h0, T h1, T h2, T x) {
0040 T h01 = h0 + h1;
0041 T h12 = h1 + h2;
0042 T h = h0 + h1 + h2;
0043 T c0, c1, c2, c3;
0044 if (!std::isfinite(h0) && !std::isfinite(h2)) {
0045 return linear(f1, f2, h1, x);
0046 } else if (!std::isfinite(h0)) {
0047 c0 = 0.;
0048 c1 = (h1 - x) * (h1 * h12 - x * x) / (h1 * h1 * h12);
0049 c2 = x * (h1 * h2 + h1 * x - x * x) / (h2 * h1 * h1);
0050 c3 = -x * x * (h1 - x) / (h1 * h2 * h12);
0051 } else if (!std::isfinite(h2)) {
0052 c0 = -(h1 - x) * (h1 - x) * x / (h0 * h1 * h01);
0053 c1 = (h1 - x) * (h0 * h1 + h1 * x - x * x) / (h0 * h1 * h1);
0054 c2 = x * (h0 * h1 + 2. * h1 * x - x * x) / (h1 * h1 * h01);
0055 c3 = 0.;
0056 } else {
0057 c0 = -(h1 - x) * (h1 - x) * x / (h0 * h1 * h01);
0058 c1 = (h1 - x) * (h0 * h1 * h12 + h1 * h12 * x - h * x * x) / (h0 * h1 * h1 * h12);
0059 c2 = x * (h0 * h1 * h2 + h1 * (h + h2) * x - h * x * x) / (h2 * h1 * h1 * h01);
0060 c3 = -x * x * (h1 - x) / (h1 * h2 * h12);
0061 }
0062 return c0 * f0 + c1 * f1 + c2 * f2 + c3 * f3;
0063 }
0064
0065 template<std::size_t N>
0066 using CellIndex = std::array<std::size_t, N>;
0067 template<typename T, std::size_t N>
0068 using Point = std::array<T, N>;
0069 template<typename T, std::size_t N>
0070 using Coords = std::array<std::vector<T>, N>;
0071
0072 template<typename T, std::size_t N>
0073 class Grid;
0074
0075 enum class Scale {
0076 LINEAR = 0,
0077 LOG = 1,
0078 };
0079
0080
0081
0082
0083
0084
0085 template<typename T, std::size_t N>
0086 class GridView final {
0087 T const* _data;
0088 Coords<T, N> _coords;
0089 std::size_t _count_total;
0090
0091 public:
0092
0093
0094 GridView(T const* data, Coords<T, N> coords);
0095
0096
0097
0098
0099 std::size_t count(std::size_t dim) const {
0100 return _coords[dim].size();
0101 }
0102
0103 CellIndex<N> count() const {
0104 CellIndex<N> result;
0105 for (std::size_t dim = 0; dim < N; ++dim) {
0106 result[dim] = _coords[dim].size();
0107 }
0108 return result;
0109 }
0110
0111 std::size_t count_total() const {
0112 return _count_total;
0113 }
0114
0115 T const* data() const {
0116 return _data;
0117 }
0118
0119
0120 GridView<T, N - 1> operator[](std::size_t idx) const;
0121
0122 T const& operator[](CellIndex<N> idx) const;
0123
0124 GridView<T, N - 1> reduce(std::size_t idx) const {
0125 return operator[](idx);
0126 }
0127
0128
0129 std::size_t grid_from_space(std::size_t dim, T x) const;
0130 std::size_t grid_from_space(std::size_t dim, T x, T* frac) const;
0131 CellIndex<N> grid_from_space(Point<T, N> x) const;
0132 CellIndex<N> grid_from_space(Point<T, N> x, Point<T, N>* frac) const;
0133
0134
0135 T space_from_grid(std::size_t dim, std::size_t idx) const;
0136 Point<T, N> space_from_grid(CellIndex<N> idx) const;
0137 };
0138
0139
0140 template<typename T>
0141 class GridView<T, 0> {
0142 T const* _data;
0143
0144 public:
0145 explicit GridView(T const* data) : _data(data) { }
0146 GridView(T const* data, Coords<T, 0> coords) :
0147 _data(data) {
0148 static_cast<void>(coords);
0149 }
0150
0151 CellIndex<0> count() const {
0152 return CellIndex<0>();
0153 }
0154 std::size_t count_total() const {
0155 return 1;
0156 }
0157 T const* data() const {
0158 return _data;
0159 }
0160
0161 T const& operator[](CellIndex<0> idx) {
0162 return *_data;
0163 }
0164 operator T const&() const {
0165 return *_data;
0166 }
0167 };
0168
0169
0170
0171
0172
0173
0174 template<typename T, std::size_t N>
0175 class Grid final {
0176 std::vector<T> _data;
0177 Coords<T, N> _coords;
0178 std::size_t _count_total;
0179
0180 public:
0181 Grid() : _data(), _coords(), _count_total(0) { }
0182 Grid(T const* data, Coords<T, N> coords);
0183 operator GridView<T, N>() const {
0184 return GridView<T, N>(_data.data(), _coords);
0185 }
0186
0187
0188 std::size_t count(std::size_t dim) const {
0189 return static_cast<GridView<T, N> >(*this).count(dim);
0190 }
0191
0192 CellIndex<N> count() const {
0193 return static_cast<GridView<T, N> >(*this).count();
0194 }
0195
0196 std::size_t count_total() const {
0197 return _count_total;
0198 }
0199
0200 T const* data() const {
0201 return _data.data();
0202 }
0203
0204
0205 GridView<T, N - 1> operator[](std::size_t idx) const {
0206 return static_cast<GridView<T, N> >(*this)[idx];
0207 }
0208
0209 T const& operator[](CellIndex<N> idx) const {
0210 return static_cast<GridView<T, N> >(*this)[idx];
0211 }
0212
0213 GridView<T, N - 1> reduce(std::size_t idx) const {
0214 return operator[](idx);
0215 }
0216
0217
0218 std::size_t grid_from_space(std::size_t dim, T x) const {
0219 return static_cast<GridView<T, N> >(*this).grid_from_space(dim, x);
0220 }
0221 std::size_t grid_from_space(std::size_t dim, T x, T* frac) const {
0222 return static_cast<GridView<T, N> >(*this).grid_from_space(dim, x, frac);
0223 }
0224 CellIndex<N> grid_from_space(Point<T, N> x) const {
0225 return static_cast<GridView<T, N> >(*this).grid_from_space(x);
0226 }
0227 CellIndex<N> grid_from_space(Point<T, N> x, Point<T, N>* frac) const {
0228 return static_cast<GridView<T, N> >(*this).grid_from_space(x, frac);
0229 }
0230
0231
0232 T space_from_grid(std::size_t dim, std::size_t idx) const {
0233 return static_cast<GridView<T, N> >(*this).space_from_grid(dim, idx);
0234 }
0235 Point<T, N> space_from_grid(CellIndex<N> idx) const {
0236 return static_cast<GridView<T, N> >(*this).space_from_grid(idx);
0237 }
0238 };
0239
0240
0241 template<typename T>
0242 class Grid<T, 0> final {
0243 T _data;
0244
0245 public:
0246 Grid() : _data() { }
0247 Grid(T const* data) : _data(*data) { };
0248 Grid(T const* data, Coords<T, 0> coords) : _data(*data) {
0249 static_cast<void>(coords);
0250 };
0251 operator GridView<T, 0>() const {
0252 return GridView<T, 0>(&_data);
0253 }
0254
0255
0256 CellIndex<0> count() const {
0257 return CellIndex<0>();
0258 }
0259
0260 std::size_t count_total() const {
0261 return 1;
0262 }
0263
0264 T const* data() const {
0265 return &_data;
0266 }
0267
0268
0269 T const& operator[](CellIndex<0> idx) const {
0270 return static_cast<GridView<T, 0> >(*this)[idx];
0271 }
0272 };
0273
0274
0275
0276
0277
0278 template<typename T, std::size_t N>
0279 class LinearView final {
0280 static_assert(
0281 std::is_floating_point<T>::value,
0282 "Cannot have a LinearView of a non-floating-point type.");
0283
0284 GridView<T, N> _grid;
0285
0286 public:
0287 LinearView(GridView<T, N> grid) : _grid(grid) { }
0288
0289 T operator()(Point<T, N> x) const;
0290 };
0291
0292
0293 template<typename T>
0294 class LinearView<T, 0> final {
0295 static_assert(
0296 std::is_floating_point<T>::value,
0297 "Cannot have a LinearView of a non-floating-point type.");
0298
0299 GridView<T, 0> _grid;
0300
0301 public:
0302 explicit LinearView(GridView<T, 0> grid) : _grid(grid) { }
0303 T operator()(Point<T, 0> x) const {
0304 static_cast<void>(x);
0305 return static_cast<T>(_grid);
0306 }
0307 };
0308
0309
0310
0311
0312
0313 template<typename T, std::size_t N>
0314 class CubicView final {
0315 static_assert(
0316 std::is_floating_point<T>::value,
0317 "Cannot have a CubicView of a non-floating-point type.");
0318
0319 GridView<T, N> _grid;
0320
0321 public:
0322 explicit CubicView(GridView<T, N> grid) : _grid(grid) { }
0323
0324 T operator()(Point<T, N> x) const;
0325 };
0326
0327
0328 template<typename T>
0329 class CubicView<T, 0> final {
0330 static_assert(
0331 std::is_floating_point<T>::value,
0332 "Cannot have a CubicView of a non-floating-point type.");
0333
0334 GridView<T, 0> _grid;
0335
0336 public:
0337 explicit CubicView(GridView<T, 0> grid) : _grid(grid) { }
0338 T operator()(Point<T, 0> x) const {
0339 static_cast<void>(x);
0340 return static_cast<T>(_grid);
0341 }
0342 };
0343
0344
0345
0346
0347
0348
0349 template<typename T, std::size_t N, std::size_t K = 1>
0350 std::array<Grid<T, N>, K> read_grids(
0351 std::vector<std::array<T, N + K> > const& raw_data);
0352
0353
0354 struct NotEnoughPointsError : public std::runtime_error {
0355 std::size_t points;
0356 std::size_t expected_points;
0357 NotEnoughPointsError(std::size_t points, std::size_t expected_points);
0358 };
0359
0360
0361 struct SingularDimensionError : public std::runtime_error {
0362 std::size_t dim;
0363 SingularDimensionError(std::size_t dim);
0364 };
0365
0366
0367
0368 struct InvalidGridPlanesError : public std::runtime_error {
0369 InvalidGridPlanesError();
0370 };
0371
0372
0373 struct InvalidSpacingError : public std::runtime_error {
0374 InvalidSpacingError();
0375 };
0376
0377
0378 struct UnexpectedGridPointError : public std::runtime_error {
0379 std::size_t line_number;
0380 UnexpectedGridPointError(std::size_t line_number);
0381 };
0382
0383 #include "Interpolate.ipp"
0384
0385 #endif
0386