libmoost
/home/mhx/git/github/libmoost/include/moost/algorithm/similarity.hpp
Go to the documentation of this file.
00001 /* vim:set ts=3 sw=3 sts=3 et: */
00028 #ifndef MOOST_ALGORITHM_SIMILARITY_HPP__
00029 #define MOOST_ALGORITHM_SIMILARITY_HPP__
00030 
00031 #include <cmath>
00032 
00033 namespace moost { namespace algorithm {
00034 
00041 template <typename FloatType>
00042 struct SimpleAccumulatorPolicy
00043 {
00044    void operator() (FloatType& accu, const FloatType& val) const
00045    {
00046       accu += val;
00047    }
00048 };
00049 
00077 template < typename FloatType,
00078            class ForwardIteratorX,
00079            class WeightAccessPolicyX,
00080            class ForwardIteratorY,
00081            class WeightAccessPolicyY,
00082            class AccumulatorPolicy >
00083 FloatType cosine_similarity(ForwardIteratorX x_beg, ForwardIteratorX x_end, WeightAccessPolicyX x_weight,
00084                             ForwardIteratorY y_beg, ForwardIteratorY y_end, WeightAccessPolicyY y_weight,
00085                             AccumulatorPolicy& accu)
00086 {
00087    FloatType sum, norm_x, norm_y;
00088 
00089    sum = norm_x = norm_y = 0.0;
00090 
00091    while (x_beg != x_end && y_beg != y_end)
00092    {
00093       if (*x_beg < *y_beg)
00094       {
00095          FloatType x = x_weight(*x_beg);
00096          norm_x += x*x;
00097          ++x_beg;
00098       }
00099       else if (*y_beg < *x_beg)
00100       {
00101          FloatType y = y_weight(*y_beg);
00102          norm_y += y*y;
00103          ++y_beg;
00104       }
00105       else
00106       {
00107          FloatType x = x_weight(*x_beg);
00108          FloatType y = y_weight(*y_beg);
00109          accu(sum, x*y);
00110          norm_x += x*x;
00111          norm_y += y*y;
00112          ++x_beg;
00113          ++y_beg;
00114       }
00115    }
00116 
00117    if (sum == 0.0)
00118    {
00119       return 0.0;
00120    }
00121 
00122    for (; x_beg != x_end; ++x_beg)
00123    {
00124       FloatType x = x_weight(*x_beg);
00125       norm_x += x*x;
00126    }
00127 
00128    for (; y_beg != y_end; ++y_beg)
00129    {
00130       FloatType y = y_weight(*y_beg);
00131       norm_y += y*y;
00132    }
00133 
00134    return sum/std::sqrt(norm_x*norm_y);
00135 }
00136 
00137 /* Default implementation using SimpleAccumulatorPolicy */
00138 template < typename FloatType,
00139            class ForwardIteratorX,
00140            class WeightAccessPolicyX,
00141            class ForwardIteratorY,
00142            class WeightAccessPolicyY >
00143 FloatType cosine_similarity(ForwardIteratorX x_beg, ForwardIteratorX x_end, WeightAccessPolicyX x_weight,
00144                             ForwardIteratorY y_beg, ForwardIteratorY y_end, WeightAccessPolicyY y_weight)
00145 {
00146    SimpleAccumulatorPolicy<FloatType> accu;
00147    return cosine_similarity<FloatType>(x_beg, x_end, x_weight, y_beg, y_end, y_weight, accu);
00148 }
00149 
00150 }}
00151 
00152 #endif