mathru/statistics/distrib/raisedcosine.rs
1use crate::{algebra::abstr::Real, statistics::distrib::Continuous};
2#[cfg(feature = "serde")]
3use serde::{Deserialize, Serialize};
4use std::clone::Clone;
5
6/// Raised Cosine distribution
7///
8/// Fore more information:
9/// <https://en.wikipedia.org/wiki/Raised_cosine_distribution>
10///
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12#[derive(Clone, Copy, Debug)]
13pub struct RaisedCosine<T> {
14 mu: T,
15 s: T,
16}
17
18impl<T> RaisedCosine<T>
19where
20 T: Real,
21{
22 /// Creates a probability distribution
23 ///
24 /// # Arguments
25 ///
26 /// * `mu`
27 /// * `s` > 0.0
28 ///
29 /// # Panics
30 ///
31 /// if s < 0.0
32 ///
33 /// # Example
34 ///
35 /// ```
36 /// use mathru::statistics::distrib::RaisedCosine;
37 /// use std::f64::consts::PI;
38 ///
39 /// let mu: f64 = PI;
40 /// let s: f64 = 0.5 * PI;
41 /// let distrib: RaisedCosine<f64> = RaisedCosine::new(mu, s);
42 /// ```
43 pub fn new(mu: T, s: T) -> RaisedCosine<T> {
44 if s < T::zero() {
45 panic!();
46 }
47 RaisedCosine { mu, s }
48 }
49}
50
51impl<T> Continuous<T> for RaisedCosine<T>
52where
53 T: Real,
54{
55 /// Probability density function
56 ///
57 /// # Arguments
58 ///
59 /// * `x` Random variable x
60 ///
61 /// # Panics
62 ///
63 ///
64 ///
65 /// # Example
66 ///
67 /// ```
68 /// use mathru::statistics::distrib::{Continuous, RaisedCosine};
69 ///
70 /// let distrib: RaisedCosine<f64> = RaisedCosine::new(-1.2, 1.5);
71 /// let x: f64 = 5.0;
72 /// let p: f64 = distrib.pdf(x);
73 /// ```
74 fn pdf(&self, x: T) -> T {
75 if (self.mu - self.s) <= x && x < (self.mu + self.s) {
76 return (T::one() + (T::pi() * (x - self.mu) / self.s).cos())
77 / (T::from_f64(2.0) * self.s);
78 }
79
80 T::zero()
81 }
82
83 /// Cumulative distribution function
84 ///
85 /// # Arguments
86 ///
87 ///
88 /// # Example
89 ///
90 /// ```
91 /// use mathru::statistics::distrib::{Continuous, RaisedCosine};
92 /// use std::f64::consts::PI;
93 ///
94 /// let distrib: RaisedCosine<f64> = RaisedCosine::new(1.0, PI);
95 /// let x: f64 = PI / 2.0;
96 /// let p: f64 = distrib.cdf(x);
97 /// ```
98 fn cdf(&self, x: T) -> T {
99 if (self.mu - self.s) <= x && x <= (self.mu + self.s) {
100 let k: T = (x - self.mu) / self.s;
101 (T::one() + k + T::one() / T::pi() * (k * T::pi()).sin()) / T::from_f64(2.0)
102 } else if x < (self.mu - self.s) {
103 T::zero()
104 } else {
105 T::one()
106 }
107 }
108
109 /// Quantile function of inverse cdf
110 fn quantile(&self, _p: T) -> T {
111 unimplemented!();
112 }
113
114 /// Expected value
115 ///
116 /// # Example
117 ///
118 /// ```
119 /// use mathru::statistics::distrib::{Continuous, RaisedCosine};
120 ///
121 /// let distrib: RaisedCosine<f64> = RaisedCosine::new(-2.0, 0.5);
122 /// let mean: f64 = distrib.mean();
123 /// ```
124 fn mean(&self) -> T {
125 self.mu
126 }
127
128 /// Variance
129 ///
130 /// # Example
131 ///
132 /// ```
133 /// use mathru::statistics::distrib::{Continuous, RaisedCosine};
134 /// use std::f64::consts::PI;
135 ///
136 /// let distrib: RaisedCosine<f64> = RaisedCosine::new(2.0, PI);
137 /// let var: f64 = distrib.variance();
138 /// ```
139 fn variance(&self) -> T {
140 self.s * self.s * (T::from_f64(1.0 / 3.0) - T::from_f64(2.0) / (T::pi() * T::pi()))
141 }
142
143 fn skewness(&self) -> T {
144 T::zero()
145 }
146
147 /// Median is the value separating the higher half from the lower half of a
148 /// probability distribution.
149 fn median(&self) -> T {
150 self.mu
151 }
152
153 fn entropy(&self) -> T {
154 unimplemented!();
155 }
156}