Skip to content

Commit

Permalink
Pull the (m, n) calculation out into sub function
Browse files Browse the repository at this point in the history
The `normalize` function spans more than a screen (on my monitor), as
such it is hard to work on.

Refactor out the (m, n)-thresh calculation to a function so that the
body of the function becomes shorter.

Refactor only, no logic changes.
  • Loading branch information
tcharding committed Oct 12, 2023
1 parent ec05e7f commit 03df11c
Showing 1 changed file with 24 additions and 13 deletions.
37 changes: 24 additions & 13 deletions src/policy/semantic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,26 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
/// Flattens out trees of `And`s and `Or`s; eliminate `Trivial` and
/// `Unsatisfiable`s. Does not reorder any branches; use `.sort`.
pub fn normalized(self) -> Policy<Pk> {
// Returns (m, n)-thresh values for the normalized (k, subs.len())-thresh.
fn normalized_threshold_values<Pk: MiniscriptKey>(
k: usize,
subs: &[Arc<Policy<Pk>>],
) -> (usize, usize) {
let trivial_count = subs
.iter()
.filter(|&pol| *pol.as_ref() == Policy::Trivial)
.count();
let unsatisfied_count = subs
.iter()
.filter(|&pol| *pol.as_ref() == Policy::Unsatisfiable)
.count();

let n = subs.len() - unsatisfied_count - trivial_count; // remove all true/false
let m = k.checked_sub(trivial_count).unwrap_or(0); // satisfy all trivial

(m, n)
}

match self {
Policy::Threshold(k, subs) => {
let mut ret_subs = Vec::with_capacity(subs.len());
Expand All @@ -418,21 +438,12 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
.into_iter()
.map(|sub| Arc::new(sub.as_ref().clone().normalized()))
.collect();
let trivial_count = subs
.iter()
.filter(|&pol| *pol.as_ref() == Policy::Trivial)
.count();
let unsatisfied_count = subs
.iter()
.filter(|&pol| *pol.as_ref() == Policy::Unsatisfiable)
.count();

let n = subs.len() - unsatisfied_count - trivial_count; // remove all true/false
let m = k.checked_sub(trivial_count).unwrap_or(0); // satisfy all trivial

let (m, n) = normalized_threshold_values(k, &subs);

// Call the current threshold "parent" to differentiate it from its "child" threshold below.
let parent_is_and = m == n; // (n, n)-thresh is an AND
let parent_is_or = m == 1; // (1, n)-thresh is an OR
let parent_is_or = m == 1; // (1, n)-thresh is an OR

for sub in subs {
match sub.as_ref() {
Expand All @@ -447,7 +458,7 @@ impl<Pk: MiniscriptKey> Policy<Pk> {
} else if parent_is_and && child_is_and {
// If both parent and child are ANDs we can flatten them.
subs.iter().for_each(|sub| ret_subs.push(Arc::clone(sub)));
} else if parent_is_or && child_is_or {
} else if parent_is_or && child_is_or {
// If both parent and child are ORs we can flatten them.
subs.iter().for_each(|sub| ret_subs.push(Arc::clone(sub)));
} else {
Expand Down

0 comments on commit 03df11c

Please sign in to comment.