00001
00002 #ifndef vnl_c_vector_txx_
00003 #define vnl_c_vector_txx_
00004
00005
00006
00007
00008
00009
00010
00011 #include "vnl_c_vector.h"
00012 #include <vcl_cmath.h>
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
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
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
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
00241 template<class T>
00242 T vnl_c_vector<T>::max_value(T const *src, unsigned n)
00243 {
00244 assert(n!=0);
00245 return vnl_sse<T>::max(src,n);
00246 }
00247
00248
00249 template<class T>
00250 T vnl_c_vector<T>::min_value(T const *src, unsigned n)
00251 {
00252 assert(n!=0);
00253 return vnl_sse<T>::min(src,n);
00254 }
00255
00256
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
00284
00285
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
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
00380 # pragma option push -w-8057
00381
00382
00383
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)
00425 s << ' ' << v[i];
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_