Path Tracer
wave.hpp
1 #pragma once
2 
3 #include <common.hpp>
4 #include <utils.hpp>
5 using namespace ptracey;
6 namespace ptracey {
7 
12 template <class T> class sampled_wave {
13 public:
17  std::vector<T> values;
18 
29  sampled_wave(T val, unsigned int size) {
30  values.clear();
31  for (unsigned int i = 0; i < size; i++) {
32  values.push_back(val);
33  }
34  D_CHECK(!has_nans());
35  }
44  sampled_wave(const std::vector<T> &vals) : values(vals) {
45  D_CHECK(!has_nans());
46  }
50  T max() const {
51  return *std::max_element(values.begin(), values.end());
52  }
57  T min() const {
58  return *std::min_element(values.begin(), values.end());
59  }
63  bool has_nans() const {
64  for (auto val : values) {
65  if (isnan(val))
66  return true;
67  }
68  return false;
69  }
74  bool has_zeros() const {
75  for (auto val : values) {
76  if (val == 0.0)
77  return true;
78  }
79  return false;
80  }
85  bool is_black() const {
86  for (auto val : values) {
87  if (val != 0.0)
88  return false;
89  }
90  return true;
91  }
97  D_CHECK(!s.has_nans());
98  values = s.values;
99  return *this;
100  }
117  apply(unsigned int index, T value,
118  const std::function<T(T, T)> &fn) const {
119  std::vector<T> vs;
120  vs.resize(values.size());
121  std::copy(values.begin(), values.end(), vs.begin());
122  auto val = fn(values[index], value);
123  COMP_CHECK_MSG(val < 0.0, val, 0.0,
124  "operation produces negative value");
125  vs[index] = val;
126  auto wave = sampled_wave(values);
127  return wave;
128  }
140  apply(T value, const std::function<T(T, T)> &fn) const {
141  std::vector<T> vs;
142  vs.resize(values.size());
143  for (std::size_t i = 0; i < values.size(); i++) {
144  auto val = fn(values[i], value);
145  COMP_CHECK_MSG(val < 0.0, val, 0.0,
146  "operation produces a negative value");
147  vs[i] = val;
148  }
149  auto wave = sampled_wave(vs);
150  return wave;
151  }
159  apply(const sampled_wave &s,
160  const std::function<T(T, T)> &fn) const {
161  D_CHECK(!s.has_nans());
162  D_CHECK(s.values.size() == values.size());
163  std::vector<T> vs;
164  vs.resize(values.size());
165 
166  for (std::size_t i = 0; i < values.size(); i++) {
167  auto val = fn(values[i], s.values[i]);
168  COMP_CHECK_MSG(val < 0.0, val, 0.0,
169  "operation produces a negative value");
170  vs[i] = val;
171  }
172  auto wave = sampled_wave(vs);
173  return wave;
174  }
175 
185  auto wave =
186  apply(s, [](auto i, auto j) { return i + j; });
187  return wave;
188  }
197  sampled_wave &operator+=(const T &s) const {
198  auto wave =
199  apply(s, [](auto i, auto j) { return i + j; });
200  return wave;
201  }
206  auto wave =
207  apply(s, [](auto i, auto j) { return i + j; });
208  return wave;
209  }
214  sampled_wave operator+(const T &s) const {
215  auto wave =
216  apply(s, [](auto i, auto j) { return i + j; });
217  return wave;
218  }
222  friend sampled_wave operator+(const T &s,
223  const sampled_wave &ss) {
224  return ss + s;
225  }
226 
235  auto wave =
236  apply(s, [](auto i, auto j) { return i - j; });
237  return wave;
238  }
248  sampled_wave &operator-=(const T &s) const {
249  auto wave =
250  apply(s, [](auto i, auto j) { return i - j; });
251  return wave;
252  }
257  auto wave =
258  apply(s, [](auto i, auto j) { return i - j; });
259  return wave;
260  }
267  sampled_wave operator-(const T &s) const {
268  auto minval = min();
269  COMP_CHECK_MSG(
270  minval <= s, minval, s,
271  "given value would produce negative powers");
272  auto wave =
273  apply(s, [](auto this_wave_value, auto value) {
274  return this_wave_value - value;
275  });
276  return wave;
277  }
281  friend sampled_wave operator-(const T &s,
282  const sampled_wave &ss) {
283  auto maxval = ss.max();
284  COMP_CHECK_MSG(
285  maxval <= s, maxval, s,
286  "given value would produce negative powers");
287  auto wave =
288  ss.apply(s, [](auto this_wave_value, auto value) {
289  return value - this_wave_value;
290  });
291  return wave;
292  }
305  auto wave =
306  apply(s, [](auto i, auto j) { return i * j; });
307  return wave;
308  }
318  sampled_wave &operator*=(const T &s) const {
319  auto wave =
320  apply(s, [](auto i, auto j) { return i * j; });
321  return wave;
322  }
323 
328  auto wave =
329  apply(s, [](auto i, auto j) { return i * j; });
330  return wave;
331  }
336  sampled_wave operator*(const T &s) const {
337  auto wave =
338  apply(s, [](auto i, auto j) { return i * j; });
339  return wave;
340  }
344  friend sampled_wave operator*(const T &s,
345  const sampled_wave &ss) {
346  return ss * s;
347  }
356  D_CHECK(!s.has_zeros());
357  auto wave =
358  apply(s, [](auto i, auto j) { return i / j; });
359  return wave;
360  }
369  sampled_wave &operator/=(const T &s) const {
370  D_CHECK(s != 0.0);
371  auto wave =
372  apply(s, [](auto i, auto j) { return i / j; });
373  return wave;
374  }
380  D_CHECK(!s.has_zeros());
381  auto wave =
382  apply(s, [](auto i, auto j) { return i / j; });
383  return wave;
384  }
391  sampled_wave operator/(const T &s) const {
392  D_CHECK(s != 0.0);
393  auto wave =
394  apply(s, [](auto i, auto j) { return i / j; });
395  return wave;
396  }
408  friend sampled_wave operator/(const T &s,
409  const sampled_wave &ss) {
410  D_CHECK(s != 0.0);
411  auto sval = 1.0 / s;
412  auto wave = ss * sval;
413  return wave;
414  }
420  T &operator[](uint i) {
421  D_CHECK(i < (uint)values.size());
422  return values[i];
423  }
429  T operator[](uint i) const {
430  D_CHECK((uint)i < values.size());
431  return values[i];
432  }
439  bool operator==(const sampled_wave &cs) const {
440  D_CHECK(!cs.has_nans());
441  for (std::size_t i = 0; i < values.size(); i++) {
442  if (cs.values[i] != values[i])
443  return false;
444  }
445  return true;
446  }
449  bool operator!=(const sampled_wave &cs) const {
450  return !(*this == cs);
451  }
458  T reduce(const std::function<T(T, T)> &fn,
459  T counter_value) const {
460  T s = counter_value;
461  for (auto v : values)
462  s = fn(s, v);
463  return s;
464  }
466  T sum() const {
467  return reduce(
468  [](T counter_value, T element) {
469  return counter_value + element;
470  },
471  0.0);
472  }
474  T product() const {
475  return reduce(
476  [](T counter_value, T element) {
477  return counter_value * element;
478  },
479  1.0);
480  }
482  Real average() const {
483  return sum() / (int)values.size();
484  }
486  uint size() const { return (uint)values.size(); }
487 
496  sampled_wave clamp(T low = 0.0, T high = FLT_MAX) {
497  sampled_wave cs = *this;
498  for (int i = 0; i < values.size(); i++) {
499  cs.values[i] = dclamp<T>(values[i], low, high);
500  }
501  D_CHECK(!cs.has_nans());
502  return cs;
503  }
511  sampled_wave interpolate(Real low = 0.0,
512  Real high = FLT_MAX) {
513  std::vector<T> csvec;
514  csvec.resize(values.size());
515  T start = min();
516  T end = max();
517  for (int i = 0; i < values.size(); i++) {
518  csvec[i] =
519  interp<T>(values[i], start, end, low, high);
520  }
521  sampled_wave cs = sampled_wave(csvec);
522  D_CHECK(!cs.has_nans());
523  return cs;
524  }
525 };
526 
528 template <typename T>
529 inline std::ostream &operator<<(std::ostream &out,
530  const sampled_wave<T> &ss) {
531  std::stringstream s;
532  for (auto r : ss.values) {
533  s << "," << std::to_string(r);
534  }
535  auto s_str = s.str();
536  out << s_str << std::endl;
537  return out;
538 }
539 }
ptracey::sampled_wave::average
Real average() const
find the average value of this wave
Definition: wave.hpp:482
ptracey::sampled_wave::operator*=
sampled_wave & operator*=(const T &s) const
Definition: wave.hpp:318
ptracey::sampled_wave::values
std::vector< T > values
holds observed power values of the wave
Definition: wave.hpp:17
ptracey::sampled_wave::operator+
friend sampled_wave operator+(const T &s, const sampled_wave &ss)
Definition: wave.hpp:222
ptracey::sampled_wave::apply
sampled_wave apply(T value, const std::function< T(T, T)> &fn) const
Definition: wave.hpp:140
ptracey::sampled_wave::operator-
friend sampled_wave operator-(const T &s, const sampled_wave &ss)
subtract every element of given sampled_wave from the value
Definition: wave.hpp:281
ptracey::sampled_wave
a wave sample representing a continuous wave in discreet form
Definition: wave.hpp:12
ptracey::sampled_wave::sum
T sum() const
reduce sampled wave by summation
Definition: wave.hpp:466
ptracey::sampled_wave::operator/
sampled_wave operator/(const T &s) const
divide power value from this wave
Definition: wave.hpp:391
ptracey::sampled_wave::is_black
bool is_black() const
check if sampled power values contain only 0 value.
Definition: wave.hpp:85
ptracey::sampled_wave::sampled_wave
sampled_wave(T val, unsigned int size)
a constant value constructor
Definition: wave.hpp:29
ptracey::sampled_wave::reduce
T reduce(const std::function< T(T, T)> &fn, T counter_value) const
reduce power values of this wave to a single value using given function
Definition: wave.hpp:458
ptracey::sampled_wave::operator/=
sampled_wave & operator/=(const T &s) const
Definition: wave.hpp:369
ptracey::sampled_wave::operator+
sampled_wave operator+(const sampled_wave &s) const
add two same sized sampled waves
Definition: wave.hpp:205
ptracey::sampled_wave::apply
sampled_wave apply(const sampled_wave &s, const std::function< T(T, T)> &fn) const
apply a function to same sized wave samples
Definition: wave.hpp:159
ptracey::sampled_wave::operator*
friend sampled_wave operator*(const T &s, const sampled_wave &ss)
Definition: wave.hpp:344
ptracey::sampled_wave::operator-
sampled_wave operator-(const T &s) const
subtract power value from this wave
Definition: wave.hpp:267
ptracey::sampled_wave::max
T max() const
gives the maximum value among sampled points
Definition: wave.hpp:50
ptracey::sampled_wave::size
uint size() const
find the number of samples inside this wave
Definition: wave.hpp:486
ptracey::sampled_wave::operator*
sampled_wave operator*(const T &s) const
multiply given power value to all of the elements of the sampled wave.
Definition: wave.hpp:336
ptracey::sampled_wave::apply
sampled_wave apply(unsigned int index, T value, const std::function< T(T, T)> &fn) const
Definition: wave.hpp:117
ptracey::sampled_wave::operator+=
sampled_wave & operator+=(const T &s) const
Definition: wave.hpp:197
ptracey::sampled_wave::operator=
sampled_wave & operator=(const sampled_wave &s)
assign a sample wave to this wave if it does not contain nan values
Definition: wave.hpp:96
ptracey::sampled_wave::has_nans
bool has_nans() const
check if sampled power values contain nan value.
Definition: wave.hpp:63
ptracey::sampled_wave::operator[]
T & operator[](uint i)
access to power value at given index. Mostly used for setting a new value for the given index;
Definition: wave.hpp:420
ptracey::sampled_wave::operator==
bool operator==(const sampled_wave &cs) const
check if given sampled wave has same power with this one.
Definition: wave.hpp:439
ptracey::sampled_wave::clamp
sampled_wave clamp(T low=0.0, T high=FLT_MAX)
clamp power values of this wave to given range We also check if the resulting wave has nan values.
Definition: wave.hpp:496
ptracey::sampled_wave::operator+=
sampled_wave & operator+=(const sampled_wave &s) const
Definition: wave.hpp:184
ptracey::sampled_wave::operator+
sampled_wave operator+(const T &s) const
add given power value to all of the elements of the sampled wave.
Definition: wave.hpp:214
ptracey::sampled_wave::operator*=
sampled_wave & operator*=(const sampled_wave &s) const
Definition: wave.hpp:304
ptracey::sampled_wave::operator-
sampled_wave operator-(const sampled_wave &s) const
subtract two same sized sampled waves
Definition: wave.hpp:256
ptracey::sampled_wave::product
T product() const
reduce sampled wave by multiplication
Definition: wave.hpp:474
ptracey::sampled_wave::operator/
friend sampled_wave operator/(const T &s, const sampled_wave &ss)
divide power value from this wave
Definition: wave.hpp:408
ptracey::sampled_wave::operator-=
sampled_wave & operator-=(const sampled_wave &s) const
Definition: wave.hpp:234
ptracey::sampled_wave::operator[]
T operator[](uint i) const
access to power value at given index. Mostly used for reading the value of the given index;
Definition: wave.hpp:429
ptracey::sampled_wave::operator*
sampled_wave operator*(const sampled_wave &s) const
multiply two same sized sampled waves
Definition: wave.hpp:327
ptracey::sampled_wave::operator-=
sampled_wave & operator-=(const T &s) const
Definition: wave.hpp:248
ptracey::sampled_wave::sampled_wave
sampled_wave(const std::vector< T > &vals)
directly construct from given values.
Definition: wave.hpp:44
ptracey::sampled_wave::min
T min() const
gives the minimum value among sampled points
Definition: wave.hpp:57
ptracey::sampled_wave::operator!=
bool operator!=(const sampled_wave &cs) const
check if given sampled_wave is not equal to this or not
Definition: wave.hpp:449
ptracey::sampled_wave::operator/
sampled_wave operator/(const sampled_wave &s) const
divide two same sized sampled waves
Definition: wave.hpp:379
ptracey::sampled_wave::operator/=
sampled_wave & operator/=(const sampled_wave &s)
Definition: wave.hpp:355
ptracey::sampled_wave::has_zeros
bool has_zeros() const
check if sampled power values contain 0 value.
Definition: wave.hpp:74