1 /**
2 * @file core/metrics/ip_metric_impl.hpp
3 * @author Ryan Curtin
4 *
5 * Implementation of the IPMetric.
6 *
7 * mlpack is free software; you may redistribute it and/or modify it under the
8 * terms of the 3-clause BSD license. You should have received a copy of the
9 * 3-clause BSD license along with mlpack. If not, see
10 * http://www.opensource.org/licenses/BSD-3-Clause for more information.
11 */
12 #ifndef MLPACK_METHODS_FASTMKS_IP_METRIC_IMPL_HPP
13 #define MLPACK_METHODS_FASTMKS_IP_METRIC_IMPL_HPP
14
15 // In case it hasn't been included yet.
16 #include "ip_metric.hpp"
17
18 #include <mlpack/core/metrics/lmetric.hpp>
19 #include <mlpack/core/kernels/linear_kernel.hpp>
20
21 namespace mlpack {
22 namespace metric {
23
24 // Constructor with no instantiated kernel.
25 template<typename KernelType>
IPMetric()26 IPMetric<KernelType>::IPMetric() :
27 kernel(new KernelType()),
28 kernelOwner(true)
29 {
30 // Nothing to do.
31 }
32
33 // Constructor with instantiated kernel.
34 template<typename KernelType>
IPMetric(KernelType & kernel)35 IPMetric<KernelType>::IPMetric(KernelType& kernel) :
36 kernel(&kernel),
37 kernelOwner(false)
38 {
39 // Nothing to do.
40 }
41
42 // Destructor for the IPMetric.
43 template<typename KernelType>
~IPMetric()44 IPMetric<KernelType>::~IPMetric()
45 {
46 if (kernelOwner)
47 delete kernel;
48 }
49
50 template<typename KernelType>
IPMetric(const IPMetric & other)51 IPMetric<KernelType>::IPMetric(const IPMetric& other) :
52 kernel(new KernelType(*other.kernel)),
53 kernelOwner(true)
54 {
55 // Nothing to do.
56 }
57
58 template<typename KernelType>
operator =(const IPMetric & other)59 IPMetric<KernelType>& IPMetric<KernelType>::operator=(const IPMetric& other)
60 {
61 if (this == &other)
62 return *this;
63
64 if (kernelOwner)
65 delete kernel;
66
67 kernel = new KernelType(*other.kernel);
68 kernelOwner = true;
69 return *this;
70 }
71
72 template<typename KernelType>
73 template<typename Vec1Type, typename Vec2Type>
Evaluate(const Vec1Type & a,const Vec2Type & b)74 inline typename Vec1Type::elem_type IPMetric<KernelType>::Evaluate(
75 const Vec1Type& a,
76 const Vec2Type& b)
77 {
78 // This is the metric induced by the kernel function.
79 // Maybe we can do better by caching some of this?
80 return sqrt(kernel->Evaluate(a, a) + kernel->Evaluate(b, b) -
81 2 * kernel->Evaluate(a, b));
82 }
83
84 // Serialize the kernel.
85 template<typename KernelType>
86 template<typename Archive>
serialize(Archive & ar,const unsigned int)87 void IPMetric<KernelType>::serialize(Archive& ar,
88 const unsigned int /* version */)
89 {
90 // If we're loading, we need to allocate space for the kernel, and we will own
91 // the kernel.
92 if (Archive::is_loading::value)
93 {
94 if (kernelOwner)
95 delete kernel;
96 kernelOwner = true;
97 }
98
99 ar & BOOST_SERIALIZATION_NVP(kernel);
100 }
101
102 // A specialization for the linear kernel, which actually just turns out to be
103 // the Euclidean distance.
104 template<>
105 template<typename Vec1Type, typename Vec2Type>
Evaluate(const Vec1Type & a,const Vec2Type & b)106 inline typename Vec1Type::elem_type IPMetric<kernel::LinearKernel>::Evaluate(
107 const Vec1Type& a,
108 const Vec2Type& b)
109 {
110 return metric::LMetric<2, true>::Evaluate(a, b);
111 }
112
113 } // namespace metric
114 } // namespace mlpack
115
116 #endif
117