criterion/stats/univariate/kde/
kernel.rs

1//! Kernels
2
3use stats::float::Float;
4
5/// Kernel function
6pub trait Kernel<A>: Copy + Sync
7where
8    A: Float,
9{
10    /// Apply the kernel function to the given x-value.
11    fn evaluate(&self, x: A) -> A;
12}
13
14/// Gaussian kernel
15#[derive(Clone, Copy)]
16pub struct Gaussian;
17
18impl<A> Kernel<A> for Gaussian
19where
20    A: Float,
21{
22    fn evaluate(&self, x: A) -> A {
23        use std::f32::consts::PI;
24
25        (x.powi(2).exp() * A::cast(2. * PI)).sqrt().recip()
26    }
27}
28
29#[cfg(test)]
30macro_rules! test {
31    ($ty:ident) => {
32        mod $ty {
33            mod gaussian {
34                use quickcheck::TestResult;
35
36                use stats::univariate::kde::kernel::{Gaussian, Kernel};
37
38                quickcheck! {
39                    fn symmetric(x: $ty) -> bool {
40                        relative_eq!(Gaussian.evaluate(-x), Gaussian.evaluate(x))
41                    }
42                }
43
44                // Any [a b] integral should be in the range [0 1]
45                quickcheck! {
46                    fn integral(a: $ty, b: $ty) -> TestResult {
47                        const DX: $ty = 1e-3;
48
49                        if a > b {
50                            TestResult::discard()
51                        } else {
52                            let mut acc = 0.;
53                            let mut x = a;
54                            let mut y = Gaussian.evaluate(a);
55
56                            while x < b {
57                                acc += DX * y / 2.;
58
59                                x += DX;
60                                y = Gaussian.evaluate(x);
61
62                                acc += DX * y / 2.;
63                            }
64
65                            TestResult::from_bool(
66                                (acc > 0. || relative_eq!(acc, 0.)) &&
67                                (acc < 1. || relative_eq!(acc, 1.)))
68                        }
69                    }
70                }
71            }
72        }
73    };
74}
75
76#[cfg(test)]
77mod test {
78    test!(f32);
79    test!(f64);
80}