49:edb95d2b83cc | 81:d2acaaddd9af |
---|---|
1 | 1 |
2 use numeric_literals::replace_float_literals; | 2 use numeric_literals::replace_float_literals; |
3 use std::iter::Sum; | 3 use std::iter::Sum; |
4 use std::marker::PhantomData; | |
5 use std::sync::Arc; | 4 use std::sync::Arc; |
6 use crate::types::Float; | 5 use crate::types::{Float, HasScalarField, HasRealField}; |
7 use crate::mapping::{Apply, Mapping, Differentiable}; | 6 use crate::mapping::{Apply, Mapping, Differentiable}; |
8 //use crate::linops::{Apply, Linear}; | 7 //use crate::linops::{Apply, Linear}; |
9 use crate::sets::Set; | 8 use crate::sets::Set; |
10 use crate::sets::Cube; | 9 use crate::sets::Cube; |
11 use crate::loc::Loc; | 10 use crate::loc::Loc; |
27 /// Identifiers of the components ([`SupportGenerator::Id`], usually `usize`) are stored stored | 26 /// Identifiers of the components ([`SupportGenerator::Id`], usually `usize`) are stored stored |
28 /// in a [bisection tree][BTImpl], when one is provided as `bt`. However `bt` may also be `()` | 27 /// in a [bisection tree][BTImpl], when one is provided as `bt`. However `bt` may also be `()` |
29 /// for a [`PreBTFN`] that is only useful for vector space operations with a full [`BTFN`]. | 28 /// for a [`PreBTFN`] that is only useful for vector space operations with a full [`BTFN`]. |
30 #[derive(Clone,Debug)] | 29 #[derive(Clone,Debug)] |
31 pub struct BTFN< | 30 pub struct BTFN< |
32 F : Float, | 31 G : SupportGenerator<N>, |
33 G : SupportGenerator<F, N>, | |
34 BT /*: BTImpl<F, N>*/, | 32 BT /*: BTImpl<F, N>*/, |
35 const N : usize | 33 const N : usize |
36 > /*where G::SupportType : LocalAnalysis<F, A, N>*/ { | 34 > { |
37 bt : BT, | 35 bt : BT, |
38 generator : Arc<G>, | 36 generator : Arc<G>, |
39 _phantoms : PhantomData<F>, | 37 } |
38 | |
39 impl<G : SupportGenerator<N>, BT, const N : usize> HasScalarField for BTFN<G, BT, N> { | |
40 type Field = G::Field; | |
40 } | 41 } |
41 | 42 |
42 impl<F : Float, G, BT, const N : usize> | 43 impl<F : Float, G, BT, const N : usize> |
43 BTFN<F, G, BT, N> | 44 BTFN<G, BT, N> |
44 where G : SupportGenerator<F, N, Id=BT::Data>, | 45 where G : SupportGenerator<N, RealField = F>, |
45 G::SupportType : LocalAnalysis<F, BT::Agg, N>, | 46 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>>, |
46 BT : BTImpl<F, N> { | 47 BT : BTImpl<F, N, Data=G::Id> { |
47 | 48 |
48 /// Create a new BTFN from a support generator and a pre-initialised bisection tree. | 49 /// Create a new BTFN from a support generator and a pre-initialised bisection tree. |
49 /// | 50 /// |
50 /// The bisection tree `bt` should be pre-initialised to correspond to the `generator`. | 51 /// The bisection tree `bt` should be pre-initialised to correspond to the `generator`. |
51 /// Use [`Self::construct`] if no preinitialised tree is available. Use [`Self::new_refresh`] | 52 /// Use [`Self::construct`] if no preinitialised tree is available. Use [`Self::new_refresh`] |
58 | 59 |
59 fn new_arc(bt : BT, generator : Arc<G>) -> Self { | 60 fn new_arc(bt : BT, generator : Arc<G>) -> Self { |
60 BTFN { | 61 BTFN { |
61 bt : bt, | 62 bt : bt, |
62 generator : generator, | 63 generator : generator, |
63 _phantoms : std::marker::PhantomData, | |
64 } | 64 } |
65 } | 65 } |
66 | 66 |
67 /// Create a new BTFN support generator and a pre-initialised bisection tree, | 67 /// Create a new BTFN support generator and a pre-initialised bisection tree, |
68 /// cloning the tree and refreshing aggregators. | 68 /// cloning the tree and refreshing aggregators. |
83 /// Create a new BTFN from a support generator, domain, and depth for a new [`BT`]. | 83 /// Create a new BTFN from a support generator, domain, and depth for a new [`BT`]. |
84 /// | 84 /// |
85 /// The top node of the created [`BT`] will have the given `domain`. | 85 /// The top node of the created [`BT`] will have the given `domain`. |
86 /// | 86 /// |
87 /// See the documentation for [`BTFN`] on the role of the `generator`. | 87 /// See the documentation for [`BTFN`] on the role of the `generator`. |
88 pub fn construct(domain : Cube<F, N>, depth : BT::Depth, generator : G) -> Self { | 88 pub fn construct(domain : Cube<G::Field, N>, depth : BT::Depth, generator : G) -> Self { |
89 Self::construct_arc(domain, depth, Arc::new(generator)) | 89 Self::construct_arc(domain, depth, Arc::new(generator)) |
90 } | 90 } |
91 | 91 |
92 fn construct_arc(domain : Cube<F, N>, depth : BT::Depth, generator : Arc<G>) -> Self { | 92 fn construct_arc(domain : Cube<G::Field, N>, depth : BT::Depth, generator : Arc<G>) -> Self { |
93 let mut bt = BT::new(domain, depth); | 93 let mut bt = BT::new(domain, depth); |
94 for (d, support) in generator.all_data() { | 94 for (d, support) in generator.all_data() { |
95 bt.insert(d, &support); | 95 bt.insert(d, &support); |
96 } | 96 } |
97 Self::new_arc(bt, generator) | 97 Self::new_arc(bt, generator) |
99 | 99 |
100 /// Convert the aggregator of the [`BTFN`] to a different one. | 100 /// Convert the aggregator of the [`BTFN`] to a different one. |
101 /// | 101 /// |
102 /// This will construct a [`BTFN`] with the same components and generator as the (consumed) | 102 /// This will construct a [`BTFN`] with the same components and generator as the (consumed) |
103 /// `self`, but a new `BT` with [`Aggregator`]s of type `ANew`. | 103 /// `self`, but a new `BT` with [`Aggregator`]s of type `ANew`. |
104 pub fn convert_aggregator<ANew>(self) -> BTFN<F, G, BT::Converted<ANew>, N> | 104 pub fn convert_aggregator<ANew>(self) -> BTFN<G, BT::Converted<ANew>, N> |
105 where ANew : Aggregator, | 105 where ANew : Aggregator, |
106 G : SupportGenerator<F, N, Id=BT::Data>, | 106 G : SupportGenerator<N>, |
107 G::SupportType : LocalAnalysis<F, ANew, N> { | 107 G::SupportType : LocalAnalysis<ANew, Cube<G::RealField, N>> { |
108 BTFN::new_arc(self.bt.convert_aggregator(&*self.generator), self.generator) | 108 BTFN::new_arc(self.bt.convert_aggregator(&*self.generator), self.generator) |
109 } | 109 } |
110 | 110 |
111 /// Change the generator (after, e.g., a scaling of the latter). | 111 /// Change the generator (after, e.g., a scaling of the latter). |
112 fn new_generator(&self, generator : G) -> Self { | 112 fn new_generator(&self, generator : G) -> Self { |
119 } | 119 } |
120 | 120 |
121 } | 121 } |
122 | 122 |
123 impl<F : Float, G, BT, const N : usize> | 123 impl<F : Float, G, BT, const N : usize> |
124 BTFN<F, G, BT, N> | 124 BTFN<G, BT, N> |
125 where G : SupportGenerator<F, N> { | 125 where G : SupportGenerator<N, RealField = F> { |
126 /// Change the [bisection tree][BTImpl] of the [`BTFN`] to a different one. | 126 /// Change the [bisection tree][BTImpl] of the [`BTFN`] to a different one. |
127 /// | 127 /// |
128 /// This can be used to convert a [`PreBTFN`] to a full [`BTFN`], or the change | 128 /// This can be used to convert a [`PreBTFN`] to a full [`BTFN`], or the change |
129 /// the aggreagator; see also [`self.convert_aggregator`]. | 129 /// the aggreagator; see also [`self.convert_aggregator`]. |
130 pub fn instantiate< | 130 pub fn instantiate< |
131 BTNew : BTImpl<F, N, Data=G::Id>, | 131 BTNew : BTImpl<F, N, Data=G::Id>, |
132 > (self, domain : Cube<F, N>, depth : BTNew::Depth) -> BTFN<F, G, BTNew, N> | 132 > (self, domain : Cube<F, N>, depth : BTNew::Depth) -> BTFN<G, BTNew, N> |
133 where G::SupportType : LocalAnalysis<F, BTNew::Agg, N> { | 133 where G::SupportType : LocalAnalysis<BTNew::Agg, Cube<F, N>> { |
134 BTFN::construct_arc(domain, depth, self.generator) | 134 BTFN::construct_arc(domain, depth, self.generator) |
135 } | 135 } |
136 } | 136 } |
137 | 137 |
138 /// A BTFN with no bisection tree. | 138 /// A BTFN with no bisection tree. |
139 /// | 139 /// |
140 /// Most BTFN methods are not available, but if a BTFN is going to be summed with another | 140 /// Most BTFN methods are not available, but if a BTFN is going to be summed with another |
141 /// before other use, it will be more efficient to not construct an unnecessary bisection tree | 141 /// before other use, it will be more efficient to not construct an unnecessary bisection tree |
142 /// that would be shortly dropped. | 142 /// that would be shortly dropped. |
143 pub type PreBTFN<F, G, const N : usize> = BTFN<F, G, (), N>; | 143 pub type PreBTFN<G, const N : usize> = BTFN<G, (), N>; |
144 | 144 |
145 impl<F : Float, G, const N : usize> PreBTFN<F, G, N> where G : SupportGenerator<F, N> { | 145 impl<G, const N : usize> PreBTFN<G, N> where G : SupportGenerator<N> { |
146 | 146 |
147 /// Create a new [`PreBTFN`] with no bisection tree. | 147 /// Create a new [`PreBTFN`] with no bisection tree. |
148 pub fn new_pre(generator : G) -> Self { | 148 pub fn new_pre(generator : G) -> Self { |
149 BTFN { | 149 BTFN { |
150 bt : (), | 150 bt : (), |
151 generator : Arc::new(generator), | 151 generator : Arc::new(generator), |
152 _phantoms : std::marker::PhantomData, | |
153 } | 152 } |
154 } | 153 } |
155 } | 154 } |
156 | 155 |
157 impl<F : Float, G, BT, const N : usize> | 156 impl<F : Float, G, BT, const N : usize> |
158 BTFN<F, G, BT, N> | 157 BTFN<G, BT, N> |
159 where G : SupportGenerator<F, N, Id=usize>, | 158 where G : SupportGenerator<N, Id=usize, RealField = F>, |
160 G::SupportType : LocalAnalysis<F, BT::Agg, N>, | 159 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>>, |
161 BT : BTImpl<F, N, Data=usize> { | 160 BT : BTImpl<F, N, Data=usize> { |
162 | 161 |
163 /// Helper function for implementing [`std::ops::Add`]. | 162 /// Helper function for implementing [`std::ops::Add`]. |
164 fn add_another<G2>(&self, g2 : Arc<G2>) -> BTFN<F, BothGenerators<G, G2>, BT, N> | 163 fn add_another<G2>(&self, g2 : Arc<G2>) -> BTFN<BothGenerators<G, G2>, BT, N> |
165 where G2 : SupportGenerator<F, N, Id=usize>, | 164 where G2 : SupportGenerator<N, Id=usize, RealField = F>, |
166 G2::SupportType : LocalAnalysis<F, BT::Agg, N> { | 165 G2::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> { |
167 | 166 |
168 let mut bt = self.bt.clone(); | 167 let mut bt = self.bt.clone(); |
169 let both = BothGenerators(Arc::clone(&self.generator), g2); | 168 let both = BothGenerators(Arc::clone(&self.generator), g2); |
170 | 169 |
171 for (d, support) in both.all_right_data() { | 170 for (d, support) in both.all_right_data() { |
173 } | 172 } |
174 | 173 |
175 BTFN { | 174 BTFN { |
176 bt : bt, | 175 bt : bt, |
177 generator : Arc::new(both), | 176 generator : Arc::new(both), |
178 _phantoms : std::marker::PhantomData, | |
179 } | 177 } |
180 } | 178 } |
181 } | 179 } |
182 | 180 |
183 macro_rules! make_btfn_add { | 181 macro_rules! make_btfn_add { |
184 ($lhs:ty, $preprocess:path, $($extra_trait:ident)?) => { | 182 ($lhs:ty, $preprocess:path, $($extra_trait:ident)?) => { |
185 impl<'a, F : Float, G1, G2, BT1, BT2, const N : usize> | 183 impl<'a, F : Float, G1, G2, BT1, BT2, const N : usize> |
186 std::ops::Add<BTFN<F, G2, BT2, N>> for | 184 std::ops::Add<BTFN<G2, BT2, N>> for |
187 $lhs | 185 $lhs |
188 where BT1 : BTImpl<F, N, Data=usize>, | 186 where BT1 : BTImpl<F, N, Data=usize>, |
189 G1 : SupportGenerator<F, N, Id=usize> + $($extra_trait)?, | 187 G1 : SupportGenerator<N, Id=usize, RealField = F> + $($extra_trait)?, |
190 G2 : SupportGenerator<F, N, Id=usize>, | 188 G2 : SupportGenerator<N, Id=usize, RealField = F>, |
191 G1::SupportType : LocalAnalysis<F, BT1::Agg, N>, | 189 G1::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>>, |
192 G2::SupportType : LocalAnalysis<F, BT1::Agg, N> { | 190 G2::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>> { |
193 type Output = BTFN<F, BothGenerators<G1, G2>, BT1, N>; | 191 type Output = BTFN<BothGenerators<G1, G2>, BT1, N>; |
194 #[inline] | 192 #[inline] |
195 fn add(self, other : BTFN<F, G2, BT2, N>) -> Self::Output { | 193 fn add(self, other : BTFN<G2, BT2, N>) -> Self::Output { |
196 $preprocess(self).add_another(other.generator) | 194 $preprocess(self).add_another(other.generator) |
197 } | 195 } |
198 } | 196 } |
199 | 197 |
200 impl<'a, 'b, F : Float, G1, G2, BT1, BT2, const N : usize> | 198 impl<'a, 'b, F : Float, G1, G2, BT1, BT2, const N : usize> |
201 std::ops::Add<&'b BTFN<F, G2, BT2, N>> for | 199 std::ops::Add<&'b BTFN<G2, BT2, N>> for |
202 $lhs | 200 $lhs |
203 where BT1 : BTImpl<F, N, Data=usize>, | 201 where BT1 : BTImpl<F, N, Data=usize>, |
204 G1 : SupportGenerator<F, N, Id=usize> + $($extra_trait)?, | 202 G1 : SupportGenerator<N, Id=usize, RealField = F> + $($extra_trait)?, |
205 G2 : SupportGenerator<F, N, Id=usize>, | 203 G2 : SupportGenerator<N, Id=usize, RealField = F>, |
206 G1::SupportType : LocalAnalysis<F, BT1::Agg, N>, | 204 G1::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>>, |
207 G2::SupportType : LocalAnalysis<F, BT1::Agg, N> { | 205 G2::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>> { |
208 | 206 |
209 type Output = BTFN<F, BothGenerators<G1, G2>, BT1, N>; | 207 type Output = BTFN<BothGenerators<G1, G2>, BT1, N>; |
210 #[inline] | 208 #[inline] |
211 fn add(self, other : &'b BTFN<F, G2, BT2, N>) -> Self::Output { | 209 fn add(self, other : &'b BTFN<G2, BT2, N>) -> Self::Output { |
212 $preprocess(self).add_another(other.generator.clone()) | 210 $preprocess(self).add_another(other.generator.clone()) |
213 } | 211 } |
214 } | 212 } |
215 } | 213 } |
216 } | 214 } |
217 | 215 |
218 make_btfn_add!(BTFN<F, G1, BT1, N>, std::convert::identity, ); | 216 make_btfn_add!(BTFN<G1, BT1, N>, std::convert::identity, ); |
219 make_btfn_add!(&'a BTFN<F, G1, BT1, N>, Clone::clone, ); | 217 make_btfn_add!(&'a BTFN<G1, BT1, N>, Clone::clone, ); |
220 | 218 |
221 macro_rules! make_btfn_sub { | 219 macro_rules! make_btfn_sub { |
222 ($lhs:ty, $preprocess:path, $($extra_trait:ident)?) => { | 220 ($lhs:ty, $preprocess:path, $($extra_trait:ident)?) => { |
223 impl<'a, F : Float, G1, G2, BT1, BT2, const N : usize> | 221 impl<'a, F : Float, G1, G2, BT1, BT2, const N : usize> |
224 std::ops::Sub<BTFN<F, G2, BT2, N>> for | 222 std::ops::Sub<BTFN<G2, BT2, N>> for |
225 $lhs | 223 $lhs |
226 where BT1 : BTImpl<F, N, Data=usize>, | 224 where BT1 : BTImpl<F, N, Data=usize>, |
227 G1 : SupportGenerator<F, N, Id=usize> + $($extra_trait)?, | 225 G1 : SupportGenerator<N, Id=usize, RealField = F> + $($extra_trait)?, |
228 G2 : SupportGenerator<F, N, Id=usize>, | 226 G2 : SupportGenerator<N, Id=usize, RealField = F>, |
229 G1::SupportType : LocalAnalysis<F, BT1::Agg, N>, | 227 G1::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>>, |
230 G2::SupportType : LocalAnalysis<F, BT1::Agg, N> { | 228 G2::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>> { |
231 type Output = BTFN<F, BothGenerators<G1, G2>, BT1, N>; | 229 type Output = BTFN<BothGenerators<G1, G2>, BT1, N>; |
232 #[inline] | 230 #[inline] |
233 fn sub(self, other : BTFN<F, G2, BT2, N>) -> Self::Output { | 231 fn sub(self, other : BTFN<G2, BT2, N>) -> Self::Output { |
234 $preprocess(self).add_another(Arc::new( | 232 $preprocess(self).add_another(Arc::new( |
235 Arc::try_unwrap(other.generator) | 233 Arc::try_unwrap(other.generator) |
236 .unwrap_or_else(|arc| (*arc).clone()) | 234 .unwrap_or_else(|arc| (*arc).clone()) |
237 .neg() | 235 .neg() |
238 )) | 236 )) |
239 } | 237 } |
240 } | 238 } |
241 | 239 |
242 impl<'a, 'b, F : Float, G1, G2, BT1, BT2, const N : usize> | 240 impl<'a, 'b, F : Float, G1, G2, BT1, BT2, const N : usize> |
243 std::ops::Sub<&'b BTFN<F, G2, BT2, N>> for | 241 std::ops::Sub<&'b BTFN<G2, BT2, N>> for |
244 $lhs | 242 $lhs |
245 where BT1 : BTImpl<F, N, Data=usize>, | 243 where BT1 : BTImpl<F, N, Data=usize>, |
246 G1 : SupportGenerator<F, N, Id=usize> + $($extra_trait)?, | 244 G1 : SupportGenerator<N, Id=usize, RealField = F> + $($extra_trait)?, |
247 G2 : SupportGenerator<F, N, Id=usize> + Clone, | 245 G2 : SupportGenerator<N, Id=usize, RealField = F> + Clone, |
248 G1::SupportType : LocalAnalysis<F, BT1::Agg, N>, | 246 G1::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>>, |
249 G2::SupportType : LocalAnalysis<F, BT1::Agg, N>, | 247 G2::SupportType : LocalAnalysis<BT1::Agg, Cube<F, N>>, |
250 &'b G2 : std::ops::Neg<Output=G2> { | 248 &'b G2 : std::ops::Neg<Output=G2> { |
251 | 249 |
252 type Output = BTFN<F, BothGenerators<G1, G2>, BT1, N>; | 250 type Output = BTFN<BothGenerators<G1, G2>, BT1, N>; |
253 #[inline] | 251 #[inline] |
254 fn sub(self, other : &'b BTFN<F, G2, BT2, N>) -> Self::Output { | 252 fn sub(self, other : &'b BTFN<G2, BT2, N>) -> Self::Output { |
255 $preprocess(self).add_another(Arc::new((*other.generator).clone().neg())) | 253 $preprocess(self).add_another(Arc::new((*other.generator).clone().neg())) |
256 } | 254 } |
257 } | 255 } |
258 } | 256 } |
259 } | 257 } |
260 | 258 |
261 make_btfn_sub!(BTFN<F, G1, BT1, N>, std::convert::identity, ); | 259 make_btfn_sub!(BTFN<G1, BT1, N>, std::convert::identity, ); |
262 make_btfn_sub!(&'a BTFN<F, G1, BT1, N>, std::convert::identity, ); | 260 make_btfn_sub!(&'a BTFN<G1, BT1, N>, std::convert::identity, ); |
263 | 261 |
264 macro_rules! make_btfn_scalarop_rhs { | 262 macro_rules! make_btfn_scalarop_rhs { |
265 ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { | 263 ($trait:ident, $fn:ident, $trait_assign:ident, $fn_assign:ident) => { |
266 impl<F : Float, G, BT, const N : usize> | 264 impl<F : Float, G, BT, const N : usize> |
267 std::ops::$trait_assign<F> | 265 std::ops::$trait_assign<F> |
268 for BTFN<F, G, BT, N> | 266 for BTFN<G, BT, N> |
269 where BT : BTImpl<F, N>, | 267 where BT : BTImpl<F, N>, |
270 G : SupportGenerator<F, N, Id=BT::Data>, | 268 G : SupportGenerator<N, Id=BT::Data, RealField = F>, |
271 G::SupportType : LocalAnalysis<F, BT::Agg, N> { | 269 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> { |
272 #[inline] | 270 #[inline] |
273 fn $fn_assign(&mut self, t : F) { | 271 fn $fn_assign(&mut self, t : F) { |
274 Arc::make_mut(&mut self.generator).$fn_assign(t); | 272 Arc::make_mut(&mut self.generator).$fn_assign(t); |
275 self.refresh_aggregator(); | 273 self.refresh_aggregator(); |
276 } | 274 } |
277 } | 275 } |
278 | 276 |
279 impl<F : Float, G, BT, const N : usize> | 277 impl<F : Float, G, BT, const N : usize> |
280 std::ops::$trait<F> | 278 std::ops::$trait<F> |
281 for BTFN<F, G, BT, N> | 279 for BTFN<G, BT, N> |
282 where BT : BTImpl<F, N>, | 280 where BT : BTImpl<F, N>, |
283 G : SupportGenerator<F, N, Id=BT::Data>, | 281 G : SupportGenerator<N, Id=BT::Data, RealField = F>, |
284 G::SupportType : LocalAnalysis<F, BT::Agg, N> { | 282 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> { |
285 type Output = Self; | 283 type Output = Self; |
286 #[inline] | 284 #[inline] |
287 fn $fn(mut self, t : F) -> Self::Output { | 285 fn $fn(mut self, t : F) -> Self::Output { |
288 Arc::make_mut(&mut self.generator).$fn_assign(t); | 286 Arc::make_mut(&mut self.generator).$fn_assign(t); |
289 self.refresh_aggregator(); | 287 self.refresh_aggregator(); |
291 } | 289 } |
292 } | 290 } |
293 | 291 |
294 impl<'a, F : Float, G, BT, const N : usize> | 292 impl<'a, F : Float, G, BT, const N : usize> |
295 std::ops::$trait<F> | 293 std::ops::$trait<F> |
296 for &'a BTFN<F, G, BT, N> | 294 for &'a BTFN<G, BT, N> |
297 where BT : BTImpl<F, N>, | 295 where BT : BTImpl<F, N>, |
298 G : SupportGenerator<F, N, Id=BT::Data>, | 296 G : SupportGenerator<N, Id=BT::Data, RealField = F>, |
299 G::SupportType : LocalAnalysis<F, BT::Agg, N>, | 297 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>>, |
300 &'a G : std::ops::$trait<F,Output=G> { | 298 &'a G : std::ops::$trait<F,Output=G> { |
301 type Output = BTFN<F, G, BT, N>; | 299 type Output = BTFN<G, BT, N>; |
302 #[inline] | 300 #[inline] |
303 fn $fn(self, t : F) -> Self::Output { | 301 fn $fn(self, t : F) -> Self::Output { |
304 self.new_generator(self.generator.$fn(t)) | 302 self.new_generator(self.generator.$fn(t)) |
305 } | 303 } |
306 } | 304 } |
311 make_btfn_scalarop_rhs!(Div, div, DivAssign, div_assign); | 309 make_btfn_scalarop_rhs!(Div, div, DivAssign, div_assign); |
312 | 310 |
313 macro_rules! make_btfn_scalarop_lhs { | 311 macro_rules! make_btfn_scalarop_lhs { |
314 ($trait:ident, $fn:ident, $fn_assign:ident, $($f:ident)+) => { $( | 312 ($trait:ident, $fn:ident, $fn_assign:ident, $($f:ident)+) => { $( |
315 impl<G, BT, const N : usize> | 313 impl<G, BT, const N : usize> |
316 std::ops::$trait<BTFN<$f, G, BT, N>> | 314 std::ops::$trait<BTFN<G, BT, N>> |
317 for $f | 315 for $f |
318 where BT : BTImpl<$f, N>, | 316 where BT : BTImpl<$f, N>, |
319 G : SupportGenerator<$f, N, Id=BT::Data>, | 317 G : SupportGenerator<N, Id=BT::Data, RealField = $f>, |
320 G::SupportType : LocalAnalysis<$f, BT::Agg, N> { | 318 G::SupportType : LocalAnalysis<BT::Agg, Cube<$f, N>> { |
321 type Output = BTFN<$f, G, BT, N>; | 319 type Output = BTFN<G, BT, N>; |
322 #[inline] | 320 #[inline] |
323 fn $fn(self, mut a : BTFN<$f, G, BT, N>) -> Self::Output { | 321 fn $fn(self, mut a : BTFN<G, BT, N>) -> Self::Output { |
324 Arc::make_mut(&mut a.generator).$fn_assign(self); | 322 Arc::make_mut(&mut a.generator).$fn_assign(self); |
325 a.refresh_aggregator(); | 323 a.refresh_aggregator(); |
326 a | 324 a |
327 } | 325 } |
328 } | 326 } |
329 | 327 |
330 impl<'a, G, BT, const N : usize> | 328 impl<'a, G, BT, const N : usize> |
331 std::ops::$trait<&'a BTFN<$f, G, BT, N>> | 329 std::ops::$trait<&'a BTFN<G, BT, N>> |
332 for $f | 330 for $f |
333 where BT : BTImpl<$f, N>, | 331 where BT : BTImpl<$f, N>, |
334 G : SupportGenerator<$f, N, Id=BT::Data> + Clone, | 332 G : SupportGenerator<N, Id=BT::Data, RealField = $f> + Clone, |
335 G::SupportType : LocalAnalysis<$f, BT::Agg, N>, | 333 G::SupportType : LocalAnalysis<BT::Agg, Cube<$f, N>>, |
336 // FIXME: This causes compiler overflow | 334 // FIXME: This causes compiler overflow |
337 /*&'a G : std::ops::$trait<$f,Output=G>*/ { | 335 /*&'a G : std::ops::$trait<$f,Output=G>*/ { |
338 type Output = BTFN<$f, G, BT, N>; | 336 type Output = BTFN<G, BT, N>; |
339 #[inline] | 337 #[inline] |
340 fn $fn(self, a : &'a BTFN<$f, G, BT, N>) -> Self::Output { | 338 fn $fn(self, a : &'a BTFN<G, BT, N>) -> Self::Output { |
341 let mut tmp = (*a.generator).clone(); | 339 let mut tmp = (*a.generator).clone(); |
342 tmp.$fn_assign(self); | 340 tmp.$fn_assign(self); |
343 a.new_generator(tmp) | 341 a.new_generator(tmp) |
344 // FIXME: Prevented by the compiler overflow above. | 342 // FIXME: Prevented by the compiler overflow above. |
345 //a.new_generator(a.generator.$fn(a)) | 343 //a.new_generator(a.generator.$fn(a)) |
353 | 351 |
354 macro_rules! make_btfn_unaryop { | 352 macro_rules! make_btfn_unaryop { |
355 ($trait:ident, $fn:ident) => { | 353 ($trait:ident, $fn:ident) => { |
356 impl<F : Float, G, BT, const N : usize> | 354 impl<F : Float, G, BT, const N : usize> |
357 std::ops::$trait | 355 std::ops::$trait |
358 for BTFN<F, G, BT, N> | 356 for BTFN<G, BT, N> |
359 where BT : BTImpl<F, N>, | 357 where BT : BTImpl<F, N>, |
360 G : SupportGenerator<F, N, Id=BT::Data>, | 358 G : SupportGenerator<N, Id=BT::Data, RealField = F>, |
361 G::SupportType : LocalAnalysis<F, BT::Agg, N> { | 359 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> { |
362 type Output = Self; | 360 type Output = Self; |
363 #[inline] | 361 #[inline] |
364 fn $fn(mut self) -> Self::Output { | 362 fn $fn(mut self) -> Self::Output { |
365 self.generator = Arc::new(Arc::unwrap_or_clone(self.generator).$fn()); | 363 self.generator = Arc::new(Arc::unwrap_or_clone(self.generator).$fn()); |
366 self.refresh_aggregator(); | 364 self.refresh_aggregator(); |
389 // | 387 // |
390 // Apply, Mapping, Differentiate | 388 // Apply, Mapping, Differentiate |
391 // | 389 // |
392 | 390 |
393 impl<'a, F : Float, G, BT, V, const N : usize> Apply<&'a Loc<F, N>> | 391 impl<'a, F : Float, G, BT, V, const N : usize> Apply<&'a Loc<F, N>> |
394 for BTFN<F, G, BT, N> | 392 for BTFN<G, BT, N> |
395 where BT : BTImpl<F, N>, | 393 where BT : BTImpl<F, N>, |
396 G : SupportGenerator<F, N, Id=BT::Data>, | 394 G : SupportGenerator<N, Id=BT::Data, RealField = F>, |
397 G::SupportType : LocalAnalysis<F, BT::Agg, N> + Apply<&'a Loc<F, N>, Output = V>, | 395 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> |
396 + Apply<&'a Loc<F, N>, Output = V>, | |
398 V : Sum { | 397 V : Sum { |
399 | 398 |
400 type Output = V; | 399 type Output = V; |
401 | 400 |
402 fn apply(&self, x : &'a Loc<F, N>) -> Self::Output { | 401 fn apply(&self, x : &'a Loc<F, N>) -> Self::Output { |
404 .map(|&d| self.generator.support_for(d).apply(x)).sum() | 403 .map(|&d| self.generator.support_for(d).apply(x)).sum() |
405 } | 404 } |
406 } | 405 } |
407 | 406 |
408 impl<F : Float, G, BT, V, const N : usize> Apply<Loc<F, N>> | 407 impl<F : Float, G, BT, V, const N : usize> Apply<Loc<F, N>> |
409 for BTFN<F, G, BT, N> | 408 for BTFN<G, BT, N> |
410 where BT : BTImpl<F, N>, | 409 where BT : BTImpl<F, N>, |
411 G : SupportGenerator<F, N, Id=BT::Data>, | 410 G : SupportGenerator<N, Id=BT::Data, RealField = F>, |
412 G::SupportType : LocalAnalysis<F, BT::Agg, N> + Apply<Loc<F, N>, Output = V>, | 411 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> |
412 + Apply<Loc<F, N>, Output = V>, | |
413 V : Sum { | 413 V : Sum { |
414 | 414 |
415 type Output = V; | 415 type Output = V; |
416 | 416 |
417 fn apply(&self, x : Loc<F, N>) -> Self::Output { | 417 fn apply(&self, x : Loc<F, N>) -> Self::Output { |
418 self.bt.iter_at(&x) | 418 self.bt.iter_at(&x) |
419 .map(|&d| self.generator.support_for(d).apply(x)).sum() | 419 .map(|&d| self.generator.support_for(d).apply(x)).sum() |
420 } | 420 } |
421 } | 421 } |
422 | 422 |
423 impl<'a, F : Float, G, BT, V, const N : usize> Differentiable<&'a Loc<F, N>> | 423 impl<'a, F : Float, G, BT, V : HasRealField<RealField=F>, const N : usize> |
424 for BTFN<F, G, BT, N> | 424 Differentiable<&'a Loc<F, N>> |
425 for BTFN<G, BT, N> | |
425 where BT : BTImpl<F, N>, | 426 where BT : BTImpl<F, N>, |
426 G : SupportGenerator<F, N, Id=BT::Data>, | 427 G : SupportGenerator<N, Id=BT::Data, RealField = F>, |
427 G::SupportType : LocalAnalysis<F, BT::Agg, N> + Differentiable<&'a Loc<F, N>, Derivative = V>, | 428 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> |
429 + Differentiable<&'a Loc<F, N>, Derivative = V>, | |
428 V : Sum { | 430 V : Sum { |
429 | 431 |
430 type Derivative = V; | 432 type Derivative = V; |
431 | 433 |
432 fn differential(&self, x : &'a Loc<F, N>) -> Self::Derivative { | 434 fn differential(&self, x : &'a Loc<F, N>) -> Self::Derivative { |
435 .sum() | 437 .sum() |
436 } | 438 } |
437 } | 439 } |
438 | 440 |
439 impl<F : Float, G, BT, V, const N : usize> Differentiable<Loc<F, N>> | 441 impl<F : Float, G, BT, V, const N : usize> Differentiable<Loc<F, N>> |
440 for BTFN<F, G, BT, N> | 442 for BTFN<G, BT, N> |
441 where BT : BTImpl<F, N>, | 443 where BT : BTImpl<F, N>, |
442 G : SupportGenerator<F, N, Id=BT::Data>, | 444 G : SupportGenerator<N, Id=BT::Data, RealField = F>, |
443 G::SupportType : LocalAnalysis<F, BT::Agg, N> + Differentiable<Loc<F, N>, Derivative = V>, | 445 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> |
444 V : Sum { | 446 + Differentiable<Loc<F, N>, Derivative = V>, |
447 V : Sum + HasRealField<RealField=F> { | |
445 | 448 |
446 type Derivative = V; | 449 type Derivative = V; |
447 | 450 |
448 fn differential(&self, x : Loc<F, N>) -> Self::Derivative { | 451 fn differential(&self, x : Loc<F, N>) -> Self::Derivative { |
449 self.bt.iter_at(&x) | 452 self.bt.iter_at(&x) |
454 | 457 |
455 // | 458 // |
456 // GlobalAnalysis | 459 // GlobalAnalysis |
457 // | 460 // |
458 | 461 |
459 impl<F : Float, G, BT, const N : usize> GlobalAnalysis<F, BT::Agg> | 462 impl<F : Float, G, BT, const N : usize> GlobalAnalysis<BT::Agg> |
460 for BTFN<F, G, BT, N> | 463 for BTFN<G, BT, N> |
461 where BT : BTImpl<F, N>, | 464 where BT : BTImpl<F, N>, |
462 G : SupportGenerator<F, N, Id=BT::Data>, | 465 G : SupportGenerator<N, Id=BT::Data, RealField = F>, |
463 G::SupportType : LocalAnalysis<F, BT::Agg, N> { | 466 G::SupportType : LocalAnalysis<BT::Agg, Cube<F, N>> { |
464 | 467 |
465 #[inline] | 468 #[inline] |
466 fn global_analysis(&self) -> BT::Agg { | 469 fn global_analysis(&self) -> BT::Agg { |
467 self.bt.global_analysis() | 470 self.bt.global_analysis() |
468 } | 471 } |
615 /// Either [`RefineMax`] or [`RefineMin`]. Used only for type system purposes. | 618 /// Either [`RefineMax`] or [`RefineMin`]. Used only for type system purposes. |
616 #[allow(dead_code)] // `how` is just for type system purposes. | 619 #[allow(dead_code)] // `how` is just for type system purposes. |
617 how : T, | 620 how : T, |
618 } | 621 } |
619 | 622 |
620 impl<F : Float, G, const N : usize> Refiner<F, Bounds<F>, G, N> | 623 impl<F : Float, G, const N : usize> Refiner<Bounds<F>, G, N> |
621 for P2Refiner<F, RefineMax> | 624 for P2Refiner<F, RefineMax> |
622 where Cube<F, N> : P2Minimise<Loc<F, N>, F>, | 625 where Cube<F, N> : P2Minimise<Loc<F, N>, F>, |
623 G : SupportGenerator<F, N>, | 626 G : SupportGenerator<N, RealField = F>, |
624 G::SupportType : Mapping<Loc<F, N>, Codomain=F> | 627 G::SupportType : Mapping<Loc<F, N>, Codomain=F> |
625 + LocalAnalysis<F, Bounds<F>, N> { | 628 + LocalAnalysis<Bounds<F>, Cube<F, N>> { |
626 type Result = Option<(Loc<F, N>, F)>; | 629 type Result = Option<(Loc<F, N>, F)>; |
627 type Sorting = UpperBoundSorting<F>; | 630 type Sorting = UpperBoundSorting<F>; |
628 | 631 |
629 fn refine( | 632 fn refine( |
630 &self, | 633 &self, |
672 } | 675 } |
673 } | 676 } |
674 } | 677 } |
675 | 678 |
676 | 679 |
677 impl<F : Float, G, const N : usize> Refiner<F, Bounds<F>, G, N> | 680 impl<F : Float, G, const N : usize> Refiner<Bounds<F>, G, N> |
678 for P2Refiner<F, RefineMin> | 681 for P2Refiner<F, RefineMin> |
679 where Cube<F, N> : P2Minimise<Loc<F, N>, F>, | 682 where Cube<F, N> : P2Minimise<Loc<F, N>, F>, |
680 G : SupportGenerator<F, N>, | 683 G : SupportGenerator<N, RealField = F>, |
681 G::SupportType : Mapping<Loc<F, N>, Codomain=F> | 684 G::SupportType : Mapping<Loc<F, N>, Codomain=F> |
682 + LocalAnalysis<F, Bounds<F>, N> { | 685 + LocalAnalysis<Bounds<F>, Cube<F, N>> { |
683 type Result = Option<(Loc<F, N>, F)>; | 686 type Result = Option<(Loc<F, N>, F)>; |
684 type Sorting = LowerBoundSorting<F>; | 687 type Sorting = LowerBoundSorting<F>; |
685 | 688 |
686 fn refine( | 689 fn refine( |
687 &self, | 690 &self, |
752 #[allow(dead_code)] // `how` is just for type system purposes. | 755 #[allow(dead_code)] // `how` is just for type system purposes. |
753 /// Either [`RefineMax`] or [`RefineMin`]. Used only for type system purposes. | 756 /// Either [`RefineMax`] or [`RefineMin`]. Used only for type system purposes. |
754 how : T, | 757 how : T, |
755 } | 758 } |
756 | 759 |
757 impl<F : Float, G, const N : usize> Refiner<F, Bounds<F>, G, N> | 760 impl<F : Float, G, const N : usize> Refiner<Bounds<F>, G, N> |
758 for BoundRefiner<F, RefineMax> | 761 for BoundRefiner<F, RefineMax> |
759 where G : SupportGenerator<F, N> { | 762 where G : SupportGenerator<N, RealField = F> { |
760 type Result = bool; | 763 type Result = bool; |
761 type Sorting = UpperBoundSorting<F>; | 764 type Sorting = UpperBoundSorting<F>; |
762 | 765 |
763 fn refine( | 766 fn refine( |
764 &self, | 767 &self, |
786 fn fuse_results(r1 : &mut Self::Result, r2 : Self::Result) { | 789 fn fuse_results(r1 : &mut Self::Result, r2 : Self::Result) { |
787 *r1 = *r1 && r2; | 790 *r1 = *r1 && r2; |
788 } | 791 } |
789 } | 792 } |
790 | 793 |
791 impl<F : Float, G, const N : usize> Refiner<F, Bounds<F>, G, N> | 794 impl<F : Float, G, const N : usize> Refiner<Bounds<F>, G, N> |
792 for BoundRefiner<F, RefineMin> | 795 for BoundRefiner<F, RefineMin> |
793 where G : SupportGenerator<F, N> { | 796 where G : SupportGenerator<N, RealField = F> { |
794 type Result = bool; | 797 type Result = bool; |
795 type Sorting = UpperBoundSorting<F>; | 798 type Sorting = UpperBoundSorting<F>; |
796 | 799 |
797 fn refine( | 800 fn refine( |
798 &self, | 801 &self, |
835 // the queue. If the queue empties as a result of that, the thread goes to wait for other threads | 838 // the queue. If the queue empties as a result of that, the thread goes to wait for other threads |
836 // to produce results. Since some node had a node whose lower bound was above the `glb`, eventually | 839 // to produce results. Since some node had a node whose lower bound was above the `glb`, eventually |
837 // there should be a result, or new nodes above the `glb` inserted into the queue. Then the waiting | 840 // there should be a result, or new nodes above the `glb` inserted into the queue. Then the waiting |
838 // threads can also continue processing. If, however, numerical inaccuracy destroyes the `glb`, | 841 // threads can also continue processing. If, however, numerical inaccuracy destroyes the `glb`, |
839 // the queue may run out, and we get “Refiner failure”. | 842 // the queue may run out, and we get “Refiner failure”. |
840 impl<F : Float, G, BT, const N : usize> BTFN<F, G, BT, N> | 843 impl<F : Float, G, BT, const N : usize> BTFN<G, BT, N> |
841 where BT : BTSearch<F, N, Agg=Bounds<F>>, | 844 where BT : BTSearch<F, N, Agg=Bounds<F>>, |
842 G : SupportGenerator<F, N, Id=BT::Data>, | 845 G : SupportGenerator<N, Id=BT::Data, RealField = F>, |
843 G::SupportType : Mapping<Loc<F, N>,Codomain=F> | 846 G::SupportType : Mapping<Loc<F, N>,Codomain=F> |
844 + LocalAnalysis<F, Bounds<F>, N>, | 847 + LocalAnalysis<Bounds<F>, Cube<F, N>>, |
845 Cube<F, N> : P2Minimise<Loc<F, N>, F> { | 848 Cube<F, N> : P2Minimise<Loc<F, N>, F> { |
846 | 849 |
847 /// Maximise the `BTFN` within stated value `tolerance`. | 850 /// Maximise the `BTFN` within stated value `tolerance`. |
848 /// | 851 /// |
849 /// At most `max_steps` refinement steps are taken. | 852 /// At most `max_steps` refinement steps are taken. |