use crate::Probability;
use std::hash::Hash;
use std::u64;
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug, PartialOrd, Ord)]
pub enum Abstraction {
Random(u64),
Equity(i8),
}
impl Abstraction {
const N: i8 = 50;
pub fn random() -> Self {
Self::Random(rand::random::<u64>())
}
fn quantize(p: Probability) -> i8 {
(p * Probability::from(Self::N)).round() as i8
}
fn floatize(q: i8) -> Probability {
Probability::from(q) / Probability::from(Self::N)
}
}
impl From<Probability> for Abstraction {
fn from(p: Probability) -> Self {
Self::Equity(Abstraction::quantize(p))
}
}
impl From<Abstraction> for Probability {
fn from(abstraction: Abstraction) -> Self {
match abstraction {
Abstraction::Equity(n) => Abstraction::floatize(n),
Abstraction::Random(_) => unreachable!("no cluster into probability"),
}
}
}
impl From<Abstraction> for u64 {
fn from(a: Abstraction) -> Self {
match a {
Abstraction::Random(n) => n,
Abstraction::Equity(_) => unreachable!("no equity into u64"),
}
}
}
impl From<u64> for Abstraction {
fn from(n: u64) -> Self {
Self::Random(n)
}
}
impl From<Abstraction> for i64 {
fn from(abstraction: Abstraction) -> Self {
u64::from(abstraction) as i64
}
}
impl From<i64> for Abstraction {
fn from(n: i64) -> Self {
Self::Random(n as u64)
}
}
impl std::fmt::Display for Abstraction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Random(n) => write!(f, "{:016x}", n),
Self::Equity(_) => unreachable!("don't log me"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn is_quantize_inverse_floatize() {
for p in (0..=100).map(|x| x as Probability / 100.0) {
let q = Abstraction::quantize(p);
let f = Abstraction::floatize(q);
assert!((p - f).abs() < 1.0 / Abstraction::N as Probability);
}
}
#[test]
fn is_floatize_inverse_quantize() {
for q in 0..=Abstraction::N {
let p = Abstraction::floatize(q);
let i = Abstraction::quantize(p);
assert!(q == i);
}
}
}