1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use crate::{
consts::{PI, PI_16, THREE_HALVES},
prelude::*,
};
use rand::Rng;
use spaces::real::Interval;
use std::{f64::INFINITY, fmt};
locscale_params! {
Params {
mu<f64>,
c<f64>
}
}
new_dist!(Levy<Params>);
macro_rules! get_params {
($self:ident) => { ($self.0.mu.0, $self.0.c.0) }
}
impl Levy {
pub fn new(mu: f64, c: f64) -> Result<Levy, failure::Error> {
Params::new(mu, c).map(|p| Levy(p))
}
pub fn new_unchecked(mu: f64, c: f64) -> Levy {
Levy(Params::new_unchecked(mu, c))
}
}
impl Distribution for Levy {
type Support = Interval;
type Params = Params;
fn support(&self) -> Interval {
Interval::left_bounded(self.0.mu.0)
}
fn params(&self) -> Params { self.0 }
fn cdf(&self, x: &f64) -> Probability {
use special_fun::FloatSpecial;
let (mu, c) = get_params!(self);
Probability::new_unchecked((c / 2.0 / (x - mu)).erfc())
}
fn sample<R: Rng + ?Sized>(&self, _: &mut R) -> f64 {
unimplemented!()
}
}
impl ContinuousDistribution for Levy {
fn pdf(&self, x: &f64) -> f64 {
let (mu, c) = get_params!(self);
let diff = x - mu;
let c_over_2 = c / 2.0;
(c_over_2 / PI).sqrt() * (-c_over_2 / diff).exp() / diff.powf(THREE_HALVES)
}
}
impl UnivariateMoments for Levy {
fn mean(&self) -> f64 { INFINITY }
fn variance(&self) -> f64 { INFINITY }
fn skewness(&self) -> f64 { undefined!() }
fn kurtosis(&self) -> f64 { undefined!() }
}
impl Quantiles for Levy {
fn quantile(&self, _: Probability) -> f64 { unimplemented!() }
fn median(&self) -> f64 {
if self.0.mu.0.abs() < 1e-7 {
unimplemented!("Need an implementation of the inverse ERFC function.")
} else {
undefined!("median of the Levy distribution is defined only for mu = 0.")
}
}
}
impl Modes for Levy {
fn modes(&self) -> Vec<f64> {
if self.0.mu.0.abs() < 1e-7 {
vec![self.0.c.0 / 3.0]
} else {
undefined!("mode of the Levy distribution is defined only for mu = 0.")
}
}
}
impl Entropy for Levy {
fn entropy(&self) -> f64 {
use special_fun::FloatSpecial;
let c = self.0.c.0;
let gamma = -(1.0f64.digamma());
(1.0 + 3.0 * gamma + (PI_16 * c * c).ln()) / 2.0
}
}
impl fmt::Display for Levy {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let (mu, c) = get_params!(self);
write!(f, "Levy({}, {})", mu, c)
}
}