pub struct Pdf { /* private fields */ }Expand description
Represents a Probability Distribution Function.
PDFs are used to indicate to schedule generators where samples should be taken.
Implementations§
Source§impl Pdf
impl Pdf
Sourcepub fn from_integral(
integral: impl Fn(f64) -> f64 + 'static + Send + Sync,
len: usize,
) -> Pdf
pub fn from_integral( integral: impl Fn(f64) -> f64 + 'static + Send + Sync, len: usize, ) -> Pdf
Create a PDF from a continuous representation.
Expects the integral of the PDF being represented. This is often called the Cumulative Distribution Function or CDF. The function will receive inputs from 0..=len. The len parameter is the length of the PDF in number of samples.
The CDF is expected to be monotonically increasing, and integral(len as f64) - integral(0.) must be one. These are the necessary conditions for a function to be a valid CDF.
It is not assumed that integral(0.) = 0..
§Example
// This represents an unweighted PDF because the integral of a constant function is linear.
// You can use the `unweighted` preset instead if you would like
let pdf = Pdf::from_integral(|v| v / 256., 256);§Panics
This function will assert that
integral(len as f64) - integral(0.) ≈ 1.with some margin for floating point error allowed;- the CDF is monotonically increasing for particular intervals; and
lenis non-zero.
Sourcepub fn from_discrete(discrete: Vec<f64>) -> Pdf
pub fn from_discrete(discrete: Vec<f64>) -> Pdf
Create a PDF from a discrete representation.
Expects a list of probabilities, one for each sample, that are all non-negative and sum to one.
§Example
let pdf = Pdf::from_discrete(vec![0.125, 0.5, 0.375]);§Panics
This function will assert that
- the sum of all of the probabilities is one, with some margin for floating point error allowed;
- all probabilities are non-negative; and
- the length of the PDF is non-zero.
Sourcepub fn get_distribution(&self) -> &[f64]
pub fn get_distribution(&self) -> &[f64]
Calculate the discrete representation of the PDF.
This method is memoized.
§Example
assert!(
unweighted(3)
.get_distribution()
.iter()
.zip([1. / 3., 1. / 3., 1. / 3.])
.all(|(l, r)| (l - r).abs() < 0.00001),
);Sourcepub fn get_integral(&self) -> &[f64]
pub fn get_integral(&self) -> &[f64]
Calculate the integral of the PDF for whole number values
The output has length self.len() + 1. The value at index 0 is guaranteed to be zero and the output at index self.len() is guaranteed to be one with a small margin for floating point error.
This method is memoized.
§Example
assert!(
Pdf::from_discrete(vec![0.3, 0.6, 0.1])
.get_integral()
.iter()
.zip([0., 0.3, 0.9, 1.])
.all(|(l, r)| (l - r).abs() < 0.00001),
);Sourcepub fn slice(&self, range: Range<usize>) -> Pdf
pub fn slice(&self, range: Range<usize>) -> Pdf
Slice a PDF to fit a certain range
The PDF will be automatically rescaled to still sum to one.
§Example
assert!(
exponential(256, 4.)
.slice(0..128)
.get_distribution()
.iter()
.zip(exponential(128, 2.)
.get_distribution()
)
.all(|(l, r)| (l - r).abs() < 0.00001),
);Sourcepub fn probabilities(&self, count: usize) -> &Probabilities
pub fn probabilities(&self, count: usize) -> &Probabilities
Calculate the probabilities of selecting each sample position under random sampling given the number of samples to select.
§Example
// With unweighted sampling and selecting 128 out of 256,
// each sample position has a 1/2 chance of being selected.
assert!(
unweighted(256)
.probabilities(128)
.iter()
.all(|v| (*v - 0.5).abs() < 0.000001)
);Note that this only gives a very good approximation because the true value is (as of now) computationally infeasible to find.
This method is memoized.
Sourcepub fn sample_pdf<R: Rng + ?Sized>(&self, rng: &mut R) -> usize
pub fn sample_pdf<R: Rng + ?Sized>(&self, rng: &mut R) -> usize
Sample the PDF using the given Rng
Returns the zero-based index of the position that was sampled.
Sourcepub fn continuous_integral<'a>(&'a self) -> Rc<dyn Fn(f64) -> f64 + 'a>
pub fn continuous_integral<'a>(&'a self) -> Rc<dyn Fn(f64) -> f64 + 'a>
Return a continuous representation of the integral of the PDF. Applying 0. to the returned function will return 0..
This function is implemented for discretely represented PDFs by interpolating self.get_integral() using Catmull-Rom to give a once-differentiable interpolation.
§Example
let pdf = qsin(256, QSinBias::Low, PI);
let integral = pdf.continuous_integral();
assert_eq!(integral(0.), 0.);
assert_eq!(integral(256.), 1.);
let c = FRAC_PI_2 - 1.;
assert_eq!(integral(128.), (FRAC_PI_4 + FRAC_PI_4.cos()) / c - 1. / c);§Panics
The function returned will panic if it is called with values outside of the range of the PDF.