statrs/distribution/
dirac.rs1use crate::distribution::{Continuous, ContinuousCDF};
2use crate::statistics::*;
3use crate::{Result, StatsError};
4use rand::Rng;
5
6#[derive(Debug, Copy, Clone, PartialEq)]
19pub struct Dirac(f64);
20
21impl Dirac {
22 pub fn new(v: f64) -> Result<Self> {
40 if v.is_nan() {
41 Err(StatsError::BadParams)
42 } else {
43 Ok(Dirac(v))
44 }
45 }
46}
47
48impl ::rand::distributions::Distribution<f64> for Dirac {
49 fn sample<R: Rng + ?Sized>(&self, _: &mut R) -> f64 {
50 self.0
51 }
52}
53
54impl ContinuousCDF<f64, f64> for Dirac {
55 fn cdf(&self, x: f64) -> f64 {
61 if x < self.0 {
62 0.0
63 } else {
64 1.0
65 }
66 }
67
68 fn sf(&self, x: f64) -> f64 {
74 if x < self.0 {
75 1.0
76 } else {
77 0.0
78 }
79 }
80}
81
82impl Min<f64> for Dirac {
83 fn min(&self) -> f64 {
92 self.0
93 }
94}
95
96impl Max<f64> for Dirac {
97 fn max(&self) -> f64 {
106 self.0
107 }
108}
109
110impl Distribution<f64> for Dirac {
111 fn mean(&self) -> Option<f64> {
118 Some(self.0)
119 }
120 fn variance(&self) -> Option<f64> {
130 Some(0.0)
131 }
132 fn entropy(&self) -> Option<f64> {
142 Some(0.0)
143 }
144 fn skewness(&self) -> Option<f64> {
152 Some(0.0)
153 }
154}
155
156impl Median<f64> for Dirac {
157 fn median(&self) -> f64 {
167 self.0
168 }
169}
170
171impl Mode<Option<f64>> for Dirac {
172 fn mode(&self) -> Option<f64> {
182 Some(self.0)
183 }
184}
185
186#[rustfmt::skip]
187#[cfg(all(test, feature = "nightly"))]
188mod tests {
189 use crate::statistics::*;
190 use crate::distribution::{ContinuousCDF, Continuous, Dirac};
191 use crate::consts::ACC;
192
193 fn try_create(v: f64) -> Dirac {
194 let d = Dirac::new(v);
195 assert!(d.is_ok());
196 d.unwrap()
197 }
198
199 fn create_case(v: f64) {
200 let d = try_create(v);
201 assert_eq!(v, d.mean().unwrap());
202 }
203
204 fn bad_create_case(v: f64) {
205 let d = Dirac::new(v);
206 assert!(d.is_err());
207 }
208
209 fn test_case<F>(v: f64, expected: f64, eval: F)
210 where F: Fn(Dirac) -> f64
211 {
212 let x = eval(try_create(v));
213 assert_eq!(expected, x);
214 }
215
216 #[test]
217 fn test_create() {
218 create_case(10.0);
219 create_case(-5.0);
220 create_case(10.0);
221 create_case(100.0);
222 create_case(f64::INFINITY);
223 }
224
225 #[test]
226 fn test_bad_create() {
227 bad_create_case(f64::NAN);
228 }
229
230 #[test]
231 fn test_variance() {
232 let variance = |x: Dirac| x.variance().unwrap();
233 test_case(0.0, 0.0, variance);
234 test_case(-5.0, 0.0, variance);
235 test_case(f64::INFINITY, 0.0, variance);
236 }
237
238 #[test]
239 fn test_entropy() {
240 let entropy = |x: Dirac| x.entropy().unwrap();
241 test_case(0.0, 0.0, entropy);
242 test_case(f64::INFINITY, 0.0, entropy);
243 }
244
245 #[test]
246 fn test_skewness() {
247 let skewness = |x: Dirac| x.skewness().unwrap();
248 test_case(0.0, 0.0, skewness);
249 test_case(4.0, 0.0, skewness);
250 test_case(0.3, 0.0, skewness);
251 test_case(f64::INFINITY, 0.0, skewness);
252 }
253
254 #[test]
255 fn test_mode() {
256 let mode = |x: Dirac| x.mode().unwrap();
257 test_case(0.0, 0.0, mode);
258 test_case(3.0, 3.0, mode);
259 test_case(f64::INFINITY, f64::INFINITY, mode);
260 }
261
262 #[test]
263 fn test_median() {
264 let median = |x: Dirac| x.median();
265 test_case(0.0, 0.0, median);
266 test_case(3.0, 3.0, median);
267 test_case(f64::INFINITY, f64::INFINITY, median);
268 }
269
270 #[test]
271 fn test_min_max() {
272 let min = |x: Dirac| x.min();
273 let max = |x: Dirac| x.max();
274 test_case(0.0, 0.0, min);
275 test_case(3.0, 3.0, min);
276 test_case(f64::INFINITY, f64::INFINITY, min);
277
278 test_case(0.0, 0.0, max);
279 test_case(3.0, 3.0, max);
280 test_case(f64::NEG_INFINITY, f64::NEG_INFINITY, max);
281 }
282
283 #[test]
284 fn test_cdf() {
285 let cdf = |arg: f64| move |x: Dirac| x.cdf(arg);
286 test_case(0.0, 1.0, cdf(0.0));
287 test_case(3.0, 1.0, cdf(3.0));
288 test_case(f64::INFINITY, 0.0, cdf(1.0));
289 test_case(f64::INFINITY, 1.0, cdf(f64::INFINITY));
290 }
291
292 #[test]
293 fn test_sf() {
294 let sf = |arg: f64| move |x: Dirac| x.sf(arg);
295 test_case(0.0, 0.0, sf(0.0));
296 test_case(3.0, 0.0, sf(3.0));
297 test_case(f64::INFINITY, 1.0, sf(1.0));
298 test_case(f64::INFINITY, 0.0, sf(f64::INFINITY));
299 }
300}