mlpack
lmetric_impl.hpp
Go to the documentation of this file.
1 
12 #ifndef MLPACK_CORE_METRICS_LMETRIC_IMPL_HPP
13 #define MLPACK_CORE_METRICS_LMETRIC_IMPL_HPP
14 
15 // In case it hasn't been included.
16 #include "lmetric.hpp"
17 
18 namespace mlpack {
19 namespace metric {
20 
21 // Unspecialized implementation. This should almost never be used...
22 template<int Power, bool TakeRoot>
23 template<typename VecTypeA, typename VecTypeB>
24 typename VecTypeA::elem_type LMetric<Power, TakeRoot>::Evaluate(
25  const VecTypeA& a,
26  const VecTypeB& b)
27 {
28  typename VecTypeA::elem_type sum = 0;
29  for (size_t i = 0; i < a.n_elem; ++i)
30  sum += std::pow(fabs(a[i] - b[i]), Power);
31 
32  if (!TakeRoot) // The compiler should optimize this correctly at compile-time.
33  return sum;
34 
35  return std::pow(sum, (1.0 / Power));
36 }
37 
38 // L1-metric specializations; the root doesn't matter.
39 template<>
40 template<typename VecTypeA, typename VecTypeB>
41 typename VecTypeA::elem_type LMetric<1, true>::Evaluate(
42  const VecTypeA& a,
43  const VecTypeB& b)
44 {
45  return arma::accu(abs(a - b));
46 }
47 
48 template<>
49 template<typename VecTypeA, typename VecTypeB>
50 typename VecTypeA::elem_type LMetric<1, false>::Evaluate(
51  const VecTypeA& a,
52  const VecTypeB& b)
53 {
54  return arma::accu(abs(a - b));
55 }
56 
57 // L2-metric specializations.
58 template<>
59 template<typename VecTypeA, typename VecTypeB>
60 typename VecTypeA::elem_type LMetric<2, true>::Evaluate(
61  const VecTypeA& a,
62  const VecTypeB& b)
63 {
64  return arma::norm(a - b, 2);
65 }
66 
67 template<>
68 template<typename VecTypeA, typename VecTypeB>
69 typename VecTypeA::elem_type LMetric<2, false>::Evaluate(
70  const VecTypeA& a,
71  const VecTypeB& b)
72 {
73  return accu(arma::square(a - b));
74 }
75 
76 // L3-metric specialization (not very likely to be used, but just in case).
77 template<>
78 template<typename VecTypeA, typename VecTypeB>
79 typename VecTypeA::elem_type LMetric<3, true>::Evaluate(
80  const VecTypeA& a,
81  const VecTypeB& b)
82 {
83  typename VecTypeA::elem_type sum = 0;
84  for (size_t i = 0; i < a.n_elem; ++i)
85  sum += std::pow(fabs(a[i] - b[i]), 3.0);
86 
87  return std::pow(arma::accu(arma::pow(arma::abs(a - b), 3.0)), 1.0 / 3.0);
88 }
89 
90 template<>
91 template<typename VecTypeA, typename VecTypeB>
92 typename VecTypeA::elem_type LMetric<3, false>::Evaluate(
93  const VecTypeA& a,
94  const VecTypeB& b)
95 {
96  return arma::accu(arma::pow(arma::abs(a - b), 3.0));
97 }
98 
99 // L-infinity (Chebyshev distance) specialization
100 template<>
101 template<typename VecTypeA, typename VecTypeB>
102 typename VecTypeA::elem_type LMetric<INT_MAX, false>::Evaluate(
103  const VecTypeA& a,
104  const VecTypeB& b)
105 {
106  return arma::as_scalar(arma::max(arma::abs(a - b)));
107 }
108 
109 } // namespace metric
110 } // namespace mlpack
111 
112 #endif
Linear algebra utility functions, generally performed on matrices or vectors.
Definition: cv.hpp:1
static VecTypeA::elem_type Evaluate(const VecTypeA &a, const VecTypeB &b)
Computes the distance between two points.
Definition: lmetric_impl.hpp:24