20 #if !defined(__MITSUBA_CORE_PMF_H_)
21 #define __MITSUBA_CORE_PMF_H_
23 #include <mitsuba/mitsuba.h>
46 m_cdf.push_back(0.0f);
52 m_cdf.reserve(nEntries+1);
57 m_cdf.push_back(m_cdf[m_cdf.size()-1] + pdfValue);
61 inline size_t size()
const {
62 return m_cdf.size()-1;
67 return m_cdf[entry+1] - m_cdf[entry];
90 return m_normalization;
103 m_sum = m_cdf[m_cdf.size()-1];
105 m_normalization = 1.0f / m_sum;
106 for (
size_t i=1; i<m_cdf.size(); ++i)
107 m_cdf[i] *= m_normalization;
108 m_cdf[m_cdf.size()-1] = 1.0f;
111 m_normalization = 0.0f;
125 std::vector<Float>::const_iterator entry =
126 std::lower_bound(m_cdf.begin(), m_cdf.end(), sampleValue);
127 size_t index = std::min(m_cdf.size()-2,
128 (size_t) std::max((ptrdiff_t) 0, entry - m_cdf.begin() - 1));
132 while (
operator[](index) == 0 && index < m_cdf.size()-1)
149 size_t index = sample(sampleValue);
150 pdf = operator[](index);
165 size_t index = sample(sampleValue);
166 sampleValue = (sampleValue - m_cdf[index])
167 / (m_cdf[index + 1] - m_cdf[index]);
184 size_t index = sample(sampleValue, pdf);
185 sampleValue = (sampleValue - m_cdf[index])
186 / (m_cdf[index + 1] - m_cdf[index]);
195 std::ostringstream oss;
196 oss <<
"DiscreteDistribution[sum=" << m_sum <<
", normalized="
197 << (int) m_normalized <<
", cdf={";
198 for (
size_t i=0; i<m_cdf.size(); ++i) {
200 if (i != m_cdf.size()-1)
207 std::vector<Float> m_cdf;
208 Float m_sum, m_normalization;
239 template <
typename Scalar,
typename QuantizedScalar,
typename Index>
float makeAliasTable(
242 Index *c =
new Index[size],
243 *c_short = c - 1, *c_long = c + size;
247 for (
size_t i=0; i<size; ++i)
250 Scalar normalization = (Scalar) 1 / sum;
251 for (Index i=0; i<size; ++i) {
254 Scalar value = size * normalization * pmf[i];
265 for (Index i=0; i < size-1 && c_long - c < size; ++i) {
266 Index short_index = c[i],
267 long_index = *c_long;
269 tbl[short_index].
index = long_index;
270 tbl[long_index].
prob -= (Scalar) 1 - tbl[short_index].prob;
272 if (tbl[long_index].prob <= 1)
282 template <
typename Scalar,
typename QuantizedScalar,
typename Index> Index
sampleAlias(
284 Index l = std::min((Index) (sample * size), (Index) (size - 1));
285 Scalar prob = (Scalar) tbl[l].prob;
287 sample = sample * size - l;
289 if (prob == 1 || (prob != 0 && sample < prob))
301 template <
typename Scalar,
typename QuantizedScalar,
typename Index> Index
sampleAliasReuse(
303 Index l = std::min((Index) (sample * size), (Index) (size - 1));
304 Scalar prob = (Scalar) tbl[l].prob;
306 sample = sample * size - l;
308 if (prob == 1 || (prob != 0 && sample < prob)) {
312 sample = (sample - prob) / (1 - prob);
Alias sampling data structure (see makeAliasTable() for details)
Definition: pmf.h:214
void append(Float pdfValue)
Append an entry with the specified discrete probability.
Definition: pmf.h:56
Index index
Index of the alias entry.
Definition: pmf.h:218
Index sampleAliasReuse(const AliasTableEntry< QuantizedScalar, Index > *tbl, Index size, Scalar &sample)
Generate a sample in constant time using the alias method.
Definition: pmf.h:301
Index sampleAlias(const AliasTableEntry< QuantizedScalar, Index > *tbl, Index size, Scalar sample)
Generate a sample in constant time using the alias method.
Definition: pmf.h:282
Float getSum() const
Return the original (unnormalized) sum of all PDF entries.
Definition: pmf.h:80
Float normalize()
Normalize the distribution.
Definition: pmf.h:101
void clear()
Clear all entries.
Definition: pmf.h:44
bool isNormalized() const
Have the probability densities been normalized?
Definition: pmf.h:71
Float operator[](size_t entry) const
Access an entry by its index.
Definition: pmf.h:66
size_t sample(Float sampleValue) const
Transform a uniformly distributed sample to the stored distribution
Definition: pmf.h:124
size_t sample(Float sampleValue, Float &pdf) const
Transform a uniformly distributed sample to the stored distribution
Definition: pmf.h:148
#define SAssert(cond)
``Static'' assertion (to be used outside of classes that derive from Object)
Definition: logger.h:79
size_t sampleReuse(Float &sampleValue, Float &pdf) const
Transform a uniformly distributed sample.
Definition: pmf.h:183
Float getNormalization() const
Return the normalization factor (i.e. the inverse of getSum())
Definition: pmf.h:89
size_t sampleReuse(Float &sampleValue) const
Transform a uniformly distributed sample to the stored distribution
Definition: pmf.h:164
QuantizedScalar prob
Probability of sampling the current entry.
Definition: pmf.h:216
void reserve(size_t nEntries)
Reserve memory for a certain number of entries.
Definition: pmf.h:51
std::string toString() const
Turn the underlying distribution into a human-readable string format.
Definition: pmf.h:194
float makeAliasTable(AliasTableEntry< QuantizedScalar, Index > *tbl, Scalar *pmf, Index size)
Create the lookup table needed for Walker's alias sampling method implemented in sampleAlias(). Runs in linear time.
Definition: pmf.h:239
DiscreteDistribution(size_t nEntries=0)
Allocate memory for a distribution with the given number of entries.
Definition: pmf.h:38
size_t size() const
Return the number of entries so far.
Definition: pmf.h:61
Discrete probability distribution.
Definition: pmf.h:35