MOS substitution: Difference between revisions
| Line 40: | Line 40: | ||
Rust code for generating MOS substitution scales: | Rust code for generating MOS substitution scales: | ||
<syntaxhighlight lang="rs> | <syntaxhighlight lang="rs> | ||
/// Return the darkest mode of the MOS axby and the dark generator, using the Bresenham line algorithm. | |||
/// We chose the darkest mode rather than the brightest because this is the mode with brightness == 0. | |||
pub fn darkest_mos_mode_and_gen_bresenham( | |||
a: usize, | |||
b: usize, | |||
) -> (Vec<Letter>, CountVector<Letter>) { | |||
let d = gcd(a as u64, b as u64) as usize; | |||
if d == 1 { | |||
let count_gen_steps = modinv(a as i64, a as i64 + b as i64) | |||
.expect("The dark generator is a (|L|⁻¹ mod |scale|)-step, since stacking it |L| times results in the s step (mod period).") | |||
as usize; | |||
let mut result_scale: Vec<usize> = vec![]; | |||
// Start from the origin (0, 0) | |||
let (mut current_x, mut current_y) = (0usize, 0usize); | |||
while (current_x, current_y) != (a, b) { | |||
if a * (current_y) >= b * (current_x + 1) { | |||
// If going east (making a (1, 0) step) doesn't lead to going below the line y == b/a*x, | |||
current_x += 1; // append the x step and reflect the change in the plane vector. | |||
result_scale.push(0); | |||
} else { | |||
// Else, make a (0, 1) step. | |||
current_y += 1; | |||
result_scale.push(1); | |||
} | |||
} | |||
// Get the dark generator. We know how many steps and that this will give the perfect generator, not the | |||
// augmented one, since we just got the darkest mode. | |||
let result_gen = CountVector::from_slice(&result_scale[0..count_gen_steps]); | |||
(result_scale, result_gen) | |||
} else { | |||
let (prim_mos, gen) = darkest_mos_mode_and_gen_bresenham(a / d, b / d); | |||
(prim_mos.repeat(d), gen) | |||
} | |||
} | |||
/// Return the collection of all MOS substitution scales `subst n0 x (n1 y n2 z)` | /// Return the collection of all MOS substitution scales `subst n0 x (n1 y n2 z)` | ||
| Line 94: | Line 128: | ||
} | } | ||
</syntaxhighlight> | </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. | ||