euclidian_rythms/
lib.rs

1extern crate smallvec;
2
3use smallvec::SmallVec;
4
5pub fn euclidian_rythm(p: &mut [u8], pulses: usize) -> Result<(), &'static str> {
6    let steps = p.len();
7    let mut pattern = SmallVec::from_slice(p);
8    pattern.clear();
9
10    if pulses > steps {
11        return Err("more pulses than steps.");
12    }
13
14    let mut divisor = steps - pulses;
15
16    let mut level = 0;
17    let mut counts = SmallVec::<[usize; 64]>::new();
18    let mut remainders = SmallVec::<[usize; 64]>::new();
19
20    remainders.push(pulses);
21
22    // Run the euclid algorithm, store all the intermediate results
23    loop {
24        counts.push(divisor / remainders[level]);
25        let r = remainders[level];
26        remainders.push(divisor % r);
27
28        divisor = remainders[level];
29        level += 1;
30
31        if remainders[level] <= 1 {
32            break;
33        }
34    }
35    counts.push(divisor);
36
37    // Build the pattern
38    fn build(
39        counts: &[usize],
40        pattern: &mut SmallVec<[u8; 64]>,
41        remainders: &[usize],
42        level: isize,
43    ) {
44        if level == -1 {
45            pattern.push(0);
46        } else if level == -2 {
47            pattern.push(1);
48        } else {
49            for _ in 0..counts[level as usize] {
50                build(counts, pattern, remainders, level - 1);
51            }
52            if remainders[level as usize] != 0 {
53                build(counts, pattern, remainders, level - 2);
54            }
55        }
56    }
57
58    build(
59        counts.as_slice(),
60        &mut pattern,
61        remainders.as_slice(),
62        level as isize,
63    );
64
65    // Put a 1 on the first step
66    let index_first_one = pattern.iter().position(|&x| x == 1).unwrap();
67    pattern.rotate_left(index_first_one);
68
69    p.copy_from_slice(&pattern);
70
71    return Ok(());
72}
73
74#[cfg(test)]
75mod tests {
76    use euclidian_rythm;
77    #[test]
78    fn it_works() {
79        let mut pattern = [0 as u8; 8];
80        let pulses = 4;
81        euclidian_rythm(&mut pattern, pulses).unwrap();
82        println!("{:?}", pattern);
83
84        let mut pattern = [0 as u8; 9];
85        let pulses = 3;
86        euclidian_rythm(&mut pattern, pulses).unwrap();
87        println!("{:?}", pattern);
88
89        let mut pattern = [0 as u8; 12];
90        let pulses = 7;
91        euclidian_rythm(&mut pattern, pulses).unwrap();
92        println!("{:?}", pattern);
93
94        let mut pattern = [0 as u8; 13];
95        let pulses = 5;
96        euclidian_rythm(&mut pattern, pulses).unwrap();
97        println!("{:?}", pattern);
98
99        let mut pattern = [0 as u8; 31];
100        let pulses = 7;
101        euclidian_rythm(&mut pattern, pulses).unwrap();
102        println!("{:?}", pattern);
103    }
104}