32 #ifndef SHARK_LINALG_METRICS_H 33 #define SHARK_LINALG_METRICS_H 48 template<
class VectorT,
class WeightT,
class Device>
49 typename VectorT::value_type diagonalMahalanobisNormSqr(
50 vector_expression<VectorT, Device>
const& vector,
51 vector_expression<WeightT, Device>
const& weights
53 SIZE_CHECK( vector().size() == weights().size() );
54 return inner_prod(weights(),
sqr(vector()));
64 template<
class VectorT,
class WeightT,
class Device>
65 typename VectorT::value_type diagonalMahalanobisNorm(
66 vector_expression<VectorT, Device>
const& vector,
67 vector_expression<WeightT, Device>
const& weights
69 SIZE_CHECK( vector().size() == weights().size() );
70 return std::sqrt(diagonalMahalanobisNormSqr(vector,weights));
84 template<
class VectorT,
class VectorU,
class WeightT>
85 typename VectorT::value_type diagonalMahalanobisDistanceSqr(
88 WeightT
const& weights,
93 typename VectorT::value_type sum=0;
94 typename VectorT::const_iterator iter1=op1.begin();
95 typename VectorU::const_iterator iter2=op2.begin();
96 typename VectorT::const_iterator end1=op1.end();
97 typename VectorU::const_iterator end2=op2.end();
99 while(iter1 != end1 && iter2 != end2)
101 std::size_t index1=iter1.index();
102 std::size_t index2=iter2.index();
104 sum += weights(index1) *
sqr(*iter1-*iter2);
108 else if(index1<index2){
109 sum += weights(index1) *
sqr(*iter1);
113 sum += weights(index2) *
sqr(*iter2);
119 std::size_t index1=iter1.index();
120 sum += weights(index1) *
sqr(*iter1);
125 std::size_t index2=iter2.index();
126 sum += weights(index2) *
sqr(*iter2);
136 template<
class VectorT,
class VectorU,
class WeightT>
137 typename VectorT::value_type diagonalMahalanobisDistanceSqr(
140 WeightT
const& weights,
145 typename VectorT::const_iterator iter=op1.begin();
146 typename VectorT::const_iterator end=op1.end();
148 std::size_t index = 0;
150 typename VectorT::value_type sum=0;
152 for(;iter != end;++iter,++pos){
153 index = iter.index();
154 for(;pos != index;++pos){
155 sum += weights(pos) *
sqr(op2(pos));
157 sum += weights(index) *
sqr(*iter-op2(pos));
159 for(;pos != op2.size();++pos){
160 sum += weights(pos) *
sqr(op2(pos));
164 template<
class VectorT,
class VectorU,
class WeightT>
165 typename VectorT::value_type diagonalMahalanobisDistanceSqr(
168 WeightT
const& weights,
172 return diagonalMahalanobisDistanceSqr(op2,op1,weights,arg2tag,arg1tag);
175 template<
class VectorT,
class VectorU,
class WeightT>
176 typename VectorT::value_type diagonalMahalanobisDistanceSqr(
179 WeightT
const& weights,
183 return inner_prod(op1-op2,(op1-op2)*weights);
187 template<
class MatrixT,
class VectorU,
class Result>
188 void distanceSqrBlockVector(
189 MatrixT
const& operands,
193 typedef typename Result::value_type value_type;
194 scalar_vector< value_type, cpu_tag > one(op2.size(),
static_cast<value_type
>(1.0));
195 for(std::size_t i = 0; i != operands.size1(); ++i){
196 result(i) = diagonalMahalanobisDistanceSqr(
197 row(operands,i),op2,one,
198 typename MatrixT::evaluation_category::tag(),
199 typename VectorU::evaluation_category::tag()
205 template<
class MatrixX,
class MatrixY,
class Result>
206 void distanceSqrBlockBlockRowWise(
211 std::size_t sizeX=X.size1();
212 std::size_t sizeY=Y.size1();
214 for(std::size_t i = 0; i != sizeX; ++i){
215 matrix_row<Result> distanceRow = row(distances,i);
216 distanceSqrBlockVector(
217 Y,row(X,i),distanceRow
221 for(std::size_t i = 0; i != sizeY; ++i){
222 auto distanceCol = column(distances,i);
223 distanceSqrBlockVector(
224 X,row(Y,i),distanceCol
231 template<
class MatrixX,
class MatrixY,
class Result>
232 void distanceSqrBlockBlock(
239 typedef typename Result::value_type value_type;
240 std::size_t sizeX=X.size1();
241 std::size_t sizeY=Y.size1();
242 ensure_size(distances,X.size1(),Y.size1());
243 if(sizeX < 10 || sizeY<10){
244 distanceSqrBlockBlockRowWise(X,Y,distances);
249 noalias(distances) = -2*prod(X,trans(Y));
251 vector<value_type> ySqr(sizeY);
252 for(std::size_t i = 0; i != sizeY; ++i){
253 ySqr(i) = norm_sqr(row(Y,i));
256 for(std::size_t i = 0; i != sizeX; ++i){
257 value_type xSqr = norm_sqr(row(X,i));
258 noalias(row(distances,i)) += repeat(xSqr,sizeY) + ySqr;
262 template<
class MatrixX,
class MatrixY,
class Result>
263 void distanceSqrBlockBlock(
270 distanceSqrBlockBlockRowWise(X,Y,distances);
286 template<
class VectorT,
class VectorU,
class WeightT,
class Device>
287 typename VectorT::value_type diagonalMahalanobisDistanceSqr(
288 vector_expression<VectorT, Device>
const& op1,
289 vector_expression<VectorU, Device>
const& op2,
290 vector_expression<WeightT, Device>
const& weights
295 return detail::diagonalMahalanobisDistanceSqr(
296 op1(), op2(), weights(),
297 typename VectorT::evaluation_category::tag(),
298 typename VectorU::evaluation_category::tag()
305 template<
class VectorT,
class VectorU,
class Device>
306 typename VectorT::value_type distanceSqr(
307 vector_expression<VectorT, Device>
const& op1,
308 vector_expression<VectorU, Device>
const& op2
311 typedef typename VectorT::value_type value_type;
312 scalar_vector< value_type, cpu_tag > one(op1().size(),static_cast<value_type>(1.0));
313 return diagonalMahalanobisDistanceSqr(op1,op2,one);
322 template<
class MatrixT,
class VectorU,
class VectorR,
class Device>
324 matrix_expression<MatrixT, Device>
const& operands,
325 vector_expression<VectorU, Device>
const& op2,
326 vector_expression<VectorR, Device>& distances
329 ensure_size(distances,operands().size1());
330 detail::distanceSqrBlockVector(
331 operands(),op2(),distances()
341 template<
class MatrixT,
class VectorU,
class Device>
342 vector<typename MatrixT::value_type> distanceSqr(
343 matrix_expression<MatrixT, Device>
const& operands,
344 vector_expression<VectorU, Device>
const& op2
347 vector<typename MatrixT::value_type> distances(operands().size1());
348 distanceSqr(operands,op2,distances);
358 template<
class MatrixT,
class VectorU,
class Device>
359 vector<typename MatrixT::value_type> distanceSqr(
360 vector_expression<VectorU, Device>
const& op1,
361 matrix_expression<MatrixT, Device>
const& operands
364 vector<typename MatrixT::value_type> distances(operands().size1());
365 distanceSqr(operands,op1,distances);
378 template<
class MatrixT,
class MatrixU,
class Device>
379 matrix<typename MatrixT::value_type> distanceSqr(
380 matrix_expression<MatrixT, Device>
const& X,
381 matrix_expression<MatrixU, Device>
const& Y
383 typedef matrix<typename MatrixT::value_type> Matrix;
385 std::size_t sizeX=X().size1();
386 std::size_t sizeY=Y().size1();
387 Matrix distances(sizeX, sizeY);
388 detail::distanceSqrBlockBlock(
390 typename MatrixT::evaluation_category::tag(),
391 typename MatrixU::evaluation_category::tag()
401 template<
class VectorT,
class VectorU,
class Device>
402 typename VectorT::value_type distance(
403 vector_expression<VectorT, Device>
const& op1,
404 vector_expression<VectorU, Device>
const& op2
407 return std::sqrt(distanceSqr(op1,op2));
417 template<
class VectorT,
class VectorU,
class WeightT,
class Device>
418 typename VectorT::value_type diagonalMahalanobisDistance(
419 vector_expression<VectorT, Device>
const& op1,
420 vector_expression<VectorU, Device>
const& op2,
421 vector_expression<WeightT, Device>
const& weights
425 return std::sqrt(diagonalMahalanobisDistanceSqr(op1(), op2(), weights));