vnl_c_vector.hxx
Go to the documentation of this file.
1 // This is core/vnl/vnl_c_vector.hxx
2 #ifndef vnl_c_vector_hxx_
3 #define vnl_c_vector_hxx_
4 //:
5 // \file
6 // \author Andrew W. Fitzgibbon, Oxford RRG
7 // \date 12 Feb 1998
8 //
9 //-----------------------------------------------------------------------------
10 
11 #include <cmath>
12 #include <new>
13 #include "vnl_c_vector.h"
14 #include <cassert>
15 #include <vnl/vnl_math.h>
16 #include <vnl/vnl_complex_traits.h>
17 #include <vnl/vnl_numeric_traits.h>
18 
19 #include <vnl/vnl_sse.h>
20 
21 template <class T>
22 T vnl_c_vector<T>::sum(T const* v, unsigned n)
23 {
24  return vnl_sse<T>::sum(v,n);
25 }
26 
27 template <class T>
28 void vnl_c_vector<T>::normalize(T* v, unsigned n)
29 {
30  typedef typename vnl_numeric_traits<T>::abs_t abs_t;
32  abs_t tmp(0);
33  for (unsigned i = 0; i < n; ++i)
34  tmp += vnl_math::squared_magnitude(v[i]);
35  if (tmp!=0)
36  {
37  tmp = abs_t(real_t(1) / std::sqrt(real_t(tmp)));
38  for (unsigned i = 0; i < n; ++i)
39  v[i] = T(tmp*v[i]);
40  }
41 }
42 
43 template <class T>
44 void vnl_c_vector<T>::apply(T const* v, unsigned n, T (*f)(T const&), T* v_out)
45 {
46  for (unsigned i = 0; i < n; ++i)
47  v_out[i] = f(v[i]);
48 }
49 
50 template <class T>
51 void vnl_c_vector<T>::apply(T const* v, unsigned n, T (*f)(T), T* v_out)
52 {
53  for (unsigned i = 0; i < n; ++i)
54  v_out[i] = f(v[i]);
55 }
56 
57 template <class T>
58 void vnl_c_vector<T>::copy(T const *src, T *dst, unsigned n)
59 {
60  for (unsigned i=0; i<n; ++i)
61  dst[i] = src[i];
62 }
63 
64 template <class T>
65 void vnl_c_vector<T>::scale(T const *x, T *y, unsigned n, T const &a_)
66 {
67  T a = a_;
68  if (x == y)
69  for (unsigned i=0; i<n; ++i)
70  y[i] *= a;
71  else
72  for (unsigned i=0; i<n; ++i)
73  y[i] = a*x[i];
74 }
75 
76 //----------------------------------------------------------------------------
77 #ifndef DOXYGEN_SHOULD_SKIP_THIS
78 #define impl_elmt_wise_commutative(op) \
79  if (z == x) \
80  for (unsigned i=0; i<n; ++i) \
81  z[i] op##= y[i]; \
82  else if (z == y) \
83  for (unsigned i=0; i<n; ++i) \
84  z[i] op##= x[i]; \
85  else \
86  for (unsigned i=0; i<n; ++i) \
87  z[i] = x[i] op y[i];
88 
89 #define impl_elmt_wise_non_commutative(op) \
90  if (z == x) \
91  for (unsigned i=0; i<n; ++i) \
92  z[i] op##= y[i]; \
93  else \
94  for (unsigned i=0; i<n; ++i) \
95  z[i] = x[i] op y[i];
96 
97 #define impl_elmt_wise_commutative_a(op) \
98  if (z == x) \
99  for (unsigned i=0; i<n; ++i) \
100  z[i] op##= y; \
101  else \
102  for (unsigned i=0; i<n; ++i) \
103  z[i] = x[i] op y;
104 
105 #define impl_elmt_wise_non_commutative_a(op) \
106  if (z == x) \
107  for (unsigned i=0; i<n; ++i) \
108  z[i] op##= y; \
109  else \
110  for (unsigned i=0; i<n; ++i) \
111  z[i] = x[i] op y;
112 #endif // DOXYGEN_SHOULD_SKIP_THIS
113 
114 template <class T>
115 void vnl_c_vector<T>::add(T const *x, T const *y, T *z, unsigned n)
116 {
117  impl_elmt_wise_commutative(+);
118 }
119 
120 template <class T>
121 void vnl_c_vector<T>::add(T const *x, T const& y, T *z, unsigned n)
122 {
123  impl_elmt_wise_commutative_a(+);
124 }
125 
126 template <class T>
127 void vnl_c_vector<T>::subtract(T const *x, T const *y, T *z, unsigned n)
128 {
129  impl_elmt_wise_non_commutative(-);
130 }
131 
132 template <class T>
133 void vnl_c_vector<T>::subtract(T const *x, T const& y, T *z, unsigned n)
134 {
135  impl_elmt_wise_commutative_a(-);
136 }
137 
138 template <class T>
139 void vnl_c_vector<T>::multiply(T const *x, T const *y, T *z, unsigned n)
140 {
141  impl_elmt_wise_commutative(*);
142 }
143 
144 template <class T>
145 void vnl_c_vector<T>::multiply(T const *x, T const& y, T *z, unsigned n)
146 {
147  impl_elmt_wise_commutative_a(*);
148 }
149 
150 template <class T>
151 void vnl_c_vector<T>::divide(T const *x, T const *y, T *z, unsigned n)
152 {
153  impl_elmt_wise_non_commutative(/);
154 }
155 
156 template <class T>
157 void vnl_c_vector<T>::divide(T const *x, T const& y, T *z, unsigned n)
158 {
159  impl_elmt_wise_commutative_a(/);
160 }
161 
162 #undef impl_elmt_wise_commutative
163 #undef impl_elmt_wise_noncommutative
164 //--------------------------------------------------------------------------
165 
166 template <class T>
167 void vnl_c_vector<T>::negate(T const *x, T *y, unsigned n)
168 {
169  if (x == y)
170  for (unsigned i=0; i<n; ++i)
171  y[i] = -y[i];
172  else
173  for (unsigned i=0; i<n; ++i)
174  y[i] = -x[i];
175 }
176 
177 template <class T>
178 void vnl_c_vector<T>::invert(T const *x, T *y, unsigned n)
179 {
180  if (x == y)
181  for (unsigned i=0; i<n; ++i)
182  y[i] = T(1)/y[i];
183  else
184  for (unsigned i=0; i<n; ++i)
185  y[i] = T(1)/x[i];
186 }
187 
188 template <class T>
189 void vnl_c_vector<T>::saxpy(T const &a_, T const *x, T *y, unsigned n)
190 {
191  T a = a_;
192  for (unsigned i=0; i<n; ++i)
193  y[i] += a*x[i];
194 }
195 
196 template <class T>
197 void vnl_c_vector<T>::fill(T *x, unsigned n, T const &v_)
198 {
199  T v = v_;
200  for (unsigned i=0; i<n; ++i)
201  x[i] = v;
202 }
203 
204 template <class T>
205 void vnl_c_vector<T>::reverse(T *x, unsigned n)
206 {
207  for (unsigned i=0; 2*i+1<n; ++i) {
208  T tmp = x[i];
209  x[i] = x[n-1-i];
210  x[n-1-i] = tmp;
211  }
212 }
213 
214 // non-conjugating "dot" product.
215 template<class T>
216 T vnl_c_vector<T>::dot_product(T const *a, T const *b, unsigned n)
217 {
218  return vnl_sse<T>::dot_product(a,b,n);
219 }
220 
221 // conjugating "dot" product.
222 template<class T>
223 T vnl_c_vector<T>::inner_product(T const *a, T const *b, unsigned n)
224 {
225  T ip(0);
226  for (unsigned i=0; i<n; ++i)
227  ip += a[i] * vnl_complex_traits<T>::conjugate(b[i]);
228  return ip;
229 }
230 
231 // conjugates one block of data into another block.
232 template<class T>
233 void vnl_c_vector<T>::conjugate(T const *src, T *dst, unsigned n)
234 {
235  for (unsigned i=0; i<n; ++i)
236  dst[i] = vnl_complex_traits<T>::conjugate( src[i] );
237 }
238 
239 //------------------------------------------------------------------------------
240 
241 //: Returns max value of the vector.
242 template<class T>
243 T vnl_c_vector<T>::max_value(T const *src, unsigned n)
244 {
245  assert(n!=0); // max_value of an empty vector is undefined
246  return vnl_sse<T>::max(src,n);
247 }
248 
249 //: Returns min value of the vector.
250 template<class T>
251 T vnl_c_vector<T>::min_value(T const *src, unsigned n)
252 {
253  assert(n!=0); // min_value of an empty vector is undefined
254  return vnl_sse<T>::min(src,n);
255 }
256 
257 //: Returns location of max value of the vector.
258 template<class T>
259 unsigned vnl_c_vector<T>::arg_max(T const *src, unsigned n)
260 {
261  assert(n!=0); // max value of an empty vector is undefined
262  return vnl_sse<T>::arg_max(src,n);
263 }
264 
265 //: Returns location of min value of the vector.
266 template<class T>
267 unsigned vnl_c_vector<T>::arg_min(T const *src, unsigned n)
268 {
269  assert(n!=0); // min value of an empty vector is undefined
270  return vnl_sse<T>::arg_min(src,n);
271 }
272 
273 //: Sum of Differences squared.
274 template<class T>
275 T vnl_c_vector<T>::euclid_dist_sq(T const *a, T const *b, unsigned n)
276 {
277  return vnl_sse<T>::euclid_dist_sq(a,b,n);
278 }
279 
280 template <class T>
281 T vnl_c_vector<T>::sum_sq_diff_means(T const* v, unsigned n)
282 {
283  T sum(0);
284  T sum_sq(0);
285  for (unsigned i = 0; i < n; ++i, ++v)
286  {
287  sum += *v;
288  sum_sq += *v * *v;
289  }
290  typedef typename vnl_numeric_traits<T>::abs_t abs_t;
291  return sum_sq - sum*sum / abs_t(n);
292 }
293 
294 //------------------------------------------------------------
295 
296 template <class T, class S>
297 void vnl_c_vector_two_norm_squared(T const *p, unsigned n, S *out)
298 {
299  // IMS: MSVC's optimiser does much better with *p++ than with p[i];
300  // consistently about 30% better over vectors from 4 to 20000 dimensions.
301  S val = S(0);
302  T const* end = p+n;
303  while (p != end)
304  val += S(vnl_math::squared_magnitude(*p++));
305  *out = val;
306 }
307 
308 template <class T, class S>
309 void vnl_c_vector_rms_norm(T const *p, unsigned n, S *out)
310 {
312  *out /= n;
313  typedef typename vnl_numeric_traits<S>::real_t real_t;
314  *out = S(std::sqrt(real_t(*out)));
315 }
316 
317 template <class T, class S>
318 void vnl_c_vector_one_norm(T const *p, unsigned n, S *out)
319 {
320  *out = 0;
321  T const* end = p+n;
322  while (p != end)
323  *out += vnl_math::abs(*p++);
324 }
325 
326 template <class T, class S>
327 void vnl_c_vector_two_norm(T const *p, unsigned n, S *out)
328 {
330  typedef typename vnl_numeric_traits<S>::real_t real_t;
331  *out = S(std::sqrt(real_t(*out)));
332 }
333 
334 template <class T, class S>
335 void vnl_c_vector_inf_norm(T const *p, unsigned n, S *out)
336 {
337  *out = 0;
338  T const* end = p+n;
339  while (p != end) {
340  S v = vnl_math::abs(*p++);
341  if (v > *out)
342  *out = v;
343  }
344 }
345 
346 
347 //---------------------------------------------------------------------------
348 
350 inline void* vnl_c_vector_alloc(std::size_t n, unsigned size)
351 {
352  return vnl_sse_alloc(n,size);
353 }
354 
356 inline void vnl_c_vector_dealloc(void* v, std::size_t n, unsigned size)
357 {
358  vnl_sse_dealloc(v,n,size);
359 }
360 
361 template<class T>
362 T** vnl_c_vector<T>::allocate_Tptr(const std::size_t n)
363 {
364  return (T**)vnl_c_vector_alloc(n, sizeof (T*));
365 }
366 
367 template<class T>
368 void vnl_c_vector<T>::deallocate(T** v, const std::size_t n)
369 {
370  vnl_c_vector_dealloc(v, n, sizeof (T*));
371 }
372 
373 // "T *" is POD, but "T" might not be.
374 #ifdef _MSC_VER
375 # include <vcl_msvc_warnings.h>
376 #endif
377 template <class T> inline void vnl_c_vector_construct(T *p, std::size_t n)
378 {
379  for (std::size_t i=0; i<n; ++i)
380  new (p+i) T();
381 }
383 inline void vnl_c_vector_construct(float *, std::size_t) { }
384 inline void vnl_c_vector_construct(double *, std::size_t) { }
385 inline void vnl_c_vector_construct(long double *, std::size_t) { }
386 inline void vnl_c_vector_construct(std::complex<float> *, std::size_t) { }
387 inline void vnl_c_vector_construct(std::complex<double> *, std::size_t) { }
388 inline void vnl_c_vector_construct(std::complex<long double> *, std::size_t) { }
390 template <class T> inline void vnl_c_vector_destruct(T *p, std::size_t n)
391 {
392  for (std::size_t i=0; i<n; ++i)
393  (p+i)->~T();
394 }
396 inline void vnl_c_vector_destruct(float *, std::size_t) { }
397 inline void vnl_c_vector_destruct(double *, std::size_t) { }
398 inline void vnl_c_vector_destruct(long double *, std::size_t) { }
399 inline void vnl_c_vector_destruct(std::complex<float> *, std::size_t) { }
400 inline void vnl_c_vector_destruct(std::complex<double> *, std::size_t) { }
401 inline void vnl_c_vector_destruct(std::complex<long double> *, std::size_t) { }
402 
403 template<class T>
404 T* vnl_c_vector<T>::allocate_T(const std::size_t n)
405 {
406  T *p = (T*)vnl_c_vector_alloc(n, sizeof (T));
408  return p;
409 }
410 
411 template<class T>
412 void vnl_c_vector<T>::deallocate(T* p, const std::size_t n)
413 {
414  vnl_c_vector_destruct(p, n);
415  vnl_c_vector_dealloc(p, n, sizeof (T));
416 }
417 
418 template<class T>
419 std::ostream& print_vector(std::ostream& s, T const* v, unsigned size)
420 {
421  if (size != 0) s << v[0];
422  for (unsigned i = 1; i < size; ++i) // For each index in vector
423  s << ' ' << v[i]; // Output data element
424  return s;
425 }
426 
427 //---------------------------------------------------------------------------
429 #define VNL_C_VECTOR_INSTANTIATE_norm(T, S) \
430 template VNL_EXPORT void vnl_c_vector_two_norm_squared(T const *, unsigned, S *); \
431 template VNL_EXPORT void vnl_c_vector_rms_norm(T const *, unsigned, S *); \
432 template VNL_EXPORT void vnl_c_vector_one_norm(T const *, unsigned, S *); \
433 template VNL_EXPORT void vnl_c_vector_two_norm(T const *, unsigned, S *); \
434 template VNL_EXPORT void vnl_c_vector_inf_norm(T const *, unsigned, S *)
435 
436 #undef VNL_C_VECTOR_INSTANTIATE_ordered
437 #define VNL_C_VECTOR_INSTANTIATE_ordered(T) \
438 VNL_C_VECTOR_INSTANTIATE_norm(T, vnl_c_vector<T >::abs_t); \
439 template class vnl_c_vector<T >; \
440 template VNL_EXPORT std::ostream& print_vector(std::ostream &,T const *,unsigned)
441 
442 #undef VNL_C_VECTOR_INSTANTIATE_unordered
443 #define VNL_C_VECTOR_INSTANTIATE_unordered(T) \
444 template <> T vnl_c_vector<T >::max_value(T const *, unsigned) { return T(0); } \
445 template <> T vnl_c_vector<T >::min_value(T const *, unsigned) { return T(0); } \
446 template <> unsigned vnl_c_vector<T >::arg_max(T const *, unsigned) { return 0U; } \
447 template <> unsigned vnl_c_vector<T >::arg_min(T const *, unsigned) { return 0U; } \
448 template class vnl_c_vector<T >; \
449 VNL_C_VECTOR_INSTANTIATE_norm(T, vnl_c_vector<T >::abs_t);
450 
451 #ifndef DOXYGEN_SHOULD_SKIP_THIS
452 #undef VNL_C_VECTOR_INSTANTIATE
453 #define VNL_C_VECTOR_INSTANTIATE(T) extern "no such macro; use e.g. VNL_C_VECTOR_INSTANTIATE_ordered instead"
454 #endif // DOXYGEN_SHOULD_SKIP_THIS
455 
456 #endif // vnl_c_vector_hxx_
static void deallocate(T **, const std::size_t n_when_allocated)
static VNL_SSE_FORCE_INLINE T min(const T *v, unsigned n)
Definition: vnl_sse.h:227
static void conjugate(T const *, T *, unsigned)
static VNL_SSE_FORCE_INLINE T euclid_dist_sq(const T *x, const T *y, unsigned n)
Definition: vnl_sse.h:174
static void copy(T const *x, T *y, unsigned)
y[i] = x[i].
static unsigned arg_min(T const *, unsigned)
Returns location of min value of the vector.
static void saxpy(T const &a, T const *x, T *y, unsigned)
y[i] += a*x[i].
static VNL_SSE_FORCE_INLINE unsigned arg_min(const T *v, unsigned n)
Definition: vnl_sse.h:248
VNL_EXPORT std::ostream & print_vector(std::ostream &, T const *, unsigned)
Input & output.
Templated zero/one/precision.
To allow templated algorithms to determine appropriate actions of conjugation, complexification etc.
Support for Streaming SIMD Extensions to speed up vector arithmetic.
static T sum(T const *v, unsigned n)
VNL_SSE_FORCE_INLINE void vnl_sse_dealloc(void *mem, std::size_t n, unsigned size)
Custom memory deallocation function to free 16 byte aligned of data.
Definition: vnl_sse.h:110
static VNL_SSE_FORCE_INLINE T dot_product(const T *x, const T *y, unsigned n)
Definition: vnl_sse.h:166
Namespace with standard math functions.
void vnl_c_vector_two_norm(T const *p, unsigned n, S *out)
void * vnl_c_vector_alloc(std::size_t n, unsigned size)
vnl_numeric_traits< T >::real_t real_t
Definition: vnl_c_vector.h:43
vnl_bignum squared_magnitude(vnl_bignum const &x)
Definition: vnl_bignum.h:433
static void divide(T const *x, T const *y, T *z, unsigned)
z[i] = x[i] / y[i].
static void apply(T const *, unsigned, T(*f)(T), T *v_out)
static VNL_SSE_FORCE_INLINE T sum(const T *v, unsigned n)
Definition: vnl_sse.h:209
#define v
Definition: vnl_vector.h:42
static void negate(T const *x, T *y, unsigned)
y[i] = -x[i].
static void reverse(T *x, unsigned)
void vnl_c_vector_two_norm_squared(T const *p, unsigned n, S *out)
static T sum_sq_diff_means(T const *v, unsigned n)
The sum of squared differences from the mean.
static unsigned arg_max(T const *, unsigned)
Returns location of max value of the vector.
static void fill(T *x, unsigned, T const &v)
x[i] = v.
static T min_value(T const *, unsigned)
Returns min value of the vector.
static T * allocate_T(const std::size_t n)
VNL_SSE_FORCE_INLINE void * vnl_sse_alloc(std::size_t n, unsigned size)
Custom memory allocation function to force 16 byte alignment of data.
Definition: vnl_sse.h:104
void vnl_c_vector_one_norm(T const *p, unsigned n, S *out)
static T inner_product(T const *, T const *, unsigned)
conjugate second.
static T ** allocate_Tptr(const std::size_t n)
Memory allocation.
void vnl_c_vector_dealloc(void *v, std::size_t n, unsigned size)
vnl_numeric_traits< T >::abs_t abs_t
Definition: vnl_c_vector.h:42
static T euclid_dist_sq(T const *, T const *, unsigned)
Euclidean Distance between two vectors.
static void normalize(T *, unsigned n)
vnl_bignum abs(vnl_bignum const &x)
Definition: vnl_bignum.h:432
void vnl_c_vector_inf_norm(T const *p, unsigned n, S *out)
static VNL_SSE_FORCE_INLINE T max(const T *v, unsigned n)
Definition: vnl_sse.h:217
void vnl_c_vector_construct(T *p, std::size_t n)
void vnl_c_vector_rms_norm(T const *p, unsigned n, S *out)
static VNL_SSE_FORCE_INLINE unsigned arg_max(const T *v, unsigned n)
Definition: vnl_sse.h:237
static T max_value(T const *, unsigned)
Returns max value of the vector.
static void subtract(T const *x, T const *y, T *z, unsigned)
z[i] = x[i] - y[i].
static void invert(T const *x, T *y, unsigned)
y[i] = 1/x[i].
static void add(T const *x, T const *y, T *z, unsigned)
z[i] = x[i] + y[i];.
static T dot_product(T const *, T const *, unsigned)
static void multiply(T const *x, T const *y, T *z, unsigned)
z[i] = x[i] * y[i].
void vnl_c_vector_destruct(T *p, std::size_t n)
Math on blocks of memory.
static void scale(T const *x, T *y, unsigned, T const &)
y[i] = a*x[i].