libmoost
|
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