rstmt_nrt/impls/
impl_triad_repr.rs1use crate::triad::TriadBase;
7
8use crate::traits::TriadRepr;
9use crate::types::{LPR, Triads};
10use num_traits::{Float, FromPrimitive, Num, ToPrimitive, Zero};
11use rstmt_core::traits::{PitchMod, Transform};
12use rstmt_core::{Augmented, Diminished, Major, Minor};
13
14impl<S, T> TriadBase<S, Augmented, T>
15where
16 S: TriadRepr<Elem = T>,
17{
18 pub fn augmented(root: T) -> Self
21 where
22 T: Copy + FromPrimitive + Zero + PitchMod<Output = T> + core::ops::Add<Output = T>,
23 {
24 TriadBase::from_root_with_class(root, Augmented)
25 }
26}
27
28impl<S, T> TriadBase<S, Diminished, T>
29where
30 S: TriadRepr<Elem = T>,
31{
32 pub fn diminished(root: T) -> Self
35 where
36 T: Copy + FromPrimitive + Zero + PitchMod<Output = T> + core::ops::Add<Output = T>,
37 {
38 TriadBase::from_root_with_class(root, Diminished)
39 }
40}
41
42impl<S, T> TriadBase<S, Major, T>
43where
44 S: TriadRepr<Elem = T>,
45{
46 pub fn major(root: T) -> Self
49 where
50 T: Copy + FromPrimitive + Zero + PitchMod<Output = T> + core::ops::Add<Output = T>,
51 {
52 TriadBase::from_root_with_class(root, Major)
53 }
54}
55
56impl<S, T> TriadBase<S, Minor, T>
57where
58 S: TriadRepr<Elem = T>,
59{
60 pub fn minor(root: T) -> Self
63 where
64 T: Copy + FromPrimitive + Zero + PitchMod<Output = T> + core::ops::Add<Output = T>,
65 {
66 TriadBase::from_root_with_class(root, Minor)
67 }
68}
69
70impl<T> TriadBase<[T; 3], Triads, T>
71where
72 T: Copy + ToPrimitive + FromPrimitive + PitchMod<Output = T> + core::ops::Add<Output = T>,
73{
74 pub fn barycentric<N, U>(&self, p: N) -> [U; 3]
101 where
102 T: Copy + ToPrimitive,
103 N: rstmt_core::IntoAspn,
104 U: Float + FromPrimitive,
105 {
106 let note = p.into_aspn();
107 let px = U::from_usize(note.class().pmod()).unwrap();
108 let py = U::from_isize(*note.octave()).unwrap();
109 let y = U::from(*self.octave).unwrap();
110 let [v0, v1, v2] = self.chord().map(|n| U::from(n).unwrap());
111
112 let d00 = v0 * v0 + y * y;
113 let d01 = v0 * v1 + y * y;
114 let d11 = v1 * v1 + y * y;
115 let d20 = v2 * px + y * py;
116 let d21 = v2 * v1 + y * y;
117
118 let denom = d00 * d11 - d01 * d01;
119 let a = (d11 * d20 - d01 * d21) / denom;
120 let b = (d00 * d21 - d01 * d20) / denom;
121 let c = U::one() - a - b;
122 [a, b, c]
123 }
124 pub fn is_valid(&self) -> bool
126 where
127 T: Copy
128 + PartialEq
129 + FromPrimitive
130 + ToPrimitive
131 + PitchMod<Output = T>
132 + core::ops::Sub<Output = T>,
133 {
134 self.class().validate(self.chord())
135 }
136 pub fn is_neighbor(&self, other: &Self) -> Option<LPR>
139 where
140 Self: Transform<LPR, Output = Self>,
141 T: PartialEq,
142 {
143 LPR::iter().find(|&dirac| self.transform(dirac) == *other)
144 }
145}
146impl<T> TriadBase<[T; 3], Triads, T>
147where
148 T: Copy + ToPrimitive + FromPrimitive + Num + PitchMod<Output = T>,
149{
150 pub fn walk<I>(&self, path: I) -> Self
153 where
154 I: IntoIterator<Item = LPR>,
155 {
156 path.into_iter()
157 .fold(*self, |triad, dirac| dirac.apply(triad))
158 }
159 pub fn walk_inplace<I>(&mut self, path: I)
161 where
162 I: IntoIterator<Item = LPR>,
163 {
164 *self = self.walk(path);
165 }
166}
167
168impl TriadBase<[usize; 3], Triads> {
169 pub fn transform_inplace(&mut self, transform: LPR) {
171 *self = self.transform(transform);
172 }
173}