Skip to main content

grafix_toolbox/kit/policies/math/tuple/
apply.rs

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