1use crate::derives::*;
8use app_units::Au;
9use euclid::default::Size2D;
10use std::iter::Sum;
11use std::ops::Add;
12
13pub trait ComputeSquaredDistance {
27 fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()>;
29}
30
31#[derive(Add, Clone, Copy, Debug, From, PartialEq, PartialOrd)]
33pub struct SquaredDistance {
34 value: f64,
35}
36
37impl SquaredDistance {
38 #[inline]
40 pub fn from_sqrt(sqrt: f64) -> Self {
41 Self { value: sqrt * sqrt }
42 }
43}
44
45impl ComputeSquaredDistance for u16 {
46 #[inline]
47 fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
48 Ok(SquaredDistance::from_sqrt(
49 ((*self as f64) - (*other as f64)).abs(),
50 ))
51 }
52}
53
54impl ComputeSquaredDistance for i16 {
55 #[inline]
56 fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
57 Ok(SquaredDistance::from_sqrt((*self - *other).abs() as f64))
58 }
59}
60
61impl ComputeSquaredDistance for i32 {
62 #[inline]
63 fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
64 Ok(SquaredDistance::from_sqrt((*self - *other).abs() as f64))
65 }
66}
67
68impl ComputeSquaredDistance for f32 {
69 #[inline]
70 fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
71 Ok(SquaredDistance::from_sqrt((*self - *other).abs() as f64))
72 }
73}
74
75impl ComputeSquaredDistance for f64 {
76 #[inline]
77 fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
78 Ok(SquaredDistance::from_sqrt((*self - *other).abs()))
79 }
80}
81
82impl ComputeSquaredDistance for Au {
83 #[inline]
84 fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
85 self.0.compute_squared_distance(&other.0)
86 }
87}
88
89impl<T> ComputeSquaredDistance for Box<T>
90where
91 T: ComputeSquaredDistance,
92{
93 #[inline]
94 fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
95 (**self).compute_squared_distance(&**other)
96 }
97}
98
99impl<T> ComputeSquaredDistance for Option<T>
100where
101 T: ComputeSquaredDistance,
102{
103 #[inline]
104 fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
105 match (self.as_ref(), other.as_ref()) {
106 (Some(this), Some(other)) => this.compute_squared_distance(other),
107 (None, None) => Ok(SquaredDistance::from_sqrt(0.)),
108 _ => Err(()),
109 }
110 }
111}
112
113impl<T> ComputeSquaredDistance for Size2D<T>
114where
115 T: ComputeSquaredDistance,
116{
117 #[inline]
118 fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
119 Ok(self.width.compute_squared_distance(&other.width)?
120 + self.height.compute_squared_distance(&other.height)?)
121 }
122}
123
124impl SquaredDistance {
125 #[inline]
127 pub fn sqrt(self) -> f64 {
128 self.value.sqrt()
129 }
130}
131
132impl Sum for SquaredDistance {
133 fn sum<I>(iter: I) -> Self
134 where
135 I: Iterator<Item = Self>,
136 {
137 iter.fold(SquaredDistance::from_sqrt(0.), Add::add)
138 }
139}