ixa/random/
mod.rs

1mod context_ext;
2mod sampling_algorithms;
3
4use crate::rand::SeedableRng;
5use crate::{define_data_plugin, HashMap, HashMapExt};
6use std::any::{Any, TypeId};
7use std::cell::RefCell;
8
9pub use context_ext::ContextRandomExt;
10pub use sampling_algorithms::{
11    sample_multiple_from_known_length, sample_multiple_l_reservoir,
12    sample_single_from_known_length, sample_single_l_reservoir,
13};
14
15/// Use this to define a unique type which will be used as a key to retrieve
16/// an independent rng instance when calling `.get_rng`.
17#[macro_export]
18macro_rules! define_rng {
19    ($random_id:ident) => {
20        #[derive(Copy, Clone)]
21        struct $random_id;
22
23        impl $crate::random::RngId for $random_id {
24            type RngType = $crate::rand::rngs::SmallRng;
25
26            fn get_name() -> &'static str {
27                stringify!($random_id)
28            }
29        }
30
31        // This ensures that you can't define two RngIds with the same name
32        $crate::paste::paste! {
33            #[doc(hidden)]
34            #[no_mangle]
35            #[allow(non_upper_case_globals)]
36            pub static [<rng_name_duplication_guard_ $random_id>]: () = ();
37        }
38    };
39}
40pub use define_rng;
41
42pub trait RngId: Copy + Clone {
43    type RngType: SeedableRng;
44    fn get_name() -> &'static str;
45}
46
47// This is a wrapper which allows for future support for different types of
48// random number generators (anything that implements SeedableRng is valid).
49struct RngHolder {
50    rng: Box<dyn Any>,
51}
52
53struct RngData {
54    base_seed: u64,
55    rng_holders: RefCell<HashMap<TypeId, RngHolder>>,
56}
57
58// Registers a data container which stores:
59// * base_seed: A base seed for all rngs
60// * rng_holders: A map of rngs, keyed by their RngId. Note that this is
61//   stored in a RefCell to allow for mutable borrow without requiring a
62//   mutable borrow of the Context itself.
63define_data_plugin!(
64    RngPlugin,
65    RngData,
66    RngData {
67        base_seed: 0,
68        rng_holders: RefCell::new(HashMap::new()),
69    }
70);