Home || Visual Search || Applications || Architecture || Important Messages || OGL || Src

MatNorm2Dist.h

Go to the documentation of this file.
00001 #ifndef Impala_Core_Matrix_MatNorm2Dist_h
00002 #define Impala_Core_Matrix_MatNorm2Dist_h
00003 
00004 #include "Core/Matrix/MatFunc.h"
00005 #include "Core/Matrix/MatSum.h"
00006 #include "Core/Matrix/MatMul.h"
00007 #include "Core/Array/Abs.h"
00008 #include "Core/Array/Add.h"
00009 #include "Core/Array/Mul.h"
00010 #include "Core/Array/MulVal.h"
00011 #include "Core/Array/Sqrt.h"
00012 #include "Basis/Timer.h"
00013 #ifdef CUDA
00014 #include "Link/Cuda/Cuda.h"
00015 #include "Link/Cuda/MatNorm2Dist.h"
00016 #endif
00017 #ifdef SSE_USED
00018 #include "Core/Matrix/MatNorm2DistSSE.h"
00019 #endif
00020 //#include "Core/Array/WriteRaw.h"
00021 
00022 namespace Impala
00023 {
00024 namespace Core
00025 {
00026 namespace Matrix
00027 {
00028 
00029 /*
00030 def distance(a,b):
00031     """Computes Euclidean distance matrix
00032 
00033     E = distance(A,B)
00034     
00035         A - (DxM) matrix
00036         B - (DxN) matrix
00037     
00038     Returns:
00039         E - (MxN) Euclidean distances between vectors in A and B
00040     
00041     
00042     Description :
00043         This fully vectorized (VERY FAST!) script computes the
00044         Euclidean distance between two vectors by:
00045     
00046                      ||A-B|| = sqrt ( ||A||^2 + ||B||^2 - 2*A.B )
00047     
00048     Example :
00049         A = rand(400,100); B = rand(400,200);
00050         d = distance(A,B);
00051     
00052     Credits for original Matlab script:
00053     % Author   : Roland Bunschoten
00054     %            University of Amsterdam
00055     %            Intelligent Autonomous Systems (IAS) group
00056     %            Kruislaan 403  1098 SJ Amsterdam
00057     %            tel.(+31)20-5257524
00058     %            bunschot@wins.uva.nl
00059     % Last Rev : Oct 29 16:35:48 MET DST 1999
00060     % Tested   : PC Matlab v5.2 and Solaris Matlab v5.3
00061     % Thanx    : Nikos Vlassis
00062     
00063     % Copyright notice: You are free to modify, extend and distribute
00064     %    this code granted that the author of the original code is
00065     %    mentioned as the original author of the code.
00066     """
00067     from numpy import multiply, transpose, sum, dot, abs, sqrt
00068     from numpy.matlib import repmat
00069 
00070     assert a.shape[0] == b.shape[0], 'A and B should be of same dimensionality'
00071 
00072     # aa=sum(a.*a,1); bb=sum(b.*b,1); ab=a'*b;
00073     #d = sqrt(abs(repmat(aa',[1 size(bb,2)]) + repmat(bb,[size(aa,2) 1]) - 2*ab));
00074 
00075     aa = sum(multiply(a,a), axis=0)      # aa = sum(a.*a,1)
00076     bb = sum(multiply(b,b), axis=0)      # bb = sum(b.*b,1)
00077     ab = dot(transpose(a),b)             # ab = a'*b   
00078     return sqrt(abs(transpose(repmat(aa,bb.shape[0],1)) + repmat(bb,aa.shape[0],1) - 2*ab))
00079 */
00080 
00081 template<class ArrayT>
00082 inline ArrayT*
00083 MatNorm2DistInternal(ArrayT* aT, ArrayT* b)
00084 {
00085 #ifdef SSE_USED
00086     return MatNorm2DistSSE(aT, b);
00087 #endif
00088     ILOG_VAR(Core.Matrix.MatNorm2Dist);
00089     if (MatNrCol(aT) != MatNrRow(b)) {
00090         ILOG_ERROR("MatNorm2DistInternal operands: dimensionality problem");
00091     }
00092 
00093     Timer timer;
00094     
00095     // aa = sum(multiply(a,a), axis=0)      # aa = sum(a.*a,1)
00096     ArrayT* tempAT = 0;
00097     Mul(tempAT, aT, aT);         // elementwise multiplication
00098     ArrayT* aaT = MatSumAxis1(tempAT);
00099     delete tempAT;
00100 
00101     ILOG_DEBUG("aaT: " << timer.SplitTimeStr());
00102 
00103     // bb = sum(multiply(b,b), axis=0)      # bb = sum(b.*b,1)
00104     ArrayT* tempB = 0;
00105     Mul(tempB, b, b);         // elementwise multiplication
00106     ArrayT* bb = MatSumAxis0(tempB);
00107     delete tempB;
00108 
00109     ILOG_DEBUG("bb: " << timer.SplitTimeStr());
00110 
00111     // ab = dot(transpose(a),b)             # ab = a'*b   
00112     //ArrayT* aT = MatTranspose(a);
00113     //ILOG_DEBUG("transpose: " << timer.SplitTimeStr());
00114 
00115     ILOG_DEBUG("aT " << MatNrRow(aT) << " " << MatNrCol(aT));
00116     ILOG_DEBUG("b  " << MatNrRow(b) << " " << MatNrCol(b));
00117 
00118     ArrayT* ab = MatMul(aT, b);
00119 
00120     ILOG_DEBUG("matmul: " << timer.SplitTimeStr());
00121 
00122     // return sqrt(abs(transpose(repmat(aa,bb.shape[0],1)) + repmat(bb,aa.shape[0],1) - 2*ab))
00123     // #d = sqrt(abs(repmat(aa',[1 size(bb,2)]) + repmat(bb,[size(aa,2) 1]) - 2*ab));
00124 
00125     //ILOG_DEBUG("aaT " << MatNrRow(aaT) << " " << MatNrCol(aaT));
00126     //ILOG_DEBUG("bb  " << MatNrRow(bb) << " " << MatNrCol(bb));
00127 
00128     #pragma omp parallel for 
00129     for (int i=0 ; i<MatNrRow(aaT) ; i++)
00130     {
00131         Real64 tmp = *MatE(aaT, i, 0);
00132         for (int j=0 ; j<MatNrCol(bb) ; j++)
00133         {
00134            *MatE(ab, i, j) = sqrt(fabs(*MatE(bb, 0, j) + tmp - 2.0 * *MatE(ab, i, j)));
00135         }
00136     }
00137     ILOG_DEBUG("sqrt(abs(aa + bb - 2ab)): " << timer.SplitTimeStr());
00138     delete bb;
00139     delete aaT;
00140 
00141     ILOG_DEBUG("delete: " << timer.SplitTimeStr());
00142 //WriteRaw(a, "matrix_a.raw", &Util::Database::GetInstance(), 1);
00143 //WriteRaw(b, "matrix_b.raw", &Util::Database::GetInstance(), 1);
00144 //WriteRaw(repAAT, "matrix_c.raw", &Util::Database::GetInstance(), 1);
00145     //ILOG_INFO("cpu-matnorm2dist-total: " << timer.SplitTime());
00146     ILOG_DEBUG(timer.SplitTime() << " (cpu-matnorm2dist-total)");
00147     return ab;
00148 }
00149 
00150 
00151 template<class ArrayT>
00152 inline ArrayT*
00153 MatNorm2Dist(ArrayT* a, ArrayT* b)
00154 {
00155 /*
00156     Computes Euclidean distance matrix
00157 
00158     E = MatNorm2Dist(A,B)
00159     
00160         A - (DxM) matrix
00161         B - (DxN) matrix
00162     
00163     Returns:
00164         E - (MxN) Euclidean distances between vectors in A and B
00165 */
00166     ILOG_VAR(Core.Matrix.MatNorm2Dist);
00167     if (MatNrRow(a) != MatNrRow(b)) {
00168         ILOG_ERROR("MatNorm2Dist operands: A and B should be of same dimensionality");
00169     }
00170     Mat* aT = MatTranspose(a);
00171     ArrayT* result = MatNorm2DistInternal(aT, b);
00172     delete aT;
00173     return result;
00174 }
00175 
00176 
00177 template<class ArrayT>
00178 inline ArrayT*
00179 MatNorm2DistTransposed(ArrayT* aT, ArrayT* bT)
00180 {
00181 /*
00182     Computes Euclidean distance matrix
00183 
00184     E = MatNorm2DistTransposed(A,B)
00185     
00186         A - (MxD) matrix
00187         B - (NxD) matrix
00188     
00189     Returns:
00190         E - (MxN) Euclidean distances between vectors in A and B
00191 */
00192     ILOG_VAR(Core.Matrix.MatNorm2DistTransposed);
00193     if (MatNrCol(aT) != MatNrCol(bT)) {
00194         ILOG_ERROR("MatNorm2DistTransposed operands: A and B should be of same dimensionality");
00195     }
00196 #ifdef CUDA
00197     if(Link::Cuda::CudaUsed())
00198     {
00199         return Link::Cuda::MatNorm2DistTransposed(aT, bT);
00200     }
00201 #endif
00202     Mat* b = MatTranspose(bT);
00203     Mat* result = MatNorm2DistInternal(aT, b);
00204     delete b;
00205     return result;
00206 }
00207 
00208 } // namespace Matrix
00209 } // namespace Core
00210 } // namespace Impala
00211 
00212 #endif

Generated on Thu Jan 13 09:04:33 2011 for ImpalaSrc by  doxygen 1.5.1