vecmat/transform/
shift.rs1#[cfg(feature = "rand")]
2use crate::distr::Normal;
3use crate::{Transform, Vector, transform::Directional};
4#[cfg(feature = "approx")]
5use approx::{abs_diff_eq, AbsDiffEq};
6use core::ops::Neg;
7use num_traits::{Num, Zero};
8#[cfg(feature = "rand")]
9use rand_::{distributions::Distribution, Rng};
10
11#[repr(transparent)]
13#[derive(Clone, Copy, PartialEq, Debug)]
14pub struct Shift<T, const N: usize> {
15 pos: Vector<T, N>,
16}
17
18pub type Shift2<T> = Shift<T, 2>;
19pub type Shift3<T> = Shift<T, 3>;
20pub type Shift4<T> = Shift<T, 4>;
21
22impl<T, const N: usize> Shift<T, N> {
23 pub fn from_vector(pos: Vector<T, N>) -> Self {
24 Self { pos }
25 }
26 pub fn into_vector(self) -> Vector<T, N> {
27 self.pos
28 }
29}
30impl<T, const N: usize> From<Vector<T, N>> for Shift<T, N> {
31 fn from(pos: Vector<T, N>) -> Self {
32 Self::from_vector(pos)
33 }
34}
35impl<T, const N: usize> From<Shift<T, N>> for Vector<T, N> {
36 fn from(shift: Shift<T, N>) -> Self {
37 shift.into_vector()
38 }
39}
40
41impl<T, const N: usize> Transform<Vector<T, N>> for Shift<T, N>
42where
43 T: Neg<Output = T> + Num + Copy,
44{
45 fn identity() -> Self {
46 Self {
47 pos: Vector::zero(),
48 }
49 }
50 fn inv(self) -> Self {
51 Self { pos: -self.pos }
52 }
53 fn apply(&self, pos: Vector<T, N>) -> Vector<T, N> {
54 pos + self.pos
55 }
56 fn deriv(&self, _pos: Vector<T, N>, dir: Vector<T, N>) -> Vector<T, N> {
57 dir
58 }
59 fn chain(self, other: Self) -> Self {
60 Self {
61 pos: self.pos + other.pos,
62 }
63 }
64}
65
66impl<T, const N: usize> Directional<Vector<T, N>> for Shift<T, N>
67where
68 Self: Transform<Vector<T, N>>
69{
70 fn apply_dir(&self, _: Vector<T, N>, dir: Vector<T, N>) -> Vector<T, N> {
71 dir
72 }
73 fn apply_normal(&self, _: Vector<T, N>, normal: Vector<T, N>) -> Vector<T, N> {
74 normal
75 }
76}
77
78#[cfg(feature = "rand")]
79impl<T, const N: usize> Distribution<Shift<T, N>> for Normal
80where
81 Normal: Distribution<Vector<T, N>>,
82{
83 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Shift<T, N> {
84 Shift::from(self.sample(rng))
85 }
86}
87
88#[cfg(feature = "approx")]
89impl<T, const N: usize> AbsDiffEq for Shift<T, N>
90where
91 T: AbsDiffEq<Epsilon = T> + Copy,
92{
93 type Epsilon = T;
94 fn default_epsilon() -> Self::Epsilon {
95 T::default_epsilon()
96 }
97 fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
98 abs_diff_eq!(self.pos, other.pos, epsilon = epsilon)
99 }
100}