| 250 } |
253 } |
| 251 } |
254 } |
| 252 }; |
255 }; |
| 253 } |
256 } |
| 254 |
257 |
| 255 impl_binary!(Add, add); |
|
| 256 impl_binary!(Sub, sub); |
|
| 257 impl_binary_mut!(AddAssign, add_assign); |
258 impl_binary_mut!(AddAssign, add_assign); |
| 258 impl_binary_mut!(SubAssign, sub_assign); |
259 impl_binary_mut!(SubAssign, sub_assign); |
| |
260 |
| |
261 macro_rules! impl_scalar_mut { |
| |
262 ($trait:ident, $fn:ident) => { |
| |
263 impl<'a, A, B, F> $trait<F> for Pair<A, B> |
| |
264 where |
| |
265 A: $trait<F>, |
| |
266 B: $trait<F>, |
| |
267 { |
| |
268 fn $fn(&mut self, t: F) { |
| |
269 let Pair(ref mut a, ref mut b) = self; |
| |
270 a.$fn(t); |
| |
271 b.$fn(t); |
| |
272 } |
| |
273 } |
| |
274 }; |
| |
275 } |
| |
276 |
| |
277 impl_scalar_mut!(MulAssign, mul_assign); |
| |
278 impl_scalar_mut!(DivAssign, div_assign); |
| 259 |
279 |
| 260 #[macro_export] |
280 #[macro_export] |
| 261 macro_rules! impl_pair_vectorspace_ops { |
281 macro_rules! impl_pair_vectorspace_ops { |
| 262 (($a:ty, $b:ty), $field:ty) => { |
282 (($a:ty, $b:ty), $field:ty) => { |
| 263 //impl_pair_vectorspace_ops!(@binary, ($a, $b), Add, add); |
283 //impl_pair_vectorspace_ops!(@binary, ($a, $b), Add, add); |
| 268 // impl_pair_vectorspace_ops!(@scalar, ($a, $b), $field, Div, div); |
288 // impl_pair_vectorspace_ops!(@scalar, ($a, $b), $field, Div, div); |
| 269 // Compiler overflow |
289 // Compiler overflow |
| 270 // $( |
290 // $( |
| 271 // impl_pair_vectorspace_ops!(@scalar_lhs, ($a, $b), $field, $impl_scalarlhs_op, Mul, mul); |
291 // impl_pair_vectorspace_ops!(@scalar_lhs, ($a, $b), $field, $impl_scalarlhs_op, Mul, mul); |
| 272 // )* |
292 // )* |
| 273 impl_pair_vectorspace_ops!(@scalar_assign, ($a, $b), $field, MulAssign, mul_assign); |
|
| 274 impl_pair_vectorspace_ops!(@scalar_assign, ($a, $b), $field, DivAssign, div_assign); |
|
| 275 }; |
|
| 276 (@binary, ($a : ty, $b : ty), $trait : ident, $fn : ident) => { |
|
| 277 impl_binop!(($a, $b), $trait, $fn, ref, ref); |
|
| 278 impl_binop!(($a, $b), $trait, $fn, ref, noref); |
|
| 279 impl_binop!(($a, $b), $trait, $fn, noref, ref); |
|
| 280 impl_binop!(($a, $b), $trait, $fn, noref, noref); |
|
| 281 }; |
293 }; |
| 282 (@scalar, ($a : ty, $b : ty), $field : ty, $trait : ident, $fn :ident) => { |
294 (@scalar, ($a : ty, $b : ty), $field : ty, $trait : ident, $fn :ident) => { |
| 283 impl_scalarop!(($a, $b), $field, $trait, $fn, ref); |
295 impl_scalarop!(($a, $b), $field, $trait, $fn, ref); |
| 284 impl_scalarop!(($a, $b), $field, $trait, $fn, noref); |
296 impl_scalarop!(($a, $b), $field, $trait, $fn, noref); |
| 285 }; |
297 }; |
| 303 impl_pair_vectorspace_ops_gen!(@scalar, $field, Mul, mul); |
315 impl_pair_vectorspace_ops_gen!(@scalar, $field, Mul, mul); |
| 304 impl_pair_vectorspace_ops_gen!(@scalar, $field, Div, div); |
316 impl_pair_vectorspace_ops_gen!(@scalar, $field, Div, div); |
| 305 // impl_pair_vectorspace_ops_gen!(@scalar_assign, $field, MulAssign, mul_assign); |
317 // impl_pair_vectorspace_ops_gen!(@scalar_assign, $field, MulAssign, mul_assign); |
| 306 // impl_pair_vectorspace_ops_gen!(@scalar_assign, $field, DivAssign, div_assign); |
318 // impl_pair_vectorspace_ops_gen!(@scalar_assign, $field, DivAssign, div_assign); |
| 307 }; |
319 }; |
| 308 // (@binary, $trait : ident, $fn : ident) => { |
|
| 309 // impl_binop_gen!(($a, $b), $trait, $fn, ref, ref); |
|
| 310 // impl_binop_gen!(($a, $b), $trait, $fn, ref, noref); |
|
| 311 // impl_binop_gen!(($a, $b), $trait, $fn, noref, ref); |
|
| 312 // impl_binop_gen!(($a, $b), $trait, $fn, noref, noref); |
|
| 313 // }; |
|
| 314 // (@assign, $trait : ident, $fn :ident) => { |
|
| 315 // impl_assignop_gen!(($a, $b), $trait, $fn, ref); |
|
| 316 // impl_assignop_gen!(($a, $b), $trait, $fn, noref); |
|
| 317 // }; |
|
| 318 (@scalar, $field : ty, $trait : ident, $fn :ident) => { |
320 (@scalar, $field : ty, $trait : ident, $fn :ident) => { |
| 319 impl_scalarop_gen!($field, $trait, $fn, ref); |
321 impl_scalarop_gen!($field, $trait, $fn, ref); |
| 320 impl_scalarop_gen!($field, $trait, $fn, noref); |
322 impl_scalarop_gen!($field, $trait, $fn, noref); |
| 321 }; |
323 }; |
| 322 // (@scalar_lhs, $field : ty, $trait : ident, $fn : ident) => { |
324 // (@scalar_lhs, $field : ty, $trait : ident, $fn : ident) => { |
| 329 } |
331 } |
| 330 |
332 |
| 331 impl_pair_vectorspace_ops_gen!(f32); |
333 impl_pair_vectorspace_ops_gen!(f32); |
| 332 impl_pair_vectorspace_ops_gen!(f64); |
334 impl_pair_vectorspace_ops_gen!(f64); |
| 333 |
335 |
| 334 impl_pair_vectorspace_ops!((f32, f32), f32); |
336 //impl_pair_vectorspace_ops!((f32, f32), f32); |
| 335 impl_pair_vectorspace_ops!((f64, f64), f64); |
337 //impl_pair_vectorspace_ops!((f64, f64), f64); |
| 336 |
|
| 337 type PairOutput<F, A, B> = Pair<<A as Euclidean<F>>::Output, <B as Euclidean<F>>::Output>; |
|
| 338 |
338 |
| 339 /// We need to restrict `A` and `B` as [`Euclidean`] to have closed `Output` |
339 /// We need to restrict `A` and `B` as [`Euclidean`] to have closed `Output` |
| 340 /// to avoid compiler overflows that the requirement |
340 |
| 341 /// ``` |
341 impl<A, B, F: Float> Euclidean<F> for Pair<A, B> |
| 342 /// Pair<<A as Euclidean<F>>::Output, <B as Euclidean<F>>::Output> : Euclidean<F> |
342 where |
| 343 /// ``` |
343 A: Euclidean<F>, |
| 344 /// would generate. |
344 B: Euclidean<F>, |
| 345 |
345 //Pair<A, B>: Euclidean<F>, |
| 346 macro_rules! impl_euclidean { |
346 Self: Sized |
| 347 ($field:ty) => { |
347 + Mul<F, Output = Pair<A, B>> |
| 348 impl<A, B> Euclidean<$field> for Pair<A, B> |
348 + MulAssign<F> |
| 349 where |
349 + Div<F, Output = Pair<A, B>> |
| 350 A: Euclidean<$field>, |
350 + DivAssign<F> |
| 351 B: Euclidean<$field>, |
351 + Add<Self, Output = Pair<A, B>> |
| 352 PairOutput<$field, A, B>: Euclidean<$field>, |
352 + Sub<Self, Output = Pair<A, B>> |
| 353 Self: Sized |
353 + for<'b> Add<&'b Self, Output = Pair<A, B>> |
| 354 + Mul<$field, Output = PairOutput<$field, A, B>> |
354 + for<'b> Sub<&'b Self, Output = Pair<A, B>> |
| 355 + MulAssign<$field> |
355 + AddAssign<Self> |
| 356 + Div<$field, Output = PairOutput<$field, A, B>> |
356 + for<'b> AddAssign<&'b Self> |
| 357 + DivAssign<$field> |
357 + SubAssign<Self> |
| 358 + Add<Self, Output = PairOutput<$field, A, B>> |
358 + for<'b> SubAssign<&'b Self> |
| 359 + Sub<Self, Output = PairOutput<$field, A, B>> |
359 + Neg<Output = Pair<A, B>>, |
| 360 + for<'b> Add<&'b Self, Output = PairOutput<$field, A, B>> |
360 { |
| 361 + for<'b> Sub<&'b Self, Output = PairOutput<$field, A, B>> |
361 type Output = Pair<A, B>; |
| 362 + AddAssign<Self> |
362 |
| 363 + for<'b> AddAssign<&'b Self> |
363 fn dot<I: Instance<Self>>(&self, other: I) -> F { |
| 364 + SubAssign<Self> |
364 let Pair(u, v) = other.decompose(); |
| 365 + for<'b> SubAssign<&'b Self>, //+ Neg<Output = PairOutput<$field, A, B>>, |
365 self.0.dot(u) + self.1.dot(v) |
| 366 { |
366 } |
| 367 type Output = PairOutput<$field, A, B>; |
367 |
| 368 |
368 fn norm2_squared(&self) -> F { |
| 369 fn dot<I: Instance<Self>>(&self, other: I) -> $field { |
369 self.0.norm2_squared() + self.1.norm2_squared() |
| 370 let Pair(u, v) = other.decompose(); |
370 } |
| 371 self.0.dot(u) + self.1.dot(v) |
371 |
| 372 } |
372 fn dist2_squared<I: Instance<Self>>(&self, other: I) -> F { |
| 373 |
373 let Pair(u, v) = other.decompose(); |
| 374 fn norm2_squared(&self) -> $field { |
374 self.0.dist2_squared(u) + self.1.dist2_squared(v) |
| 375 self.0.norm2_squared() + self.1.norm2_squared() |
375 } |
| 376 } |
376 } |
| 377 |
|
| 378 fn dist2_squared<I: Instance<Self>>(&self, other: I) -> $field { |
|
| 379 let Pair(u, v) = other.decompose(); |
|
| 380 self.0.dist2_squared(u) + self.1.dist2_squared(v) |
|
| 381 } |
|
| 382 } |
|
| 383 }; |
|
| 384 } |
|
| 385 |
|
| 386 impl_euclidean!(f32); |
|
| 387 impl_euclidean!(f64); |
|
| 388 |
377 |
| 389 impl<F, A, B, U, V> AXPY<F, Pair<U, V>> for Pair<A, B> |
378 impl<F, A, B, U, V> AXPY<F, Pair<U, V>> for Pair<A, B> |
| 390 where |
379 where |
| 391 U: Space, |
380 U: Space, |
| 392 V: Space, |
381 V: Space, |