pub struct Config<T: Clone + Eq + Hash> {
pub table: Table<T>,
pub inversed: bool,
pub repetitive: bool,
}
Expand description
Configuration required by Picker
. All members are public
and are supposed to be modified by the user.
Fields§
§table: Table<T>
Table of choices and weights which are proportional to the probabilities on repetitive mode or single-item mode.
inversed: bool
Do multiplicative inversion for each value in the table.
repetitive: bool
Allow the same item to be picked for multiple times in the result.
Implementations§
Source§impl<T: Clone + Eq + Hash> Config<T>
impl<T: Clone + Eq + Hash> Config<T>
Sourcepub fn calc_probabilities(&self, pick_amount: usize) -> Result<Table<T>, Error>
pub fn calc_probabilities(&self, pick_amount: usize) -> Result<Table<T>, Error>
Calculates probabilities of existences of table items in each picking result
of length pick_amount
. In non-repetitive mode, the multi-thread tree algorithm
may be used.
Preorder traversal is performed in each thread. Something like depth-first or postorder algorithm may achieve higher precision (consider the error produced while adding a small floating-point number to a much larger number, which is the current way), but it will probably increase complexity and memory usage.
TODO: figure out why its single-thread performance is about 7% slower than
the single-thread C++ version compiled with clang++
without -march=native
,
and unsafe operations can’t make this Rust program faster.
It is faster than the C++ version compiled with GCC, though.
Source§impl<T: Clone + Eq + Hash> Config<T>
impl<T: Clone + Eq + Hash> Config<T>
Sourcepub fn new() -> Self
pub fn new() -> Self
Returns an invalid configuration with an empty table.
Please add items into the table before using it to construct Picker
.
let conf = random_picker::Config::<String>::new();
assert!(!conf.inversed && !conf.repetitive);
assert!(conf.check().is_err());
Sourcepub fn check(&self) -> Result<(), Error>
pub fn check(&self) -> Result<(), Error>
Checks whether or not the table can be used by Picker
.
let mut conf: random_picker::Config<String> = "
a = -1; b = 0; c = 2
".parse().unwrap();
assert!(conf.check().is_err());
conf.table.insert("a".to_string(), 1.);
assert!(conf.check().is_ok());
conf.inversed = true;
assert!(conf.check().is_err());
conf.table.insert("b".to_string(), 0.1);
assert!(conf.check().is_ok());
Sourcepub fn is_fair(&self) -> bool
pub fn is_fair(&self) -> bool
Returns true
if all items have equal (and valid) weight values.
let mut conf: random_picker::Config<String> = "
a = -1; b = 1; c = 1.1
".parse().unwrap();
assert!(!conf.is_fair());
conf.table.insert("a".to_string(), 1.);
assert!(!conf.is_fair());
conf.table.insert("c".to_string(), 1.);
assert!(conf.is_fair());
Source§impl Config<String>
impl Config<String>
Sourcepub fn append_str(&mut self, str_items: &str)
pub fn append_str(&mut self, str_items: &str)
Appends, modifies or deletes items in the table according to the configuration input string.
let mut conf: random_picker::Config<String> = "
# 'repetitive' and 'inversed' are special items
repetitive = true
inversed = false
# this line can be ignored
[items]
oxygen = 47
silicon = 28
aluminium=8; iron=5; magnesium=4;
calcium=2; potassium=2; sodium=2
others = 2; nonexistium = 31
aluminium 7.9; delete nonexistium
".parse().unwrap();
assert_eq!(conf.table.len(), 9);
assert_eq!(conf.repetitive, true);
assert_eq!(conf.inversed, false);
assert_eq!(conf.table.get("aluminium"), Some(&7.9));
conf.append_str("\
# power_inversed/repetitive_picking without '=' are for the old format
power_inversed
# invalid: repetitive = 0 (0 is not bool)
repetitive = 0
silicon = 28.1
");
assert_eq!(conf.inversed, true);
conf.append_str("inversed = false");
assert_eq!(conf, random_picker::Config {
table: [
("oxygen", 47.), ("silicon", 28.1), ("aluminium", 7.9),
("iron", 5.), ("magnesium", 4.), ("calcium", 2.),
("sodium", 2.), ("potassium", 2.), ("others", 2.),
].iter().map(|&(k, v)| (k.to_string(), v)).collect(),
inversed: false,
repetitive: true
});