src/bisection_tree/support.rs

branch
dev
changeset 81
d2acaaddd9af
parent 47
a0db98c16ab5
equal deleted inserted replaced
49:edb95d2b83cc 81:d2acaaddd9af
8 use crate::maputil::map2; 8 use crate::maputil::map2;
9 use crate::mapping::{Apply, Differentiable}; 9 use crate::mapping::{Apply, Differentiable};
10 use crate::sets::Cube; 10 use crate::sets::Cube;
11 use crate::loc::Loc; 11 use crate::loc::Loc;
12 use super::aggregator::Bounds; 12 use super::aggregator::Bounds;
13 use crate::norms::{Norm, L1, L2, Linfinity}; 13 use crate::norms::{Norm, L1, L2, Linfinity, HasScalarField, HasRealField};
14 14
15 /// A trait for encoding constant [`Float`] values 15 /// A trait for encoding constant [`Float`] values
16 pub trait Constant : Copy + Sync + Send + 'static + std::fmt::Debug + Into<Self::Type> { 16 pub trait Constant : Copy + Sync + Send + 'static
17 /// The type of the value 17 + std::fmt::Debug + HasRealField
18 type Type : Float; 18 + Into<Self::Field> {
19 /// Returns the value of the constant 19 /// Returns the value of the constant
20 fn value(&self) -> Self::Type; 20 fn value(&self) -> Self::Field;
21 } 21 }
22 22
23 impl<F : Float> Constant for F { 23 impl<F : Float> Constant for F {
24 type Type = F;
25 #[inline] 24 #[inline]
26 fn value(&self) -> F { *self } 25 fn value(&self) -> F { *self }
27 } 26 }
28 27
29 28
30 /// A trait for working with the supports of [`Apply`]s. 29 /// A trait for working with the supports of [`Apply`]s.
31 /// 30 ///
32 /// Apply is not a super-trait to allow more general use. 31 /// Apply is not a super-trait to allow more general use.
33 pub trait Support<F : Num, const N : usize> : Sized + Sync + Send + 'static { 32 pub trait Support<const N : usize> : Sized + Sync + Send + 'static + HasRealField {
34 /// Return a cube containing the support of the function represented by `self`. 33 /// Return a cube containing the support of the function represented by `self`.
35 /// 34 ///
36 /// The hint may be larger than the actual support, but must contain it. 35 /// The hint may be larger than the actual support, but must contain it.
37 fn support_hint(&self) -> Cube<F,N>; 36 fn support_hint(&self) -> Cube<Self::Field,N>;
38 37
39 /// Indicate whether `x` is in the support of the function represented by `self`. 38 /// Indicate whether `x` is in the support of the function represented by `self`.
40 fn in_support(&self, x : &Loc<F,N>) -> bool; 39 fn in_support(&self, x : &Loc<Self::Field,N>) -> bool;
41 40
42 // Indicate whether `cube` is fully in the support of the function represented by `self`. 41 // Indicate whether `cube` is fully in the support of the function represented by `self`.
43 //fn fully_in_support(&self, cube : &Cube<F,N>) -> bool; 42 //fn fully_in_support(&self, cube : &Cube<Self::Field,N>) -> bool;
44 43
45 /// Return an optional hint for bisecting the support. 44 /// Return an optional hint for bisecting the support.
46 /// 45 ///
47 /// The output along each axis a possible coordinate at which to bisect `cube`. 46 /// The output along each axis a possible coordinate at which to bisect `cube`.
48 /// 47 ///
51 /// non-differentiability. 50 /// non-differentiability.
52 /// 51 ///
53 /// The default implementation returns `[None; N]`. 52 /// The default implementation returns `[None; N]`.
54 #[inline] 53 #[inline]
55 #[allow(unused_variables)] 54 #[allow(unused_variables)]
56 fn bisection_hint(&self, cube : &Cube<F, N>) -> [Option<F>; N] { 55 fn bisection_hint(&self, cube : &Cube<Self::Field, N>) -> [Option<Self::Field>; N] {
57 [None; N] 56 [None; N]
58 } 57 }
59 58
60 /// Translate `self` by `x`. 59 /// Translate `self` by `x`.
61 #[inline] 60 #[inline]
62 fn shift(self, x : Loc<F, N>) -> Shift<Self, F, N> { 61 fn shift(self, x : Loc<Self::Field, N>) -> Shift<Self, Self::Field, N> {
63 Shift { shift : x, base_fn : self } 62 Shift { shift : x, base_fn : self }
64 } 63 }
65 64
66 /// Multiply `self` by the scalar `a`. 65 /// Multiply `self` by the scalar `a`.
67 #[inline] 66 #[inline]
68 fn weigh<C : Constant<Type=F>>(self, a : C) -> Weighted<Self, C> { 67 fn weigh<C : Constant<RealField=Self::RealField>>(self, a : C) -> Weighted<Self, C> {
69 Weighted { weight : a, base_fn : self } 68 Weighted { weight : a, base_fn : self }
70 } 69 }
71 } 70 }
72 71
73 /// Trait for globally analysing a property `A` of a [`Apply`]. 72 /// Trait for globally analysing a property `A` of a [`Apply`].
74 /// 73 ///
75 /// Typically `A` is an [`Aggregator`][super::aggregator::Aggregator] such as 74 /// Typically `A` is an [`Aggregator`][super::aggregator::Aggregator] such as
76 /// [`Bounds`][super::aggregator::Bounds]. 75 /// [`Bounds`][super::aggregator::Bounds].
77 pub trait GlobalAnalysis<F : Num, A> { 76 pub trait GlobalAnalysis<A> {
78 /// Perform global analysis of the property `A` of `Self`. 77 /// Perform global analysis of the property `A` of `Self`.
79 /// 78 ///
80 /// As an example, in the case of `A` being [`Bounds`][super::aggregator::Bounds], 79 /// As an example, in the case of `A` being [`Bounds`][super::aggregator::Bounds],
81 /// this function will return global upper and lower bounds for the mapping 80 /// this function will return global upper and lower bounds for the mapping
82 /// represented by `self`. 81 /// represented by `self`.
83 fn global_analysis(&self) -> A; 82 fn global_analysis(&self) -> A;
84 } 83 }
85
86 // default impl<F, A, N, L> GlobalAnalysis<F, A, N> for L
87 // where L : LocalAnalysis<F, A, N> {
88 // #[inline]
89 // fn global_analysis(&self) -> Bounds<F> {
90 // self.local_analysis(&self.support_hint())
91 // }
92 // }
93 84
94 /// Trait for locally analysing a property `A` of a [`Apply`] (implementing [`Support`]) 85 /// Trait for locally analysing a property `A` of a [`Apply`] (implementing [`Support`])
95 /// within a [`Cube`]. 86 /// within a [`Cube`].
96 /// 87 ///
97 /// Typically `A` is an [`Aggregator`][super::aggregator::Aggregator] such as 88 /// Typically `A` is an [`Aggregator`][super::aggregator::Aggregator] such as
98 /// [`Bounds`][super::aggregator::Bounds]. 89 /// [`Bounds`][super::aggregator::Bounds].
99 pub trait LocalAnalysis<F : Num, A, const N : usize> : GlobalAnalysis<F, A> + Support<F, N> { 90 pub trait LocalAnalysis<A, LocalSet> : GlobalAnalysis<A> {
100 /// Perform local analysis of the property `A` of `Self`. 91 /// Perform local analysis of the property `A` of `Self`.
101 /// 92 ///
102 /// As an example, in the case of `A` being [`Bounds`][super::aggregator::Bounds], 93 /// As an example, in the case of `A` being [`Bounds`][super::aggregator::Bounds],
103 /// this function will return upper and lower bounds within `cube` for the mapping 94 /// this function will return upper and lower bounds within `cube` for the mapping
104 /// represented by `self`. 95 /// represented by `self`.
105 fn local_analysis(&self, cube : &Cube<F, N>) -> A; 96 fn local_analysis(&self, cube : &LocalSet) -> A;
106 } 97 }
107 98
108 /// Trait for determining the upper and lower bounds of an float-valued [`Apply`]. 99 /// Trait for determining the upper and lower bounds of an float-valued [`Apply`].
109 /// 100 ///
110 /// This is a blanket-implemented alias for [`GlobalAnalysis`]`<F, Bounds<F>>` 101 /// This is a blanket-implemented alias for [`GlobalAnalysis`]`<F, Bounds<F>>`
111 /// [`Apply`] is not a supertrait to allow flexibility in the implementation of either 102 /// [`Apply`] is not a supertrait to allow flexibility in the implementation of either
112 /// reference or non-reference arguments. 103 /// reference or non-reference arguments.
113 pub trait Bounded<F : Float> : GlobalAnalysis<F, Bounds<F>> { 104 pub trait Bounded : GlobalAnalysis<Bounds<Self::Field>> + HasScalarField {
114 /// Return lower and upper bounds for the values of of `self`. 105 /// Return lower and upper bounds for the values of of `self`.
115 #[inline] 106 #[inline]
116 fn bounds(&self) -> Bounds<F> { 107 fn bounds(&self) -> Bounds<Self::Field> {
117 self.global_analysis() 108 self.global_analysis()
118 } 109 }
119 } 110 }
120 111
121 impl<F : Float, T : GlobalAnalysis<F, Bounds<F>>> Bounded<F> for T { } 112 impl<T : GlobalAnalysis<Bounds<Self::Field>> + HasScalarField> Bounded for T { }
122 113
123 /// Shift of [`Support`] and [`Apply`]; output of [`Support::shift`]. 114 /// Shift of [`Support`] and [`Apply`]; output of [`Support::shift`].
124 #[derive(Copy,Clone,Debug,Serialize)] // Serialize! but not implemented by Loc. 115 #[derive(Copy,Clone,Debug,Serialize)] // Serialize! but not implemented by Loc.
125 pub struct Shift<T, F, const N : usize> { 116 pub struct Shift<T, F, const N : usize> {
126 shift : Loc<F, N>, 117 shift : Loc<F, N>,
127 base_fn : T, 118 base_fn : T,
128 } 119 }
129 120
121 impl<T, F : Num, const N : usize> HasScalarField for Shift<T, F, N> {
122 type Field = F;
123 }
124
130 impl<'a, T, V, F : Float, const N : usize> Apply<&'a Loc<F, N>> for Shift<T,F,N> 125 impl<'a, T, V, F : Float, const N : usize> Apply<&'a Loc<F, N>> for Shift<T,F,N>
131 where T : Apply<Loc<F, N>, Output=V> { 126 where T : Apply<Loc<F, N>, Output=V> {
132 type Output = V; 127 type Output = V;
133 #[inline] 128 #[inline]
134 fn apply(&self, x : &'a Loc<F, N>) -> Self::Output { 129 fn apply(&self, x : &'a Loc<F, N>) -> Self::Output {
143 fn apply(&self, x : Loc<F, N>) -> Self::Output { 138 fn apply(&self, x : Loc<F, N>) -> Self::Output {
144 self.base_fn.apply(x - &self.shift) 139 self.base_fn.apply(x - &self.shift)
145 } 140 }
146 } 141 }
147 142
148 impl<'a, T, V, F : Float, const N : usize> Differentiable<&'a Loc<F, N>> for Shift<T,F,N> 143 impl<'a, T, V : HasRealField<RealField=F>, F : Float, const N : usize>
144 Differentiable<&'a Loc<F, N>> for Shift<T,F,N>
149 where T : Differentiable<Loc<F, N>, Derivative=V> { 145 where T : Differentiable<Loc<F, N>, Derivative=V> {
150 type Derivative = V; 146 type Derivative = V;
151 #[inline] 147 #[inline]
152 fn differential(&self, x : &'a Loc<F, N>) -> Self::Derivative { 148 fn differential(&self, x : &'a Loc<F, N>) -> Self::Derivative {
153 self.base_fn.differential(x - &self.shift) 149 self.base_fn.differential(x - &self.shift)
154 } 150 }
155 } 151 }
156 152
157 impl<'a, T, V, F : Float, const N : usize> Differentiable<Loc<F, N>> for Shift<T,F,N> 153 impl<'a, T, V : HasRealField<RealField=F>, F : Float, const N : usize>
154 Differentiable<Loc<F, N>> for Shift<T,F,N>
158 where T : Differentiable<Loc<F, N>, Derivative=V> { 155 where T : Differentiable<Loc<F, N>, Derivative=V> {
159 type Derivative = V; 156 type Derivative = V;
160 #[inline] 157 #[inline]
161 fn differential(&self, x : Loc<F, N>) -> Self::Derivative { 158 fn differential(&self, x : Loc<F, N>) -> Self::Derivative {
162 self.base_fn.differential(x - &self.shift) 159 self.base_fn.differential(x - &self.shift)
163 } 160 }
164 } 161 }
165 162
166 impl<'a, T, F : Float, const N : usize> Support<F,N> for Shift<T,F,N> 163 impl<'a, T, F : Float, const N : usize> Support<N> for Shift<T,F,N>
167 where T : Support<F, N> { 164 where T : Support<N, RealField = F> {
168 #[inline] 165 #[inline]
169 fn support_hint(&self) -> Cube<F,N> { 166 fn support_hint(&self) -> Cube<F,N> {
170 self.base_fn.support_hint().shift(&self.shift) 167 self.base_fn.support_hint().shift(&self.shift)
171 } 168 }
172 169
186 map2(base_hint, &self.shift, |h, s| h.map(|z| z + *s)) 183 map2(base_hint, &self.shift, |h, s| h.map(|z| z + *s))
187 } 184 }
188 185
189 } 186 }
190 187
191 impl<'a, T, F : Float, const N : usize> GlobalAnalysis<F, Bounds<F>> for Shift<T,F,N> 188 impl<'a, T, F : Float, const N : usize> GlobalAnalysis<Bounds<F>> for Shift<T,F,N>
192 where T : LocalAnalysis<F, Bounds<F>, N> { 189 where T : GlobalAnalysis<Bounds<F>> {
193 #[inline] 190 #[inline]
194 fn global_analysis(&self) -> Bounds<F> { 191 fn global_analysis(&self) -> Bounds<F> {
195 self.base_fn.global_analysis() 192 self.base_fn.global_analysis()
196 } 193 }
197 } 194 }
198 195
199 impl<'a, T, F : Float, const N : usize> LocalAnalysis<F, Bounds<F>, N> for Shift<T,F,N> 196 impl<'a, T, F : Float, const N : usize> LocalAnalysis<Bounds<F>, Cube<F, N>>
200 where T : LocalAnalysis<F, Bounds<F>, N> { 197 for Shift<T,F,N>
198 where T : LocalAnalysis<Bounds<F>, Cube<F, N>> {
201 #[inline] 199 #[inline]
202 fn local_analysis(&self, cube : &Cube<F, N>) -> Bounds<F> { 200 fn local_analysis(&self, cube : &Cube<F, N>) -> Bounds<F> {
203 self.base_fn.local_analysis(&cube.shift(&(-self.shift))) 201 self.base_fn.local_analysis(&cube.shift(&(-self.shift)))
204 } 202 }
205 } 203 }
206 204
207 macro_rules! impl_shift_norm { 205 macro_rules! impl_shift_norm {
208 ($($norm:ident)*) => { $( 206 ($($norm:ident)*) => { $(
209 impl<'a, T, F : Float, const N : usize> Norm<F, $norm> for Shift<T,F,N> 207 impl<'a, T, const N : usize> Norm<$norm> for Shift<T,T::Field,N>
210 where T : Norm<F, $norm> { 208 where T : Norm<$norm> {
211 #[inline] 209 #[inline]
212 fn norm(&self, n : $norm) -> F { 210 fn norm(&self, n : $norm) -> T::Field {
213 self.base_fn.norm(n) 211 self.base_fn.norm(n)
214 } 212 }
215 } 213 }
216 )* } 214 )* }
217 } 215 }
226 pub weight : C, 224 pub weight : C,
227 /// The base [`Support`] or [`Apply`] being weighted. 225 /// The base [`Support`] or [`Apply`] being weighted.
228 pub base_fn : T, 226 pub base_fn : T,
229 } 227 }
230 228
229 impl<T, C, F : Float> HasScalarField for Weighted<T, C>
230 where T : HasRealField<RealField = F>,
231 C : Constant<RealField = F> {
232 type Field = F;
233 }
234
231 impl<'a, T, V, F : Float, C, const N : usize> Apply<&'a Loc<F, N>> for Weighted<T, C> 235 impl<'a, T, V, F : Float, C, const N : usize> Apply<&'a Loc<F, N>> for Weighted<T, C>
232 where T : for<'b> Apply<&'b Loc<F, N>, Output=V>, 236 where T : for<'b> Apply<&'b Loc<F, N>, Output=V>,
233 V : std::ops::Mul<F,Output=V>, 237 V : std::ops::Mul<F,Output=V>,
234 C : Constant<Type=F> { 238 C : Constant<RealField=F> {
235 type Output = V; 239 type Output = V;
236 #[inline] 240 #[inline]
237 fn apply(&self, x : &'a Loc<F, N>) -> Self::Output { 241 fn apply(&self, x : &'a Loc<F, N>) -> Self::Output {
238 self.base_fn.apply(x) * self.weight.value() 242 self.base_fn.apply(x) * self.weight.value()
239 } 243 }
240 } 244 }
241 245
242 impl<'a, T, V, F : Float, C, const N : usize> Apply<Loc<F, N>> for Weighted<T, C> 246 impl<'a, T, V, F : Float, C, const N : usize> Apply<Loc<F, N>> for Weighted<T, C>
243 where T : Apply<Loc<F, N>, Output=V>, 247 where T : Apply<Loc<F, N>, Output=V>,
244 V : std::ops::Mul<F,Output=V>, 248 V : std::ops::Mul<F,Output=V>,
245 C : Constant<Type=F> { 249 C : Constant<RealField=F> {
246 type Output = V; 250 type Output = V;
247 #[inline] 251 #[inline]
248 fn apply(&self, x : Loc<F, N>) -> Self::Output { 252 fn apply(&self, x : Loc<F, N>) -> Self::Output {
249 self.base_fn.apply(x) * self.weight.value() 253 self.base_fn.apply(x) * self.weight.value()
250 } 254 }
251 } 255 }
252 256
253 impl<'a, T, V, F : Float, C, const N : usize> Differentiable<&'a Loc<F, N>> for Weighted<T, C> 257 impl<'a, T, V : HasRealField<RealField=F>, F : Float, C, const N : usize>
254 where T : for<'b> Differentiable<&'b Loc<F, N>, Derivative=V>, 258 Differentiable<&'a Loc<F, N>> for Weighted<T, C>
259 where T : for<'b> Differentiable<&'b Loc<F, N>, Derivative=V, RealField=F>,
255 V : std::ops::Mul<F, Output=V>, 260 V : std::ops::Mul<F, Output=V>,
256 C : Constant<Type=F> { 261 C : Constant<RealField=F> {
257 type Derivative = V; 262 type Derivative = V;
258 #[inline] 263 #[inline]
259 fn differential(&self, x : &'a Loc<F, N>) -> Self::Derivative { 264 fn differential(&self, x : &'a Loc<F, N>) -> Self::Derivative {
260 self.base_fn.differential(x) * self.weight.value() 265 self.base_fn.differential(x) * self.weight.value()
261 } 266 }
262 } 267 }
263 268
264 impl<'a, T, V, F : Float, C, const N : usize> Differentiable<Loc<F, N>> for Weighted<T, C> 269 impl<'a, T, V : HasRealField<RealField = F>, F : Float, C, const N : usize>
265 where T : Differentiable<Loc<F, N>, Derivative=V>, 270 Differentiable<Loc<F, N>> for Weighted<T, C>
271 where T : Differentiable<Loc<F, N>, Derivative=V, RealField = F>,
266 V : std::ops::Mul<F, Output=V>, 272 V : std::ops::Mul<F, Output=V>,
267 C : Constant<Type=F> { 273 C : Constant<RealField=F> {
268 type Derivative = V; 274 type Derivative = V;
269 #[inline] 275 #[inline]
270 fn differential(&self, x : Loc<F, N>) -> Self::Derivative { 276 fn differential(&self, x : Loc<F, N>) -> Self::Derivative {
271 self.base_fn.differential(x) * self.weight.value() 277 self.base_fn.differential(x) * self.weight.value()
272 } 278 }
273 } 279 }
274 280
275 impl<'a, T, F : Float, C, const N : usize> Support<F,N> for Weighted<T, C> 281 impl<'a, T, F : Float, C, const N : usize> Support<N> for Weighted<T, C>
276 where T : Support<F, N>, 282 where T : Support<N, RealField = F>,
277 C : Constant<Type=F> { 283 C : Constant<RealField=F> {
278 284
279 #[inline] 285 #[inline]
280 fn support_hint(&self) -> Cube<F,N> { 286 fn support_hint(&self) -> Cube<F,N> {
281 self.base_fn.support_hint() 287 self.base_fn.support_hint()
282 } 288 }
294 fn bisection_hint(&self, cube : &Cube<F,N>) -> [Option<F>; N] { 300 fn bisection_hint(&self, cube : &Cube<F,N>) -> [Option<F>; N] {
295 self.base_fn.bisection_hint(cube) 301 self.base_fn.bisection_hint(cube)
296 } 302 }
297 } 303 }
298 304
299 impl<'a, T, F : Float, C> GlobalAnalysis<F, Bounds<F>> for Weighted<T, C> 305 impl<'a, T, F : Float, C> GlobalAnalysis<Bounds<F>> for Weighted<T, C>
300 where T : GlobalAnalysis<F, Bounds<F>>, 306 where T : GlobalAnalysis<Bounds<F>>,
301 C : Constant<Type=F> { 307 C : Constant<RealField=F> {
302 #[inline] 308 #[inline]
303 fn global_analysis(&self) -> Bounds<F> { 309 fn global_analysis(&self) -> Bounds<F> {
304 let Bounds(lower, upper) = self.base_fn.global_analysis(); 310 let Bounds(lower, upper) = self.base_fn.global_analysis();
305 debug_assert!(lower <= upper); 311 debug_assert!(lower <= upper);
306 match self.weight.value() { 312 match self.weight.value() {
308 w => Bounds(w * lower, w * upper), 314 w => Bounds(w * lower, w * upper),
309 } 315 }
310 } 316 }
311 } 317 }
312 318
313 impl<'a, T, F : Float, C, const N : usize> LocalAnalysis<F, Bounds<F>, N> for Weighted<T, C> 319 impl<'a, T, F : Float, C, const N : usize> LocalAnalysis<Bounds<F>, Cube<F, N>>
314 where T : LocalAnalysis<F, Bounds<F>, N>, 320 for Weighted<T, C>
315 C : Constant<Type=F> { 321 where T : LocalAnalysis<Bounds<F>, Cube<F, N>>,
322 C : Constant<RealField=F> {
316 #[inline] 323 #[inline]
317 fn local_analysis(&self, cube : &Cube<F, N>) -> Bounds<F> { 324 fn local_analysis(&self, cube : &Cube<F, N>) -> Bounds<F> {
318 let Bounds(lower, upper) = self.base_fn.local_analysis(cube); 325 let Bounds(lower, upper) = self.base_fn.local_analysis(cube);
319 debug_assert!(lower <= upper); 326 debug_assert!(lower <= upper);
320 match self.weight.value() { 327 match self.weight.value() {
356 make_weighted_scalarop_rhs!(Mul, mul, MulAssign, mul_assign); 363 make_weighted_scalarop_rhs!(Mul, mul, MulAssign, mul_assign);
357 make_weighted_scalarop_rhs!(Div, div, DivAssign, div_assign); 364 make_weighted_scalarop_rhs!(Div, div, DivAssign, div_assign);
358 365
359 macro_rules! impl_weighted_norm { 366 macro_rules! impl_weighted_norm {
360 ($($norm:ident)*) => { $( 367 ($($norm:ident)*) => { $(
361 impl<'a, T, F : Float> Norm<F, $norm> for Weighted<T,F> 368 impl<'a, T, F : Float> Norm<$norm> for Weighted<T,F>
362 where T : Norm<F, $norm> { 369 where T : Norm<$norm, Field = F> {
370
363 #[inline] 371 #[inline]
364 fn norm(&self, n : $norm) -> F { 372 fn norm(&self, n : $norm) -> F {
365 self.base_fn.norm(n) * self.weight.abs() 373 self.base_fn.norm(n) * self.weight.abs()
366 } 374 }
367 } 375 }
379 /// The base [`Support`] or [`Apply`]. 387 /// The base [`Support`] or [`Apply`].
380 pub T 388 pub T
381 ); 389 );
382 390
383 impl<'a, T, F : Float, const N : usize> Apply<&'a Loc<F, N>> for Normalised<T> 391 impl<'a, T, F : Float, const N : usize> Apply<&'a Loc<F, N>> for Normalised<T>
384 where T : Norm<F, L1> + for<'b> Apply<&'b Loc<F, N>, Output=F> { 392 where T : Norm<L1, Field=F> + for<'b> Apply<&'b Loc<F, N>, Output=F> {
385 type Output = F; 393 type Output = F;
386 #[inline] 394 #[inline]
387 fn apply(&self, x : &'a Loc<F, N>) -> Self::Output { 395 fn apply(&self, x : &'a Loc<F, N>) -> Self::Output {
388 let w = self.0.norm(L1); 396 let w = self.0.norm(L1);
389 if w == F::ZERO { F::ZERO } else { self.0.apply(x) / w } 397 if w == F::ZERO { F::ZERO } else { self.0.apply(x) / w }
390 } 398 }
391 } 399 }
392 400
393 impl<'a, T, F : Float, const N : usize> Apply<Loc<F, N>> for Normalised<T> 401 impl<'a, T, F : Float, const N : usize> Apply<Loc<F, N>> for Normalised<T>
394 where T : Norm<F, L1> + Apply<Loc<F,N>, Output=F> { 402 where T : Norm<L1, Field = F> + Apply<Loc<F,N>, Output=F> {
395 type Output = F; 403 type Output = F;
396 #[inline] 404 #[inline]
397 fn apply(&self, x : Loc<F, N>) -> Self::Output { 405 fn apply(&self, x : Loc<F, N>) -> Self::Output {
398 let w = self.0.norm(L1); 406 let w = self.0.norm(L1);
399 if w == F::ZERO { F::ZERO } else { self.0.apply(x) / w } 407 if w == F::ZERO { F::ZERO } else { self.0.apply(x) / w }
400 } 408 }
401 } 409 }
402 410
403 impl<'a, T, F : Float, const N : usize> Support<F,N> for Normalised<T> 411 impl<'a, T, F : Float, const N : usize> Support<N> for Normalised<T>
404 where T : Norm<F, L1> + Support<F, N> { 412 where T : Norm<L1> + Support<N, RealField = F> {
405 413
406 #[inline] 414 #[inline]
407 fn support_hint(&self) -> Cube<F,N> { 415 fn support_hint(&self) -> Cube<F,N> {
408 self.0.support_hint() 416 self.0.support_hint()
409 } 417 }
421 fn bisection_hint(&self, cube : &Cube<F,N>) -> [Option<F>; N] { 429 fn bisection_hint(&self, cube : &Cube<F,N>) -> [Option<F>; N] {
422 self.0.bisection_hint(cube) 430 self.0.bisection_hint(cube)
423 } 431 }
424 } 432 }
425 433
426 impl<'a, T, F : Float> GlobalAnalysis<F, Bounds<F>> for Normalised<T> 434 impl<'a, T, F : Float> GlobalAnalysis<Bounds<F>> for Normalised<T>
427 where T : Norm<F, L1> + GlobalAnalysis<F, Bounds<F>> { 435 where T : Norm<L1, Field = F> + GlobalAnalysis<Bounds<F>> {
428 #[inline] 436 #[inline]
429 fn global_analysis(&self) -> Bounds<F> { 437 fn global_analysis(&self) -> Bounds<F> {
430 let Bounds(lower, upper) = self.0.global_analysis(); 438 let Bounds(lower, upper) = self.0.global_analysis();
431 debug_assert!(lower <= upper); 439 debug_assert!(lower <= upper);
432 let w = self.0.norm(L1); 440 let w = self.0.norm(L1);
433 debug_assert!(w >= F::ZERO); 441 debug_assert!(w >= F::ZERO);
434 Bounds(w * lower, w * upper) 442 Bounds(w * lower, w * upper)
435 } 443 }
436 } 444 }
437 445
438 impl<'a, T, F : Float, const N : usize> LocalAnalysis<F, Bounds<F>, N> for Normalised<T> 446 impl<'a, T, F : Float, const N : usize> LocalAnalysis<Bounds<F>, Cube<F, N>>
439 where T : Norm<F, L1> + LocalAnalysis<F, Bounds<F>, N> { 447 for Normalised<T>
448 where T : Norm<L1, Field = F> + LocalAnalysis<Bounds<F>, Cube<F, N>> {
440 #[inline] 449 #[inline]
441 fn local_analysis(&self, cube : &Cube<F, N>) -> Bounds<F> { 450 fn local_analysis(&self, cube : &Cube<F, N>) -> Bounds<F> {
442 let Bounds(lower, upper) = self.0.local_analysis(cube); 451 let Bounds(lower, upper) = self.0.local_analysis(cube);
443 debug_assert!(lower <= upper); 452 debug_assert!(lower <= upper);
444 let w = self.0.norm(L1); 453 let w = self.0.norm(L1);
445 debug_assert!(w >= F::ZERO); 454 debug_assert!(w >= F::ZERO);
446 Bounds(w * lower, w * upper) 455 Bounds(w * lower, w * upper)
447 } 456 }
448 } 457 }
449 458
450 impl<'a, T, F : Float> Norm<F, L1> for Normalised<T> 459 impl<'a, T> HasScalarField for Normalised<T> where T : HasScalarField {
451 where T : Norm<F, L1> { 460 type Field = T::Field;
452 #[inline] 461 }
453 fn norm(&self, _ : L1) -> F { 462
463 impl<'a, T> Norm<L1> for Normalised<T> where T : Norm<L1> {
464 #[inline]
465 fn norm(&self, _ : L1) -> Self::Field {
454 let w = self.0.norm(L1); 466 let w = self.0.norm(L1);
455 if w == F::ZERO { F::ZERO } else { F::ONE } 467 if w == Self::Field::ZERO { Self::Field::ZERO } else { Self::Field::ONE }
456 } 468 }
457 } 469 }
458 470
459 macro_rules! impl_normalised_norm { 471 macro_rules! impl_normalised_norm {
460 ($($norm:ident)*) => { $( 472 ($($norm:ident)*) => { $(
461 impl<'a, T, F : Float> Norm<F, $norm> for Normalised<T> 473 impl<'a, T> Norm<$norm> for Normalised<T> where T : Norm<$norm> + Norm<L1> {
462 where T : Norm<F, $norm> + Norm<F, L1> { 474
463 #[inline] 475 #[inline]
464 fn norm(&self, n : $norm) -> F { 476 fn norm(&self, n : $norm) -> Self::Field {
465 let w = self.0.norm(L1); 477 let w = self.0.norm(L1);
466 if w == F::ZERO { F::ZERO } else { self.0.norm(n) / w } 478 if w == Self::Field::ZERO { Self::Field::ZERO } else { self.0.norm(n) / w }
467 } 479 }
468 } 480 }
469 )* } 481 )* }
470 } 482 }
471 483
472 impl_normalised_norm!(L2 Linfinity); 484 impl_normalised_norm!(L2 Linfinity);
473 485
474 /*
475 impl<F : Num, S : Support<F, N>, const N : usize> LocalAnalysis<F, NullAggregator, N> for S {
476 fn local_analysis(&self, _cube : &Cube<F, N>) -> NullAggregator { NullAggregator }
477 }
478
479 impl<F : Float, S : Bounded<F>, const N : usize> LocalAnalysis<F, Bounds<F>, N> for S {
480 #[inline]
481 fn local_analysis(&self, cube : &Cube<F, N>) -> Bounds<F> {
482 self.bounds(cube)
483 }
484 }*/
485 486
486 /// Generator of [`Support`]-implementing component functions based on low storage requirement 487 /// Generator of [`Support`]-implementing component functions based on low storage requirement
487 /// [ids][`Self::Id`]. 488 /// [ids][`Self::Id`].
488 pub trait SupportGenerator<F : Float, const N : usize> 489 pub trait SupportGenerator<const N : usize>
489 : MulAssign<F> + DivAssign<F> + Neg<Output=Self> + Clone + Sync + Send + 'static { 490 : MulAssign<Self::Field> + DivAssign<Self::Field> + Neg<Output=Self> + HasRealField
491 + Clone + Sync + Send + 'static {
490 /// The identification type 492 /// The identification type
491 type Id : 'static + Copy; 493 type Id : 'static + Copy;
492 /// The type of the [`Support`] (often also a [`Apply`]). 494 /// The type of the [`Support`] (often also a [`Apply`]).
493 type SupportType : 'static + Support<F, N>; 495 type SupportType : 'static + Support<N, RealField=Self::RealField>;
494 /// An iterator over all the [`Support`]s of the generator. 496 /// An iterator over all the [`Support`]s of the generator.
495 type AllDataIter<'a> : Iterator<Item=(Self::Id, Self::SupportType)> where Self : 'a; 497 type AllDataIter<'a> : Iterator<Item=(Self::Id, Self::SupportType)> where Self : 'a;
496 498
497 /// Returns the component identified by `id`. 499 /// Returns the component identified by `id`.
498 /// 500 ///

mercurial