use strafe_type::{pos64, r64, Checked, LogProbability64, Positive64, Probability64, Real64};
use crate::{
distribution::multinom::{d::dmultinom, r::rmultinom},
traits::{Distribution, RNG},
};
mod d;
mod r;
pub struct Multinomial {
probability: Vec<Checked<Positive64>>,
}
impl Distribution for Multinomial {
type X = Vec<Checked<Real64>>;
fn density(&self, x: Self::X) -> Checked<Real64> {
dmultinom(&x, &self.probability, false)
}
fn log_density(&self, x: Self::X) -> Checked<Real64> {
dmultinom(&x, &self.probability, true)
}
fn probability(&self, _q: Checked<Real64>, _lower_tail: bool) -> Checked<Probability64> {
unimplemented!()
}
fn log_probability(&self, _q: Checked<Real64>, _lower_tail: bool) -> Checked<LogProbability64> {
unimplemented!()
}
fn quantile(&self, _p: Checked<Probability64>, _lower_tail: bool) -> Checked<Real64> {
unimplemented!()
}
fn log_quantile(&self, _p: Checked<LogProbability64>, _lower_tail: bool) -> Checked<Real64> {
unimplemented!()
}
fn random_sample<R>(&self, rng: &mut R) -> Self::X
where
R: RNG,
{
let k = self.probability.len();
let mut ret = vec![r64!(0.0); k];
rmultinom(1, &self.probability, k, &mut ret, rng);
ret
}
}
pub struct MultinomialBuilder {
size: Option<usize>,
probability: Option<Vec<Checked<Positive64>>>,
}
impl MultinomialBuilder {
pub fn new() -> Self {
Self {
size: None,
probability: None,
}
}
pub fn set_size(&mut self, size: usize) {
self.size = Some(size);
}
pub fn set_probability(&mut self, probability: Vec<Checked<Positive64>>) {
self.probability = Some(probability);
}
pub fn build(self) -> Multinomial {
let probability = if let Some(size) = self.size {
vec![pos64!(1.0 / size as f64); size]
} else {
self.probability.unwrap_or_default()
};
Multinomial { probability }
}
}
#[cfg(test)]
mod tests;
#[cfg(all(test, feature = "enable_proptest"))]
mod proptests;
#[cfg(all(test, feature = "enable_covtest"))]
mod covtests;