1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#[cfg(feature = "rand")]
use crate::distr::Normal;
use crate::{
    transform::{Reorder, Shift, Directional},
    Transform, Vector,
};
#[cfg(feature = "approx")]
use approx::{abs_diff_eq, AbsDiffEq};
use num_traits::{Num, Inv};
#[cfg(feature = "rand")]
use rand_::{distributions::Distribution, Rng};

/// Scale transformation.
#[repr(transparent)]
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct Scale<T> {
    mag: T,
}

impl<T> Scale<T> {
    pub fn from_mag(mag: T) -> Self {
        Self { mag }
    }
    pub fn into_mag(self) -> T {
        self.mag
    }
}
impl<T> From<T> for Scale<T> {
    fn from(mag: T) -> Self {
        Self::from_mag(mag)
    }
}
/*
impl<T> From<Scale<T>> for T {
    fn from(scale: Scale<T>) -> T {
        scale.into_mag()
    }
}
*/

impl<T, const N: usize> Transform<Vector<T, N>> for Scale<T>
where
    T: Num + Inv<Output = T> + Copy,
{
    fn identity() -> Self {
        Self { mag: T::one() }
    }
    fn inv(self) -> Self {
        Self { mag: self.mag.inv() }
    }
    fn apply(&self, pos: Vector<T, N>) -> Vector<T, N> {
        pos * self.mag
    }
    fn deriv(&self, _pos: Vector<T, N>, dir: Vector<T, N>) -> Vector<T, N> {
        self.apply(dir)
    }
    fn chain(self, other: Self) -> Self {
        Self { mag: self.mag * other.mag }
    }
}

impl<T, const N: usize> Directional<Vector<T, N>> for Scale<T>
where
    Self: Transform<Vector<T, N>>,
{
    fn apply_dir(&self, _: Vector<T, N>, dir: Vector<T, N>) -> Vector<T, N> {
        dir
    }
    fn apply_normal(&self, _: Vector<T, N>, normal: Vector<T, N>) -> Vector<T, N> {
        normal
    }
}

#[cfg(feature = "rand")]
impl<T> Distribution<Scale<T>> for Normal
where
    Normal: Distribution<T>,
{
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Scale<T> {
        Scale::from_mag(self.sample(rng))
    }
}

#[cfg(feature = "approx")]
impl<T> AbsDiffEq for Scale<T>
where
    T: AbsDiffEq<Epsilon = T> + Copy,
{
    type Epsilon = T;
    fn default_epsilon() -> Self::Epsilon {
        T::default_epsilon()
    }
    fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
        abs_diff_eq!(self.mag, other.mag, epsilon = epsilon)
    }
}

impl<T, const N: usize> Reorder<Scale<T>, Vector<T, N>> for Shift<T, N>
where
    Scale<T>: Transform<Vector<T, N>> + Copy,
    Self: Transform<Vector<T, N>>,
{
    fn reorder(self, other: Scale<T>) -> (Scale<T>, Shift<T, N>) {
        (other, other.inv().apply(self.into_vector()).into())
    }
}

impl<T, const N: usize> Reorder<Shift<T, N>, Vector<T, N>> for Scale<T>
where
    Self: Transform<Vector<T, N>>,
    Shift<T, N>: Transform<Vector<T, N>>,
{
    fn reorder(self, other: Shift<T, N>) -> (Shift<T, N>, Scale<T>) {
        (self.apply(other.into_vector()).into(), self)
    }
}