1use crate::defaults::{FloatType, UnsignedIntegerType};
16use crate::error::{Error, Result};
17
18const OFFSET_TOLERANCE: FloatType = 1e-9;
20
21const VALID_DENOMINATORS: [UnsignedIntegerType; 8] = [1, 2, 4, 8, 16, 32, 64, 128];
23
24#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
27#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
28pub enum OffsetAlign {
29 #[default]
32 Quantize,
33 Start,
35 End,
37}
38
39#[derive(Clone, Debug, PartialEq)]
41#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
42pub struct MeterTerminal {
43 numerator: UnsignedIntegerType,
44 denominator: UnsignedIntegerType,
45 weight: FloatType,
46 parts: Vec<MeterTerminal>,
49 #[cfg_attr(feature = "serde", serde(default))]
53 summed_numerator: bool,
54}
55
56impl MeterTerminal {
57 pub fn new(numerator: UnsignedIntegerType, denominator: UnsignedIntegerType) -> Result<Self> {
59 if numerator == 0 {
60 return Err(Error::Meter(
61 "a meter terminal numerator must be non-zero".to_string(),
62 ));
63 }
64 if denominator == 0 {
65 return Err(Error::Meter(
66 "a meter terminal denominator must be non-zero".to_string(),
67 ));
68 }
69 Ok(Self {
70 numerator,
71 denominator,
72 weight: 1.0,
73 parts: Vec::new(),
74 summed_numerator: false,
75 })
76 }
77
78 pub fn from_ratio_string(ratio: &str) -> Result<Self> {
80 let (numerator, denominator) = split_ratio(ratio)?;
81 Self::new(numerator, denominator)
82 }
83
84 pub fn from_partition_string(written: &str) -> Result<Self> {
95 let mut parts = Vec::new();
96 let tokens: Vec<&str> = written.split('+').map(str::trim).collect();
97 let mut denominators: Vec<UnsignedIntegerType> = vec![0; tokens.len()];
100 let mut carried = None;
101 for (index, token) in tokens.iter().enumerate().rev() {
102 if let Some((_, denominator)) = token.split_once('/') {
103 carried = Some(parse_number(denominator)?);
104 }
105 denominators[index] = carried.ok_or_else(|| {
106 Error::Meter(format!(
107 "cannot read a denominator from {token:?} in {written:?}"
108 ))
109 })?;
110 }
111
112 parts.reserve(tokens.len());
113 for (token, denominator) in tokens.iter().zip(denominators) {
114 let numerator = parse_number(token.split('/').next().unwrap_or(token))?;
115 parts.push(Self::new(numerator, denominator)?);
116 }
117 let mut span = Self::from_parts(parts, written)?;
118 span.summed_numerator = tokens.iter().any(|token| !token.contains('/'));
119 Ok(span)
120 }
121
122 #[must_use]
128 pub fn summed_numerator(&self) -> bool {
129 self.summed_numerator
130 }
131
132 pub fn set_summed_numerator(&mut self, summed: bool) {
134 self.summed_numerator = summed;
135 }
136
137 pub fn from_parts_given(parts: Vec<Self>) -> Result<Self> {
143 Self::from_parts(parts, "a list of spans")
144 }
145
146 fn from_parts(mut parts: Vec<Self>, written: &str) -> Result<Self> {
147 if parts.len() == 1 {
148 return Ok(parts.remove(0));
151 }
152 Self::joining(parts, written)
153 }
154
155 fn joining(parts: Vec<Self>, written: &str) -> Result<Self> {
159 let shared = parts
160 .iter()
161 .map(Self::denominator)
162 .reduce(num::integer::lcm)
163 .ok_or_else(|| Error::Meter(format!("{written:?} is no meter at all")))?;
164 let total = parts
165 .iter()
166 .map(|part| part.numerator() * (shared / part.denominator()))
167 .sum();
168 let mut span = Self::new(total, shared)?;
169 *span.parts_mut() = parts;
170 Ok(span)
171 }
172
173 #[must_use]
175 pub fn numerator(&self) -> UnsignedIntegerType {
176 self.numerator
177 }
178
179 #[must_use]
181 pub fn denominator(&self) -> UnsignedIntegerType {
182 self.denominator
183 }
184
185 #[must_use]
187 pub fn quarter_length(&self) -> FloatType {
188 FloatType::from(self.numerator) * (4.0 / FloatType::from(self.denominator))
189 }
190
191 pub fn offset_to_address(&self, offset: FloatType) -> Result<Vec<usize>> {
195 let length = self.quarter_length();
196 if offset.is_nan() || offset < 0.0 || offset >= length {
197 return Err(Error::Meter(format!(
198 "cannot access from qLenPos {}",
199 super::offset_repr(offset)
200 )));
201 }
202 let index = self.offset_to_index(offset)?;
203 let mut address = vec![index];
204 let (start, _) = self.offset_to_span(offset, false)?;
205 let part = &self.parts[index];
206 if !part.is_empty() {
207 address.extend(part.offset_to_address(offset - start)?);
208 }
209 Ok(address)
210 }
211
212 #[must_use]
217 pub fn weight(&self) -> FloatType {
218 if self.parts.is_empty() {
219 self.weight
220 } else {
221 self.parts.iter().map(Self::weight).sum()
222 }
223 }
224
225 pub fn set_weight(&mut self, weight: FloatType) {
232 self.weight = weight;
233 let whole = self.quarter_length();
234 if self.parts.is_empty() || whole == 0.0 {
235 return;
236 }
237 for part in &mut self.parts {
238 let share = part.quarter_length() / whole;
239 part.set_weight(weight * share);
240 }
241 }
242
243 #[must_use]
245 pub fn parts(&self) -> &[MeterTerminal] {
246 &self.parts
247 }
248
249 pub fn parts_mut(&mut self) -> &mut Vec<MeterTerminal> {
251 &mut self.parts
252 }
253
254 #[must_use]
256 pub fn len(&self) -> usize {
257 self.parts.len()
258 }
259
260 #[must_use]
262 pub fn is_empty(&self) -> bool {
263 self.parts.is_empty()
264 }
265
266 #[must_use]
269 pub fn depth(&self) -> usize {
270 self.parts
271 .iter()
272 .map(|part| 1 + part.depth())
273 .max()
274 .unwrap_or(0)
275 }
276
277 #[must_use]
280 pub fn flattened(&self) -> Vec<MeterTerminal> {
281 if self.parts.is_empty() {
282 return vec![self.clone()];
283 }
284 self.parts
285 .iter()
286 .flat_map(MeterTerminal::flattened)
287 .collect()
288 }
289
290 pub fn flatten(&self) -> Result<Self> {
293 Self::joining(self.flattened(), "a flattened span")
296 }
297
298 #[must_use]
300 pub fn flat_weights(&self) -> Vec<FloatType> {
301 self.flattened().iter().map(MeterTerminal::weight).collect()
302 }
303
304 #[must_use]
308 pub fn ratio_equal(&self, other: &Self) -> bool {
309 self.numerator == other.numerator && self.denominator == other.denominator
310 }
311
312 pub fn partition_by_parts(&mut self, parts: &[&str]) -> Result<()> {
317 let mut built = Vec::with_capacity(parts.len());
318 for part in parts {
319 built.push(MeterTerminal::from_ratio_string(part)?);
320 }
321 let total: FloatType = built.iter().map(MeterTerminal::quarter_length).sum();
322 if (total - self.quarter_length()).abs() > OFFSET_TOLERANCE {
323 return Err(Error::Meter(format!(
324 "Cannot set partition by {}",
325 python_list(parts)
326 )));
327 }
328 let held = self.weight();
329 self.parts = built;
330 self.set_weight(held);
331 Ok(())
332 }
333
334 pub fn partition_by_count(&mut self, count: usize, load_default: bool) -> Result<()> {
340 let options = self.partition_options();
341 let chosen = options.iter().find(|option| option.len() == count);
342 let chosen = match chosen {
343 Some(option) => option.clone(),
344 None => {
345 if !load_default || options.is_empty() {
346 return Err(Error::Meter(format!(
347 "Cannot set partition by {count} ({}/{})",
348 self.numerator, self.denominator
349 )));
350 }
351 options[0].clone()
352 }
353 };
354 let borrowed: Vec<&str> = chosen.iter().map(String::as_str).collect();
355 self.partition_by_parts(&borrowed)
356 }
357
358 pub fn partition_by_list(&mut self, numerators: &[UnsignedIntegerType]) -> Result<()> {
369 if numerators.is_empty() {
370 return Err(Error::Meter(
371 "cannot partition a meter into nothing".to_string(),
372 ));
373 }
374 let total: UnsignedIntegerType = numerators.iter().sum();
375 for multiple in 1..=8 {
376 if total != self.numerator * multiple {
377 continue;
378 }
379 let denominator = self.denominator * multiple;
380 let parts: Vec<String> = numerators
381 .iter()
382 .map(|numerator| format!("{numerator}/{denominator}"))
383 .collect();
384 let borrowed: Vec<&str> = parts.iter().map(String::as_str).collect();
385 return self.partition_by_parts(&borrowed);
386 }
387 let asked: Vec<UnsignedIntegerType> = numerators.to_vec();
388 let matching = self.partition_options().into_iter().find(|option| {
389 option
390 .iter()
391 .map(|part| {
392 part.split('/')
393 .next()
394 .and_then(|numerator| numerator.parse().ok())
395 })
396 .collect::<Option<Vec<UnsignedIntegerType>>>()
397 == Some(asked.clone())
398 });
399 if let Some(option) = matching {
400 let borrowed: Vec<&str> = option.iter().map(String::as_str).collect();
401 return self.partition_by_parts(&borrowed);
402 }
403 Err(Error::Meter(format!(
404 "Cannot set partition by {} ({}/{})",
405 python_list(numerators),
406 self.numerator,
407 self.denominator
408 )))
409 }
410
411 pub fn subdivide(&mut self, count: usize) -> Result<()> {
414 self.partition_by_count(count, false)
415 }
416
417 pub fn subdivide_partitions_equal(&mut self, divisions: Option<usize>) -> Result<()> {
427 for part in &mut self.parts {
428 let count = match divisions {
429 Some(count) => count,
430 None => match part.numerator {
431 1 | 2 | 4 | 8 | 16 | 32 | 64 => 2,
432 3 => 3,
433 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 => (part.numerator / 3) as usize,
434 other => other as usize,
435 },
436 };
437 part.partition_by_count(count, false)?;
438 }
439 Ok(())
440 }
441
442 fn part_at(&self, path: &[usize]) -> &Self {
444 path.iter().fold(self, |span, index| &span.parts[*index])
445 }
446
447 fn part_at_mut(&mut self, path: &[usize]) -> &mut Self {
448 path.iter()
449 .fold(self, |span, index| &mut span.parts[*index])
450 }
451
452 fn subdivide_parts_of(
456 &mut self,
457 spans: &[Vec<usize>],
458 divisions: Option<usize>,
459 ) -> Result<Vec<Vec<usize>>> {
460 let mut deeper = Vec::new();
461 for path in spans {
462 let span = self.part_at_mut(path);
463 span.subdivide_partitions_equal(divisions)?;
464 for index in 0..span.len() {
465 let mut child = path.clone();
466 child.push(index);
467 deeper.push(child);
468 }
469 }
470 Ok(deeper)
471 }
472
473 pub fn subdivide_nested_hierarchy(
493 &mut self,
494 depth: usize,
495 first_partition_form: Option<UnsignedIntegerType>,
496 normalize_denominators: bool,
497 ) -> Result<()> {
498 self.partition_by_count(1, false)?;
499 if depth == 0 {
500 return Ok(());
501 }
502 let form = first_partition_form.unwrap_or(self.numerator);
503 let first = match form {
504 1 | 2 | 4 | 8 | 16 | 32 => 2,
505 3 => 3,
506 other => other as usize,
507 };
508 self.subdivide_partitions_equal(Some(first))?;
509 self.subdivide_nested_below_the_first(depth, normalize_denominators)
510 }
511
512 pub fn subdivide_nested_hierarchy_by(
530 &mut self,
531 depth: usize,
532 first_partition_form: &Self,
533 normalize_denominators: bool,
534 ) -> Result<()> {
535 self.partition_by_count(1, false)?;
536 if depth == 0 {
537 return Ok(());
538 }
539 let ratio = |span: &Self| format!("{}/{}", span.numerator, span.denominator);
540 let written: Vec<String> = if first_partition_form.parts.is_empty() {
541 vec![ratio(first_partition_form)]
542 } else {
543 first_partition_form.parts.iter().map(ratio).collect()
544 };
545 let borrowed: Vec<&str> = written.iter().map(String::as_str).collect();
546 self.parts[0].partition_by_parts(&borrowed)?;
547 self.subdivide_nested_below_the_first(depth, normalize_denominators)
548 }
549
550 fn subdivide_nested_below_the_first(
553 &mut self,
554 depth: usize,
555 normalize_denominators: bool,
556 ) -> Result<()> {
557 let mut frontier = vec![vec![0]];
558 for _ in 1..depth {
559 frontier = self.subdivide_parts_of(&frontier, None)?;
560 if !normalize_denominators {
561 continue;
562 }
563 loop {
566 let denominators: Vec<UnsignedIntegerType> = frontier
567 .iter()
568 .map(|path| self.part_at(path).denominator())
569 .collect();
570 let Some(shortest) = denominators.iter().min().copied() else {
571 break;
572 };
573 if denominators
574 .iter()
575 .all(|denominator| *denominator == shortest)
576 {
577 break;
578 }
579 let mut evened = Vec::new();
580 for path in &frontier {
581 if self.part_at(path).denominator() == shortest {
582 evened.extend(self.subdivide_parts_of(std::slice::from_ref(path), None)?);
583 } else {
584 evened.push(path.clone());
585 }
586 }
587 frontier = evened;
588 }
589 }
590 Ok(())
591 }
592
593 #[must_use]
596 pub fn partition_options(&self) -> Vec<Vec<String>> {
597 let mut options = division_options_algorithmic(self.numerator, self.denominator);
598 options.extend(division_options_preset(self.numerator, self.denominator));
599 let mut seen = Vec::new();
600 options.retain(|option| {
601 if option.is_empty() || seen.contains(option) {
602 return false;
603 }
604 seen.push(option.clone());
605 true
606 });
607 options
608 }
609
610 #[must_use]
617 pub fn level_list(&self, level: usize, flat: bool) -> Vec<MeterTerminal> {
618 let mut out = Vec::new();
619 for part in &self.parts {
620 if part.parts.is_empty() {
621 out.push(part.clone());
622 } else if level > 0 {
623 out.extend(part.level_list(level - 1, flat));
624 } else if flat {
625 let mut flattened = part.clone();
626 flattened.parts.clear();
627 out.push(flattened);
628 } else {
629 out.push(part.clone());
630 }
631 }
632 out
633 }
634
635 pub fn level(&self, level: usize, flat: bool) -> Result<Self> {
638 let mut out = Self::new(self.numerator, self.denominator)?;
639 out.weight = self.weight;
640 out.parts = self.level_list(level, flat);
641 Ok(out)
642 }
643
644 #[must_use]
647 pub fn level_span(&self, level: usize) -> Vec<(FloatType, FloatType)> {
648 let mut spans = Vec::new();
649 let mut position = 0.0;
650 for part in self.level_list(level, true) {
651 let end = position + part.quarter_length();
652 spans.push((position, end));
653 position = end;
654 }
655 spans
656 }
657
658 pub fn offset_to_depth(&self, offset: FloatType, align: OffsetAlign) -> Result<usize> {
666 let length = self.quarter_length();
667 if offset.is_nan() || offset < 0.0 || offset >= length {
668 return Err(Error::Meter(format!(
669 "cannot access from qLenPos {}",
670 super::offset_repr(offset)
671 )));
672 }
673 let depth = self.depth();
674 if depth == 0 {
675 return Ok(0);
676 }
677 let finest = self.level(depth - 1, true)?;
678 let index = finest.offset_to_index(offset)?;
679 let spans = self.level_span(depth - 1);
680 let position = match align {
681 OffsetAlign::Quantize => spans[index].0,
682 OffsetAlign::Start | OffsetAlign::End => offset,
683 };
684 let mut score = 0;
685 for level in 0..depth {
686 for (start, end) in self.level_span(level) {
687 let boundary = match align {
688 OffsetAlign::Start | OffsetAlign::Quantize => start,
689 OffsetAlign::End => end,
690 };
691 if (boundary - position).abs() < OFFSET_TOLERANCE {
692 score += 1;
693 }
694 }
695 }
696 Ok(score)
697 }
698
699 pub fn set_level_weight(&mut self, level: usize, weights: &[FloatType]) -> Result<()> {
705 if weights.is_empty() {
706 return Err(Error::Meter(
707 "a weight has to be given to weigh a level with".to_string(),
708 ));
709 }
710 let mut index = 0;
711 Self::weigh(&mut self.parts, level, weights, &mut index);
712 if index == 0 {
713 return Err(Error::Meter(format!(
714 "this meter has no level {level} to weigh"
715 )));
716 }
717 Ok(())
718 }
719
720 fn weigh(parts: &mut [MeterTerminal], level: usize, weights: &[FloatType], index: &mut usize) {
722 for part in parts.iter_mut() {
723 if part.parts.is_empty() || level == 0 {
724 part.weight = weights[*index % weights.len()];
725 *index += 1;
726 } else {
727 Self::weigh(&mut part.parts, level - 1, weights, index);
728 }
729 }
730 }
731
732 #[must_use]
735 pub fn is_uniform_partition(&self, depth: usize) -> bool {
736 let mut numerator = None;
737 let mut denominator = None;
738 for part in self.level_list(depth, false) {
739 if *numerator.get_or_insert(part.numerator) != part.numerator
740 || *denominator.get_or_insert(part.denominator) != part.denominator
741 {
742 return false;
743 }
744 }
745 true
746 }
747
748 #[must_use]
751 pub fn partition_display(&self) -> String {
752 self.parts
753 .iter()
754 .map(MeterTerminal::to_string)
755 .collect::<Vec<String>>()
756 .join("+")
757 }
758
759 pub fn subdivide_by_count(&self, count: usize) -> Result<Self> {
762 let mut out = Self::new(self.numerator, self.denominator)?;
763 out.weight = self.weight;
764 out.partition_by_count(count, true)?;
765 Ok(out)
766 }
767
768 pub fn subdivide_by_other(&self, other: &Self) -> Result<Self> {
773 if (other.quarter_length() - self.quarter_length()).abs() > OFFSET_TOLERANCE {
774 return Err(Error::Meter(format!("cannot subdivide by other: {other}")));
775 }
776 let mut out = Self::new(other.numerator, other.denominator)?;
777 out.parts_mut().push(other.clone());
778 Ok(out)
779 }
780
781 pub fn partition_by_other(&mut self, other: &Self) -> Result<()> {
785 if !self.ratio_equal(other) {
786 return Err(Error::Meter(
787 "Cannot set partition for unequal MeterSequences".to_string(),
788 ));
789 }
790 let weight = self.weight();
791 self.parts = other.parts.clone();
792 self.set_weight(weight);
793 Ok(())
794 }
795
796 #[must_use]
798 pub fn level_weight(&self, level: usize) -> Vec<FloatType> {
799 self.level_list(level, true)
800 .iter()
801 .map(MeterTerminal::weight)
802 .collect()
803 }
804
805 pub fn subdivide_by_list(&self, numerators: &[UnsignedIntegerType]) -> Result<Self> {
808 let mut out = Self::new(self.numerator, self.denominator)?;
809 out.weight = self.weight;
810 out.partition_by_list(numerators)?;
811 Ok(out)
812 }
813
814 pub fn offset_to_index(&self, offset: FloatType) -> Result<usize> {
817 let offset = super::offset_within(offset, self.quarter_length())?;
818 let mut start = 0.0;
819 for (index, part) in self.parts.iter().enumerate() {
820 let end = start + part.quarter_length();
821 if offset >= start - OFFSET_TOLERANCE && offset < end - OFFSET_TOLERANCE {
822 return Ok(index);
823 }
824 start = end;
825 }
826 Ok(self.parts.len().saturating_sub(1))
827 }
828
829 pub fn offset_to_span(
833 &self,
834 offset: FloatType,
835 permit_meter_modulus: bool,
836 ) -> Result<(FloatType, FloatType)> {
837 let length = self.quarter_length();
838 let offset = if permit_meter_modulus && offset >= length {
839 offset.rem_euclid(length)
840 } else {
841 offset
842 };
843 let index = self.offset_to_index(offset)?;
844 let mut start = 0.0;
845 for (position, part) in self.parts.iter().enumerate() {
846 let end = start + part.quarter_length();
847 if position == index {
848 return Ok((start, end));
849 }
850 start = end;
851 }
852 Ok((0.0, length))
853 }
854
855 pub fn offset_to_weight(&self, offset: FloatType) -> Result<FloatType> {
857 let index = self.offset_to_index(offset)?;
858 Ok(self
859 .parts
860 .get(index)
861 .map_or(self.weight, MeterTerminal::weight))
862 }
863
864 #[must_use]
866 pub fn partition_string(&self) -> String {
867 if self.parts.is_empty() {
868 return format!("{}/{}", self.numerator, self.denominator);
869 }
870 let inner: Vec<String> = self
871 .parts
872 .iter()
873 .map(MeterTerminal::partition_string)
874 .collect();
875 format!("{{{}}}", inner.join("+"))
876 }
877}
878
879impl std::fmt::Display for MeterTerminal {
880 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
881 formatter.write_str(&self.partition_string())
882 }
883}
884
885fn python_list<T: std::fmt::Display>(parts: &[T]) -> String {
889 let quote = |part: &T| {
890 let written = part.to_string();
891 if written.parse::<FloatType>().is_ok() {
892 written
893 } else {
894 format!("'{written}'")
895 }
896 };
897 format!(
898 "[{}]",
899 parts.iter().map(quote).collect::<Vec<String>>().join(", ")
900 )
901}
902
903fn parse_number(text: &str) -> Result<UnsignedIntegerType> {
905 text.trim()
906 .parse()
907 .map_err(|_| Error::Meter(format!("{text:?} is not a number a meter is written with")))
908}
909
910fn split_ratio(ratio: &str) -> Result<(UnsignedIntegerType, UnsignedIntegerType)> {
912 let trimmed = ratio.trim();
913 let (numerator, denominator) = trimmed.split_once('/').ok_or_else(|| {
914 Error::Meter(format!(
915 "a meter terminal is written numerator/denominator, not {ratio:?}"
916 ))
917 })?;
918 let read = |part: &str, label: &str| {
919 part.trim()
920 .parse::<UnsignedIntegerType>()
921 .map_err(|_| Error::Meter(format!("cannot read a {label} from {part:?} in {ratio:?}")))
922 };
923 Ok((
924 read(numerator, "numerator")?,
925 read(denominator, "denominator")?,
926 ))
927}
928
929fn fractions_upward(
932 numerator: UnsignedIntegerType,
933 denominator: UnsignedIntegerType,
934) -> Vec<String> {
935 let largest = VALID_DENOMINATORS[VALID_DENOMINATORS.len() - 1];
936 let mut out = Vec::new();
937 if denominator >= largest {
938 return out;
939 }
940 let (mut numerator, mut denominator) = (numerator * 2, denominator * 2);
941 while denominator <= largest {
942 out.push(format!("{numerator}/{denominator}"));
943 numerator *= 2;
944 denominator *= 2;
945 }
946 out
947}
948
949fn fractions_downward(
952 numerator: UnsignedIntegerType,
953 denominator: UnsignedIntegerType,
954) -> Vec<String> {
955 let smallest = VALID_DENOMINATORS[0];
956 let mut out = Vec::new();
957 if denominator <= smallest || !numerator.is_multiple_of(2) {
958 return out;
959 }
960 let (mut numerator, mut denominator) = (numerator / 2, denominator / 2);
961 loop {
962 out.push(format!("{numerator}/{denominator}"));
963 if !numerator.is_multiple_of(2) || denominator <= smallest {
964 break;
965 }
966 numerator /= 2;
967 denominator /= 2;
968 }
969 out
970}
971
972fn additive_multiples_upward(
976 numerator: UnsignedIntegerType,
977 denominator: UnsignedIntegerType,
978) -> Vec<Vec<String>> {
979 let mut out = Vec::new();
980 if numerator <= 1 {
981 return out;
982 }
983 let largest = VALID_DENOMINATORS[VALID_DENOMINATORS.len() - 1];
984 let limit = if numerator > 16 { numerator } else { 16 };
985 let (mut denominator, mut count) = (denominator, numerator);
986 while denominator <= largest && count <= limit {
987 out.push(vec![format!("1/{denominator}"); count as usize]);
988 denominator *= 2;
989 count *= 2;
990 }
991 out
992}
993
994fn additive_multiples_even_division(
998 numerator: UnsignedIntegerType,
999 denominator: UnsignedIntegerType,
1000) -> Vec<Vec<String>> {
1001 let mut out = Vec::new();
1002 if !numerator.is_multiple_of(2) || denominator < 2 {
1003 return out;
1004 }
1005 let (mut count, mut denominator) = (numerator / 2, denominator / 2);
1006 while denominator >= 1 && count > 1 {
1007 out.push(vec![format!("1/{denominator}"); count as usize]);
1008 if !count.is_multiple_of(2) || denominator == 1 {
1009 break;
1010 }
1011 denominator /= 2;
1012 count /= 2;
1013 }
1014 out
1015}
1016
1017fn additive_multiples(
1020 numerator: UnsignedIntegerType,
1021 denominator: UnsignedIntegerType,
1022) -> Vec<Vec<String>> {
1023 let mut out = Vec::new();
1024 if numerator <= 3 || !numerator.is_multiple_of(2) {
1025 return out;
1026 }
1027 let mut divisor = 2;
1028 while numerator.is_multiple_of(divisor) {
1029 let count = numerator / divisor;
1030 if count <= 1 {
1031 break;
1032 }
1033 out.push(vec![format!("{count}/{denominator}"); divisor as usize]);
1034 divisor *= 2;
1035 }
1036 out
1037}
1038
1039fn additive_multiples_downward(
1043 numerator: UnsignedIntegerType,
1044 denominator: UnsignedIntegerType,
1045) -> Vec<Vec<String>> {
1046 let largest = VALID_DENOMINATORS[VALID_DENOMINATORS.len() - 1];
1047 let mut out = Vec::new();
1048 if denominator >= largest || numerator != 1 {
1049 return out;
1050 }
1051 let (mut count, mut denominator) = (2usize, denominator * 2);
1052 while denominator <= largest {
1053 out.push(vec![format!("{numerator}/{denominator}"); count]);
1054 denominator *= 2;
1055 count *= 2;
1056 }
1057 out
1058}
1059
1060fn division_options_algorithmic(
1068 numerator: UnsignedIntegerType,
1069 denominator: UnsignedIntegerType,
1070) -> Vec<Vec<String>> {
1071 let mut options: Vec<Vec<String>> = Vec::new();
1072
1073 if numerator > 3 && numerator.is_multiple_of(3) {
1075 options.push(vec![format!("3/{denominator}"); (numerator / 3) as usize]);
1076 }
1077 let groupings: &[&[UnsignedIntegerType]] = match numerator {
1079 5 => &[&[2, 3], &[3, 2]],
1080 7 => &[&[2, 2, 3], &[3, 2, 2], &[2, 3, 2]],
1081 10 => &[&[2, 2, 3, 3]],
1082 _ => &[],
1083 };
1084 for grouping in groupings {
1085 options.push(
1086 grouping
1087 .iter()
1088 .map(|count| format!("{count}/{denominator}"))
1089 .collect(),
1090 );
1091 }
1092 options.extend(additive_multiples_upward(numerator, denominator));
1093 options.extend(additive_multiples_even_division(numerator, denominator));
1094 options.push(vec![format!("{numerator}/{denominator}")]);
1095 options.extend(additive_multiples(numerator, denominator));
1096 options.extend(additive_multiples_downward(numerator, denominator));
1097 for written in fractions_downward(numerator, denominator) {
1098 options.push(vec![written]);
1099 }
1100 for written in fractions_upward(numerator, denominator) {
1101 options.push(vec![written]);
1102 }
1103 options
1104}
1105
1106fn division_options_preset(
1109 numerator: UnsignedIntegerType,
1110 denominator: UnsignedIntegerType,
1111) -> Vec<Vec<String>> {
1112 if numerator != 5 {
1113 return Vec::new();
1114 }
1115 vec![
1116 vec![
1117 format!("2/{denominator}"),
1118 format!("2/{denominator}"),
1119 format!("1/{denominator}"),
1120 ],
1121 vec![
1122 format!("2/{denominator}"),
1123 format!("1/{denominator}"),
1124 format!("2/{denominator}"),
1125 ],
1126 ]
1127}
1128
1129#[cfg(test)]
1130mod tests {
1131 use super::MeterTerminal;
1132 use super::OffsetAlign;
1133
1134 #[test]
1140 fn levels_are_read_as_music21_reads_them() {
1141 let mut bar = MeterTerminal::new(4, 4).unwrap();
1143 bar.partition_by_parts(&["4/4"]).unwrap();
1144 bar.partition_by_count(4, true).unwrap();
1145 bar.subdivide_partitions_equal(None).unwrap();
1146 assert_eq!(bar.to_string(), "{{1/8+1/8}+{1/8+1/8}+{1/8+1/8}+{1/8+1/8}}");
1147
1148 let first: Vec<String> = bar
1150 .level_list(0, true)
1151 .iter()
1152 .map(MeterTerminal::to_string)
1153 .collect();
1154 assert_eq!(first, ["1/4", "1/4", "1/4", "1/4"]);
1155 let second: Vec<String> = bar
1156 .level_list(1, true)
1157 .iter()
1158 .map(MeterTerminal::to_string)
1159 .collect();
1160 assert_eq!(second, ["1/8"; 8]);
1161
1162 assert_eq!(bar.depth(), 2);
1164 assert_eq!(bar.level_span(0).len(), 4);
1165 assert_eq!(bar.level_span(0)[1], (1.0, 2.0));
1166
1167 assert!(bar.is_uniform_partition(0));
1169 assert!(bar.is_uniform_partition(1));
1170 assert_eq!(bar.offset_to_depth(0.0, OffsetAlign::Quantize).unwrap(), 2);
1172 assert_eq!(bar.offset_to_depth(0.5, OffsetAlign::Quantize).unwrap(), 1);
1173 assert_eq!(bar.offset_to_depth(1.0, OffsetAlign::Quantize).unwrap(), 2);
1174 }
1175
1176 #[test]
1177 fn a_bar_written_in_unequal_parts_is_not_uniform() {
1178 let mut bar = MeterTerminal::new(5, 8).unwrap();
1179 bar.partition_by_parts(&["2/8", "3/8"]).unwrap();
1180 assert!(!bar.is_uniform_partition(0));
1181 assert_eq!(bar.partition_display(), "2/8+3/8");
1182 assert_eq!(bar.depth(), 1);
1183 }
1184
1185 #[test]
1186 fn subdividing_leaves_the_span_alone_and_returns_a_new_one() {
1187 let mut beat = MeterTerminal::new(1, 4).unwrap();
1188 beat.set_weight(0.5);
1189 let divided = beat.subdivide_by_count(2).unwrap();
1190 assert_eq!(divided.to_string(), "{1/8+1/8}");
1191 assert!(beat.is_empty());
1194 assert!((divided.weight() - 0.5).abs() < 1e-9);
1195
1196 let listed = MeterTerminal::new(5, 8)
1197 .unwrap()
1198 .subdivide_by_list(&[2, 3])
1199 .unwrap();
1200 assert_eq!(listed.to_string(), "{2/8+3/8}");
1201 }
1202
1203 #[test]
1204 fn the_options_come_in_the_order_music21_offers_them() {
1205 use super::division_options_algorithmic;
1206
1207 let offered: Vec<Vec<String>> = division_options_algorithmic(4, 4)
1208 .into_iter()
1209 .take(6)
1210 .collect();
1211 assert_eq!(
1212 offered,
1213 vec![
1214 vec!["1/4"; 4],
1215 vec!["1/8"; 8],
1216 vec!["1/16"; 16],
1217 vec!["1/2"; 2],
1218 vec!["4/4"],
1219 vec!["2/4"; 2],
1220 ]
1221 );
1222
1223 assert_eq!(division_options_algorithmic(6, 8)[0], vec!["3/8"; 2]);
1226 assert_eq!(
1227 division_options_algorithmic(5, 8)[0],
1228 vec!["2/8".to_string(), "3/8".to_string()]
1229 );
1230 }
1231
1232 #[test]
1234 fn a_bar_divides_the_way_music21_divides_it() {
1235 let mut four_four = MeterTerminal::from_ratio_string("4/4").unwrap();
1236 four_four.partition_by_count(2, true).unwrap();
1237 assert_eq!(four_four.partition_string(), "{1/2+1/2}");
1238 four_four.partition_by_count(4, true).unwrap();
1239 assert_eq!(four_four.partition_string(), "{1/4+1/4+1/4+1/4}");
1240
1241 let mut five_eight = MeterTerminal::from_ratio_string("5/8").unwrap();
1243 five_eight.partition_by_count(2, true).unwrap();
1244 assert_eq!(five_eight.partition_string(), "{2/8+3/8}");
1245 five_eight.partition_by_count(3, true).unwrap();
1246 assert_eq!(five_eight.partition_string(), "{2/8+2/8+1/8}");
1247
1248 let mut also_five = MeterTerminal::from_ratio_string("5/8").unwrap();
1250 also_five.partition_by_count(11, true).unwrap();
1251 assert_eq!(also_five.partition_string(), "{2/8+3/8}");
1252 assert!(
1253 MeterTerminal::from_ratio_string("5/8")
1254 .unwrap()
1255 .partition_by_count(11, false)
1256 .is_err()
1257 );
1258
1259 let mut six_eight = MeterTerminal::from_ratio_string("6/8").unwrap();
1261 six_eight.partition_by_count(2, true).unwrap();
1262 assert_eq!(six_eight.partition_string(), "{3/8+3/8}");
1263 }
1264
1265 #[test]
1266 fn a_partition_must_come_to_what_the_bar_is() {
1267 let mut bar = MeterTerminal::from_ratio_string("4/4").unwrap();
1268 bar.partition_by_parts(&["3/4", "1/8", "1/8"]).unwrap();
1269 assert_eq!(bar.partition_string(), "{3/4+1/8+1/8}");
1270 assert!(bar.partition_by_parts(&["3/4", "1/8", "5/8"]).is_err());
1271
1272 let mut halves = MeterTerminal::from_ratio_string("2/4").unwrap();
1275 halves.partition_by_list(&[1, 1]).unwrap();
1276 assert_eq!(halves.partition_string(), "{1/4+1/4}");
1277 halves.partition_by_list(&[1, 1, 1, 1]).unwrap();
1278 assert_eq!(halves.partition_string(), "{1/8+1/8+1/8+1/8}");
1279 assert!(halves.partition_by_list(&[1, 1, 1]).is_err());
1280 }
1281
1282 #[test]
1283 fn an_offset_finds_the_part_it_falls_in() {
1284 let mut bar = MeterTerminal::from_ratio_string("4/4").unwrap();
1285 bar.partition_by_count(4, true).unwrap();
1286 assert_eq!(bar.offset_to_index(0.0).unwrap(), 0);
1287 assert_eq!(bar.offset_to_index(1.5).unwrap(), 1);
1288 assert_eq!(bar.offset_to_index(3.99).unwrap(), 3);
1289 assert_eq!(bar.offset_to_span(1.5, false).unwrap(), (1.0, 2.0));
1290 assert!(bar.offset_to_index(4.0).is_err());
1292 assert!(bar.offset_to_index(-0.5).is_err());
1293 assert_eq!(bar.offset_to_span(5.5, true).unwrap(), (1.0, 2.0));
1294 }
1295
1296 #[test]
1297 fn a_span_says_how_deep_and_how_flat_it_is() {
1298 let mut bar = MeterTerminal::from_ratio_string("4/4").unwrap();
1299 assert_eq!(bar.depth(), 0);
1300 bar.partition_by_count(2, true).unwrap();
1301 assert_eq!(bar.depth(), 1);
1302 bar.parts_mut()[0].partition_by_count(2, true).unwrap();
1303 assert_eq!(bar.depth(), 2);
1304 assert_eq!(bar.partition_string(), "{{1/4+1/4}+1/2}");
1305 assert_eq!(bar.flattened().len(), 3);
1306 assert!((bar.flattened()[0].quarter_length() - 1.0).abs() < 1e-9);
1307 }
1308
1309 #[test]
1311 fn parts_joined_by_a_plus_are_read_as_a_partition() {
1312 let joined = MeterTerminal::from_partition_string("2/4+2/4").unwrap();
1313 assert_eq!(joined.to_string(), "{2/4+2/4}");
1314 assert_eq!((joined.numerator(), joined.denominator()), (4, 4));
1315 assert_eq!(joined.len(), 2);
1316
1317 let shared = MeterTerminal::from_partition_string("3+2/8").unwrap();
1319 assert_eq!(shared.to_string(), "{3/8+2/8}");
1320 assert_eq!((shared.numerator(), shared.denominator()), (5, 8));
1321
1322 let mixed = MeterTerminal::from_partition_string("3/4+2/4+1/8").unwrap();
1324 assert_eq!(mixed.to_string(), "{3/4+2/4+1/8}");
1325 assert_eq!((mixed.numerator(), mixed.denominator()), (11, 8));
1326 assert!((mixed.quarter_length() - 5.5).abs() < 1e-9);
1327
1328 let alone = MeterTerminal::from_partition_string("4/4").unwrap();
1330 assert_eq!(alone.to_string(), "4/4");
1331 assert!(alone.is_empty());
1332
1333 assert!(MeterTerminal::from_partition_string("2+2").is_err());
1334 assert!(MeterTerminal::from_partition_string("half/4").is_err());
1335 }
1336
1337 #[test]
1340 fn an_address_says_every_index_down_to_the_terminal() {
1341 let mut bar = MeterTerminal::new(4, 4).unwrap();
1342 bar.partition_by_count(4, true).unwrap();
1343 bar.parts_mut()[1].partition_by_count(4, true).unwrap();
1344 assert_eq!(bar.to_string(), "{1/4+{1/16+1/16+1/16+1/16}+1/4+1/4}");
1345
1346 assert_eq!(bar.offset_to_address(0.0).unwrap(), [0]);
1347 assert_eq!(bar.offset_to_address(1.0).unwrap(), [1, 0]);
1348 assert_eq!(bar.offset_to_address(1.5).unwrap(), [1, 2]);
1349 assert_eq!(bar.offset_to_address(3.0).unwrap(), [3]);
1350 assert_eq!(bar.offset_to_address(1.5).unwrap().len(), 2);
1352 assert!(bar.offset_to_address(-1.0).is_err());
1353 }
1354
1355 #[test]
1357 fn a_span_flattens_to_what_its_leaves_come_to() {
1358 let mut bar = MeterTerminal::new(4, 4).unwrap();
1359 bar.partition_by_count(4, true).unwrap();
1360 bar.subdivide_partitions_equal(Some(2)).unwrap();
1361
1362 let flat = bar.flatten().unwrap();
1363 assert_eq!(flat.to_string(), "{1/8+1/8+1/8+1/8+1/8+1/8+1/8+1/8}");
1364 assert_eq!((flat.numerator(), flat.denominator()), (8, 8));
1366 assert_eq!(bar.flat_weights(), vec![0.125; 8]);
1367 assert_eq!(bar.level_weight(0), vec![0.25; 4]);
1368 assert_eq!(bar.level_weight(1), vec![0.125; 8]);
1369 }
1370
1371 #[test]
1373 fn a_span_takes_the_division_and_the_shape_of_another() {
1374 let mut quarters = MeterTerminal::new(4, 4).unwrap();
1375 quarters.partition_by_count(4, true).unwrap();
1376 let mut halves = MeterTerminal::new(4, 4).unwrap();
1377 halves.partition_by_count(2, true).unwrap();
1378
1379 quarters.partition_by_other(&halves).unwrap();
1380 assert_eq!(quarters.to_string(), "{1/2+1/2}");
1381 assert_eq!(quarters.weight(), 1.0);
1383
1384 let three = MeterTerminal::new(3, 4).unwrap();
1386 assert!(quarters.partition_by_other(&three).is_err());
1387 assert!(quarters.subdivide_by_other(&three).is_err());
1388
1389 let thirds = MeterTerminal::from_partition_string("1/4+1/4+1/4").unwrap();
1390 let sixths = MeterTerminal::from_partition_string("3/8+3/8").unwrap();
1391 let divided = thirds.subdivide_by_other(&sixths).unwrap();
1392 assert_eq!(divided.to_string(), "{{3/8+3/8}}");
1395 assert_eq!(divided.weight(), 2.0);
1396
1397 assert!(thirds.ratio_equal(&MeterTerminal::new(3, 4).unwrap()));
1398 assert!(!thirds.ratio_equal(&sixths));
1399 }
1400}