vec_vp_tree/dist/
num.rs

1// Copyright 2016 Austin Bonander
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8//! Distance functions for numeric types.
9
10use super::{DistFn, KnownDist};
11
12/// Distance function for signed integers.
13///
14/// Returns `(left - right).abs() as u64`
15#[derive(Copy, Clone)]
16pub struct SignedDist;
17
18macro_rules! impl_signed_dist {
19        ($($ty:ty),*) => (
20            $(
21                impl DistFn<$ty> for SignedDist {
22                    /// Returns `(left - right).abs() as u64`
23                    fn dist(&self, left: &$ty, right: &$ty) -> u64 {
24                        (left - right).abs() as u64
25                    }
26                }
27
28                impl KnownDist for $ty {
29                    type DistFn = SignedDist;
30
31                    fn dist_fn() -> SignedDist { SignedDist }
32                }
33            )*
34        )
35    }
36
37impl_signed_dist! { i8, i16, i32, i64, isize }
38
39/// Distance function for unsigned integers.
40///
41/// Returns ` if left < right { left - right } else { right - left } as u64`
42#[derive(Copy, Clone)]
43pub struct UnsignedDist;
44
45macro_rules! impl_unsigned_dist {
46        ($($ty:ty),*) => (
47            $(
48                impl DistFn<$ty> for UnsignedDist {
49                    /// Returns ` if left < right { left - right } else { right - left } as u64`
50                    fn dist(&self, left: &$ty, right: &$ty) -> u64 {
51                        let dist = if left < right { left - right } else { right - left };
52                        dist as u64
53                    }
54                }
55
56                impl KnownDist for $ty {
57                    type DistFn = UnsignedDist;
58
59                    fn dist_fn() -> UnsignedDist { UnsignedDist }
60                }
61            )*
62        )
63    }
64
65impl_unsigned_dist! { u8, u16, u32, u64, usize }
66
67/// Implements `DistFn` for floating-point numbers.
68///
69/// Returns `(left - right).abs().round() as u64`.
70#[derive(Copy, Clone)]
71pub struct FloatDist;
72
73/// Implements `DistFn` for floating-point numbers with a scaling factor.
74///
75/// Returns `((left - right) * self.0).abs().round() as u64`
76#[derive(Copy, Clone)]
77pub struct ScaledFloatDist<T>(pub T);
78
79macro_rules! impl_float_dist {
80        ($($ty:ty),*) => (
81            $(
82                impl DistFn<$ty> for FloatDist {
83                    /// Returns `(left - right).abs().round() as u64`.
84                    fn dist(&self, left: &$ty, right: &$ty) -> u64 {
85                        (left - right).abs().round() as u64
86                    }
87                }
88
89                impl KnownDist for $ty {
90                    type DistFn = FloatDist;
91
92                    fn dist_fn() -> FloatDist { FloatDist }
93                }
94
95                impl DistFn<$ty> for ScaledFloatDist<$ty> {
96                    /// Returns `((left - right) * self.0).abs().round() as u64`
97                    fn dist(&self, left: &$ty, right: &$ty) -> u64 {
98                        ((left - right) * self.0).abs().round() as u64
99                    }
100                }
101            )*
102        )
103    }
104
105impl_float_dist! { f32, f64 }