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 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 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 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}