pub trait Family {
type Eta;
type Theta;
type ScoreEta;
fn theta(&self, eta: Self::Eta) -> Self::Theta;
fn nll(&self, y: f64, theta: Self::Theta) -> f64;
fn nll_eta(&self, y: f64, eta: Self::Eta) -> f64 {
self.nll(y, self.theta(eta))
}
fn nll_and_score_eta(&self, y: f64, eta: Self::Eta) -> (f64, Self::ScoreEta);
}
pub trait ParameterParts<const K: usize>: Sized {
fn from_array(values: [f64; K]) -> Self;
fn part(&self, index: usize) -> f64;
}
impl ParameterParts<1> for f64 {
#[inline(always)]
fn from_array(values: [f64; 1]) -> Self {
values[0]
}
#[inline(always)]
fn part(&self, index: usize) -> f64 {
match index {
0 => *self,
_ => unreachable!("one-parameter parts only have index 0"),
}
}
}
impl ParameterParts<2> for (f64, f64) {
#[inline(always)]
fn from_array(values: [f64; 2]) -> Self {
(values[0], values[1])
}
#[inline(always)]
fn part(&self, index: usize) -> f64 {
match index {
0 => self.0,
1 => self.1,
_ => unreachable!("two-parameter parts only have indices 0 and 1"),
}
}
}
impl ParameterParts<3> for (f64, f64, f64) {
#[inline(always)]
fn from_array(values: [f64; 3]) -> Self {
(values[0], values[1], values[2])
}
#[inline(always)]
fn part(&self, index: usize) -> f64 {
match index {
0 => self.0,
1 => self.1,
2 => self.2,
_ => unreachable!("three-parameter parts only have indices 0, 1 and 2"),
}
}
}
impl ParameterParts<4> for (f64, f64, f64, f64) {
#[inline(always)]
fn from_array(values: [f64; 4]) -> Self {
(values[0], values[1], values[2], values[3])
}
#[inline(always)]
fn part(&self, index: usize) -> f64 {
match index {
0 => self.0,
1 => self.1,
2 => self.2,
3 => self.3,
_ => unreachable!("four-parameter parts only have indices 0, 1, 2 and 3"),
}
}
}
pub trait ParameterizedFamily<const K: usize>: Family
where
Self::Eta: ParameterParts<K>,
Self::ScoreEta: ParameterParts<K>,
{
type Params;
type Links;
}
pub trait HasCdf: Family {
fn cdf(&self, y: f64, theta: Self::Theta) -> f64;
}
pub trait HasQuantile: Family {
fn quantile(&self, p: f64, theta: Self::Theta) -> f64;
}
pub trait CanSimulate<Rng>: Family {
fn sample(&self, rng: &mut Rng, theta: Self::Theta) -> f64;
}