sustaining_gazes/lib/3rdParty/dlib/include/dlib/svm/kernel_matrix.h
2016-04-28 15:40:36 -04:00

268 lines
9.1 KiB
C++

// Copyright (C) 2009 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_SVm_KERNEL_MATRIX_
#define DLIB_SVm_KERNEL_MATRIX_
#include <vector>
#include "kernel_matrix_abstract.h"
#include "../matrix.h"
#include "../algs.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
namespace impl
{
template <typename kernel_type, typename T>
inline const typename T::type& access ( const matrix_exp<T>& m, long i)
{
return m(i);
}
// bind to anything that looks like an array and isn't a matrix
template <typename kernel_type, typename T>
inline const typename disable_if<is_matrix<T>,typename T::type>::type& access ( const T& m, long i)
{
return m[i];
}
// Only use this function if T isn't a std::pair because in that case the entire vector is
// probably itself a sparse sample.
template <typename kernel_type, typename T, typename alloc>
inline typename disable_if<is_pair<T>,const T&>::type access ( const std::vector<T,alloc>& m, long i)
{
return m[i];
}
// Only use this function if T isn't a std::pair because in that case the entire vector is
// probably a sparse sample.
template <typename kernel_type, typename T, typename alloc>
inline typename disable_if<is_pair<T>,const T&>::type access ( const std_vector_c<T,alloc>& m, long i)
{
return m[i];
}
template <typename kernel_type>
inline const typename kernel_type::sample_type& access (
const typename kernel_type::sample_type& samp,
long
)
{
return samp;
}
// --------------------------------------------
template <typename kernel_type, typename T>
inline typename disable_if<is_same_type<T,typename kernel_type::sample_type>,unsigned long>::type
size ( const T& m)
{
return m.size();
}
template <typename kernel_type>
inline unsigned long size (
const typename kernel_type::sample_type&
)
{
return 1;
}
// --------------------------------------------
template <typename T>
typename disable_if<is_matrix<T> >::type assert_is_vector(const T&)
{}
template <typename T>
// This funny #ifdef thing is here because gcc sometimes gives a warning
// about v being unused otherwise.
#ifdef ENABLE_ASSERTS
void assert_is_vector(const matrix_exp<T>& v)
#else
void assert_is_vector(const matrix_exp<T>& )
#endif
{
// make sure requires clause is not broken
DLIB_ASSERT(is_vector(v) == true,
"\tconst matrix_exp kernel_matrix()"
<< "\n\t You have to supply this function with row or column vectors"
<< "\n\t v.nr(): " << v.nr()
<< "\n\t v.nc(): " << v.nc()
);
}
}
template <typename K, typename vect_type1, typename vect_type2>
struct op_kern_mat
{
op_kern_mat(
const K& kern_,
const vect_type1& vect1_,
const vect_type2& vect2_
) :
kern(kern_),
vect1(vect1_),
vect2(vect2_)
{
// make sure the requires clauses get checked eventually
impl::assert_is_vector(vect1);
impl::assert_is_vector(vect2);
}
const K& kern;
const vect_type1& vect1;
const vect_type2& vect2;
typedef typename K::scalar_type type;
const static long cost = 100;
const static long NR = (is_same_type<vect_type1,typename K::sample_type>::value) ? 1 : 0;
const static long NC = (is_same_type<vect_type2,typename K::sample_type>::value) ? 1 : 0;
typedef const type const_ret_type;
typedef typename K::mem_manager_type mem_manager_type;
typedef row_major_layout layout_type;
const_ret_type apply (long r, long c ) const
{
return kern(impl::access<K>(vect1,r), impl::access<K>(vect2,c));
}
long nr () const { return impl::size<K>(vect1); }
long nc () const { return impl::size<K>(vect2); }
template <typename U> bool aliases ( const matrix_exp<U>& item ) const { return alias_helper(item.ref()); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item ) const { return alias_helper(item.ref()); }
template <typename U> bool alias_helper ( const U& ) const { return false; }
typedef typename K::sample_type samp_type;
// Say we destructively alias if one of the vect* objects is actually item.
bool alias_helper (const samp_type& item ) const { return are_same(item, vect1) || are_same(item, vect2); }
template <typename U> bool are_same (const samp_type& , const U& ) const { return false; }
bool are_same (const samp_type& a, const samp_type& b) const { return (&a == &b); }
};
// ----------------------------------------------------------------------------------------
template <
typename K,
typename V1,
typename V2
>
const matrix_op<op_kern_mat<K,V1,V2> > kernel_matrix (
const K& kern,
const V1& v1,
const V2& v2
)
{
typedef op_kern_mat<K,V1,V2> op;
return matrix_op<op>(op(kern,v1,v2));
}
// ----------------------------------------------------------------------------------------
/*
It is possible to implement the kernel_matrix() operator with just one operator
class but treating the version that takes only a single vector separately
leads to more efficient output by gcc in certain instances.
*/
template <typename K, typename vect_type1>
struct op_kern_mat_single
{
op_kern_mat_single(
const K& kern_,
const vect_type1& vect1_
) :
kern(kern_),
vect1(vect1_)
{
// make sure the requires clauses get checked eventually
impl::assert_is_vector(vect1);
}
const K& kern;
const vect_type1& vect1;
typedef typename K::scalar_type type;
const static long cost = 100;
const static long NR = (is_same_type<vect_type1,typename K::sample_type>::value) ? 1 : 0;
const static long NC = (is_same_type<vect_type1,typename K::sample_type>::value) ? 1 : 0;
typedef const type const_ret_type;
typedef typename K::mem_manager_type mem_manager_type;
typedef row_major_layout layout_type;
const_ret_type apply (long r, long c ) const
{
return kern(impl::access<K>(vect1,r), impl::access<K>(vect1,c));
}
long nr () const { return impl::size<K>(vect1); }
long nc () const { return impl::size<K>(vect1); }
template <typename U> bool aliases ( const matrix_exp<U>& item ) const { return alias_helper(item.ref()); }
template <typename U> bool destructively_aliases ( const matrix_exp<U>& item ) const { return alias_helper(item.ref()); }
template <typename U> bool alias_helper ( const U& ) const { return false; }
typedef typename K::sample_type samp_type;
// Say we destructively alias if vect1 is actually item.
bool alias_helper (const samp_type& item ) const { return are_same(item, vect1); }
template <typename U> bool are_same (const samp_type& , const U& ) const { return false; }
bool are_same (const samp_type& a, const samp_type& b) const { return (&a == &b); }
};
template <
typename K,
typename V
>
const matrix_op<op_kern_mat_single<K,V> > kernel_matrix (
const K& kern,
const V& v
)
{
typedef op_kern_mat_single<K,V> op;
return matrix_op<op>(op(kern,v));
}
// ----------------------------------------------------------------------------------------
template <
typename matrix_dest_type,
typename K,
typename V
>
inline void matrix_assign (
matrix_dest_type& dest,
const matrix_exp<matrix_op<op_kern_mat_single<K,V> > >& src
)
/*!
Overload matrix assignment so that when a kernel_matrix expression
gets assigned it only evaluates half the kernel matrix (since it is symmetric)
!*/
{
for (long r = 0; r < src.nr(); ++r)
{
for (long c = r; c < src.nc(); ++c)
{
dest(r,c) = dest(c,r) = src(r,c);
}
}
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_SVm_KERNEL_MATRIX_