Skip to content

Commit 3c8942a

Browse files
committed
concrete: use PositiveF64 directly in TapleafProbabilityIter
Look ma, no type conversions!
1 parent 31f7cc7 commit 3c8942a

2 files changed

Lines changed: 33 additions & 9 deletions

File tree

src/policy/concrete.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -168,12 +168,12 @@ impl error::Error for PolicyError {
168168

169169
#[cfg(feature = "compiler")]
170170
struct TapleafProbabilityIter<'p, Pk: MiniscriptKey> {
171-
stack: Vec<(f64, &'p Policy<Pk>)>,
171+
stack: Vec<(PositiveF64, &'p Policy<Pk>)>,
172172
}
173173

174174
#[cfg(feature = "compiler")]
175175
impl<'p, Pk: MiniscriptKey> Iterator for TapleafProbabilityIter<'p, Pk> {
176-
type Item = (f64, &'p Policy<Pk>);
176+
type Item = (PositiveF64, &'p Policy<Pk>);
177177

178178
fn next(&mut self) -> Option<Self::Item> {
179179
loop {
@@ -184,11 +184,11 @@ impl<'p, Pk: MiniscriptKey> Iterator for TapleafProbabilityIter<'p, Pk> {
184184
let normalized_iter =
185185
PositiveF64::normalized_iter(subs.iter().map(|x| x.0.into()));
186186
for (ratio, (_, sub)) in normalized_iter.zip(subs.iter()).rev() {
187-
self.stack.push((top_prob * f64::from(ratio), sub));
187+
self.stack.push((top_prob * ratio, sub));
188188
}
189189
}
190190
Policy::Thresh(ref thresh) if thresh.is_or() => {
191-
let n64 = thresh.n() as f64;
191+
let n64 = PositiveF64::n(thresh);
192192
for sub in thresh.iter().rev() {
193193
self.stack.push((top_prob / n64, sub));
194194
}
@@ -240,7 +240,7 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
240240
/// leaf-nodes to [`MAX_COMPILATION_LEAVES`].
241241
#[cfg(feature = "compiler")]
242242
fn tapleaf_probability_iter(&self) -> TapleafProbabilityIter<'_, Pk> {
243-
TapleafProbabilityIter { stack: vec![(1.0, self)] }
243+
TapleafProbabilityIter { stack: vec![(PositiveF64::ONE, self)] }
244244
}
245245

246246
/// Extracts the internal_key from this policy tree.
@@ -249,7 +249,7 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
249249
let internal_key = self
250250
.tapleaf_probability_iter()
251251
.filter_map(|(prob, ref pol)| match pol {
252-
Self::Key(pk) => Some((PositiveF64(prob), pk)),
252+
Self::Key(pk) => Some((prob, pk)),
253253
_ => None,
254254
})
255255
.max_by_key(|(prob, _)| *prob)
@@ -302,7 +302,7 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
302302
continue;
303303
}
304304
let compilation = compiler::best_compilation::<Pk, Tap>(pol)?;
305-
leaf_compilations.push((PositiveF64(prob), compilation));
305+
leaf_compilations.push((prob, compilation));
306306
}
307307
if !leaf_compilations.is_empty() {
308308
let tap_tree = with_huffman_tree::<Pk>(leaf_compilations);

src/primitives/positive_f64.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
// SPDX-License-Identifier: CC0-1.0
22

33
//! Positive floats ("branch probabilities" for policies)
4-
54
use core::iter::FusedIterator;
65
use core::num::NonZeroU32;
7-
use core::{cmp, hash};
6+
use core::{cmp, hash, ops};
7+
8+
use crate::Threshold;
89

910
/// Ordered f64 for comparison.
1011
#[derive(Copy, Clone, PartialEq, Debug)]
1112
pub struct PositiveF64(pub f64);
1213

1314
impl PositiveF64 {
15+
/// The constant one.
16+
pub const ONE: Self = Self(1.0);
17+
1418
/// Takes an iterator over [`PositiveF64`] and produces a new iterator where
1519
/// each item is divided so that they all total to 1.
1620
///
@@ -28,6 +32,11 @@ impl PositiveF64 {
2832
let sum = iter.clone().map(|x| x.0).sum::<f64>();
2933
NormalizedIterator { iter, sum }
3034
}
35+
36+
/// The 'n' value of a threshold, as a [`PositiveF64`]
37+
pub fn n<const MAX: usize, T>(t: &Threshold<T, MAX>) -> Self {
38+
Self(t.n() as f64) // cast okay, worst case wil lose precision
39+
}
3140
}
3241

3342
impl Eq for PositiveF64 {}
@@ -58,6 +67,21 @@ impl From<NonZeroU32> for PositiveF64 {
5867
fn from(value: NonZeroU32) -> Self { Self(f64::from(u32::from(value))) }
5968
}
6069

70+
impl ops::Add for PositiveF64 {
71+
type Output = Self;
72+
fn add(self, rhs: Self) -> Self::Output { Self(self.0 + rhs.0) }
73+
}
74+
75+
impl ops::Mul for PositiveF64 {
76+
type Output = Self;
77+
fn mul(self, rhs: Self) -> Self::Output { Self(self.0 * rhs.0) }
78+
}
79+
80+
impl ops::Div for PositiveF64 {
81+
type Output = Self;
82+
fn div(self, rhs: Self) -> Self::Output { Self(self.0 / rhs.0) }
83+
}
84+
6185
pub struct NormalizedIterator<I> {
6286
iter: I,
6387
/// Sum must be nonnegative, and may only be zero if `iter` is empty.

0 commit comments

Comments
 (0)