Skip to content

Commit

Permalink
remove unneeded naive impl of least mode; fix clippy warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
inthar-raven committed Aug 10, 2024
1 parent 21fa3d4 commit 673ceb7
Show file tree
Hide file tree
Showing 12 changed files with 193 additions and 231 deletions.
6 changes: 5 additions & 1 deletion benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Letter> {
let sorted_modes = rotations(scale).into_iter().sorted().collect::<Vec<_>>();
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);
}
});
});
Expand Down
24 changes: 11 additions & 13 deletions src/comb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ fn partitions_exact_part_count_rec(n: usize, m: usize, parts: usize) -> Vec<Vec<
(n, 0, _) if n > 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()
Expand All @@ -27,18 +26,14 @@ fn partitions_exact_part_count_rec(n: usize, m: usize, parts: usize) -> Vec<Vec<

/// Return the collection of all partitions of `n` with exactly `k` parts.
pub fn partitions_exact_part_count(n: usize, parts: usize) -> Vec<Vec<usize>> {
(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<Vec<usize>> {
(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<Vec<usize>> {
Expand All @@ -56,7 +51,6 @@ fn partitions_rec(n: usize, m: usize) -> Vec<Vec<usize>> {
vec![]
}
_ => (0..=m)
.into_iter()
.flat_map(|k| {
partitions_rec(n - m, k)
.into_iter()
Expand Down Expand Up @@ -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<VecPerm, PermutationError> {
let domain = (0..slice.len()).collect::<BTreeSet<_>>();
let image = slice.into_iter().cloned().collect::<BTreeSet<_>>();
if slice.len() == 0 {
let image = slice.iter().cloned().collect::<BTreeSet<_>>();
if slice.is_empty() {
// return the empty perm
Ok(VecPerm { pi: vec![] })
} else if image != domain {
Expand Down Expand Up @@ -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() {
Expand All @@ -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<Self, PermutationError> {
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<Vec<usize>, 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()..]);
}
Expand Down
5 changes: 2 additions & 3 deletions src/equal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ pub fn ed_tunings_for_ternary(
aber_upper: f64,
) -> Vec<Vec<i32>> {
(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 =
Expand All @@ -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.
Expand Down Expand Up @@ -140,7 +139,7 @@ macro_rules! val {
$crate::equal::Val::ZERO
);
($elem:expr; $n:expr) => (
$crate::equal::Val(nalgebra::RowSVector::<i32, {crate::primes::SMALL_PRIMES_COUNT}>::from_row_slice(&[$elem; crate::primes::SMALL_PRIMES_COUNT]))
$crate::equal::Val(nalgebra::RowSVector::<i32, {$crate::primes::SMALL_PRIMES_COUNT}>::from_row_slice(&[$elem; $crate::primes::SMALL_PRIMES_COUNT]))
);
($($x:expr),+ $(,)?) => (
$crate::equal::Val::from_slice(&[$($x),+])
Expand Down
45 changes: 17 additions & 28 deletions src/guide.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]))
Expand All @@ -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| <T as Subtendable>::interval_from_slice(&subword))
.collect()
Expand All @@ -49,7 +48,6 @@ where
pub fn wfgs_list(neck: &[usize]) -> Vec<Vec<CountVector<usize>>> {
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()
Expand All @@ -59,7 +57,6 @@ pub fn wfgs_list(neck: &[usize]) -> Vec<Vec<CountVector<usize>>> {
pub fn wfgs_list_of_len(l: usize, neck: &[usize]) -> Vec<Vec<CountVector<usize>>> {
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())
Expand All @@ -73,7 +70,6 @@ fn wfgs_list_for_subscale(subscale: &[CountVector<usize>]) -> Vec<Vec<CountVecto
} else {
let len = subscale.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_for_subscale(k, subscale))
.collect()
Expand Down Expand Up @@ -129,12 +125,12 @@ impl GuideFrame {
}
// Try to get simple or interleaved guide frames with k-step generators.
pub fn try_simple_or_interleaved(scale: &[usize], k: usize) -> Vec<Self> {
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()
})
Expand All @@ -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`.
Expand All @@ -172,7 +164,7 @@ impl GuideFrame {
let offsets: Vec<CountVector<usize>> =
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,
Expand All @@ -183,8 +175,7 @@ impl GuideFrame {
.dedup()
.collect::<Vec<_>>()
} 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,
Expand All @@ -202,7 +193,7 @@ impl GuideFrame {
}
pub fn try_multiple(scale: &[usize], multiplicity: usize, k: usize) -> Vec<Self> {
// 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;
Expand All @@ -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)]
Expand All @@ -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()
Expand Down Expand Up @@ -267,15 +257,14 @@ impl GuideFrame {
.map(|p| p as usize)
.collect();
let simple_guide_moses: Vec<GuideFrame> = Self::try_simple_or_interleaved(scale, k);
let multiple_guide_moses: Vec<GuideFrame> =
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<GuideFrame> = 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()
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/interval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
26 changes: 9 additions & 17 deletions src/ji.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ use crate::words::{rotate, CountVector};
/// not including the unison.
pub fn specified_odd_limit(odds: &[u64]) -> Vec<RawJiRatio> {
let odds: Vec<u64> = 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()
Expand Down Expand Up @@ -149,7 +149,6 @@ pub fn step_form(cumul_form: &[RawJiRatio]) -> Vec<RawJiRatio> {
[
&[cumul_form[0]],
(0..cumul_form.len() - 1)
.into_iter()
.map(|i| cumul_form[i + 1] / cumul_form[i])
.collect::<Vec<_>>()
.as_slice(),
Expand All @@ -160,7 +159,7 @@ pub fn step_form(cumul_form: &[RawJiRatio]) -> Vec<RawJiRatio> {
/// Convert a step form into a cumulative form.
pub fn cumulative_form(step_form: &[RawJiRatio]) -> Vec<RawJiRatio> {
step_form
.into_iter()
.iter()
.scan(RawJiRatio::UNISON, |acc, &step| {
*acc *= step;
Some(*acc)
Expand All @@ -170,10 +169,7 @@ pub fn cumulative_form(step_form: &[RawJiRatio]) -> Vec<RawJiRatio> {

/// Modes of a JI scale written in cumulative form.
pub fn ji_scale_modes(scale: &[RawJiRatio]) -> Vec<Vec<RawJiRatio>> {
(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`.
Expand All @@ -182,7 +178,6 @@ pub fn harmonic_mode(mode_num: u64) -> Result<Vec<RawJiRatio>, 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())
}
Expand All @@ -194,15 +189,14 @@ pub fn harmonic_mode_no_oct(mode_num: u64) -> Result<Vec<RawJiRatio>, 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())
}
}

/// 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()
Expand Down Expand Up @@ -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<RawJiRatio> =
interval_classes[i].iter().cloned().collect();
for j in (i + 1)..(n - 1) {
let unique_j_plus_1_steps: BTreeSet<RawJiRatio> =
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<RawJiRatio> = 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;
Expand All @@ -346,14 +339,14 @@ pub fn gs_scale(
n: usize,
equave: RawJiRatio,
) -> Result<Vec<RawJiRatio>, Box<dyn std::error::Error>> {
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);
Expand All @@ -373,7 +366,6 @@ pub fn well_formed_necklace_in_ji_scale(
) -> Result<Vec<RawJiRatio>, 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)
Expand Down
Loading

0 comments on commit 673ceb7

Please sign in to comment.