Mon, 23 Dec 2024 23:27:45 -0500
Basic arithmetric opt-in hack attempt: not allowed by Rust.
5 | 1 | |
2 | use std::iter::Chain; | |
8
4e09b7829b51
Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
3 | use std::sync::Arc; |
0 | 4 | |
5 | use crate::types::*; | |
59
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
6 | use crate::mapping::{ |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
7 | Instance, |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
8 | Mapping, |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
9 | DifferentiableImpl, |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
10 | DifferentiableMapping, |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
11 | Space, |
80
f802ddbabcfc
Basic arithmetric opt-in hack attempt: not allowed by Rust.
Tuomo Valkonen <tuomov@iki.fi>
parents:
59
diff
changeset
|
12 | ArithmeticTrue, |
59
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
13 | }; |
27
00029c20c0ee
Implement Differentiate for BTFN
Tuomo Valkonen <tuomov@iki.fi>
parents:
13
diff
changeset
|
14 | use crate::iter::{Mappable, MapF, MapZ}; |
5 | 15 | use crate::sets::Cube; |
16 | use crate::loc::Loc; | |
17 | ||
0 | 18 | use super::support::*; |
19 | use super::aggregator::*; | |
20 | ||
5 | 21 | /// A structure for storing two [`SupportGenerator`]s summed/chain together. |
22 | /// | |
23 | /// This is needed to work with sums of different types of [`Support`]s. | |
0 | 24 | #[derive(Debug,Clone)] |
25 | pub struct BothGenerators<A, B>( | |
8
4e09b7829b51
Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
26 | pub(super) Arc<A>, |
4e09b7829b51
Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
27 | pub(super) Arc<B>, |
0 | 28 | ); |
29 | ||
5 | 30 | /// A structure for a [`Support`] that can be either `A` or `B`. |
31 | /// | |
32 | /// This is needed to work with sums of different types of [`Support`]s. | |
0 | 33 | #[derive(Debug,Clone)] |
34 | pub enum EitherSupport<A, B> { | |
35 | Left(A), | |
36 | Right(B), | |
37 | } | |
38 | ||
39 | // We need type alias bounds to access associate types. | |
40 | #[allow(type_alias_bounds)] | |
41 | type BothAllDataIter< | |
42 | 'a, F, | |
43 | G1 : SupportGenerator<F, N>, | |
44 | G2 : SupportGenerator<F, N>, | |
45 | const N : usize | |
46 | > = Chain< | |
47 | MapF<G1::AllDataIter<'a>, (usize, EitherSupport<G1::SupportType, G2::SupportType>)>, | |
48 | MapZ<G2::AllDataIter<'a>, usize, (usize, EitherSupport<G1::SupportType, G2::SupportType>)>, | |
49 | >; | |
50 | ||
51 | impl<G1, G2> BothGenerators<G1, G2> { | |
5 | 52 | /// Helper for [`all_left_data`]. |
0 | 53 | #[inline] |
54 | fn map_left<F : Float, const N : usize>((d, support) : (G1::Id, G1::SupportType)) | |
55 | -> (usize, EitherSupport<G1::SupportType, G2::SupportType>) | |
56 | where G1 : SupportGenerator<F, N, Id=usize>, | |
57 | G2 : SupportGenerator<F, N, Id=usize> { | |
58 | ||
59 | let id : usize = d.into(); | |
60 | (id.into(), EitherSupport::Left(support)) | |
61 | } | |
62 | ||
5 | 63 | /// Helper for [`all_right_data`]. |
0 | 64 | #[inline] |
65 | fn map_right<F : Float, const N : usize>(n0 : &usize, (d, support) : (G2::Id, G2::SupportType)) | |
66 | -> (usize, EitherSupport<G1::SupportType, G2::SupportType>) | |
67 | where G1 : SupportGenerator<F, N, Id=usize>, | |
68 | G2 : SupportGenerator<F, N, Id=usize> { | |
69 | ||
70 | let id : usize = d.into(); | |
71 | ((n0+id).into(), EitherSupport::Right(support)) | |
72 | } | |
73 | ||
5 | 74 | /// Calls [`SupportGenerator::all_data`] on the “left” support generator. |
75 | /// | |
76 | /// Converts both the id and the [`Support`] into a form that corresponds to `BothGenerators`. | |
0 | 77 | #[inline] |
78 | pub(super) fn all_left_data<F : Float, const N : usize>(&self) | |
79 | -> MapF<G1::AllDataIter<'_>, (usize, EitherSupport<G1::SupportType, G2::SupportType>)> | |
80 | where G1 : SupportGenerator<F, N, Id=usize>, | |
81 | G2 : SupportGenerator<F, N, Id=usize> { | |
82 | self.0.all_data().mapF(Self::map_left) | |
83 | } | |
84 | ||
5 | 85 | /// Calls [`SupportGenerator::all_data`] on the “right” support generator. |
86 | /// | |
87 | /// Converts both the id and the [`Support`] into a form that corresponds to `BothGenerators`. | |
0 | 88 | #[inline] |
89 | pub(super) fn all_right_data<F : Float, const N : usize>(&self) | |
90 | -> MapZ<G2::AllDataIter<'_>, usize, (usize, EitherSupport<G1::SupportType, G2::SupportType>)> | |
91 | where G1 : SupportGenerator<F, N, Id=usize>, | |
92 | G2 : SupportGenerator<F, N, Id=usize> { | |
93 | let n0 = self.0.support_count(); | |
94 | self.1.all_data().mapZ(n0, Self::map_right) | |
95 | } | |
96 | } | |
97 | ||
98 | impl<F : Float, G1, G2, const N : usize> | |
99 | SupportGenerator<F, N> | |
100 | for BothGenerators<G1, G2> | |
101 | where G1 : SupportGenerator<F, N, Id=usize>, | |
102 | G2 : SupportGenerator<F, N, Id=usize> { | |
103 | ||
104 | type Id = usize; | |
105 | type SupportType = EitherSupport<G1::SupportType, G2::SupportType>; | |
106 | type AllDataIter<'a> = BothAllDataIter<'a, F, G1, G2, N> where G1 : 'a, G2 : 'a; | |
107 | ||
108 | #[inline] | |
109 | fn support_for(&self, id : Self::Id) | |
110 | -> Self::SupportType { | |
111 | let n0 = self.0.support_count(); | |
112 | if id < n0 { | |
113 | EitherSupport::Left(self.0.support_for(id.into())) | |
114 | } else { | |
115 | EitherSupport::Right(self.1.support_for((id-n0).into())) | |
116 | } | |
117 | } | |
118 | ||
119 | #[inline] | |
120 | fn support_count(&self) -> usize { | |
121 | self.0.support_count() + self.1.support_count() | |
122 | } | |
123 | ||
124 | #[inline] | |
125 | fn all_data(&self) -> Self::AllDataIter<'_> { | |
126 | self.all_left_data().chain(self.all_right_data()) | |
127 | } | |
128 | } | |
129 | ||
130 | impl<F: Float, S1, S2, const N : usize> Support<F, N> for EitherSupport<S1, S2> | |
131 | where S1 : Support<F, N>, | |
132 | S2 : Support<F, N> { | |
133 | ||
134 | #[inline] | |
135 | fn support_hint(&self) -> Cube<F,N> { | |
136 | match self { | |
137 | EitherSupport::Left(ref a) => a.support_hint(), | |
138 | EitherSupport::Right(ref b) => b.support_hint(), | |
139 | } | |
140 | } | |
141 | ||
142 | #[inline] | |
143 | fn in_support(&self, x : &Loc<F,N>) -> bool { | |
144 | match self { | |
145 | EitherSupport::Left(ref a) => a.in_support(x), | |
146 | EitherSupport::Right(ref b) => b.in_support(x), | |
147 | } | |
148 | } | |
149 | ||
150 | #[inline] | |
151 | fn bisection_hint(&self, cube : &Cube<F, N>) -> [Option<F>; N] { | |
152 | match self { | |
153 | EitherSupport::Left(ref a) => a.bisection_hint(cube), | |
154 | EitherSupport::Right(ref b) => b.bisection_hint(cube), | |
155 | } | |
156 | } | |
157 | } | |
158 | ||
159 | impl<F : Float, A, S1, S2, const N : usize> LocalAnalysis<F, A, N> for EitherSupport<S1, S2> | |
160 | where A : Aggregator, | |
161 | S1 : LocalAnalysis<F, A, N>, | |
162 | S2 : LocalAnalysis<F, A, N>, { | |
163 | ||
164 | #[inline] | |
165 | fn local_analysis(&self, cube : &Cube<F, N>) -> A { | |
166 | match self { | |
167 | EitherSupport::Left(ref a) => a.local_analysis(cube), | |
168 | EitherSupport::Right(ref b) => b.local_analysis(cube), | |
169 | } | |
170 | } | |
171 | } | |
172 | ||
173 | impl<F : Float, A, S1, S2> GlobalAnalysis<F, A> for EitherSupport<S1, S2> | |
174 | where A : Aggregator, | |
175 | S1 : GlobalAnalysis<F, A>, | |
176 | S2 : GlobalAnalysis<F, A>, { | |
177 | ||
178 | #[inline] | |
179 | fn global_analysis(&self) -> A { | |
180 | match self { | |
181 | EitherSupport::Left(ref a) => a.global_analysis(), | |
182 | EitherSupport::Right(ref b) => b.global_analysis(), | |
183 | } | |
184 | } | |
185 | } | |
186 | ||
59
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
187 | impl<F, S1, S2, X> Mapping<X> for EitherSupport<S1, S2> |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
188 | where |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
189 | F : Space, |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
190 | X : Space, |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
191 | S1 : Mapping<X, Codomain=F>, |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
192 | S2 : Mapping<X, Codomain=F>, |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
193 | { |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
194 | type Codomain = F; |
80
f802ddbabcfc
Basic arithmetric opt-in hack attempt: not allowed by Rust.
Tuomo Valkonen <tuomov@iki.fi>
parents:
59
diff
changeset
|
195 | type ArithmeticOptIn = ArithmeticTrue; |
59
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
196 | |
0 | 197 | #[inline] |
59
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
198 | fn apply<I : Instance<X>>(&self, x : I) -> F { |
0 | 199 | match self { |
13
465fa2121ccb
Better Linear and Mapping structure that can provide consuming and reference `apply`.
Tuomo Valkonen <tuomov@iki.fi>
parents:
8
diff
changeset
|
200 | EitherSupport::Left(ref a) => a.apply(x), |
465fa2121ccb
Better Linear and Mapping structure that can provide consuming and reference `apply`.
Tuomo Valkonen <tuomov@iki.fi>
parents:
8
diff
changeset
|
201 | EitherSupport::Right(ref b) => b.apply(x), |
0 | 202 | } |
203 | } | |
204 | } | |
205 | ||
59
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
206 | impl<X, S1, S2, O> DifferentiableImpl<X> for EitherSupport<S1, S2> |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
207 | where |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
208 | O : Space, |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
209 | X : Space, |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
210 | S1 : DifferentiableMapping<X, DerivativeDomain=O>, |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
211 | S2 : DifferentiableMapping<X, DerivativeDomain=O>, |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
212 | { |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
213 | type Derivative = O; |
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
214 | |
27
00029c20c0ee
Implement Differentiate for BTFN
Tuomo Valkonen <tuomov@iki.fi>
parents:
13
diff
changeset
|
215 | #[inline] |
59
9226980e45a7
Significantly simplify Mapping / Apply through Instance
Tuomo Valkonen <tuomov@iki.fi>
parents:
47
diff
changeset
|
216 | fn differential_impl<I : Instance<X>>(&self, x : I) -> O { |
27
00029c20c0ee
Implement Differentiate for BTFN
Tuomo Valkonen <tuomov@iki.fi>
parents:
13
diff
changeset
|
217 | match self { |
00029c20c0ee
Implement Differentiate for BTFN
Tuomo Valkonen <tuomov@iki.fi>
parents:
13
diff
changeset
|
218 | EitherSupport::Left(ref a) => a.differential(x), |
00029c20c0ee
Implement Differentiate for BTFN
Tuomo Valkonen <tuomov@iki.fi>
parents:
13
diff
changeset
|
219 | EitherSupport::Right(ref b) => b.differential(x), |
00029c20c0ee
Implement Differentiate for BTFN
Tuomo Valkonen <tuomov@iki.fi>
parents:
13
diff
changeset
|
220 | } |
00029c20c0ee
Implement Differentiate for BTFN
Tuomo Valkonen <tuomov@iki.fi>
parents:
13
diff
changeset
|
221 | } |
00029c20c0ee
Implement Differentiate for BTFN
Tuomo Valkonen <tuomov@iki.fi>
parents:
13
diff
changeset
|
222 | } |
00029c20c0ee
Implement Differentiate for BTFN
Tuomo Valkonen <tuomov@iki.fi>
parents:
13
diff
changeset
|
223 | |
0 | 224 | macro_rules! make_either_scalarop_rhs { |
225 | ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { | |
226 | impl<F : Float, G1, G2> | |
227 | std::ops::$trait_assign<F> | |
228 | for BothGenerators<G1, G2> | |
8
4e09b7829b51
Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
229 | where G1 : std::ops::$trait_assign<F> + Clone, |
4e09b7829b51
Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
230 | G2 : std::ops::$trait_assign<F> + Clone, { |
0 | 231 | #[inline] |
232 | fn $fn_assign(&mut self, t : F) { | |
8
4e09b7829b51
Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
233 | Arc::make_mut(&mut self.0).$fn_assign(t); |
4e09b7829b51
Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
234 | Arc::make_mut(&mut self.1).$fn_assign(t); |
0 | 235 | } |
236 | } | |
237 | ||
238 | impl<'a, F : Float, G1, G2> | |
239 | std::ops::$trait<F> | |
240 | for &'a BothGenerators<G1, G2> | |
241 | where &'a G1 : std::ops::$trait<F,Output=G1>, | |
242 | &'a G2 : std::ops::$trait<F,Output=G2> { | |
243 | type Output = BothGenerators<G1, G2>; | |
244 | #[inline] | |
245 | fn $fn(self, t : F) -> BothGenerators<G1, G2> { | |
8
4e09b7829b51
Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
246 | BothGenerators(Arc::new(self.0.$fn(t)), |
4e09b7829b51
Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
247 | Arc::new(self.1.$fn(t))) |
0 | 248 | } |
249 | } | |
250 | } | |
251 | } | |
252 | ||
253 | make_either_scalarop_rhs!(Mul, mul, MulAssign, mul_assign); | |
254 | make_either_scalarop_rhs!(Div, div, DivAssign, div_assign); | |
255 | ||
256 | impl<G1, G2> std::ops::Neg for BothGenerators<G1, G2> | |
8
4e09b7829b51
Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
257 | where G1 : std::ops::Neg + Clone, |
4e09b7829b51
Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
258 | G2 : std::ops::Neg + Clone, { |
0 | 259 | type Output = BothGenerators<G1::Output, G2::Output>; |
260 | #[inline] | |
261 | fn neg(self) -> Self::Output { | |
8
4e09b7829b51
Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
262 | BothGenerators(Arc::new(Arc::unwrap_or_clone(self.0).neg()), |
4e09b7829b51
Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
263 | Arc::new(Arc::unwrap_or_clone(self.1).neg())) |
0 | 264 | } |
265 | } | |
266 | /* | |
267 | impl<'a, G1, G2> std::ops::Neg for &'a BothGenerators<G1, G2> | |
268 | where &'a G1 : std::ops::Neg, &'a G2 : std::ops::Neg, { | |
269 | type Output = BothGenerators<<&'a G1 as std::ops::Neg>::Output, | |
270 | <&'a G2 as std::ops::Neg>::Output>; | |
271 | fn neg(self) -> Self::Output { | |
272 | BothGenerators(self.0.neg(), self.1.neg()) | |
273 | } | |
274 | } | |
275 | */ |