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 }