MOS substitution: Difference between revisions

Inthar (talk | contribs)
Tags: Mobile edit Mobile web edit
Inthar (talk | contribs)
Line 37: Line 37:
where <math>\mathbf{z}</math> is the new step size inserted, <math>\mathbf{y}</math> is the step size in the starting MOS identified with <math>\mathbf{z}</math> by the template MOS, and <math>k</math> is the brightness of the mode of the filling MOS used (<math>k = 0</math> corresponds to the darkest mode; the conventional understanding of "brightness" makes sense as <math>\mathbf{L}</math> (resp. <math>\mathbf{m}</math>) > <math>\mathbf{s}</math>).
where <math>\mathbf{z}</math> is the new step size inserted, <math>\mathbf{y}</math> is the step size in the starting MOS identified with <math>\mathbf{z}</math> by the template MOS, and <math>k</math> is the brightness of the mode of the filling MOS used (<math>k = 0</math> corresponds to the darkest mode; the conventional understanding of "brightness" makes sense as <math>\mathbf{L}</math> (resp. <math>\mathbf{m}</math>) > <math>\mathbf{s}</math>).


== Algorithm ==
Rust code for generating MOS substitution scales:
<syntaxhighlight lang="rs>
/// Return the collection of all MOS substitution scales `subst n0 x (n1 y n2 z)`
/// where the template MOS is assumed to have step signature `n0*0 (n1 + n2)*X` (`X` is the slot letter)
/// and the filling MOS has step signature `n1*1 n2*2`.
fn mos_substitution_scales_one_perm(n0: usize, n1: usize, n2: usize) -> Vec<Vec<Letter>> {
    let (template, _) = darkest_mos_mode_and_gen_bresenham(n0, n1 + n2);
    let (filler, gener) = darkest_mos_mode_and_gen_bresenham(n1, n2);
    let filler = filler.into_iter().map(|x| x + 1).collect::<Vec<_>>();
    let gener_size = gener.len();
    (0..(n1 + n2))
        .map(|i| {
            subst(
                &template,
                1usize,
                &rotate(&filler, (i * gener_size) % filler.len()),
            )
        })
        .collect()
}
/// The set of all [MOS substitution](https://en.xen.wiki/w/User:Inthar/MOS_substitution) ternary scales.
pub fn mos_substitution_scales(sig: &[usize]) -> Vec<Vec<Letter>> {
    let (n0, n1, n2) = (sig[0], sig[1], sig[2]);
    // Only need 3 permutations of (0, 1, 2) for the MOS substitution patterns n0*_ (n1*_ n2*_)
    let redundant_list = [
        // n0L (n1m n2s)
        mos_substitution_scales_one_perm(n0, n1, n2),
        // n1m (n0L n2s)
        mos_substitution_scales_one_perm(n1, n2, n0)
            .into_iter()
            .map(|scale| scale.into_iter().map(|x| (x + 1) % 3).collect())
            .collect(),
        // n2s (n0L n1m)
        mos_substitution_scales_one_perm(n2, n0, n1)
            .into_iter()
            .map(|scale| {
                scale
                    .into_iter()
                    .map(|x| if x == 0 { 2 } else { (x - 1) % 3 })
                    .collect()
            })
            .collect(),
    ]
    .concat();
    // Canonicalize every scale and remove duplicates
    redundant_list
        .into_iter()
        .map(|scale| least_mode(&scale))
        .sorted()
        .dedup()
        .collect()
}
</syntaxhighlight>
==Examples==
==Examples==
In the following tables, the interval class of the generators stacked in the generator sequence is such that the perfect generator has fewer <math>\mathbf{X}</math> steps than the imperfect counterpart.
In the following tables, the interval class of the generators stacked in the generator sequence is such that the perfect generator has fewer <math>\mathbf{X}</math> steps than the imperfect counterpart.