|
173 | 173 |
|
174 | 174 | use Rng;
|
175 | 175 |
|
176 |
| -#[doc(inline)] pub use self::other::Alphanumeric; |
| 176 | +pub use self::other::Alphanumeric; |
177 | 177 | #[doc(inline)] pub use self::uniform::Uniform;
|
178 |
| -#[doc(inline)] pub use self::float::{OpenClosed01, Open01}; |
179 |
| -#[cfg(feature="alloc")] |
180 |
| -#[doc(inline)] pub use self::weighted::{WeightedIndex, WeightedError}; |
181 |
| -#[cfg(feature="std")] |
182 |
| -#[doc(inline)] pub use self::gamma::{Gamma, ChiSquared, FisherF, StudentT}; |
183 |
| -#[cfg(feature="std")] |
184 |
| -#[doc(inline)] pub use self::normal::{Normal, LogNormal, StandardNormal}; |
185 |
| -#[cfg(feature="std")] |
186 |
| -#[doc(inline)] pub use self::exponential::{Exp, Exp1}; |
187 |
| -#[cfg(feature="std")] |
188 |
| -#[doc(inline)] pub use self::pareto::Pareto; |
189 |
| -#[cfg(feature = "std")] |
190 |
| -#[doc(inline)] pub use self::poisson::Poisson; |
191 |
| -#[cfg(feature = "std")] |
192 |
| -#[doc(inline)] pub use self::binomial::Binomial; |
193 |
| -#[doc(inline)] pub use self::bernoulli::Bernoulli; |
194 |
| -#[cfg(feature = "std")] |
195 |
| -#[doc(inline)] pub use self::cauchy::Cauchy; |
196 |
| -#[cfg(feature = "std")] |
197 |
| -#[doc(inline)] pub use self::dirichlet::Dirichlet; |
| 178 | +pub use self::float::{OpenClosed01, Open01}; |
| 179 | +pub use self::bernoulli::Bernoulli; |
| 180 | +#[cfg(feature="alloc")] pub use self::weighted::{WeightedIndex, WeightedError}; |
| 181 | +#[cfg(feature="std")] pub use self::gamma::{Gamma, ChiSquared, FisherF, StudentT}; |
| 182 | +#[cfg(feature="std")] pub use self::normal::{Normal, LogNormal, StandardNormal}; |
| 183 | +#[cfg(feature="std")] pub use self::exponential::{Exp, Exp1}; |
| 184 | +#[cfg(feature="std")] pub use self::pareto::Pareto; |
| 185 | +#[cfg(feature="std")] pub use self::poisson::Poisson; |
| 186 | +#[cfg(feature="std")] pub use self::binomial::Binomial; |
| 187 | +#[cfg(feature="std")] pub use self::cauchy::Cauchy; |
| 188 | +#[cfg(feature="std")] pub use self::dirichlet::Dirichlet; |
198 | 189 |
|
199 | 190 | pub mod uniform;
|
200 |
| -#[cfg(feature="alloc")] |
201 |
| -#[doc(hidden)] pub mod weighted; |
202 |
| -#[cfg(feature="std")] |
203 |
| -#[doc(hidden)] pub mod gamma; |
204 |
| -#[cfg(feature="std")] |
205 |
| -#[doc(hidden)] pub mod normal; |
206 |
| -#[cfg(feature="std")] |
207 |
| -#[doc(hidden)] pub mod exponential; |
208 |
| -#[cfg(feature="std")] |
209 |
| -#[doc(hidden)] pub mod pareto; |
210 |
| -#[cfg(feature = "std")] |
211 |
| -#[doc(hidden)] pub mod poisson; |
212 |
| -#[cfg(feature = "std")] |
213 |
| -#[doc(hidden)] pub mod binomial; |
214 |
| -#[doc(hidden)] pub mod bernoulli; |
215 |
| -#[cfg(feature = "std")] |
216 |
| -#[doc(hidden)] pub mod cauchy; |
217 |
| -#[cfg(feature = "std")] |
218 |
| -#[doc(hidden)] pub mod dirichlet; |
| 191 | +mod bernoulli; |
| 192 | +#[cfg(feature="alloc")] mod weighted; |
| 193 | +#[cfg(feature="std")] mod gamma; |
| 194 | +#[cfg(feature="std")] mod normal; |
| 195 | +#[cfg(feature="std")] mod exponential; |
| 196 | +#[cfg(feature="std")] mod pareto; |
| 197 | +#[cfg(feature="std")] mod poisson; |
| 198 | +#[cfg(feature="std")] mod binomial; |
| 199 | +#[cfg(feature="std")] mod cauchy; |
| 200 | +#[cfg(feature="std")] mod dirichlet; |
219 | 201 |
|
220 | 202 | mod float;
|
221 | 203 | mod integer;
|
222 |
| -#[cfg(feature="std")] |
223 |
| -mod log_gamma; |
224 | 204 | mod other;
|
225 | 205 | mod utils;
|
226 |
| -#[cfg(feature="std")] |
227 |
| -mod ziggurat_tables; |
228 |
| -#[cfg(feature="std")] |
229 |
| -use distributions::float::IntoFloat; |
| 206 | +#[cfg(feature="std")] mod ziggurat_tables; |
230 | 207 |
|
231 | 208 | /// Types (distributions) that can be used to create a random instance of `T`.
|
232 | 209 | ///
|
@@ -487,69 +464,6 @@ impl<'a, T: Clone> Distribution<T> for WeightedChoice<'a, T> {
|
487 | 464 | }
|
488 | 465 | }
|
489 | 466 |
|
490 |
| -/// Sample a random number using the Ziggurat method (specifically the |
491 |
| -/// ZIGNOR variant from Doornik 2005). Most of the arguments are |
492 |
| -/// directly from the paper: |
493 |
| -/// |
494 |
| -/// * `rng`: source of randomness |
495 |
| -/// * `symmetric`: whether this is a symmetric distribution, or one-sided with P(x < 0) = 0. |
496 |
| -/// * `X`: the $x_i$ abscissae. |
497 |
| -/// * `F`: precomputed values of the PDF at the $x_i$, (i.e. $f(x_i)$) |
498 |
| -/// * `F_DIFF`: precomputed values of $f(x_i) - f(x_{i+1})$ |
499 |
| -/// * `pdf`: the probability density function |
500 |
| -/// * `zero_case`: manual sampling from the tail when we chose the |
501 |
| -/// bottom box (i.e. i == 0) |
502 |
| -
|
503 |
| -// the perf improvement (25-50%) is definitely worth the extra code |
504 |
| -// size from force-inlining. |
505 |
| -#[cfg(feature="std")] |
506 |
| -#[inline(always)] |
507 |
| -fn ziggurat<R: Rng + ?Sized, P, Z>( |
508 |
| - rng: &mut R, |
509 |
| - symmetric: bool, |
510 |
| - x_tab: ziggurat_tables::ZigTable, |
511 |
| - f_tab: ziggurat_tables::ZigTable, |
512 |
| - mut pdf: P, |
513 |
| - mut zero_case: Z) |
514 |
| - -> f64 where P: FnMut(f64) -> f64, Z: FnMut(&mut R, f64) -> f64 { |
515 |
| - loop { |
516 |
| - // As an optimisation we re-implement the conversion to a f64. |
517 |
| - // From the remaining 12 most significant bits we use 8 to construct `i`. |
518 |
| - // This saves us generating a whole extra random number, while the added |
519 |
| - // precision of using 64 bits for f64 does not buy us much. |
520 |
| - let bits = rng.next_u64(); |
521 |
| - let i = bits as usize & 0xff; |
522 |
| - |
523 |
| - let u = if symmetric { |
524 |
| - // Convert to a value in the range [2,4) and substract to get [-1,1) |
525 |
| - // We can't convert to an open range directly, that would require |
526 |
| - // substracting `3.0 - EPSILON`, which is not representable. |
527 |
| - // It is possible with an extra step, but an open range does not |
528 |
| - // seem neccesary for the ziggurat algorithm anyway. |
529 |
| - (bits >> 12).into_float_with_exponent(1) - 3.0 |
530 |
| - } else { |
531 |
| - // Convert to a value in the range [1,2) and substract to get (0,1) |
532 |
| - (bits >> 12).into_float_with_exponent(0) |
533 |
| - - (1.0 - ::core::f64::EPSILON / 2.0) |
534 |
| - }; |
535 |
| - let x = u * x_tab[i]; |
536 |
| - |
537 |
| - let test_x = if symmetric { x.abs() } else {x}; |
538 |
| - |
539 |
| - // algebraically equivalent to |u| < x_tab[i+1]/x_tab[i] (or u < x_tab[i+1]/x_tab[i]) |
540 |
| - if test_x < x_tab[i + 1] { |
541 |
| - return x; |
542 |
| - } |
543 |
| - if i == 0 { |
544 |
| - return zero_case(rng, u); |
545 |
| - } |
546 |
| - // algebraically equivalent to f1 + DRanU()*(f0 - f1) < 1 |
547 |
| - if f_tab[i + 1] + (f_tab[i] - f_tab[i + 1]) * rng.gen::<f64>() < pdf(x) { |
548 |
| - return x; |
549 |
| - } |
550 |
| - } |
551 |
| -} |
552 |
| - |
553 | 467 | #[cfg(test)]
|
554 | 468 | mod tests {
|
555 | 469 | use rngs::mock::StepRng;
|
|
0 commit comments