core/vnl/vnl_c_vector.txx

Go to the documentation of this file.
00001 // This is core/vnl/vnl_c_vector.txx
00002 #ifndef vnl_c_vector_txx_
00003 #define vnl_c_vector_txx_
00004 //:
00005 // \file
00006 // \author Andrew W. Fitzgibbon, Oxford RRG
00007 // \date   12 Feb 98
00008 //
00009 //-----------------------------------------------------------------------------
00010 
00011 #include "vnl_c_vector.h"
00012 #include <vcl_cmath.h>     // vcl_sqrt()
00013 #include <vcl_cassert.h>
00014 #include <vnl/vnl_math.h>
00015 #include <vnl/vnl_complex_traits.h>
00016 #include <vnl/vnl_numeric_traits.h>
00017 
00018 #include <vnl/vnl_sse.h>
00019 
00020 template <class T>
00021 T vnl_c_vector<T>::sum(T const* v, unsigned n)
00022 {
00023   return vnl_sse<T>::sum(v,n);
00024 }
00025 
00026 template <class T>
00027 void vnl_c_vector<T>::normalize(T* v, unsigned n)
00028 {
00029   typedef typename vnl_numeric_traits<T>::abs_t abs_t;
00030   typedef typename vnl_numeric_traits<abs_t>::real_t real_t;
00031   abs_t tmp(0);
00032   for (unsigned i = 0; i < n; ++i)
00033     tmp += vnl_math_squared_magnitude(v[i]);
00034   if (tmp!=0)
00035   {
00036     tmp = abs_t(real_t(1) / vcl_sqrt(real_t(tmp)));
00037     for (unsigned i = 0; i < n; ++i)
00038       v[i] = T(tmp*v[i]);
00039   }
00040 }
00041 
00042 template <class T>
00043 void vnl_c_vector<T>::apply(T const* v, unsigned n, T (*f)(T const&), T* v_out)
00044 {
00045   for (unsigned i = 0; i < n; ++i)
00046     v_out[i] = f(v[i]);
00047 }
00048 
00049 template <class T>
00050 void vnl_c_vector<T>::apply(T const* v, unsigned n, T (*f)(T), T* v_out)
00051 {
00052   for (unsigned i = 0; i < n; ++i)
00053     v_out[i] = f(v[i]);
00054 }
00055 
00056 template <class T>
00057 void vnl_c_vector<T>::copy(T const *src, T *dst, unsigned n)
00058 {
00059   for (unsigned i=0; i<n; ++i)
00060     dst[i] = src[i];
00061 }
00062 
00063 template <class T>
00064 void vnl_c_vector<T>::scale(T const *x, T *y, unsigned n, T const &a_)
00065 {
00066   T a = a_;
00067   if (x == y)
00068     for (unsigned i=0; i<n; ++i)
00069       y[i] *= a;
00070   else
00071     for (unsigned i=0; i<n; ++i)
00072       y[i] = a*x[i];
00073 }
00074 
00075 //----------------------------------------------------------------------------
00076 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00077 #define impl_elmt_wise_commutative(op) \
00078   if (z == x) \
00079     for (unsigned i=0; i<n; ++i) \
00080       z[i] op##= y[i]; \
00081   else if (z == y) \
00082     for (unsigned i=0; i<n; ++i) \
00083       z[i] op##= x[i]; \
00084   else \
00085     for (unsigned i=0; i<n; ++i) \
00086       z[i] = x[i] op y[i];
00087 
00088 #define impl_elmt_wise_non_commutative(op) \
00089   if (z == x) \
00090     for (unsigned i=0; i<n; ++i) \
00091       z[i] op##= y[i]; \
00092   else \
00093     for (unsigned i=0; i<n; ++i) \
00094       z[i] = x[i] op y[i];
00095 
00096 #define impl_elmt_wise_commutative_a(op) \
00097   if (z == x) \
00098     for (unsigned i=0; i<n; ++i) \
00099       z[i] op##= y; \
00100   else \
00101     for (unsigned i=0; i<n; ++i) \
00102       z[i] = x[i] op y;
00103 
00104 #define impl_elmt_wise_non_commutative_a(op) \
00105   if (z == x) \
00106     for (unsigned i=0; i<n; ++i) \
00107       z[i] op##= y; \
00108   else \
00109     for (unsigned i=0; i<n; ++i) \
00110       z[i] = x[i] op y;
00111 #endif // DOXYGEN_SHOULD_SKIP_THIS
00112 
00113 template <class T>
00114 void vnl_c_vector<T>::add(T const *x, T const *y, T *z, unsigned n)
00115 {
00116   impl_elmt_wise_commutative(+);
00117 }
00118 
00119 template <class T>
00120 void vnl_c_vector<T>::add(T const *x, T const& y, T *z, unsigned n)
00121 {
00122   impl_elmt_wise_commutative_a(+);
00123 }
00124 
00125 template <class T>
00126 void vnl_c_vector<T>::subtract(T const *x, T const *y, T *z, unsigned n)
00127 {
00128   impl_elmt_wise_non_commutative(-);
00129 }
00130 
00131 template <class T>
00132 void vnl_c_vector<T>::subtract(T const *x, T const& y, T *z, unsigned n)
00133 {
00134   impl_elmt_wise_commutative_a(-);
00135 }
00136 
00137 template <class T>
00138 void vnl_c_vector<T>::multiply(T const *x, T const *y, T *z, unsigned n)
00139 {
00140   impl_elmt_wise_commutative(*);
00141 }
00142 
00143 template <class T>
00144 void vnl_c_vector<T>::multiply(T const *x, T const& y, T *z, unsigned n)
00145 {
00146   impl_elmt_wise_commutative_a(*);
00147 }
00148 
00149 template <class T>
00150 void vnl_c_vector<T>::divide(T const *x, T const *y, T *z, unsigned n)
00151 {
00152   impl_elmt_wise_non_commutative(/);
00153 }
00154 
00155 template <class T>
00156 void vnl_c_vector<T>::divide(T const *x, T const& y, T *z, unsigned n)
00157 {
00158   impl_elmt_wise_commutative_a(/);
00159 }
00160 
00161 #undef impl_elmt_wise_commutative
00162 #undef impl_elmt_wise_noncommutative
00163 //--------------------------------------------------------------------------
00164 
00165 template <class T>
00166 void vnl_c_vector<T>::negate(T const *x, T *y, unsigned n)
00167 {
00168   if (x == y)
00169     for (unsigned i=0; i<n; ++i)
00170       y[i] = -y[i];
00171   else
00172     for (unsigned i=0; i<n; ++i)
00173       y[i] = -x[i];
00174 }
00175 
00176 template <class T>
00177 void vnl_c_vector<T>::invert(T const *x, T *y, unsigned n)
00178 {
00179   if (x == y)
00180     for (unsigned i=0; i<n; ++i)
00181       y[i] = T(1)/y[i];
00182   else
00183     for (unsigned i=0; i<n; ++i)
00184       y[i] = T(1)/x[i];
00185 }
00186 
00187 template <class T>
00188 void vnl_c_vector<T>::saxpy(T const &a_, T const *x, T *y, unsigned n)
00189 {
00190   T a = a_;
00191   for (unsigned i=0; i<n; ++i)
00192     y[i] += a*x[i];
00193 }
00194 
00195 template <class T>
00196 void vnl_c_vector<T>::fill(T *x, unsigned n, T const &v_)
00197 {
00198   T v = v_;
00199   for (unsigned i=0; i<n; ++i)
00200     x[i] = v;
00201 }
00202 
00203 template <class T>
00204 void vnl_c_vector<T>::reverse(T *x, unsigned n)
00205 {
00206   for (unsigned i=0; 2*i+1<n; ++i) {
00207     T tmp = x[i];
00208     x[i] = x[n-1-i];
00209     x[n-1-i] = tmp;
00210   }
00211 }
00212 
00213 // non-conjugating "dot" product.
00214 template<class T>
00215 T vnl_c_vector<T>::dot_product(T const *a, T const *b, unsigned n)
00216 {
00217   return vnl_sse<T>::dot_product(a,b,n);
00218 }
00219 
00220 // conjugating "dot" product.
00221 template<class T>
00222 T vnl_c_vector<T>::inner_product(T const *a, T const *b, unsigned n)
00223 {
00224   T ip(0);
00225   for (unsigned i=0; i<n; ++i)
00226     ip += a[i] * vnl_complex_traits<T>::conjugate(b[i]);
00227   return ip;
00228 }
00229 
00230 // conjugates one block of data into another block.
00231 template<class T>
00232 void vnl_c_vector<T>::conjugate(T const *src, T *dst, unsigned n)
00233 {
00234   for (unsigned i=0; i<n; ++i)
00235     dst[i] = vnl_complex_traits<T>::conjugate( src[i] );
00236 }
00237 
00238 //------------------------------------------------------------------------------
00239 
00240 //: Returns max value of the vector.
00241 template<class T>
00242 T vnl_c_vector<T>::max_value(T const *src, unsigned n)
00243 {
00244   assert(n!=0); // max_value of an empty vector is undefined
00245   return vnl_sse<T>::max(src,n);
00246 }
00247 
00248 //: Returns min value of the vector.
00249 template<class T>
00250 T vnl_c_vector<T>::min_value(T const *src, unsigned n)
00251 {
00252   assert(n!=0); // min_value of an empty vector is undefined
00253   return vnl_sse<T>::min(src,n);
00254 }
00255 
00256 //: Sum of Differences squared.
00257 template<class T>
00258 T vnl_c_vector<T>::euclid_dist_sq(T const *a, T const *b, unsigned n)
00259 {
00260   return vnl_sse<T>::euclid_dist_sq(a,b,n);
00261 }
00262 
00263 template <class T>
00264 T vnl_c_vector<T>::sum_sq_diff_means(T const* v, unsigned n)
00265 {
00266   T sum(0);
00267   T sum_sq(0);
00268   for (unsigned i = 0; i < n; ++i, ++v)
00269   {
00270     sum += *v;
00271     sum_sq += *v * *v;
00272   }
00273   typedef typename vnl_numeric_traits<T>::abs_t abs_t;
00274   return sum_sq - sum*sum / abs_t(n);
00275 }
00276 
00277 //------------------------------------------------------------
00278 
00279 template <class T, class S>
00280 void vnl_c_vector_two_norm_squared(T const *p, unsigned n, S *out)
00281 {
00282 #if 1
00283   // IMS: MSVC's optimiser does much better with *p++ than with p[i];
00284   // consistently about 30% better over vectors from 4 to 20000 dimensions.
00285   // PVr: with gcc 3.0 on alpha this is even a factor 3 faster!
00286   S val =0;
00287   T const* end = p+n;
00288   while (p != end)
00289     val += vnl_math_squared_magnitude(*p++);
00290   *out = val;
00291 #else
00292   *out = 0;
00293   for (unsigned i=0; i<n; ++i)
00294     *out += vnl_math_squared_magnitude(p[i]);
00295 #endif
00296 }
00297 
00298 template <class T, class S>
00299 void vnl_c_vector_rms_norm(T const *p, unsigned n, S *out)
00300 {
00301   vnl_c_vector_two_norm_squared(p, n, out);
00302   *out /= n;
00303   typedef typename vnl_numeric_traits<S>::real_t real_t;
00304   *out = S(vcl_sqrt(real_t(*out)));
00305 }
00306 
00307 template <class T, class S>
00308 void vnl_c_vector_one_norm(T const *p, unsigned n, S *out)
00309 {
00310   *out = 0;
00311   T const* end = p+n;
00312   while (p != end)
00313     *out += vnl_math_abs(*p++);
00314 }
00315 
00316 template <class T, class S>
00317 void vnl_c_vector_two_norm(T const *p, unsigned n, S *out)
00318 {
00319   vnl_c_vector_two_norm_squared(p, n, out);
00320   typedef typename vnl_numeric_traits<S>::real_t real_t;
00321   *out = S(vcl_sqrt(real_t(*out)));
00322 }
00323 
00324 template <class T, class S>
00325 void vnl_c_vector_inf_norm(T const *p, unsigned n, S *out)
00326 {
00327   *out = 0;
00328   T const* end = p+n;
00329   while (p != end) {
00330     S v = vnl_math_abs(*p++);
00331     if (v > *out)
00332       *out = v;
00333   }
00334 }
00335 
00336 
00337 //---------------------------------------------------------------------------
00338 
00339 
00340 inline void* vnl_c_vector_alloc(int n, int size)
00341 {
00342   return vnl_sse_alloc(n,size);
00343 }
00344 
00345 
00346 inline void vnl_c_vector_dealloc(void* v, int n, int size)
00347 {
00348   vnl_sse_dealloc(v,n,size);
00349 }
00350 
00351 template<class T>
00352 T** vnl_c_vector<T>::allocate_Tptr(int n)
00353 {
00354   return (T**)vnl_c_vector_alloc(n, sizeof (T*));
00355 }
00356 
00357 template<class T>
00358 void vnl_c_vector<T>::deallocate(T** v, int n)
00359 {
00360   vnl_c_vector_dealloc(v, n, sizeof (T*));
00361 }
00362 
00363 // "T *" is POD, but "T" might not be.
00364 #include <vcl_new.h>
00365 template <class T> inline void vnl_c_vector_construct(T *p, int n)
00366 {
00367   for (int i=0; i<n; ++i)
00368     new (p+i) T();
00369 }
00370 
00371 inline void vnl_c_vector_construct(float *, int) { }
00372 inline void vnl_c_vector_construct(double *, int) { }
00373 inline void vnl_c_vector_construct(long double *, int) { }
00374 inline void vnl_c_vector_construct(vcl_complex<float> *, int) { }
00375 inline void vnl_c_vector_construct(vcl_complex<double> *, int) { }
00376 inline void vnl_c_vector_construct(vcl_complex<long double> *, int) { }
00377 
00378 #ifdef __BORLANDC__
00379 // The compiler is confused
00380 # pragma option push -w-8057
00381 // Warning W8057 vnl/vnl_c_vector.txx 414:
00382 // Parameter 'p' is never used in function
00383 // vnl_c_vector_destruct<int>(int *,int)
00384 #endif
00385 
00386 
00387 template <class T> inline void vnl_c_vector_destruct(T *p, int n)
00388 {
00389   for (int i=0; i<n; ++i)
00390     (p+i)->~T();
00391 }
00392 
00393 #ifdef __BORLANDC__
00394 # pragma option pop
00395 #endif
00396 
00397 
00398 inline void vnl_c_vector_destruct(float *, int) { }
00399 inline void vnl_c_vector_destruct(double *, int) { }
00400 inline void vnl_c_vector_destruct(long double *, int) { }
00401 inline void vnl_c_vector_destruct(vcl_complex<float> *, int) { }
00402 inline void vnl_c_vector_destruct(vcl_complex<double> *, int) { }
00403 inline void vnl_c_vector_destruct(vcl_complex<long double> *, int) { }
00404 
00405 template<class T>
00406 T* vnl_c_vector<T>::allocate_T(int n)
00407 {
00408   T *p = (T*)vnl_c_vector_alloc(n, sizeof (T));
00409   vnl_c_vector_construct(p, n);
00410   return p;
00411 }
00412 
00413 template<class T>
00414 void vnl_c_vector<T>::deallocate(T* p, int n)
00415 {
00416   vnl_c_vector_destruct(p, n);
00417   vnl_c_vector_dealloc(p, n, sizeof (T));
00418 }
00419 
00420 template<class T>
00421 vcl_ostream& print_vector(vcl_ostream& s, T const* v, unsigned size)
00422 {
00423   if (size != 0) s << v[0];
00424   for (unsigned i = 1; i < size; ++i)   // For each index in vector
00425     s << ' ' << v[i];                   // Output data element
00426   return s;
00427 }
00428 
00429 //---------------------------------------------------------------------------
00430 
00431 #define VNL_C_VECTOR_INSTANTIATE_norm(T, S) \
00432 template void vnl_c_vector_two_norm_squared(T const *, unsigned, S *); \
00433 template void vnl_c_vector_rms_norm(T const *, unsigned, S *); \
00434 template void vnl_c_vector_one_norm(T const *, unsigned, S *); \
00435 template void vnl_c_vector_two_norm(T const *, unsigned, S *); \
00436 template void vnl_c_vector_inf_norm(T const *, unsigned, S *)
00437 
00438 #undef VNL_C_VECTOR_INSTANTIATE_ordered
00439 #define VNL_C_VECTOR_INSTANTIATE_ordered(T) \
00440 VNL_C_VECTOR_INSTANTIATE_norm(T, vnl_c_vector<T >::abs_t); \
00441 template class vnl_c_vector<T >; \
00442 template vcl_ostream& print_vector(vcl_ostream &,T const *,unsigned)
00443 
00444 
00445 #undef VNL_C_VECTOR_INSTANTIATE_unordered
00446 #define VNL_C_VECTOR_INSTANTIATE_unordered(T) \
00447 VCL_DO_NOT_INSTANTIATE(T vnl_c_vector<T >::max_value(T const *, unsigned), T(0)); \
00448 VCL_DO_NOT_INSTANTIATE(T vnl_c_vector<T >::min_value(T const *, unsigned), T(0)); \
00449 VNL_C_VECTOR_INSTANTIATE_norm(T, vnl_c_vector<T >::abs_t); \
00450 template class vnl_c_vector<T >; \
00451 VCL_UNINSTANTIATE_SPECIALIZATION(T vnl_c_vector<T >::max_value(T const *, unsigned)); \
00452 VCL_UNINSTANTIATE_SPECIALIZATION(T vnl_c_vector<T >::min_value(T const *, unsigned))
00453 
00454 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00455 #undef VNL_C_VECTOR_INSTANTIATE
00456 #define VNL_C_VECTOR_INSTANTIATE(T) extern "no such macro; use e.g. VNL_C_VECTOR_INSTANTIATE_ordered instead"
00457 #endif // DOXYGEN_SHOULD_SKIP_THIS
00458 
00459 #endif // vnl_c_vector_txx_

Generated on Sat Nov 22 05:06:20 2008 for core/vnl by  doxygen 1.5.1