grafix_toolbox/kit/policies/math/tuple/
apply.rs1use crate::lib::*;
2
3pub trait TupleApply<RA, A>: Sized {
4 type R<B>;
5 fn apply<B, F: Fn(A, A) -> B>(self, r: RA, op: F) -> Self::R<B>;
6}
7pub trait TupleMap<A>: Sized {
8 type R<B>;
9 fn map<B, F: Fn(A) -> B>(self, op: F) -> Self::R<B>;
10}
11pub trait TupleFold<A>: Sized {
12 fn fold<F: Fn(A, A) -> A>(self, op: F) -> A;
13}
14
15impl<RA, A> TupleApply<RA, A> for (A, A)
16where
17 Self: Cast<RA>,
18{
19 type R<B> = (B, B);
20 #[inline(always)]
21 fn apply<B, F: Fn(A, A) -> B>(self, r: RA, op: F) -> Self::R<B> {
22 let (l, r) = (self, Self::to(r));
23 (op(l.0, r.0), op(l.1, r.1))
24 }
25}
26impl<A> TupleMap<A> for (A, A) {
27 type R<B> = (B, B);
28 #[inline(always)]
29 fn map<B, F: Fn(A) -> B>(self, op: F) -> Self::R<B> {
30 (op(self.0), op(self.1))
31 }
32}
33impl<A> TupleFold<A> for (A, A) {
34 #[inline(always)]
35 fn fold<F: Fn(A, A) -> A>(self, op: F) -> A {
36 op(self.0, self.1)
37 }
38}
39
40impl<RA, A> TupleApply<RA, A> for (A, A, A)
41where
42 Self: Cast<RA>,
43{
44 type R<B> = (B, B, B);
45 #[inline(always)]
46 fn apply<B, F: Fn(A, A) -> B>(self, r: RA, op: F) -> Self::R<B> {
47 let (l, r) = (self, Self::to(r));
48 (op(l.0, r.0), op(l.1, r.1), op(l.2, r.2))
49 }
50}
51impl<A> TupleMap<A> for (A, A, A) {
52 type R<B> = (B, B, B);
53 #[inline(always)]
54 fn map<B, F: Fn(A) -> B>(self, op: F) -> Self::R<B> {
55 (op(self.0), op(self.1), op(self.2))
56 }
57}
58impl<A> TupleFold<A> for (A, A, A) {
59 #[inline(always)]
60 fn fold<F: Fn(A, A) -> A>(self, op: F) -> A {
61 op(op(self.0, self.1), self.2)
62 }
63}
64
65impl<RA, A> TupleApply<RA, A> for (A, A, A, A)
66where
67 Self: Cast<RA>,
68{
69 type R<B> = (B, B, B, B);
70 #[inline(always)]
71 fn apply<B, F: Fn(A, A) -> B>(self, r: RA, op: F) -> Self::R<B> {
72 let (l, r) = (self, Self::to(r));
73 (op(l.0, r.0), op(l.1, r.1), op(l.2, r.2), op(l.3, r.3))
74 }
75}
76impl<A> TupleMap<A> for (A, A, A, A) {
77 type R<B> = (B, B, B, B);
78 #[inline(always)]
79 fn map<B, F: Fn(A) -> B>(self, op: F) -> Self::R<B> {
80 (op(self.0), op(self.1), op(self.2), op(self.3))
81 }
82}
83impl<A> TupleFold<A> for (A, A, A, A) {
84 #[inline(always)]
85 fn fold<F: Fn(A, A) -> A>(self, op: F) -> A {
86 op(op(op(self.0, self.1), self.2), self.3)
87 }
88}
89
90impl<RA, A, const N: usize> TupleApply<RA, A> for [A; N]
91where
92 Self: Cast<RA>,
93{
94 type R<B> = [B; N];
95 #[inline(always)]
96 fn apply<B, F: Fn(A, A) -> B>(self, r: RA, op: F) -> Self::R<B> {
97 let (l, r) = (self, Self::to(r));
98 let Ok(b) = l.into_iter().zip(r).map(|(l, r)| op(l, r)).collect::<Vec<_>>().try_into() else {
99 unreachable!()
100 };
101 b
102 }
103}
104impl<A, const N: usize> TupleMap<A> for [A; N] {
105 type R<B> = [B; N];
106 #[inline(always)]
107 fn map<B, F: Fn(A) -> B>(self, op: F) -> Self::R<B> {
108 self.map(op)
109 }
110}
111impl<A, const N: usize> TupleFold<A> for [A; N] {
112 #[inline(always)]
113 fn fold<F: Fn(A, A) -> A>(self, op: F) -> A {
114 let mut i = self.into_iter();
115 let h = i.next().valid();
116 i.fold(h, op)
117 }
118}