diff --git a/benches/bench.rs b/benches/bench.rs index 17135056..991dadc4 100644 --- a/benches/bench.rs +++ b/benches/bench.rs @@ -187,10 +187,14 @@ pub fn bench_guide(c: &mut Criterion) { } pub fn bench_lyndon(c: &mut Criterion) { + pub fn least_mode_naive(scale: &[Letter]) -> Vec { + let sorted_modes = rotations(scale).into_iter().sorted().collect::>(); + sorted_modes[0].to_owned() + } c.bench_function("naive", |b| { b.iter(|| { for scale in black_box(ternary::words::mos_substitution_scales(&[5, 2, 10])) { - ternary::words::least_mode_naive(&scale); + least_mode_naive(&scale); } }); }); diff --git a/src/comb.rs b/src/comb.rs index a84e06f2..5f486c0f 100644 --- a/src/comb.rs +++ b/src/comb.rs @@ -15,7 +15,6 @@ fn partitions_exact_part_count_rec(n: usize, m: usize, parts: usize) -> Vec 0 => vec![], (n, _, 0) if n > 0 => vec![], _ => (0..=m) - .into_iter() .flat_map(|l| { partitions_exact_part_count_rec(n - m, l, parts - 1) .into_iter() @@ -27,18 +26,14 @@ fn partitions_exact_part_count_rec(n: usize, m: usize, parts: usize) -> Vec Vec> { - (1usize..=(n + 1).checked_sub(parts).unwrap_or(0)) - .into_iter() + (1usize..=(n + 1).saturating_sub(parts)) .flat_map(|m| partitions_exact_part_count_rec(n, m, parts)) .collect() } /// A partition of n >= 0 is a (possibly empty) sorted list of positive summands to n. pub fn partitions(n: usize) -> Vec> { - (1usize..=n) - .into_iter() - .flat_map(|m| partitions_rec(n, m)) - .collect() + (1usize..=n).flat_map(|m| partitions_rec(n, m)).collect() } fn partitions_rec(n: usize, m: usize) -> Vec> { @@ -56,7 +51,6 @@ fn partitions_rec(n: usize, m: usize) -> Vec> { vec![] } _ => (0..=m) - .into_iter() .flat_map(|k| { partitions_rec(n - m, k) .into_iter() @@ -253,11 +247,14 @@ impl VecPerm { Err(PermutationError::IndexOutOfBounds(self.len(), index)) } } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } /// Tries to create a new `VecPerm`. pub fn try_new(slice: &[usize]) -> Result { let domain = (0..slice.len()).collect::>(); - let image = slice.into_iter().cloned().collect::>(); - if slice.len() == 0 { + let image = slice.iter().cloned().collect::>(); + if slice.is_empty() { // return the empty perm Ok(VecPerm { pi: vec![] }) } else if image != domain { @@ -314,6 +311,7 @@ impl VecPerm { } } /// The inverse of a permutation. + #[allow(clippy::needless_range_loop)] pub fn inv(&self) -> Self { let mut pi = vec![usize::MAX; self.len()]; for i in 0..self.len() { @@ -332,15 +330,15 @@ impl VecPerm { /// For example, if `g` acts on `0, 1, 2` by cycling through them, /// `g.conj(&h)` acts on `h(0)`, `h(1)`, and `h(2)` in the same way. pub fn conj(&self, other: &Self) -> Result { - Ok(other.o(&self)?.o(&other.inv())?) + other.o(self)?.o(&other.inv()) } /// Replaces elements of `self` starting from `index` with `other` if possible. fn nest_replacing(v: &[usize], other: &[usize], index: usize) -> Result, String> { - if other.len() == 0 { + if other.is_empty() { Ok(v.to_owned()) } else if index + other.len() - 1 < v.len() { - let mut result = [&v[0..index], &other].concat().to_vec(); + let mut result = [&v[0..index], other].concat().to_vec(); if index + other.len() < v.len() { result.extend_from_slice(&v[index + other.len()..]); } diff --git a/src/equal.rs b/src/equal.rs index 4d7ba1b6..327c1f6e 100644 --- a/src/equal.rs +++ b/src/equal.rs @@ -91,7 +91,6 @@ pub fn ed_tunings_for_ternary( aber_upper: f64, ) -> Vec> { (3..ed_bound) - .into_iter() .flat_map(|l| (2..l).flat_map(move |m| (1..m).map(move |s| vec![l, m, s]))) .filter(|v| { let ed: i32 = @@ -109,7 +108,7 @@ pub fn ed_tunings_for_ternary( pub fn relative_error(monzo: Monzo, edo: f64) -> f64 { let val = gpval(edo); let steps = val.evaluate(monzo); - return (steps_as_cents(steps, edo, RawJiRatio::OCTAVE) - monzo.cents()) * edo / 1200.0; + (steps_as_cents(steps, edo, RawJiRatio::OCTAVE) - monzo.cents()) * edo / 1200.0 } /// L^1 error on a specified odd limit. @@ -140,7 +139,7 @@ macro_rules! val { $crate::equal::Val::ZERO ); ($elem:expr; $n:expr) => ( - $crate::equal::Val(nalgebra::RowSVector::::from_row_slice(&[$elem; crate::primes::SMALL_PRIMES_COUNT])) + $crate::equal::Val(nalgebra::RowSVector::::from_row_slice(&[$elem; $crate::primes::SMALL_PRIMES_COUNT])) ); ($($x:expr),+ $(,)?) => ( $crate::equal::Val::from_slice(&[$($x),+]) diff --git a/src/guide.rs b/src/guide.rs index 1534119b..6561735a 100644 --- a/src/guide.rs +++ b/src/guide.rs @@ -16,7 +16,7 @@ where T: core::fmt::Debug + PartialEq + Clone + Eq + Send, { let len = chain.len(); - rotations(&chain) + rotations(chain) .into_iter() .filter(|list| !(list[..len - 1].contains(&list[len - 1]))) .map(|chain| weak_period(&chain[..len - 1])) @@ -38,7 +38,6 @@ where T: Subtendable + std::fmt::Debug, { (0..neck.len()) - .into_iter() .map(|i| word_on_degree(neck, k * i, k)) .map(|subword| ::interval_from_slice(&subword)) .collect() @@ -49,7 +48,6 @@ where pub fn wfgs_list(neck: &[usize]) -> Vec>> { let len = neck.len(); (2..=len - 2) // Don't include 1-step GSes - .into_iter() .filter(|&k| gcd(k as u64, len as u64) == 1) .flat_map(|k| k_step_wfgs_list(k, neck)) .collect() @@ -59,7 +57,6 @@ pub fn wfgs_list(neck: &[usize]) -> Vec>> { pub fn wfgs_list_of_len(l: usize, neck: &[usize]) -> Vec>> { let neck_len = neck.len(); (2..=neck_len / 2) // Don't include 1-step GSes - .into_iter() .filter(|&k| gcd(k as u64, neck_len as u64) == 1) .flat_map(|k| k_step_wfgs_list(k, neck)) .filter(|vs| l == vs.len()) @@ -73,7 +70,6 @@ fn wfgs_list_for_subscale(subscale: &[CountVector]) -> Vec Vec { - if scale.len() == 0 { + if scale.is_empty() { vec![] } else { let d = gcd(scale.len() as u64, k as u64) as usize; let subscales = (0..d) - .map(|degree| rotate(&scale, degree)) + .map(|degree| rotate(scale, degree)) .map(|rotation| { stacked_k_steps(d, &rotation[..scale.len()])[..scale.len() / d].to_vec() }) @@ -154,13 +150,9 @@ impl GuideFrame { .into_iter() .enumerate() .map(|(i, subscale)| { - offset_vec(&subscale_on_root, &subscale).and_then(|offset| { + offset_vec(subscale_on_root, &subscale).map(|offset| { // `.and_then()` returns `None` if the previous result is `None`. - Some(CountVector::from_slice(&word_on_degree( - scale, - 0, - offset * d + i, - ))) + CountVector::from_slice(&word_on_degree(scale, 0, offset * d + i)) }) }) // None if there is any `None` returned by `map`. @@ -172,7 +164,7 @@ impl GuideFrame { let offsets: Vec> = offsets.into_iter().sorted_by_key(|v| v.len()).collect(); if offsets == [CountVector::ZERO] { - wfgs_list(&scale) + wfgs_list(scale) .into_iter() .map(|gs| Self { gs, @@ -183,8 +175,7 @@ impl GuideFrame { .dedup() .collect::>() } else { - ("{:?}", wfgs_list_for_subscale(&subscale_on_root)); - wfgs_list_for_subscale(&subscale_on_root) + wfgs_list_for_subscale(subscale_on_root) .into_iter() .map(|gs| Self { gs, @@ -202,7 +193,7 @@ impl GuideFrame { } pub fn try_multiple(scale: &[usize], multiplicity: usize, k: usize) -> Vec { // The scale cannot be empty and its size must be divisible by `multiplicity`. - if is_prime(scale.len() as u64) || scale.len() == 0 || scale.len() % multiplicity != 0 { + if is_prime(scale.len() as u64) || scale.is_empty() || scale.len() % multiplicity != 0 { vec![] } else { let d = gcd(k as u64, scale.len() as u64) as usize; @@ -216,7 +207,6 @@ impl GuideFrame { // Stack k-steps and split the result into `multiplicity` vecs of equal length let s = stacked_k_steps(k, &rotate(scale, degree)); (0..multiplicity) - .into_iter() .map(|i| { s[scale.len() / multiplicity * i ..scale.len() / multiplicity * (i + 1)] @@ -227,7 +217,7 @@ impl GuideFrame { .filter(|gses| { // To qualify as a valid GS, the last element cannot be in the GS. !gses[0][0..scale.len() / multiplicity - 1] - .into_iter() + .iter() .contains(&gses[0][scale.len() / multiplicity - 1]) // Ignoring the last element, all of the vecs have to be equal. && gses.iter() @@ -267,15 +257,14 @@ impl GuideFrame { .map(|p| p as usize) .collect(); let simple_guide_moses: Vec = Self::try_simple_or_interleaved(scale, k); - let multiple_guide_moses: Vec = - if BTreeSet::from_iter(scale.into_iter()).len() > 1 { - prime_factors - .into_iter() - .flat_map(|p| Self::try_multiple(scale, p, k)) - .collect() - } else { - vec![] - }; + let multiple_guide_moses: Vec = if BTreeSet::from_iter(scale.iter()).len() > 1 { + prime_factors + .into_iter() + .flat_map(|p| Self::try_multiple(scale, p, k)) + .collect() + } else { + vec![] + }; [simple_guide_moses, multiple_guide_moses].concat() } } diff --git a/src/interval.rs b/src/interval.rs index c19081c2..b2692971 100644 --- a/src/interval.rs +++ b/src/interval.rs @@ -47,7 +47,7 @@ pub trait Dyad: Copy + Eq + PartialEq + std::fmt::Debug + Send + Sync { ret } _ => { - while !(ret.cmp_dyad(&modulo) == Ordering::Less) { + while ret.cmp_dyad(&modulo) != Ordering::Less { ret = ret.unstack(modulo); } ret diff --git a/src/ji.rs b/src/ji.rs index 0031771b..0b3df099 100644 --- a/src/ji.rs +++ b/src/ji.rs @@ -16,9 +16,9 @@ use crate::words::{rotate, CountVector}; /// not including the unison. pub fn specified_odd_limit(odds: &[u64]) -> Vec { let odds: Vec = odds - .into_iter() + .iter() .filter(|x| **x > 0 && **x % 2 == 1) - .map(|x| *x) + .copied() .collect(); // filter out invalid input pairs(&odds, &odds.clone()) .into_iter() @@ -149,7 +149,6 @@ pub fn step_form(cumul_form: &[RawJiRatio]) -> Vec { [ &[cumul_form[0]], (0..cumul_form.len() - 1) - .into_iter() .map(|i| cumul_form[i + 1] / cumul_form[i]) .collect::>() .as_slice(), @@ -160,7 +159,7 @@ pub fn step_form(cumul_form: &[RawJiRatio]) -> Vec { /// Convert a step form into a cumulative form. pub fn cumulative_form(step_form: &[RawJiRatio]) -> Vec { step_form - .into_iter() + .iter() .scan(RawJiRatio::UNISON, |acc, &step| { *acc *= step; Some(*acc) @@ -170,10 +169,7 @@ pub fn cumulative_form(step_form: &[RawJiRatio]) -> Vec { /// Modes of a JI scale written in cumulative form. pub fn ji_scale_modes(scale: &[RawJiRatio]) -> Vec> { - (0..scale.len()) - .into_iter() - .map(|degree| mode(&scale, degree)) - .collect() + (0..scale.len()).map(|degree| mode(scale, degree)).collect() } /// Returns the JI chord `mode_num`:...:`2*mode_num`. @@ -182,7 +178,6 @@ pub fn harmonic_mode(mode_num: u64) -> Result, ScaleError> { Err(ScaleError::CannotMakeScale) } else { Ok((mode_num + 1..=(2 * mode_num)) - .into_iter() .map(|x| RawJiRatio::try_new(x, mode_num).expect("`numer` should be > `denom` here")) .collect()) } @@ -194,7 +189,6 @@ pub fn harmonic_mode_no_oct(mode_num: u64) -> Result, ScaleError Err(ScaleError::CannotMakeScale) } else { Ok((mode_num + 1..=(2 * mode_num - 1)) - .into_iter() .map(|x| RawJiRatio::try_new(x, mode_num).expect("`numer` should be > `denom`")) .collect()) } @@ -202,7 +196,7 @@ pub fn harmonic_mode_no_oct(mode_num: u64) -> Result, ScaleError /// Compute if `offset` is valid for an interleaved scale with strand `strand`. pub fn is_valid_offset(strand: &[RawJiRatio], offset: RawJiRatio) -> bool { - (1..=(strand.len() - 1)).into_iter().try_for_each(|i| { + (1..=(strand.len() - 1)).try_for_each(|i| { let i_steps = spectrum(strand, i); let min_i_step = *i_steps .into_inner() @@ -326,9 +320,8 @@ pub fn is_cs_ji_scale(arr: &[RawJiRatio]) -> bool { // This loop makes at most (n-1)(n-2)/2 comparisons between sets. let unique_i_plus_1_steps: BTreeSet = interval_classes[i].iter().cloned().collect(); - for j in (i + 1)..(n - 1) { - let unique_j_plus_1_steps: BTreeSet = - interval_classes[j].iter().cloned().collect(); + for class in interval_classes.iter().take(n - 1).skip(i + 1) { + let unique_j_plus_1_steps: BTreeSet = class.iter().cloned().collect(); if !unique_i_plus_1_steps.is_disjoint(&unique_j_plus_1_steps) { // If two different classes have a non-empty intersection, return false. return false; @@ -346,14 +339,14 @@ pub fn gs_scale( n: usize, equave: RawJiRatio, ) -> Result, Box> { - if gs.len() == 0 || n == 0 || equave == RawJiRatio::UNISON { + if gs.is_empty() || n == 0 || equave == RawJiRatio::UNISON { Err(Box::new(ScaleError::CannotMakeScale)) } else if equave == RawJiRatio::UNISON { Err(Box::new(BadJiArith::LogDivByUnison)) } else { let equave = equave.magnitude(); // Take the equave's magnitude let mut result = vec![]; - let mut gs_cycle = gs.into_iter().cycle(); + let mut gs_cycle = gs.iter().cycle(); let mut accumulator = RawJiRatio::UNISON; for _ in 0..n - 1 { accumulator = (accumulator * *gs_cycle.next().expect("`gs.len() > 0` in this branch, thus `gs.into_iter().cycle()` is infinite and can never run out") ).rd(equave); @@ -373,7 +366,6 @@ pub fn well_formed_necklace_in_ji_scale( ) -> Result, ScaleError> { if gcd(scale.len() as i64, gen_class as i64) == 1 { Ok((0..(scale.len())) - .into_iter() .map(|k| { (scale[(gen_class * (k + 1)) % scale.len()] / scale[(gen_class * k) % scale.len()]) .rd(RawJiRatio::OCTAVE) diff --git a/src/ji_ratio.rs b/src/ji_ratio.rs index 75501274..955c4387 100644 --- a/src/ji_ratio.rs +++ b/src/ji_ratio.rs @@ -253,8 +253,8 @@ impl RawJiRatio { RawJiRatio::OCTAVE, ]; - pub fn checked_product>(iter: I) -> Option { - iter.fold(Some(RawJiRatio::UNISON), |x, y| x?.checked_mul(&y)) + pub fn checked_product>(iter: &mut I) -> Option { + iter.try_fold(RawJiRatio::UNISON, |x, y| x.checked_mul(&y)) } pub fn checked_pow(&self, n: i32) -> Option { @@ -262,18 +262,14 @@ impl RawJiRatio { let mut result = Some(Self::UNISON); for _ in 0..n { result = result?.checked_mul(self); - if result == None { - return None; - } + result?; } result } else { let mut result = Some(Self::UNISON); for _ in 0..-n { result = result?.checked_div(self); - if result == None { - return None; - } + result?; } result } diff --git a/src/main.rs b/src/main.rs index e56a553d..2ec124ae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,6 @@ #![deny(warnings)] -const STEP_LETTERS: [&'static str; 12] = [ +const STEP_LETTERS: [&str; 12] = [ "", // 0 "X", // 1 "Ls", // 2 @@ -118,64 +118,71 @@ async fn main() -> Result<(), std::io::Error> { } fn guide_structure_to_json(structure: &GuideFrame, arity: usize) -> GuideResult { - match structure { - GuideFrame { - gs, - polyoffset, - multiplicity, - } => { - if *multiplicity == 1 { - GuideResult { - gs: gs - .into_iter() - .map(|cv| { - CountVector::from_iter(cv.into_inner().into_iter().map(|(k, v)| { - (STEP_LETTERS[min(arity, 12)].chars().nth(k).unwrap(), v) - })) - }) - .collect(), - aggregate: gs - .into_iter() - .map(|cv| { - CountVector::from_iter(cv.into_inner().into_iter().map(|(k, v)| { - (STEP_LETTERS[min(arity, 12)].chars().nth(k).unwrap(), v) - })) - }) - .fold(CountVector::::ZERO, |acc, v| acc.add(&v)), - polyoffset: polyoffset - .into_iter() - .map(|cv| { - CountVector::from_iter(cv.into_inner().into_iter().map(|(k, v)| { - (STEP_LETTERS[min(arity, 12)].chars().nth(k).unwrap(), v) - })) - }) - .collect(), - multiplicity: 1, - complexity: structure.complexity(), - } - } else { - GuideResult { - gs: gs - .into_iter() - .map(|cv| { - CountVector::from_iter(cv.into_inner().into_iter().map(|(k, v)| { - (STEP_LETTERS[min(arity, 12)].chars().nth(k).unwrap(), v) - })) - }) - .collect(), - aggregate: gs - .into_iter() - .map(|cv| { - CountVector::from_iter(cv.into_inner().into_iter().map(|(k, v)| { - (STEP_LETTERS[min(arity, 12)].chars().nth(k).unwrap(), v) - })) - }) - .fold(CountVector::::ZERO, |acc, v| acc.add(&v)), - polyoffset: vec![CountVector::::ZERO], - multiplicity: *multiplicity, - complexity: structure.complexity(), - } - } + let GuideFrame { + gs, + polyoffset, + multiplicity, + } = structure; + if *multiplicity == 1 { + GuideResult { + gs: gs + .iter() + .map(|cv| { + CountVector::from_tuples( + cv.into_inner().into_iter().map(|(k, v)| { + (STEP_LETTERS[min(arity, 12)].chars().nth(k).unwrap(), v) + }), + ) + }) + .collect(), + aggregate: gs + .iter() + .map(|cv| { + CountVector::from_tuples( + cv.into_inner().into_iter().map(|(k, v)| { + (STEP_LETTERS[min(arity, 12)].chars().nth(k).unwrap(), v) + }), + ) + }) + .fold(CountVector::::ZERO, |acc, v| acc.add(&v)), + polyoffset: polyoffset + .iter() + .map(|cv| { + CountVector::from_tuples( + cv.into_inner().into_iter().map(|(k, v)| { + (STEP_LETTERS[min(arity, 12)].chars().nth(k).unwrap(), v) + }), + ) + }) + .collect(), + multiplicity: 1, + complexity: structure.complexity(), + } + } else { + GuideResult { + gs: gs + .iter() + .map(|cv| { + CountVector::from_tuples( + cv.into_inner().into_iter().map(|(k, v)| { + (STEP_LETTERS[min(arity, 12)].chars().nth(k).unwrap(), v) + }), + ) + }) + .collect(), + aggregate: gs + .iter() + .map(|cv| { + CountVector::from_tuples( + cv.into_inner().into_iter().map(|(k, v)| { + (STEP_LETTERS[min(arity, 12)].chars().nth(k).unwrap(), v) + }), + ) + }) + .fold(CountVector::::ZERO, |acc, v| acc.add(&v)), + polyoffset: vec![CountVector::::ZERO], + multiplicity: *multiplicity, + complexity: structure.complexity(), } } } @@ -262,42 +269,40 @@ async fn word_result(req: Query) -> HttpResponse { "ji_tunings": ji_tunings, })) } + } else if step_sig.len() == 3 { + let ed_tunings = crate::equal::ed_tunings_for_ternary( + &step_sig, + crate::ji_ratio::RawJiRatio::OCTAVE, + 53, + 20.0, + 60.0, + ); + yield_now().await; + let profile = json!({ + "structure": None::, + "lm": monotone_lm(&word), + "ms": monotone_ms(&word), + "s0": monotone_s0(&word), + "mv": maximum_variety(&word), + }); + yield_now().await; + HttpResponse::Ok().json(json!({ + "profile": profile, + "brightest": brightest, + "ji_tunings": ji_tunings, + "ed_tunings": ed_tunings, + })) } else { - if step_sig.len() == 3 { - let ed_tunings = crate::equal::ed_tunings_for_ternary( - &step_sig, - crate::ji_ratio::RawJiRatio::OCTAVE, - 53, - 20.0, - 60.0, - ); - yield_now().await; - let profile = json!({ - "structure": None::, - "lm": monotone_lm(&word), - "ms": monotone_ms(&word), - "s0": monotone_s0(&word), - "mv": maximum_variety(&word), - }); - yield_now().await; - HttpResponse::Ok().json(json!({ - "profile": profile, - "brightest": brightest, - "ji_tunings": ji_tunings, - "ed_tunings": ed_tunings, - })) - } else { - let profile = json!({ - "structure": None::, - "mv": maximum_variety(&word), - }); - yield_now().await; - HttpResponse::Ok().json(json!({ - "brightest": brightest, - "profile": profile, - "ji_tunings": ji_tunings, - })) - } + let profile = json!({ + "structure": None::, + "mv": maximum_variety(&word), + }); + yield_now().await; + HttpResponse::Ok().json(json!({ + "brightest": brightest, + "profile": profile, + "ji_tunings": ji_tunings, + })) } }; timeout(TIMEOUT_DURATION, task).await.unwrap_or({ diff --git a/src/monzo.rs b/src/monzo.rs index c08ddbba..54dd9c13 100644 --- a/src/monzo.rs +++ b/src/monzo.rs @@ -43,7 +43,7 @@ macro_rules! monzo { $crate::monzo::Monzo::UNISON ); ($elem:expr; $n:expr) => ( - $crate::monzo::Monzo(nalgebra::SVector::::from_column_slice(&[$elem; crate::primes::SMALL_PRIMES_COUNT])) + $crate::monzo::Monzo(nalgebra::SVector::::from_column_slice(&[$elem; $crate::primes::SMALL_PRIMES_COUNT])) ); ($($x:expr),+ $(,)?) => ( $crate::monzo::Monzo::from_slice(&[$($x),+]) @@ -138,7 +138,7 @@ impl Monzo { ) } /// Whether the monzo is an interval with positive logarithmic size. - pub fn is_positive(self: Self) -> bool { + pub fn is_positive(self) -> bool { self.cents() > 0.0 } /// Tries to convert the JI ratio `numer`/`denom` into monzo form. @@ -149,7 +149,7 @@ impl Monzo { if denom == 0 { return Err(CantMakeMonzo::DenomCantBeZero); } - let numer_factors = factorize(numer.into()); + let numer_factors = factorize(numer); let numer_primes_too_big: Vec = numer_factors .iter() .copied() @@ -158,7 +158,7 @@ impl Monzo { if !numer_primes_too_big.is_empty() { Err(CantMakeMonzo::NumerExceededPrimeLimit(numer_primes_too_big)) } else { - let denom_factors = factorize(denom.into()); + let denom_factors = factorize(denom); let denom_primes_too_big: Vec = denom_factors .iter() .copied() @@ -1558,26 +1558,14 @@ impl Index for Monzo { impl std::ops::Mul for Monzo { type Output = Monzo; fn mul(self, coeff: i32) -> Self { - Monzo::from_slice( - &self - .0 - .into_iter() - .map(|ex| ex * (coeff as i32)) - .collect::>(), - ) + Monzo::from_slice(&self.0.into_iter().map(|ex| ex * coeff).collect::>()) } } impl std::ops::Div for Monzo { type Output = Monzo; fn div(self, coeff: i32) -> Self { - Monzo::from_slice( - &self - .0 - .into_iter() - .map(|ex| ex / (coeff as i32)) - .collect::>(), - ) + Monzo::from_slice(&self.0.into_iter().map(|ex| ex / coeff).collect::>()) } } @@ -1702,10 +1690,9 @@ pub fn l2_norm(v: Monzo) -> f64 { /// The unweighted L^\infty norm of a monzo. pub fn linf_norm(v: Monzo) -> f64 { - v.0.into_iter() + v.0.iter() .map(|x| (*x as f64)) .map(|x| x.abs()) - .into_iter() .reduce(f64::max) .unwrap_or(0.0) } @@ -1723,7 +1710,6 @@ pub fn weighted_l2_norm(weighting: Box, v: Monzo) -> f64 { /// The weighted $L^\infty$ norm of a monzo. pub fn weighted_linf_norm(weighting: Box, v: Monzo) -> f64 { weighting(v) - .into_iter() .map(|x| x.abs()) .into_iter() .reduce(f64::max) @@ -1731,9 +1717,8 @@ pub fn weighted_linf_norm(weighting: Box, v: Monzo) -> f64 { } #[allow(unused)] -fn tenney_weighting(v: Monzo) -> SVector { +fn tenney_weighting(v: Monzo) -> SVector { let vec = (0..SMALL_PRIMES_COUNT) - .into_iter() .map(|i| log_primes()[i] * (v[i] as f64)) .collect(); SVector::from_vec(vec) @@ -1746,7 +1731,7 @@ fn unweighting(v: Monzo) -> SVector { } #[allow(unused)] -fn weil_weighting(v: Monzo) -> SVector { +fn weil_weighting(v: Monzo) -> SVector { let diagonal: &[f64] = &log_primes()[0..SMALL_PRIMES_COUNT]; let m: SMatrix = SMatrix::from_fn(|r, c| { @@ -1847,7 +1832,7 @@ fn solve_linear_diophantine_rec(coeffs: &[i32], constant: i32, bound: i32) -> Ve .into_iter() .map(|x| x * (constant / d)) .collect::>(); - let result = homogeneous_solns + homogeneous_solns .into_iter() .map(|soln| { // Add `particular_soln` to each `soln` @@ -1856,8 +1841,7 @@ fn solve_linear_diophantine_rec(coeffs: &[i32], constant: i32, bound: i32) -> Ve .map(|(i, expon)| expon + particular_soln[i]) .collect::>() }) - .collect::>(); - result + .collect::>() } else { vec![] } @@ -1879,7 +1863,7 @@ fn solve_linear_diophantine_homogeneous(coeffs: &[i32], bound: i32) -> Vec= 3"); - let result = (-bound..=bound) + (-bound..=bound) .flat_map(|k| { let mut solns = solve_linear_diophantine_rec(tail, -k * head, bound); for vec in solns.iter_mut() { @@ -1887,8 +1871,7 @@ fn solve_linear_diophantine_homogeneous(coeffs: &[i32], bound: i32) -> Vec>(); - result + .collect::>() } } @@ -1912,7 +1895,7 @@ pub fn solve_step_sig(step_sig: &[usize], equave: Monzo, exponent_bound: i32) -> // assuming a particular solution exists. // It might happen that no solution exists, // since for example `gcd(a_1, ..., a_n)` might not divide a constant term. - let step_sig = step_sig.into_iter().map(|i| *i as i32).collect::>(); + let step_sig = step_sig.iter().map(|i| *i as i32).collect::>(); let iter_of_iters = equave .0 .into_iter() @@ -1929,7 +1912,7 @@ pub fn solve_step_sig(step_sig: &[usize], equave: Monzo, exponent_bound: i32) -> .collect(); let result: Vec> = result .into_iter() - .map(|vs| vs.iter().map(|v| Monzo::from_slice(&v)).collect::>()) + .map(|vs| vs.iter().map(|v| Monzo::from_slice(v)).collect::>()) .filter(|soln| soln.iter().all(|&step| step.is_positive())) .collect(); result diff --git a/src/primes.rs b/src/primes.rs index 4ffdcebd..c8a3d934 100644 --- a/src/primes.rs +++ b/src/primes.rs @@ -101,7 +101,7 @@ pub fn eratosthenes(n: u64) -> Vec { known_composites.dedup(); primes_so_far.extend( (i..=n) - .filter(|j| !known_composites.contains(&j)) + .filter(|j| !known_composites.contains(j)) .collect::>(), ); primes_so_far @@ -156,7 +156,7 @@ pub fn atkin(n: u64) -> Vec { } } for i in 7..=n { - if status[i as usize] == true { + if status[i as usize] { primes.push(i); for j in (0..n / (i * i)) .map(|k| (2 * k + 1) * i * i) diff --git a/src/utils.rs b/src/utils.rs index 0f445cac..eca20c11 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -50,8 +50,8 @@ where T: Clone, U: Clone, { - v1.into_iter() - .flat_map(|t| v2.into_iter().cloned().map(move |u| (t.clone(), u))) + v1.iter() + .flat_map(|t| v2.iter().cloned().map(move |u| (t.clone(), u))) .collect() } @@ -72,9 +72,9 @@ where } /// Check if given subset is a maximal set in the collection. -pub fn is_maximal_in(set: Vec, sets: &Vec>) -> bool +pub fn is_maximal_in(set: Vec, sets: &Vec>) -> bool where - T: Clone + Ord, + T: Clone + Eq + Ord, { for set2 in sets { if (set.clone().into_iter().collect::>()) @@ -248,7 +248,7 @@ pub fn lcm(m: u64, n: u64) -> u64 { /// `x_0, x_1, ..., x_n` /// to `coeffs[0] x_0 + coeffs[1] x_1 + ... + coeffs[n] x_n = gcd(coeffs)`. pub fn bezout(coeffs: &[i32]) -> (i32, Vec) { - assert!(coeffs.len() > 0, "`coeffs` should not be empty"); + debug_assert!(!coeffs.is_empty(), "`coeffs` should not be empty"); if coeffs.len() == 1 { (coeffs[0], vec![1]) } else if coeffs.len() == 2 { diff --git a/src/words.rs b/src/words.rs index c5753a49..0ac89b1f 100644 --- a/src/words.rs +++ b/src/words.rs @@ -1,10 +1,8 @@ +use itertools::Itertools; +use serde::Serialize; use std::cmp::{max, Ordering}; use std::collections::{BTreeMap, BTreeSet, HashSet}; use std::hash::Hash; -use std::usize; - -use itertools::Itertools; -use serde::Serialize; use crate::utils::{gcd, modinv, ScaleError}; @@ -32,8 +30,8 @@ impl Subtendable for CountVector { type Interval = CountVector; fn interval_from_slice(slice: &[Self]) -> Self::Interval { slice - .into_iter() - .fold(CountVector::ZERO, |a, b| CountVector::add(&a, &b)) + .iter() + .fold(CountVector::ZERO, |a, b| CountVector::add(&a, b)) } } @@ -60,12 +58,17 @@ impl CountVector { /// Creates a zero count vector. pub const ZERO: Self = CountVector(BTreeMap::::new()); + /// Whether the `CountVector` is empty. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + /// The sum of the absolute values of the components. pub fn len(&self) -> usize { - self.0.values().map(|v| v.abs() as usize).sum() + self.0.values().map(|v| v.unsigned_abs() as usize).sum() } /// The sum of two count vectors. Each component gets added. - pub fn add(self: &Self, w: &Self) -> Self + pub fn add(&self, w: &Self) -> Self where T: Ord + Clone, { @@ -83,7 +86,7 @@ impl CountVector { Self(result) } /// Additive inverse of a `CountVector`. - pub fn neg(self: &Self) -> Self + pub fn neg(&self) -> Self where T: Ord + Clone + Send + Sync, { @@ -91,7 +94,7 @@ impl CountVector { } /// Multiply a CountVector by a scalar. - pub fn scalar_mul(self: &Self, lambda: i32) -> Self + pub fn scalar_mul(&self, lambda: i32) -> Self where T: Ord + Clone + Send + Sync, { @@ -130,7 +133,7 @@ impl CountVector { ) } /// Convert a `BTreeSet` to a `CountVector` (with every nonzero component equal to 1). - pub fn from_iter(iter: impl Iterator) -> CountVector + pub fn from_tuples(iter: impl Iterator) -> CountVector where T: Ord + Send, { @@ -237,7 +240,7 @@ where } else { let length = scale1.len(); for i in 0..length { - if rotate(&scale2, i) == scale1.to_vec() { + if rotate(scale2, i) == scale1.to_vec() { // scale2 has been rotated i steps to the left. return Some(i); } @@ -258,7 +261,7 @@ where let len = vec1.len(); for i in 0..len { let vec2_rotated = rotate(vec2, i); // vec2 has been rotated i steps to the left. - if &vec2_rotated == vec1 { + if vec2_rotated == vec1 { return Some(i); } } @@ -307,7 +310,7 @@ where } else { let mut max = 0; let floor_half: usize = scale.len() / 2; - let distinct_letters = scale.into_iter().cloned().collect::>(); + let distinct_letters = scale.iter().cloned().collect::>(); for subword_length in 1..=floor_half { for letter in distinct_letters.iter() { let counts = CountVector::distinct_spectrum(scale, subword_length) @@ -426,7 +429,7 @@ pub fn mos_mode(a: usize, b: usize, brightness: usize) -> Result, Sc } else { let (mos, dark_gen) = darkest_mos_mode_and_gen_bresenham(a, b); let dark_gen_step_count: usize = dark_gen.len(); - Ok(rotate(&mos, (brightness * dark_gen_step_count) as usize)) + Ok(rotate(&mos, brightness * dark_gen_step_count)) } } @@ -444,7 +447,7 @@ pub fn are_conjugate(s1: &[T], s2: &[T]) -> bool where T: Clone + Eq, { - (s1.len() == s2.len()) && { (0..s1.len()).any(|i| rotate(&s1, i) == s2.to_vec()) } + (s1.len() == s2.len()) && { (0..s1.len()).any(|i| rotate(s1, i) == s2.to_vec()) } } /// [Letterwise substitution](https://en.xen.wiki/w/MOS_substitution) for scale words. @@ -457,7 +460,7 @@ where { let mut ret = vec![]; let mut i: usize = 0; - if filler.len() > 0 { + if !filler.is_empty() { for letter in template { if *letter == *x { ret.push(filler[i % filler.len()].clone()); @@ -485,7 +488,6 @@ fn mos_substitution_scales_one_perm(n0: usize, n1: usize, n2: usize) -> Vec>(); let gener_size = gener.len(); (0..(n1 + n2)) - .into_iter() .map(|i| { subst::( &template, @@ -496,12 +498,6 @@ fn mos_substitution_scales_one_perm(n0: usize, n1: usize, n2: usize) -> Vec Vec { - let sorted_modes = rotations(scale).into_iter().sorted().collect::>(); - let result = sorted_modes[0].to_owned(); - result -} - /// The lexicographically brightest mode of a word (where the letters are in their usual order). /// (Booth's algorithm) pub fn least_mode(scale: &[Letter]) -> Vec { @@ -517,7 +513,7 @@ pub fn booth(scale: &[Letter]) -> usize { let mut k: usize = 0; for j in 1..2 * n { let mut i = f[j - k - 1]; - while i != usize::MAX && s[(j % n) as usize] != s[k.wrapping_add(i).wrapping_add(1) % n] { + while i != usize::MAX && s[j % n] != s[k.wrapping_add(i).wrapping_add(1) % n] { if s[j % n] < s[k.wrapping_add(i).wrapping_add(1) % n] { k = j.wrapping_sub(i).wrapping_sub(1); } @@ -629,7 +625,7 @@ pub fn replace(scale: &[Letter], from: Letter, to: Letter) -> Vec { /// Delete all instances of one letter. pub fn delete(scale: &[Letter], letter: Letter) -> Vec { - scale.iter().filter(|x| **x != letter).map(|x| *x).collect() + scale.iter().filter(|x| **x != letter).copied().collect() } /// If `scale` is ternary, return whether identifying L = m, m = s, and s = 0 results in a MOS. @@ -720,7 +716,7 @@ where /// The chirality of a scale word. pub fn chirality(word: &[Letter]) -> Chirality { - let mut modes = rotations(&word); + let mut modes = rotations(word); modes.sort_unstable(); let word_rev: Vec = word.iter().cloned().rev().collect();