| 1 /*! |
1 /*! |
| 2 Traits for mathematical functions. |
2 Traits for mathematical functions. |
| 3 */ |
3 */ |
| 4 |
4 |
| 5 use std::marker::PhantomData; |
5 use std::marker::PhantomData; |
| |
6 use std::borrow::Cow; |
| 6 use crate::types::Float; |
7 use crate::types::Float; |
| 7 use serde::Serialize; |
8 use serde::Serialize; |
| 8 use crate::loc::Loc; |
9 use crate::loc::Loc; |
| 9 |
10 pub use crate::instance::{Instance, Decomposition, BasicDecomposition, Space}; |
| 10 /// Trait for application of `Self` as a mathematical function or operator on `X`. |
|
| 11 pub trait Apply<X> { |
|
| 12 type Output; |
|
| 13 |
|
| 14 /// Compute the value of `self` at `x`. |
|
| 15 fn apply(&self, x : X) -> Self::Output; |
|
| 16 } |
|
| 17 |
|
| 18 /// This blanket implementation is a workaround helper to Rust trait system limitations. |
|
| 19 /// |
|
| 20 /// It is introduced because the trait system does not allow blanket implementations of both |
|
| 21 /// [`Apply<X>`] and [`Apply<&'a X>`]. With this, the latter is implemented automatically for |
|
| 22 /// the reference, which can be sufficient to apply the operation in another blanket implementation. |
|
| 23 impl<'a, T, X> Apply<X> for &'a T where T : Apply<X> { |
|
| 24 type Output = <T as Apply<X>>::Output; |
|
| 25 |
|
| 26 #[inline] |
|
| 27 fn apply(&self, x : X) -> Self::Output { |
|
| 28 (*self).apply(x) |
|
| 29 } |
|
| 30 } |
|
| 31 |
11 |
| 32 /// A mapping from `Domain` to `Codomain`. |
12 /// A mapping from `Domain` to `Codomain`. |
| 33 /// |
13 /// |
| 34 /// This is automatically implemented when the relevant [`Apply`] are implemented. |
14 /// This is automatically implemented when the relevant [`Apply`] are implemented. |
| 35 pub trait Mapping<Domain> : Apply<Domain, Output=Self::Codomain> |
15 pub trait Mapping<Domain : Space> { |
| 36 + for<'a> Apply<&'a Domain, Output=Self::Codomain> { |
16 type Codomain : Space; |
| 37 type Codomain; |
17 |
| 38 } |
18 /// Compute the value of `self` at `x`. |
| 39 |
19 fn apply<I : Instance<Domain>>(&self, x : I) -> Self::Codomain; |
| 40 impl<Domain, Codomain, T> Mapping<Domain> for T |
|
| 41 where T : Apply<Domain, Output=Codomain> + for<'a> Apply<&'a Domain, Output=Codomain> { |
|
| 42 type Codomain = Codomain; |
|
| 43 } |
20 } |
| 44 |
21 |
| 45 /// Automatically implemented shorthand for referring to [`Mapping`]s from [`Loc<F, N>`] to `F`. |
22 /// Automatically implemented shorthand for referring to [`Mapping`]s from [`Loc<F, N>`] to `F`. |
| 46 pub trait RealMapping<F : Float, const N : usize> |
23 pub trait RealMapping<F : Float, const N : usize> |
| 47 : Mapping<Loc<F, N>, Codomain = F> {} |
24 : Mapping<Loc<F, N>, Codomain = F> {} |
| 48 |
25 |
| 49 impl<F : Float, T, const N : usize> RealMapping<F, N> for T |
26 impl<F : Float, T, const N : usize> RealMapping<F, N> for T |
| 50 where T : Mapping<Loc<F, N>, Codomain = F> {} |
27 where T : Mapping<Loc<F, N>, Codomain = F> {} |
| 51 |
28 |
| |
29 /// A helper trait alias for referring to [`Mapping`]s from [`Loc<F, N>`] to [`Loc<F, M>`]. |
| |
30 pub trait RealVectorField<F : Float, const N : usize, const M : usize> |
| |
31 : Mapping<Loc<F, N>, Codomain = Loc<F, M>> {} |
| |
32 |
| |
33 impl<F : Float, T, const N : usize, const M : usize> RealVectorField<F, N, M> for T |
| |
34 where T : Mapping<Loc<F, N>, Codomain = Loc<F, M>> {} |
| |
35 |
| |
36 /// A differentiable mapping from `Domain` to [`Mapping::Codomain`], with differentials |
| |
37 /// `Differential`. |
| |
38 /// |
| |
39 /// This is automatically implemented when [`DifferentiableImpl`] is. |
| |
40 pub trait DifferentiableMapping<Domain : Space> : Mapping<Domain> { |
| |
41 type DerivativeDomain : Space; |
| |
42 type Differential<'b> : Mapping<Domain, Codomain=Self::DerivativeDomain> where Self : 'b; |
| |
43 |
| |
44 /// Calculate differential at `x` |
| |
45 fn differential<I : Instance<Domain>>(&self, x : I) -> Self::DerivativeDomain; |
| |
46 |
| |
47 /// Form the differential mapping of `self`. |
| |
48 fn diff(self) -> Self::Differential<'static>; |
| |
49 |
| |
50 /// Form the differential mapping of `self`. |
| |
51 fn diff_ref(&self) -> Self::Differential<'_>; |
| |
52 } |
| |
53 |
| 52 /// Automatically implemented shorthand for referring to differentiable [`Mapping`]s from |
54 /// Automatically implemented shorthand for referring to differentiable [`Mapping`]s from |
| 53 /// [`Loc<F, N>`] to `F`. |
55 /// [`Loc<F, N>`] to `F`. |
| 54 pub trait DifferentiableRealMapping<F : Float, const N : usize> |
56 pub trait DifferentiableRealMapping<F : Float, const N : usize> |
| 55 : DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain=Loc<F, N>> {} |
57 : DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain = Loc<F, N>> {} |
| 56 |
58 |
| 57 impl<F : Float, T, const N : usize> DifferentiableRealMapping<F, N> for T |
59 impl<F : Float, T, const N : usize> DifferentiableRealMapping<F, N> for T |
| 58 where T : DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain=Loc<F, N>> {} |
60 where T : DifferentiableMapping<Loc<F, N>, Codomain = F, DerivativeDomain = Loc<F, N>> {} |
| 59 |
61 |
| 60 |
62 /// Helper trait for implementing [`DifferentiableMapping`] |
| 61 /// A helper trait alias for referring to [`Mapping`]s from [`Loc<F, N>`] to [`Loc<F, M>`]. |
63 pub trait DifferentiableImpl<X : Space> : Sized { |
| 62 pub trait RealVectorField<F : Float, const N : usize, const M : usize> |
64 type Derivative : Space; |
| 63 : Mapping<Loc<F, N>, Codomain = Loc<F, M>> {} |
65 |
| 64 |
66 /// Compute the differential of `self` at `x`, consuming the input. |
| 65 impl<F : Float, T, const N : usize, const M : usize> RealVectorField<F, N, M> for T |
67 fn differential_impl<I : Instance<X>>(&self, x : I) -> Self::Derivative; |
| 66 where T : Mapping<Loc<F, N>, Codomain = Loc<F, M>> {} |
68 } |
| 67 |
69 |
| 68 |
70 impl<T, Domain> DifferentiableMapping<Domain> for T |
| 69 /// Trait for calculation the differential of `Self` as a mathematical function on `X`. |
71 where |
| 70 pub trait Differentiable<X> : Sized { |
72 Domain : Space, |
| 71 type Derivative; |
73 T : Clone + Mapping<Domain> + DifferentiableImpl<Domain> |
| 72 |
74 { |
| 73 /// Compute the differential of `self` at `x`. |
75 type DerivativeDomain = T::Derivative; |
| 74 fn differential(&self, x : X) -> Self::Derivative; |
76 type Differential<'b> = Differential<'b, Domain, Self> where Self : 'b; |
| 75 } |
|
| 76 |
|
| 77 impl<'g, X, G : Differentiable<X>> Differentiable<X> for &'g G { |
|
| 78 type Derivative = G::Derivative; |
|
| 79 #[inline] |
|
| 80 fn differential(&self, x : X) -> Self::Derivative { |
|
| 81 (*self).differential(x) |
|
| 82 } |
|
| 83 } |
|
| 84 |
|
| 85 /// A differentiable mapping from `Domain` to [`Mapping::Codomain`], with differentials |
|
| 86 /// `Differential`. |
|
| 87 /// |
|
| 88 /// This is automatically implemented when the relevant [`Differentiable`] are implemented. |
|
| 89 pub trait DifferentiableMapping<Domain> |
|
| 90 : Mapping<Domain> |
|
| 91 + Differentiable<Domain, Derivative=Self::DerivativeDomain> |
|
| 92 + for<'a> Differentiable<&'a Domain, Derivative=Self::DerivativeDomain> { |
|
| 93 type DerivativeDomain; |
|
| 94 type Differential : Mapping<Domain, Codomain=Self::DerivativeDomain>; |
|
| 95 type DifferentialRef<'b> : Mapping<Domain, Codomain=Self::DerivativeDomain> where Self : 'b; |
|
| 96 |
|
| 97 /// Form the differential mapping of `self`. |
|
| 98 fn diff(self) -> Self::Differential; |
|
| 99 /// Form the differential mapping of `self`. |
|
| 100 fn diff_ref(&self) -> Self::DifferentialRef<'_>; |
|
| 101 } |
|
| 102 |
|
| 103 |
|
| 104 impl<Domain, Derivative, T> DifferentiableMapping<Domain> for T |
|
| 105 where T : Mapping<Domain> |
|
| 106 + Differentiable<Domain, Derivative=Derivative> |
|
| 107 + for<'a> Differentiable<&'a Domain,Derivative=Derivative> { |
|
| 108 type DerivativeDomain = Derivative; |
|
| 109 type Differential = Differential<Domain, Self>; |
|
| 110 type DifferentialRef<'b> = Differential<Domain, &'b Self> where Self : 'b; |
|
| 111 |
77 |
| 112 /// Form the differential mapping of `self`. |
78 #[inline] |
| 113 fn diff(self) -> Self::Differential { |
79 fn differential<I : Instance<Domain>>(&self, x : I) -> Self::DerivativeDomain { |
| 114 Differential{ g : self, _space : PhantomData } |
80 self.differential_impl(x) |
| 115 } |
81 } |
| 116 |
82 |
| 117 /// Form the differential mapping of `self`. |
83 fn diff(self) -> Differential<'static, Domain, Self> { |
| 118 fn diff_ref(&self) -> Self::DifferentialRef<'_> { |
84 Differential{ g : Cow::Owned(self), _space : PhantomData } |
| 119 Differential{ g : self, _space : PhantomData } |
85 } |
| |
86 |
| |
87 fn diff_ref(&self) -> Differential<'_, Domain, Self> { |
| |
88 Differential{ g : Cow::Borrowed(self), _space : PhantomData } |
| 120 } |
89 } |
| 121 } |
90 } |
| 122 |
91 |
| 123 /// A sum of [`Mapping`]s. |
92 /// A sum of [`Mapping`]s. |
| 124 #[derive(Serialize, Debug, Clone)] |
93 #[derive(Serialize, Debug, Clone)] |
| 125 pub struct Sum<Domain, M : Mapping<Domain>> { |
94 pub struct Sum<Domain, M> { |
| 126 components : Vec<M>, |
95 components : Vec<M>, |
| 127 _domain : PhantomData<Domain>, |
96 _domain : PhantomData<Domain>, |
| 128 } |
97 } |
| 129 |
98 |
| 130 impl<Domain, M : Mapping<Domain>> Sum<Domain, M> { |
99 impl<Domain, M> Sum<Domain, M> { |
| 131 /// Construct from an iterator. |
100 /// Construct from an iterator. |
| 132 pub fn new<I : Iterator<Item = M>>(iter : I) -> Self { |
101 pub fn new<I : Iterator<Item = M>>(iter : I) -> Self { |
| 133 Sum { components : iter.collect(), _domain : PhantomData } |
102 Sum { components : iter.collect(), _domain : PhantomData } |
| 134 } |
103 } |
| 135 |
104 |
| 138 self.components.iter() |
107 self.components.iter() |
| 139 } |
108 } |
| 140 } |
109 } |
| 141 |
110 |
| 142 |
111 |
| 143 impl<Domain, M> Apply<Domain> for Sum<Domain, M> |
112 impl<Domain, M> Mapping<Domain> for Sum<Domain, M> |
| 144 where M : Mapping<Domain>, |
113 where |
| 145 M::Codomain : std::iter::Sum { |
114 Domain : Space + Clone, |
| 146 type Output = M::Codomain; |
115 M : Mapping<Domain>, |
| 147 |
116 M::Codomain : std::iter::Sum + Clone |
| 148 fn apply(&self, x : Domain) -> Self::Output { |
117 { |
| 149 self.components.iter().map(|c| c.apply(&x)).sum() |
118 type Codomain = M::Codomain; |
| 150 } |
119 |
| 151 } |
120 fn apply<I : Instance<Domain>>(&self, x : I) -> Self::Codomain { |
| 152 |
121 let xr = x.ref_instance(); |
| 153 impl<'a, Domain, M> Apply<&'a Domain> for Sum<Domain, M> |
122 self.components.iter().map(|c| c.apply(xr)).sum() |
| 154 where M : Mapping<Domain>, |
123 } |
| 155 M::Codomain : std::iter::Sum { |
124 } |
| 156 type Output = M::Codomain; |
125 |
| 157 |
126 impl<Domain, M> DifferentiableImpl<Domain> for Sum<Domain, M> |
| 158 fn apply(&self, x : &'a Domain) -> Self::Output { |
127 where |
| 159 self.components.iter().map(|c| c.apply(x)).sum() |
128 Domain : Space + Clone, |
| 160 } |
129 M : DifferentiableMapping<Domain>, |
| 161 } |
130 M :: DerivativeDomain : std::iter::Sum |
| 162 |
131 { |
| 163 impl<Domain, M> Differentiable<Domain> for Sum<Domain, M> |
|
| 164 where M : DifferentiableMapping<Domain>, |
|
| 165 M :: Codomain : std::iter::Sum, |
|
| 166 M :: DerivativeDomain : std::iter::Sum, |
|
| 167 Domain : Copy { |
|
| 168 |
|
| 169 type Derivative = M::DerivativeDomain; |
132 type Derivative = M::DerivativeDomain; |
| 170 |
133 |
| 171 fn differential(&self, x : Domain) -> Self::Derivative { |
134 fn differential_impl<I : Instance<Domain>>(&self, x : I) -> Self::Derivative { |
| 172 self.components.iter().map(|c| c.differential(x)).sum() |
135 let xr = x.ref_instance(); |
| |
136 self.components.iter().map(|c| c.differential(xr)).sum() |
| 173 } |
137 } |
| 174 } |
138 } |
| 175 |
139 |
| 176 /// Container for the differential [`Mapping`] of a [`Differentiable`] mapping. |
140 /// Container for the differential [`Mapping`] of a [`Differentiable`] mapping. |
| 177 pub struct Differential<X, G : DifferentiableMapping<X>> { |
141 pub struct Differential<'a, X, G : Clone> { |
| 178 g : G, |
142 g : Cow<'a, G>, |
| 179 _space : PhantomData<X> |
143 _space : PhantomData<X> |
| 180 } |
144 } |
| 181 |
145 |
| 182 impl<X, G : DifferentiableMapping<X>> Differential<X, G> { |
146 impl<'a, X, G : Clone> Differential<'a, X, G> { |
| 183 pub fn base_fn(&self) -> &G { |
147 pub fn base_fn(&self) -> &G { |
| 184 &self.g |
148 &self.g |
| 185 } |
149 } |
| 186 } |
150 } |
| 187 |
151 |
| 188 impl<X, G : DifferentiableMapping<X>> Apply<X> for Differential<X, G> { |
152 impl<'a, X, G> Mapping<X> for Differential<'a, X, G> |
| 189 type Output = G::DerivativeDomain; |
153 where |
| 190 |
154 X : Space, |
| 191 #[inline] |
155 G : Clone + DifferentiableMapping<X> |
| 192 fn apply(&self, x : X) -> Self::Output { |
156 { |
| 193 self.g.differential(x) |
157 type Codomain = G::DerivativeDomain; |
| 194 } |
158 |
| 195 } |
159 #[inline] |
| 196 |
160 fn apply<I : Instance<X>>(&self, x : I) -> Self::Codomain { |
| 197 impl<'a, X, G : DifferentiableMapping<X>> Apply<&'a X> for Differential<X, G> { |
161 (*self.g).differential(x) |
| 198 type Output = G::DerivativeDomain; |
162 } |
| 199 |
163 } |
| 200 #[inline] |
|
| 201 fn apply(&self, x : &'a X) -> Self::Output { |
|
| 202 self.g.differential(x) |
|
| 203 } |
|
| 204 } |
|
| 205 |
|
| 206 |
164 |
| 207 /// Container for flattening [`Loc`]`<F, 1>` codomain of a [`Mapping`] to `F`. |
165 /// Container for flattening [`Loc`]`<F, 1>` codomain of a [`Mapping`] to `F`. |
| 208 pub struct FlattenedCodomain<X, F, G : Mapping<X, Codomain=Loc<F, 1>>> { |
166 pub struct FlattenedCodomain<X, F, G> { |
| 209 g : G, |
167 g : G, |
| 210 _phantoms : PhantomData<(X, F)> |
168 _phantoms : PhantomData<(X, F)> |
| 211 } |
169 } |
| 212 |
170 |
| 213 impl<X, F, G : Mapping<X, Codomain=Loc<F, 1>>> Apply<X> for FlattenedCodomain<X, F, G> { |
171 impl<F : Space, X, G> Mapping<X> for FlattenedCodomain<X, F, G> |
| 214 type Output = F; |
172 where |
| 215 |
173 X : Space, |
| 216 #[inline] |
174 G: Mapping<X, Codomain=Loc<F, 1>> |
| 217 fn apply(&self, x : X) -> Self::Output { |
175 { |
| |
176 type Codomain = F; |
| |
177 |
| |
178 #[inline] |
| |
179 fn apply<I : Instance<X>>(&self, x : I) -> Self::Codomain { |
| 218 self.g.apply(x).flatten1d() |
180 self.g.apply(x).flatten1d() |
| 219 } |
181 } |
| 220 } |
182 } |
| 221 |
183 |
| 222 /// An auto-trait for constructing a [`FlattenCodomain`] structure for |
184 /// An auto-trait for constructing a [`FlattenCodomain`] structure for |
| 223 /// flattening the codomain of a [`Mapping`] from [`Loc`]`<F, 1>` to `F`. |
185 /// flattening the codomain of a [`Mapping`] from [`Loc`]`<F, 1>` to `F`. |
| 224 pub trait FlattenCodomain<X, F> : Mapping<X, Codomain=Loc<F, 1>> + Sized { |
186 pub trait FlattenCodomain<X : Space, F> : Mapping<X, Codomain=Loc<F, 1>> + Sized { |
| 225 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. |
187 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. |
| 226 fn flatten_codomain(self) -> FlattenedCodomain<X, F, Self> { |
188 fn flatten_codomain(self) -> FlattenedCodomain<X, F, Self> { |
| 227 FlattenedCodomain{ g : self, _phantoms : PhantomData } |
189 FlattenedCodomain{ g : self, _phantoms : PhantomData } |
| 228 } |
190 } |
| 229 } |
191 } |
| 230 |
192 |
| 231 impl<X, F, G : Sized + Mapping<X, Codomain=Loc<F, 1>>> FlattenCodomain<X, F> for G {} |
193 impl<X : Space, F, G : Sized + Mapping<X, Codomain=Loc<F, 1>>> FlattenCodomain<X, F> for G {} |
| 232 |
|
| 233 |
194 |
| 234 /// Container for dimensional slicing [`Loc`]`<F, N>` codomain of a [`Mapping`] to `F`. |
195 /// Container for dimensional slicing [`Loc`]`<F, N>` codomain of a [`Mapping`] to `F`. |
| 235 pub struct SlicedCodomain<X, F, G : Mapping<X, Codomain=Loc<F, N>>, const N : usize> { |
196 pub struct SlicedCodomain<'a, X, F, G : Clone, const N : usize> { |
| 236 g : G, |
197 g : Cow<'a, G>, |
| 237 slice : usize, |
198 slice : usize, |
| 238 _phantoms : PhantomData<(X, F)> |
199 _phantoms : PhantomData<(X, F)> |
| 239 } |
200 } |
| 240 |
201 |
| 241 impl<X, F : Copy, G : Mapping<X, Codomain=Loc<F, N>>, const N : usize> Apply<X> |
202 impl<'a, X, F, G, const N : usize> Mapping<X> for SlicedCodomain<'a, X, F, G, N> |
| 242 for SlicedCodomain<X, F, G, N> { |
203 where |
| 243 type Output = F; |
204 X : Space, |
| 244 |
205 F : Copy + Space, |
| 245 #[inline] |
206 G : Mapping<X, Codomain=Loc<F, N>> + Clone, |
| 246 fn apply(&self, x : X) -> Self::Output { |
207 { |
| 247 let tmp : [F; N] = self.g.apply(x).into(); |
208 type Codomain = F; |
| |
209 |
| |
210 #[inline] |
| |
211 fn apply<I : Instance<X>>(&self, x : I) -> Self::Codomain { |
| |
212 let tmp : [F; N] = (*self.g).apply(x).into(); |
| 248 // Safety: `slice_codomain` below checks the range. |
213 // Safety: `slice_codomain` below checks the range. |
| 249 unsafe { *tmp.get_unchecked(self.slice) } |
214 unsafe { *tmp.get_unchecked(self.slice) } |
| 250 } |
215 } |
| 251 } |
216 } |
| 252 |
217 |
| 253 impl<'a, X, F : Copy, G : Mapping<X, Codomain=Loc<F, N>>, const N : usize> Apply<&'a X> |
|
| 254 for SlicedCodomain<X, F, G, N> { |
|
| 255 type Output = F; |
|
| 256 |
|
| 257 #[inline] |
|
| 258 fn apply(&self, x : &'a X) -> Self::Output { |
|
| 259 let tmp : [F; N] = self.g.apply(x).into(); |
|
| 260 // Safety: `slice_codomain` below checks the range. |
|
| 261 unsafe { *tmp.get_unchecked(self.slice) } |
|
| 262 } |
|
| 263 } |
|
| 264 |
|
| 265 /// An auto-trait for constructing a [`FlattenCodomain`] structure for |
218 /// An auto-trait for constructing a [`FlattenCodomain`] structure for |
| 266 /// flattening the codomain of a [`Mapping`] from [`Loc`]`<F, 1>` to `F`. |
219 /// flattening the codomain of a [`Mapping`] from [`Loc`]`<F, 1>` to `F`. |
| 267 pub trait SliceCodomain<X, F : Copy, const N : usize> : Mapping<X, Codomain=Loc<F, N>> + Sized { |
220 pub trait SliceCodomain<X : Space, F : Copy, const N : usize> |
| |
221 : Mapping<X, Codomain=Loc<F, N>> + Clone + Sized |
| |
222 { |
| 268 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. |
223 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. |
| 269 fn slice_codomain(self, slice : usize) -> SlicedCodomain<X, F, Self, N> { |
224 fn slice_codomain(self, slice : usize) -> SlicedCodomain<'static, X, F, Self, N> { |
| 270 assert!(slice < N); |
225 assert!(slice < N); |
| 271 SlicedCodomain{ g : self, slice, _phantoms : PhantomData } |
226 SlicedCodomain{ g : Cow::Owned(self), slice, _phantoms : PhantomData } |
| 272 } |
227 } |
| 273 |
228 |
| 274 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. |
229 /// Flatten the codomain from [`Loc`]`<F, 1>` to `F`. |
| 275 fn slice_codomain_ref(&self, slice : usize) -> SlicedCodomain<X, F, &'_ Self, N> { |
230 fn slice_codomain_ref(&self, slice : usize) -> SlicedCodomain<'_, X, F, Self, N> { |
| 276 assert!(slice < N); |
231 assert!(slice < N); |
| 277 SlicedCodomain{ g : self, slice, _phantoms : PhantomData } |
232 SlicedCodomain{ g : Cow::Borrowed(self), slice, _phantoms : PhantomData } |
| 278 } |
233 } |
| 279 } |
234 } |
| 280 |
235 |
| 281 impl<X, F : Copy, G : Sized + Mapping<X, Codomain=Loc<F, N>>, const N : usize> |
236 impl<X : Space, F : Copy, G : Sized + Mapping<X, Codomain=Loc<F, N>> + Clone, const N : usize> |
| 282 SliceCodomain<X, F, N> |
237 SliceCodomain<X, F, N> |
| 283 for G {} |
238 for G {} |
| 284 |
|