optimal_binary/lib.rs
1//! Utilities for working with binary optimizers.
2
3use num_traits::{pow, One, Zero};
4use std::ops::{Add, Div, Mul, RangeInclusive, Sub};
5
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8
9/// Reduce innermost axis
10/// to numbers within range.
11/// Leftmost is least significant.
12///
13/// # Examples
14///
15/// ```
16/// use optimal_binary::ToRealLE;
17///
18/// // It returns lower bound for empty arrays:
19/// assert_eq!(ToRealLE::new(1.0..=2.0, 0).decode([]), 1.);
20///
21/// // It returns lower bound when all bits are false:
22/// assert_eq!(ToRealLE::new(0.0..=1.0, 1).decode([false]), 0.);
23/// assert_eq!(ToRealLE::new(1.0..=2.0, 2).decode([false, false]), 1.);
24///
25/// // It returns upper bound when all bits are true:
26/// assert_eq!(ToRealLE::new(0.0..=1.0, 1).decode([true]), 1.);
27/// assert_eq!(ToRealLE::new(1.0..=2.0, 2).decode([true, true]), 2.);
28///
29/// // It returns a number between lower and upper bound when some bits are true:
30/// assert_eq!(ToRealLE::new(1.0..=4.0, 2).decode([true, false]), 2.);
31/// assert_eq!(ToRealLE::new(1.0..=4.0, 2).decode([false, true]), 3.);
32/// ```
33#[derive(Clone, Debug, PartialEq, Eq)]
34#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
35#[cfg_attr(
36 feature = "serde",
37 serde(bound(deserialize = "T: One + Add<Output = T> + Deserialize<'de>"))
38)]
39pub struct ToRealLE<T> {
40 #[cfg_attr(feature = "serde", serde(skip))]
41 to_int: ToIntLE<T>,
42 start: T,
43 a: Option<T>,
44}
45
46impl<T> ToRealLE<T> {
47 pub fn new(range: RangeInclusive<T>, len: usize) -> Self
48 where
49 T: Copy + One + Add<Output = T> + Sub<Output = T> + Div<Output = T>,
50 {
51 let to_int = ToIntLE::new();
52 let (start, end) = range.into_inner();
53 Self {
54 a: if len > 0 {
55 Some((end - start) / (pow(to_int.two, len) - T::one()))
56 } else {
57 None
58 },
59 start,
60 to_int,
61 }
62 }
63
64 pub fn decode(&self, bits: impl IntoIterator<Item = bool>) -> T
65 where
66 T: Copy + Zero + One + Add<Output = T> + Mul<Output = T>,
67 {
68 match self.a {
69 Some(a) => a * self.to_int.decode(bits) + self.start,
70 None => self.start,
71 }
72 }
73}
74
75/// Reduce to base 10 integer representations of bits.
76/// Leftmost is least significant.
77///
78/// # Examples
79///
80/// ```
81/// use optimal_binary::ToIntLE;
82///
83/// let to_int_le: ToIntLE<u8> = ToIntLE::new();
84///
85/// // It returns 0 when empty:
86/// assert_eq!(to_int_le.decode([]), 0_u8);
87///
88/// // It returns the base 10 integer represented by binary bits:
89/// assert_eq!(to_int_le.decode([false]), 0_u8);
90/// assert_eq!(to_int_le.decode([false, false]), 0_u8);
91/// assert_eq!(to_int_le.decode([false, false, false]), 0_u8);
92/// assert_eq!(to_int_le.decode([true]), 1_u8);
93/// assert_eq!(to_int_le.decode([true, true]), 3_u8);
94/// assert_eq!(to_int_le.decode([true, true, true]), 7_u8);
95///
96/// // It treats leftmost as least significant:
97/// assert_eq!(to_int_le.decode([false, true]), 2_u8);
98/// assert_eq!(to_int_le.decode([false, false, true]), 4_u8);
99/// ```
100#[derive(Clone, Debug, PartialEq, Eq)]
101#[cfg_attr(feature = "serde", derive(Serialize))]
102pub struct ToIntLE<T> {
103 #[cfg_attr(feature = "serde", serde(skip))]
104 two: T,
105}
106
107impl<T> Default for ToIntLE<T>
108where
109 T: One + Add<Output = T>,
110{
111 fn default() -> Self {
112 Self::new()
113 }
114}
115
116#[cfg(feature = "serde")]
117impl<'de, T> Deserialize<'de> for ToIntLE<T>
118where
119 T: One + Add<Output = T>,
120{
121 fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
122 where
123 D: serde::Deserializer<'de>,
124 {
125 Ok(Self::new())
126 }
127}
128
129impl<T> ToIntLE<T> {
130 pub fn new() -> Self
131 where
132 T: One + Add<Output = T>,
133 {
134 Self {
135 two: T::one() + T::one(),
136 }
137 }
138
139 pub fn decode(&self, bits: impl IntoIterator<Item = bool>) -> T
140 where
141 T: Copy + Zero + One + Add<Output = T> + Mul<Output = T>,
142 {
143 bits.into_iter()
144 .fold((T::zero(), T::one()), |(acc, a), b| {
145 (if b { acc + a } else { acc }, self.two * a)
146 })
147 .0
148 }
149}