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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
use crate::special::Probability;
use crate::Functions;
/// A module containing functions to work with the Hypergeometric distribution.
pub struct Hypergeometric;
impl Hypergeometric {
/// Calculates the Probability Mass Function for the Hypergeometric Distribution.
///
/// The Hypergeometric distribution models the probability of drawing a certain number of successes
/// in a sample without replacement from a finite population containing both successes and failures.
///
/// # Parameters
///
/// - `population`: The total population size.
/// - `success`: The number of successful items in the population.
/// - `draws`: The number of items drawn in the sample.
/// - `observed`: The number of successful items observed in the drawn sample.
///
/// # Returns
///
/// The value of the PMF at the given parameters.
///
/// # Example
///
/// ```
/// use numerilib::stats::distr::Hypergeometric;
///
/// let population = 100_f64;
/// let success = 20_f64;
/// let draws = 10_f64;
/// let observed = 4_f64;
///
/// let pmf = Hypergeometric::pmf(population, success, draws, observed);
///
/// println!("PMF: {}", pmf);
/// ```
/// <hr/>
pub fn pmf(population: f64, success: f64, draws: f64, observed: f64) -> f64 {
(Probability::combination(success, observed)
* Probability::combination(population - success, draws - observed))
/ Probability::combination(population, draws)
}
/// Calculates the Lower Cumulative Distribution Function (CDF) of the Hypergeometric Distribution.
///
/// The Lower CDF gives the probability that the number of successful items in the drawn sample is less than
/// or equal to a given number.
///
/// # Parameters
///
/// - `population`: The total population size.
/// - `success`: The number of successful items in the population.
/// - `draws`: The number of items drawn in the sample.
/// - `observed`: The number of successful items observed in the drawn sample.
///
/// # Returns
///
/// The value of the Lower CDF at the given parameters.
///
/// # Example
///
/// ```
/// use numerilib::stats::distr::Hypergeometric;
///
/// let population = 100_f64;
/// let success = 20_f64;
/// let draws = 10_f64;
/// let observed = 4_f64;
///
/// let cdf = Hypergeometric::lcdf(population, success, draws, observed);
///
/// println!("CDF: {}", cdf);
/// ```
/// <hr/>
pub fn lcdf(population: f64, success: f64, draws: f64, observed: f64) -> f64 {
let func = |x: f64| Self::pmf(population, success, draws, x);
Functions::summation(0_f64, observed, func)
}
/// Calculates the Upper Cumulative Distribution Function (CDF) of the Hypergeometric Distribution.
///
/// The Upper CDF gives the probability that the number of successful items in the drawn sample is less than
/// or equal to a given number.
///
/// # Parameters
///
/// - `population`: The total population size.
/// - `success`: The number of successful items in the population.
/// - `draws`: The number of items drawn in the sample.
/// - `observed`: The number of successful items observed in the drawn sample.
///
/// # Returns
///
/// The value of the Upper CDF at the given parameters.
///
/// # Example
///
/// ```
/// use numerilib::stats::distr::Hypergeometric;
///
/// let population = 100_f64;
/// let success = 20_f64;
/// let draws = 10_f64;
/// let observed = 4_f64;
///
/// let cdf = Hypergeometric::ucdf(population, success, draws, observed);
///
/// println!("CDF: {}", cdf);
/// ```
/// <hr/>
pub fn ucdf(population: f64, success: f64, draws: f64, observed: f64) -> f64 {
let func = |x: f64| Self::pmf(population, success, draws, x);
Functions::summation(observed, success, func)
}
/// Calculates the mean of the Hypergeometric Distribution.
///
/// The mean is the average number of successful items in the drawn sample.
///
/// # Parameters
///
/// - `population`: The total population size.
/// - `success`: The number of successful items in the population.
/// - `draws`: The number of items drawn in the sample.
///
/// # Returns
///
/// The mean of the distribution.
///
/// # Example
///
/// ```
/// use numerilib::stats::distr::Hypergeometric;
///
/// let population = 100_f64;
/// let success = 20_f64;
/// let draws = 10_f64;
///
/// let mean = Hypergeometric::mean(population, success, draws);
///
/// println!("Mean: {}", mean);
/// ```
/// <hr/>
pub fn mean(population: f64, success: f64, draws: f64) -> f64 {
draws * (success / population)
}
/// Calculates the mode of the Hypergeometric Distribution.
///
/// The mode is the value that appears most frequently in the distribution.
///
/// # Parameters
///
/// - `population`: The total population size.
/// - `success`: The number of successful items in the population.
/// - `draws`: The number of items drawn in the sample.
///
/// # Returns
///
/// The mode of the distribution.
///
/// # Example
///
/// ```
/// use numerilib::stats::distr::Hypergeometric;
///
/// let population = 100_f64;
/// let success = 20_f64;
/// let draws = 10_f64;
///
/// let mode = Hypergeometric::mode(population, success, draws);
///
/// println!("Mode: {}", mode);
/// ```
/// <hr/>
pub fn mode(population: f64, success: f64, draws: f64) -> f64 {
(((draws + 1_f64) * (success + 1_f64)) / (population + 2_f64)).floor()
}
/// Calculates the variance of the Hypergeometric Distribution.
///
/// The variance measures the spread of the distribution.
///
/// # Parameters
///
/// - `population`: The total population size.
/// - `success`: The number of successful items in the population.
/// - `draws`: The number of items drawn in the sample.
///
/// # Returns
///
/// The variance of the distribution.
///
/// # Example
///
/// ```
/// use numerilib::stats::distr::Hypergeometric;
///
/// let population = 100_f64;
/// let success = 20_f64;
/// let draws = 10_f64;
///
/// let variance = Hypergeometric::variance(population, success, draws);
///
/// println!("Variance: {}", variance);
/// ```
/// <hr/>
pub fn variance(population: f64, success: f64, draws: f64) -> f64 {
draws
* (success / population)
* ((population - success) / population)
* ((population - draws) / (population - 1_f64))
}
/// Calculates the standard deviation of the Hypergeometric Distribution.
///
/// The standard deviation measures the spread of the distribution.
///
/// # Parameters
///
/// - `population`: The total population size.
/// - `success`: The number of successful items in the population.
/// - `draws`: The number of items drawn in the sample.
///
/// # Returns
///
/// The standard deviation of the distribution.
///
/// # Example
///
/// ```
/// use numerilib::stats::distr::Hypergeometric;
///
/// let population = 100_f64;
/// let success = 20_f64;
/// let draws = 10_f64;
///
/// let sd = Hypergeometric::sd(population, success, draws);
///
/// println!("Standard Deviation: {}", sd);
/// ```
/// <hr/>
pub fn sd(population: f64, success: f64, draws: f64) -> f64 {
Self::variance(population, success, draws).sqrt()
}
/// Calculates the skewness of the Hypergeometric Distribution.
///
/// The skewness measures the asymmetry of the distribution.
///
/// # Parameters
///
/// - `population`: The total population size.
/// - `success`: The number of successful items in the population.
/// - `draws`: The number of items drawn in the sample.
///
/// # Returns
///
/// The skewness of the distribution.
///
/// # Example
///
/// ```
/// use numerilib::stats::distr::Hypergeometric;
///
/// let population = 100_f64;
/// let success = 20_f64;
/// let draws = 10_f64;
///
/// let skewness = Hypergeometric::skewness(population, success, draws);
///
/// println!("Skewness: {}", skewness);
/// ```
/// <hr/>
pub fn skewness(population: f64, success: f64, draws: f64) -> f64 {
((population - (2_f64 * success))
* (population - 1_f64).sqrt()
* (population - (2_f64 * draws)))
/ ((draws * population * (population - success) * (population - draws)).sqrt()
* (population - 2_f64))
}
/// Calculates the kurtosis of the Hypergeometric Distribution.
///
/// The kurtosis measures the "tailedness" of the distribution.
///
/// # Parameters
///
/// - `population`: The total population size.
/// - `success`: The number of successful items in the population.
/// - `draws`: The number of items drawn in the sample.
///
/// # Returns
///
/// The kurtosis of the distribution.
///
/// # Example
///
/// ```
/// use numerilib::stats::distr::Hypergeometric;
///
/// let population = 100_f64;
/// let success = 20_f64;
/// let draws = 10_f64;
///
/// let kurtosis = Hypergeometric::kurtosis(population, success, draws);
///
/// println!("Kurtosis: {}", kurtosis);
/// ```
/// <hr/>
pub fn kurtosis(population: f64, success: f64, draws: f64) -> f64 {
let p1 = 1_f64
/ (draws
* success
* (population - success)
* (population - draws)
* (population - 2_f64)
* (population - 3_f64));
let p2 = (population - 1_f64)
* population.powi(2)
* (population * (population + 1_f64)
- (6_f64 * success) * (population - success)
- (6_f64 * draws) * (population - draws))
+ (6_f64 * draws * success)
* (population - success)
* (population - draws)
* ((5_f64 * population) - 6_f64);
p1 * p2
}
}