SPH
Lut.h
Go to the documentation of this file.
1 #pragma once
2 
7 
10 
12 
13 template <typename TValue, typename TScalar = Float>
14 class Lut;
15 
16 template <typename TValue, typename TScalar = Float>
17 class LutIterator {
18 private:
20  Size index;
21  Size size;
22  Interval range;
23 
24 public:
26  const Size index,
27  const Size size,
28  const Interval& range,
30  : iter(iter)
31  , index(index)
32  , size(size)
33  , range(range) {}
34 
36  ++iter;
37  ++index;
38  return *this;
39  }
40 
41  struct Value {
42  TScalar x;
43  TValue y;
44 
45  bool operator==(const Value& other) const {
46  return x == other.x && y == other.y;
47  }
48  };
49 
50  Value operator*() const {
51  return Value{ Float(index) / Float(size - 1) * range.size() + range.lower(), *iter };
52  }
53 
54  bool operator!=(const LutIterator& other) const {
55  return iter != other.iter;
56  }
57 };
58 
60 template <typename TValue, typename TScalar>
61 class Lut : public Noncopyable {
62 private:
63  Array<TValue> data;
64  Interval range;
65 
66 public:
67  Lut() = default;
68 
69  Lut(const Interval range, Array<TValue>&& data)
70  : data(std::move(data))
71  , range(range) {}
72 
73  template <typename TFunction>
74  Lut(const Interval range, const Size resolution, TFunction&& func)
75  : data(resolution)
76  , range(range) {
77  for (Size i = 0; i < resolution; ++i) {
78  const Float x = range.lower() + Float(i) * range.size() / (resolution - 1);
79  data[i] = func(x);
80  }
81  }
82 
83  INLINE TValue operator()(const TScalar x) const {
84  const TScalar fidx = TScalar((x - range.lower()) / range.size() * (data.size() - 1));
85  const int idx1 = int(floor(fidx));
86  const int idx2 = idx1 + 1;
87  if (idx2 >= int(data.size() - 1)) {
89  return data.back();
90  } else if (idx1 <= 0) {
91  return data.front();
92  } else {
93  const TScalar ratio = fidx - idx1;
94  SPH_ASSERT(ratio >= TScalar(0) && ratio < TScalar(1));
95  return lerp(data[idx1], data[idx2], ratio);
96  }
97  }
98 
101  return LutIterator<TValue, TScalar>(data.begin(), 0, data.size(), range, {});
102  }
103 
106  return LutIterator<TValue, TScalar>(data.end(), data.size(), data.size(), range, {});
107  }
108 
110  Size size() const {
111  return data.size();
112  }
113 
115  Interval getRange() const {
116  return range;
117  }
118 
120  Lut derivative() const {
121  Array<Float> deriv(data.size());
122  const Float dx = range.size() / data.size();
123  for (Size i = 0; i < data.size() - 1; ++i) {
124  deriv[i] = (data[i + 1] - data[i]) / dx;
125  }
126  deriv[data.size() - 1] = deriv[data.size() - 2];
127  return Lut(range, std::move(deriv));
128  }
129 
133  Lut integral(const Float x0, const Float y0) const {
134  SPH_ASSERT(range.contains(x0));
135  Array<Float> integ(data.size());
136  integ[0] = 0;
137  const Float dx = range.size() / data.size();
138  for (Size i = 1; i < data.size(); ++i) {
139  integ[i] = integ[i - 1] + data[i] * dx;
140  }
141  const Lut lut(range, std::move(integ));
142  return lut + (y0 - lut(x0));
143  }
144 };
145 
150 template <typename TValue, typename TScalar, typename TBinaryOp>
152  const Lut<TValue, TScalar>& lut2,
153  const TBinaryOp& op) {
154  // use the higher resolution
155  const Float dx = min(lut1.getRange().size() / lut1.size(), lut2.getRange().size() / lut2.size());
156 
157  const Interval range = lut1.getRange().intersect(lut2.getRange());
158  const Size resolution = Size(round(range.size() / dx));
159 
160  auto func = [&lut1, &lut2, &op](const Float x) { return op(lut1(x), lut2(x)); };
161  return Lut<TValue, TScalar>(range, resolution, func);
162 }
163 
165 template <typename TValue, typename TScalar, typename TBinaryOp>
167  const TScalar& value,
168  const TBinaryOp& op) {
169  auto func = [&lut, &value, &op](const Float x) { return op(lut(x), value); };
170  return Lut<TValue, TScalar>(lut.getRange(), lut.size(), func);
171 }
172 
173 template <typename TValue, typename TScalar>
175  return lutOperation(lut1, lut2, [](const Float x1, const Float x2) { return x1 + x2; });
176 }
177 
178 template <typename TValue, typename TScalar>
180  return lutOperation(lut1, lut2, [](const Float x1, const Float x2) { return x1 - x2; });
181 }
182 
183 template <typename TValue, typename TScalar>
185  return lutOperation(lut1, lut2, [](const Float x1, const Float x2) { return x1 * x2; });
186 }
187 
188 template <typename TValue, typename TScalar>
190  return lutOperation(lut1, lut2, [](const Float x1, const Float x2) { return x1 / x2; });
191 }
192 
193 template <typename TValue, typename TScalar>
194 Lut<TValue, TScalar> operator+(const Lut<TValue, TScalar>& lut1, const TScalar& mult) {
195  return lutOperation(lut1, mult, [](const Float x1, const Float x2) { return x1 + x2; });
196 }
197 
198 template <typename TValue, typename TScalar>
199 Lut<TValue, TScalar> operator-(const Lut<TValue, TScalar>& lut1, const TScalar& mult) {
200  return lutOperation(lut1, mult, [](const Float x1, const Float x2) { return x1 - x2; });
201 }
202 
203 template <typename TValue, typename TScalar>
204 Lut<TValue, TScalar> operator*(const Lut<TValue, TScalar>& lut1, const TScalar& mult) {
205  return lutOperation(lut1, mult, [](const Float x1, const Float x2) { return x1 * x2; });
206 }
207 
208 template <typename TValue, typename TScalar>
209 Lut<TValue, TScalar> operator/(const Lut<TValue, TScalar>& lut1, const TScalar& mult) {
210  return lutOperation(lut1, mult, [](const Float x1, const Float x2) { return x1 / x2; });
211 }
212 
Generic dynamically allocated resizable storage.
#define SPH_ASSERT(x,...)
Definition: Assert.h:94
NAMESPACE_SPH_BEGIN
Definition: BarnesHut.cpp:13
uint32_t Size
Integral type used to index arrays (by default).
Definition: Globals.h:16
double Float
Precision used withing the code. Use Float instead of float or double where precision is important.
Definition: Globals.h:13
Object representing interval of real values.
Lut< TValue, TScalar > operator-(const Lut< TValue, TScalar > &lut1, const Lut< TValue, TScalar > &lut2)
Definition: Lut.h:179
Lut< TValue, TScalar > operator+(const Lut< TValue, TScalar > &lut1, const Lut< TValue, TScalar > &lut2)
Definition: Lut.h:174
Lut< TValue, TScalar > operator/(const Lut< TValue, TScalar > &lut1, const Lut< TValue, TScalar > &lut2)
Definition: Lut.h:189
Lut< TValue, TScalar > lutOperation(const Lut< TValue, TScalar > &lut1, const Lut< TValue, TScalar > &lut2, const TBinaryOp &op)
Returns a LUT given by a generic binary operator.
Definition: Lut.h:151
Lut< TValue, TScalar > operator*(const Lut< TValue, TScalar > &lut1, const Lut< TValue, TScalar > &lut2)
Definition: Lut.h:184
NAMESPACE_SPH_BEGIN constexpr INLINE T min(const T &f1, const T &f2)
Minimum & Maximum value.
Definition: MathBasic.h:15
INLINE T lerp(const T v1, const T v2, const TAmount amount)
Definition: MathUtils.h:341
INLINE auto floor(const T &f)
Definition: MathUtils.h:346
INLINE auto round(const T &f)
Definition: MathUtils.h:356
#define INLINE
Macros for conditional compilation based on selected compiler.
Definition: Object.h:31
#define NAMESPACE_SPH_END
Definition: Object.h:12
INLINE Iterator< StorageType > end() noexcept
Definition: Array.h:462
INLINE T & back() noexcept
Definition: Array.h:176
INLINE TCounter size() const noexcept
Definition: Array.h:193
INLINE T & front() noexcept
Definition: Array.h:166
INLINE Iterator< StorageType > begin() noexcept
Definition: Array.h:450
Helper class used to allow calling a function only from within T.
Definition: Object.h:94
Object representing a 1D interval of real numbers.
Definition: Interval.h:17
INLINE Float lower() const
Returns lower bound of the interval.
Definition: Interval.h:74
INLINE Float size() const
Returns the size of the interval.
Definition: Interval.h:89
INLINE bool contains(const Float &value) const
Checks whether value is inside the interval.
Definition: Interval.h:55
INLINE Interval intersect(const Interval &other) const
Computes the intersection with another interval.
Definition: Interval.h:60
bool operator!=(const LutIterator &other) const
Definition: Lut.h:54
Value operator*() const
Definition: Lut.h:50
LutIterator & operator++()
Definition: Lut.h:35
LutIterator(Iterator< const TValue > iter, const Size index, const Size size, const Interval &range, Badge< Lut< TValue, TScalar >>)
Definition: Lut.h:25
Callable representing a generic R->T function, approximated using look-up table.
Definition: Lut.h:61
LutIterator< TValue, TScalar > begin() const
Returns an iterator accessing tabulated values.
Definition: Lut.h:100
Lut(const Interval range, Array< TValue > &&data)
Definition: Lut.h:69
LutIterator< TValue, TScalar > end() const
Returns an iterator accessing tabulated values.
Definition: Lut.h:105
Lut()=default
Lut(const Interval range, const Size resolution, TFunction &&func)
Definition: Lut.h:74
Lut derivative() const
Computes the derivative of the function.
Definition: Lut.h:120
INLINE TValue operator()(const TScalar x) const
Definition: Lut.h:83
Interval getRange() const
Returns the definition interval of the function.
Definition: Lut.h:115
Size size() const
Returns the number of tabulated value.
Definition: Lut.h:110
Lut integral(const Float x0, const Float y0) const
Computes the indefinite integral of the function.
Definition: Lut.h:133
Overload of std::swap for Sph::Array.
Definition: Array.h:578
TScalar x
Definition: Lut.h:42
bool operator==(const Value &other) const
Definition: Lut.h:45
TValue y
Definition: Lut.h:43
Object with deleted copy constructor and copy operator.
Definition: Object.h:54