FastBernoulli

Struct FastBernoulli 

Source
pub struct FastBernoulli { /* private fields */ }
Expand description

Fast Bernoulli sampling: each event has equal probability of being sampled.

See the crate-level documentation for more general information.

§Example

use fast_bernoulli::FastBernoulli;
use rand::Rng;

// Get the thread-local random number generator.
let mut rng = rand::thread_rng();

// Create a `FastBernoulli` instance that samples events with probability 1/20.
let mut bernoulli = FastBernoulli::new(0.05, &mut rng);

// Each time your event occurs, perform a Bernoulli trail to determine whether
// you should sample the event or not.
let on_my_event = || {
    if bernoulli.trial(&mut rng) {
        // Record the sample...
    }
};

Implementations§

Source§

impl FastBernoulli

Source

pub fn new<R>(probability: f64, rng: &mut R) -> Self
where R: Rng + ?Sized,

Construct a new FastBernoulli instance that samples events with the given probability.

§Panics

The probability must be within the range 0.0 <= probability <= 1.0 and this method will panic if that is not the case.

§Example
use rand::Rng;
use fast_bernoulli::FastBernoulli;

let mut rng = rand::thread_rng();
let sample_one_in_a_hundred = FastBernoulli::new(0.01, &mut rng);
Source

pub fn trial<R>(&mut self, rng: &mut R) -> bool
where R: Rng + ?Sized,

Perform a Bernoulli trial: returns true with the configured probability.

Call this each time an event occurs to determine whether to sample the event.

The lower the configured probability, the less overhead calling this function has.

§Example
use rand::Rng;
use fast_bernoulli::FastBernoulli;

let mut rng = rand::thread_rng();
let mut bernoulli = FastBernoulli::new(0.1, &mut rng);

// Each time an event occurs, call `trial`...
if bernoulli.trial(&mut rng) {
    // ...and if it returns true, record a sample of this event.
}
Source

pub fn multi_trial<R>(&mut self, n: u32, rng: &mut R) -> bool
where R: Rng + ?Sized,

Perform n Bernoulli trials at once.

This is semantically equivalent to calling the trial() method n times and returning true if any of those calls returned true, but runs in O(1) time instead of O(n) time.

What is this good for? In some applications, some events are “bigger” than others. For example, large memory allocations are more significant than small memory allocations. Perhaps we’d like to imagine that we’re drawing allocations from a stream of bytes, and performing a separate Bernoulli trial on every byte from the stream. We can accomplish this by calling multi_trial(s) for the number of bytes s, and sampling the event if that call returns true.

Of course, this style of sampling needs to be paired with analysis and presentation that makes the “size” of the event apparent, lest trials with large values for n appear to be indistinguishable from those with small values for n, despite being potentially much more likely to be sampled.

§Example
use rand::Rng;
use fast_bernoulli::FastBernoulli;

let mut rng = rand::thread_rng();
let mut byte_sampler = FastBernoulli::new(0.05, &mut rng);

// When we observe a `malloc` of ten bytes event...
if byte_sampler.multi_trial(10, &mut rng) {
    // ... if `multi_trial` returns `true` then we sample it.
    record_malloc_sample(10);
}

// And when we observe a `malloc` of 1024 bytes event...
if byte_sampler.multi_trial(1024, &mut rng) {
    // ... if `multi_trial` returns `true` then we sample this larger
    // allocation.
    record_malloc_sample(1024);
}
Source

pub fn probability(&self) -> f64

Get the probability with which events are sampled.

This is a number between 0.0 and 1.0.

This is the same value that was passed to FastBernoulli::new when constructing this instance.

Source

pub fn skip_count(&self) -> u32

How many events will be skipped until the next event is sampled?

When self.probability() == 0.0 this method’s return value is inaccurate, and logically should be infinity.

§Example
use rand::Rng;
use fast_bernoulli::FastBernoulli;

let mut rng = rand::thread_rng();
let mut bernoulli = FastBernoulli::new(0.1, &mut rng);

// Get the number of upcoming events that will not be sampled.
let skip_count = bernoulli.skip_count();

// That many events will not be sampled.
for _ in 0..skip_count {
    assert!(!bernoulli.trial(&mut rng));
}

// The next event will be sampled.
assert!(bernoulli.trial(&mut rng));

Trait Implementations§

Source§

impl Clone for FastBernoulli

Source§

fn clone(&self) -> FastBernoulli

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for FastBernoulli

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Copy for FastBernoulli

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V