32#ifndef SHARK_LINALG_METRICS_H
33#define SHARK_LINALG_METRICS_H
48template<
class VectorT,
class WeightT,
class Device>
49typename 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()));
64template<
class VectorT,
class WeightT,
class Device>
65typename 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::value_type sum=0;
147 for(
auto iter=op1.begin();iter != end;++iter,++pos){
148 for(;pos != iter.index();++pos){
149 sum += weights(pos) * op2(pos) * op2(pos);
151 double diff = *iter-op2(pos);
152 sum += weights(pos) * diff * diff;
154 for(;pos != op2.size();++pos){
155 sum += weights(pos) * op2(pos) * op2(pos);
159 template<
class VectorT,
class VectorU,
class WeightT>
160 typename VectorT::value_type diagonalMahalanobisDistanceSqr(
163 WeightT
const& weights,
167 return diagonalMahalanobisDistanceSqr(op2,op1,weights,arg2tag,arg1tag);
170 template<
class VectorT,
class VectorU,
class WeightT>
171 typename VectorT::value_type diagonalMahalanobisDistanceSqr(
174 WeightT
const& weights,
178 return inner_prod(op1-op2,(op1-op2)*weights);
182 template<
class MatrixT,
class VectorU,
class Result>
183 void distanceSqrBlockVector(
184 MatrixT
const& operands,
188 typedef typename Result::value_type value_type;
189 scalar_vector< value_type, cpu_tag > one(op2.size(),
static_cast<value_type
>(1.0));
190 for(std::size_t i = 0; i != operands.size1(); ++i){
191 result(i) = diagonalMahalanobisDistanceSqr(
192 row(operands,i),op2,one,
193 typename MatrixT::evaluation_category::tag(),
194 typename VectorU::evaluation_category::tag()
200 template<
class MatrixX,
class MatrixY,
class Result>
201 void distanceSqrBlockBlockRowWise(
206 std::size_t sizeX=X.size1();
207 std::size_t sizeY=Y.size1();
209 for(std::size_t i = 0; i != sizeX; ++i){
210 auto distanceRow = row(distances,i);
211 distanceSqrBlockVector(
212 Y,row(X,i),distanceRow
216 for(std::size_t i = 0; i != sizeY; ++i){
217 auto distanceCol = column(distances,i);
218 distanceSqrBlockVector(
219 X,row(Y,i),distanceCol
226 template<
class MatrixX,
class MatrixY,
class Result>
227 void distanceSqrBlockBlock(
234 typedef typename Result::value_type value_type;
235 std::size_t sizeX=X.size1();
236 std::size_t sizeY=Y.size1();
237 ensure_size(distances,X.size1(),Y.size1());
238 if(sizeX < 10 || sizeY<10){
239 distanceSqrBlockBlockRowWise(X,Y,distances);
244 noalias(distances) = -2*prod(X,trans(Y));
246 vector<value_type> ySqr(sizeY);
247 for(std::size_t i = 0; i != sizeY; ++i){
248 ySqr(i) = norm_sqr(row(Y,i));
251 for(std::size_t i = 0; i != sizeX; ++i){
252 value_type xSqr = norm_sqr(row(X,i));
253 noalias(row(distances,i)) += repeat(xSqr,sizeY) + ySqr;
257 template<
class MatrixX,
class MatrixY,
class Result>
258 void distanceSqrBlockBlock(
265 distanceSqrBlockBlockRowWise(X,Y,distances);
281template<
class VectorT,
class VectorU,
class WeightT,
class Device>
282typename VectorT::value_type diagonalMahalanobisDistanceSqr(
283 vector_expression<VectorT, Device>
const& op1,
284 vector_expression<VectorU, Device>
const& op2,
285 vector_expression<WeightT, Device>
const& weights
290 return detail::diagonalMahalanobisDistanceSqr(
291 op1(), op2(), weights(),
292 typename VectorT::evaluation_category::tag(),
293 typename VectorU::evaluation_category::tag()
300template<
class VectorT,
class VectorU,
class Device>
301typename VectorT::value_type distanceSqr(
302 vector_expression<VectorT, Device>
const& op1,
303 vector_expression<VectorU, Device>
const& op2
306 typedef typename VectorT::value_type value_type;
307 scalar_vector< value_type, cpu_tag > one(op1().size(),
static_cast<value_type
>(1.0));
308 return diagonalMahalanobisDistanceSqr(op1,op2,one);
317template<
class MatrixT,
class VectorU,
class VectorR,
class Device>
319 matrix_expression<MatrixT, Device>
const& operands,
320 vector_expression<VectorU, Device>
const& op2,
321 vector_expression<VectorR, Device>& distances
324 ensure_size(distances,operands().size1());
325 detail::distanceSqrBlockVector(
326 operands(),op2(),distances()
336template<
class MatrixT,
class VectorU,
class Device>
337vector<typename MatrixT::value_type> distanceSqr(
338 matrix_expression<MatrixT, Device>
const& operands,
339 vector_expression<VectorU, Device>
const& op2
342 vector<typename MatrixT::value_type> distances(operands().size1());
343 distanceSqr(operands,op2,distances);
353template<
class MatrixT,
class VectorU,
class Device>
354vector<typename MatrixT::value_type> distanceSqr(
355 vector_expression<VectorU, Device>
const& op1,
356 matrix_expression<MatrixT, Device>
const& operands
359 vector<typename MatrixT::value_type> distances(operands().size1());
360 distanceSqr(operands,op1,distances);
373template<
class MatrixT,
class MatrixU,
class Device>
374matrix<typename MatrixT::value_type> distanceSqr(
375 matrix_expression<MatrixT, Device>
const& X,
376 matrix_expression<MatrixU, Device>
const& Y
378 typedef matrix<typename MatrixT::value_type> Matrix;
380 std::size_t sizeX=X().size1();
381 std::size_t sizeY=Y().size1();
382 Matrix distances(sizeX, sizeY);
383 detail::distanceSqrBlockBlock(
385 typename MatrixT::evaluation_category::tag(),
386 typename MatrixU::evaluation_category::tag()
396template<
class VectorT,
class VectorU,
class Device>
397typename VectorT::value_type distance(
398 vector_expression<VectorT, Device>
const& op1,
399 vector_expression<VectorU, Device>
const& op2
402 return std::sqrt(distanceSqr(op1,op2));
412template<
class VectorT,
class VectorU,
class WeightT,
class Device>
413typename VectorT::value_type diagonalMahalanobisDistance(
414 vector_expression<VectorT, Device>
const& op1,
415 vector_expression<VectorU, Device>
const& op2,
416 vector_expression<WeightT, Device>
const& weights
420 return std::sqrt(diagonalMahalanobisDistanceSqr(op1(), op2(), weights));