| 318 impl_pair_vectorspace_ops!((f32, f32), f32); |
318 impl_pair_vectorspace_ops!((f32, f32), f32); |
| 319 impl_pair_vectorspace_ops!((f64, f64), f64); |
319 impl_pair_vectorspace_ops!((f64, f64), f64); |
| 320 |
320 |
| 321 type PairOutput<F, A, B> = Pair<<A as Euclidean<F>>::Output, <B as Euclidean<F>>::Output>; |
321 type PairOutput<F, A, B> = Pair<<A as Euclidean<F>>::Output, <B as Euclidean<F>>::Output>; |
| 322 |
322 |
| 323 impl<A, B, F> Euclidean<F> for Pair<A, B> |
323 /// We need to restrict `A` and `B` as [`Euclidean`] to have closed `Output` |
| 324 where |
324 /// to avoid compiler overflows that the requirement |
| 325 A: Euclidean<F>, |
325 /// ``` |
| 326 B: Euclidean<F>, |
326 /// Pair<<A as Euclidean<F>>::Output, <B as Euclidean<F>>::Output> : Euclidean<F> |
| 327 F: Float, |
327 /// ``` |
| 328 PairOutput<F, A, B>: Euclidean<F>, |
328 /// would generate. |
| 329 Self: Sized |
329 |
| 330 + Mul<F, Output = PairOutput<F, A, B>> |
330 macro_rules! impl_euclidean { |
| 331 + MulAssign<F> |
331 ($field:ty) => { |
| 332 + Div<F, Output = PairOutput<F, A, B>> |
332 impl<A, B> Euclidean<$field> for Pair<A, B> |
| 333 + DivAssign<F> |
333 where |
| 334 + Add<Self, Output = PairOutput<F, A, B>> |
334 A: Euclidean<$field>, |
| 335 + Sub<Self, Output = PairOutput<F, A, B>> |
335 B: Euclidean<$field>, |
| 336 + for<'b> Add<&'b Self, Output = PairOutput<F, A, B>> |
336 PairOutput<$field, A, B>: Euclidean<$field>, |
| 337 + for<'b> Sub<&'b Self, Output = PairOutput<F, A, B>> |
337 Self: Sized |
| 338 + AddAssign<Self> |
338 + Mul<$field, Output = PairOutput<$field, A, B>> |
| 339 + for<'b> AddAssign<&'b Self> |
339 + MulAssign<$field> |
| 340 + SubAssign<Self> |
340 + Div<$field, Output = PairOutput<$field, A, B>> |
| 341 + for<'b> SubAssign<&'b Self> |
341 + DivAssign<$field> |
| 342 + Neg<Output = PairOutput<F, A, B>>, |
342 + Add<Self, Output = PairOutput<$field, A, B>> |
| 343 { |
343 + Sub<Self, Output = PairOutput<$field, A, B>> |
| 344 type Output = PairOutput<F, A, B>; |
344 + for<'b> Add<&'b Self, Output = PairOutput<$field, A, B>> |
| 345 |
345 + for<'b> Sub<&'b Self, Output = PairOutput<$field, A, B>> |
| 346 fn dot<I: Instance<Self>>(&self, other: I) -> F { |
346 + AddAssign<Self> |
| 347 let Pair(u, v) = other.decompose(); |
347 + for<'b> AddAssign<&'b Self> |
| 348 self.0.dot(u) + self.1.dot(v) |
348 + SubAssign<Self> |
| 349 } |
349 + for<'b> SubAssign<&'b Self> |
| 350 |
350 + Neg<Output = PairOutput<$field, A, B>>, |
| 351 fn norm2_squared(&self) -> F { |
351 { |
| 352 self.0.norm2_squared() + self.1.norm2_squared() |
352 type Output = PairOutput<$field, A, B>; |
| 353 } |
353 |
| 354 |
354 fn dot<I: Instance<Self>>(&self, other: I) -> $field { |
| 355 fn dist2_squared<I: Instance<Self>>(&self, other: I) -> F { |
355 let Pair(u, v) = other.decompose(); |
| 356 let Pair(u, v) = other.decompose(); |
356 self.0.dot(u) + self.1.dot(v) |
| 357 self.0.dist2_squared(u) + self.1.dist2_squared(v) |
357 } |
| 358 } |
358 |
| 359 } |
359 fn norm2_squared(&self) -> $field { |
| |
360 self.0.norm2_squared() + self.1.norm2_squared() |
| |
361 } |
| |
362 |
| |
363 fn dist2_squared<I: Instance<Self>>(&self, other: I) -> $field { |
| |
364 let Pair(u, v) = other.decompose(); |
| |
365 self.0.dist2_squared(u) + self.1.dist2_squared(v) |
| |
366 } |
| |
367 } |
| |
368 }; |
| |
369 } |
| |
370 |
| |
371 impl_euclidean!(f32); |
| |
372 impl_euclidean!(f64); |
| 360 |
373 |
| 361 impl<F, A, B, U, V> AXPY<F, Pair<U, V>> for Pair<A, B> |
374 impl<F, A, B, U, V> AXPY<F, Pair<U, V>> for Pair<A, B> |
| 362 where |
375 where |
| 363 U: Space, |
376 U: Space, |
| 364 V: Space, |
377 V: Space, |