Nori  23
dpdf.h
1 /*
2  This file is part of Nori, a simple educational ray tracer
3 
4  Copyright (c) 2015 by Wenzel Jakob
5 
6  Nori is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License Version 3
8  as published by the Free Software Foundation.
9 
10  Nori is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #if !defined(__NORI_DISCRETE_PDF_H)
20 #define __NORI_DISCRETE_PDF_H
21 
22 #include <nori/common.h>
23 
24 NORI_NAMESPACE_BEGIN
25 
34 struct DiscretePDF {
35 public:
37  explicit DiscretePDF(size_t nEntries = 0) {
38  reserve(nEntries);
39  clear();
40  }
41 
43  void clear() {
44  m_cdf.clear();
45  m_cdf.push_back(0.0f);
46  m_normalized = false;
47  }
48 
50  void reserve(size_t nEntries) {
51  m_cdf.reserve(nEntries+1);
52  }
53 
55  void append(float pdfValue) {
56  m_cdf.push_back(m_cdf[m_cdf.size()-1] + pdfValue);
57  }
58 
60  size_t size() const {
61  return m_cdf.size()-1;
62  }
63 
65  float operator[](size_t entry) const {
66  return m_cdf[entry+1] - m_cdf[entry];
67  }
68 
70  bool isNormalized() const {
71  return m_normalized;
72  }
73 
79  float getSum() const {
80  return m_sum;
81  }
82 
88  float getNormalization() const {
89  return m_normalization;
90  }
91 
97  float normalize() {
98  m_sum = m_cdf[m_cdf.size()-1];
99  if (m_sum > 0) {
100  m_normalization = 1.0f / m_sum;
101  for (size_t i=1; i<m_cdf.size(); ++i)
102  m_cdf[i] *= m_normalization;
103  m_cdf[m_cdf.size()-1] = 1.0f;
104  m_normalized = true;
105  } else {
106  m_normalization = 0.0f;
107  }
108  return m_sum;
109  }
110 
119  size_t sample(float sampleValue) const {
120  std::vector<float>::const_iterator entry =
121  std::lower_bound(m_cdf.begin(), m_cdf.end(), sampleValue);
122  size_t index = (size_t) std::max((ptrdiff_t) 0, entry - m_cdf.begin() - 1);
123  return std::min(index, m_cdf.size()-2);
124  }
125 
136  size_t sample(float sampleValue, float &pdf) const {
137  size_t index = sample(sampleValue);
138  pdf = operator[](index);
139  return index;
140  }
141 
152  size_t sampleReuse(float &sampleValue) const {
153  size_t index = sample(sampleValue);
154  sampleValue = (sampleValue - m_cdf[index])
155  / (m_cdf[index + 1] - m_cdf[index]);
156  return index;
157  }
158 
171  size_t sampleReuse(float &sampleValue, float &pdf) const {
172  size_t index = sample(sampleValue, pdf);
173  sampleValue = (sampleValue - m_cdf[index])
174  / (m_cdf[index + 1] - m_cdf[index]);
175  return index;
176  }
177 
182  std::string toString() const {
183  std::string result = tfm::format("DiscretePDF[sum=%f, "
184  "normalized=%f, pdf = {", m_sum, m_normalized);
185 
186  for (size_t i=0; i<m_cdf.size(); ++i) {
187  result += std::to_string(operator[](i));
188  if (i != m_cdf.size()-1)
189  result += ", ";
190  }
191  return result + "}]";
192  }
193 private:
194  std::vector<float> m_cdf;
195  float m_sum, m_normalization;
196  bool m_normalized;
197 };
198 
199 NORI_NAMESPACE_END
200 
201 #endif /* __NORI_DISCRETE_PDF_H */
Discrete probability distribution.
Definition: dpdf.h:34
float getSum() const
Return the original (unnormalized) sum of all PDF entries.
Definition: dpdf.h:79
float getNormalization() const
Return the normalization factor (i.e. the inverse of getSum())
Definition: dpdf.h:88
size_t sampleReuse(float &sampleValue) const
Transform a uniformly distributed sample to the stored distribution
Definition: dpdf.h:152
size_t size() const
Return the number of entries so far.
Definition: dpdf.h:60
void clear()
Clear all entries.
Definition: dpdf.h:43
void append(float pdfValue)
Append an entry with the specified discrete probability.
Definition: dpdf.h:55
std::string toString() const
Turn the underlying distribution into a human-readable string format.
Definition: dpdf.h:182
size_t sampleReuse(float &sampleValue, float &pdf) const
Transform a uniformly distributed sample.
Definition: dpdf.h:171
void reserve(size_t nEntries)
Reserve memory for a certain number of entries.
Definition: dpdf.h:50
bool isNormalized() const
Have the probability densities been normalized?
Definition: dpdf.h:70
float normalize()
Normalize the distribution.
Definition: dpdf.h:97
size_t sample(float sampleValue) const
Transform a uniformly distributed sample to the stored distribution
Definition: dpdf.h:119
size_t sample(float sampleValue, float &pdf) const
Transform a uniformly distributed sample to the stored distribution
Definition: dpdf.h:136
float operator[](size_t entry) const
Access an entry by its index.
Definition: dpdf.h:65
DiscretePDF(size_t nEntries=0)
Allocate memory for a distribution with the given number of entries.
Definition: dpdf.h:37