$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
metal/vec.hh
1 // Copyright (C) 2006, 2007, 2008, 2009, 2010 EPITA Research and
2 // Development Laboratory (LRDE)
3 //
4 // This file is part of Olena.
5 //
6 // Olena is free software: you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation, version 2 of the License.
9 //
10 // Olena is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
17 //
18 // As a special exception, you may use this file as part of a free
19 // software project without restriction. Specifically, if other files
20 // instantiate templates or use macros or inline functions from this
21 // file, or you compile this file and link it with other files to produce
22 // an executable, this file does not by itself cause the resulting
23 // executable to be covered by the GNU General Public License. This
24 // exception does not however invalidate any other reasons why the
25 // executable file might be covered by the GNU General Public License.
26 
27 #ifndef MLN_METAL_VEC_HH
28 # define MLN_METAL_VEC_HH
29 
33 
34 # include <iostream>
35 # include <cmath>
36 
37 # include <mln/core/concept/object.hh>
38 # include <mln/algebra/h_vec.hh>
39 
40 # include <mln/trait/all.hh>
41 # include <mln/trait/value_.hh>
42 # include <mln/fun/i2v/all_to.hh>
43 # include <mln/debug/format.hh>
44 
45 # include <mln/value/ops.hh>
46 
47 
48 // FIXME: Document.
49 
50 
51 namespace mln
52 {
53 
54  // Fwd decls.
55  namespace metal {
56  template <unsigned n, typename T> class vec;
57  }
58  namespace literal {
59  struct zero_t;
60  }
61  template <unsigned d, typename C> class h_vec;
62 
63 
64 
65  namespace trait
66  {
67 
68  template <unsigned n, typename T>
69  struct value_< mln::metal::vec<n,T> >
70  {
71  typedef trait::value::nature::vectorial nature;
72  typedef trait::value::kind::data kind;
73 
74  enum {
75  nbits = n * mln_nbits(T),
76  card = n * mln_card(T)
77  };
78  typedef mln_value_quant_from_(card) quant;
79 
80  typedef metal::vec<n, mln_sum(T)> sum;
81  };
82 
83  } // end of namespace mln::trait
84 
85 
86 
87  namespace metal
88  {
89 
90  namespace internal
91  {
92 
93  template <unsigned n, typename T>
94  class vec_base_ : public Object< vec<n,T> >
95  {
96  protected:
97  T data_[n];
98  };
99 
100  template <typename T>
101  class vec_base_ <1, T> : public Object< vec<1,T> >
102  {
103  public:
104  void set(const T& val0)
105  {
106  data_[0] = val0;
107  }
108  protected:
109  T data_[1];
110  };
111 
112  template <typename T>
113  class vec_base_ <2, T> : public Object< vec<2,T> >
114  {
115  public:
116  void set(const T& val0, const T& val1)
117  {
118  data_[0] = val0;
119  data_[1] = val1;
120  }
121  protected:
122  T data_[2];
123  };
124 
125  template <typename T>
126  class vec_base_ <3, T> : public Object< vec<3,T> >
127  {
128  public:
129  void set(const T& val0, const T& val1, const T& val2)
130  {
131  data_[0] = val0;
132  data_[1] = val1;
133  data_[2] = val2;
134  }
135  protected:
136  T data_[3];
137  };
138 
139  template <typename T>
140  class vec_base_ <4, T> : public Object< vec<4,T> >
141  {
142  public:
143  void set(const T& val0, const T& val1, const T& val2, const T& val3)
144  {
145  data_[0] = val0;
146  data_[1] = val1;
147  data_[2] = val2;
148  data_[3] = val3;
149  }
150  protected:
151  T data_[4];
152  };
153 
154 
155  } // end of namespace mln::metal::internal
156 
157 
158 
159  template <unsigned n, typename T>
160  class vec : public internal::vec_base_<n, T>
161  {
162  typedef internal::vec_base_<n, T> super_;
163 
164  protected:
165  using super_::data_;
166 
167  public:
168 
169  typedef T equiv[n];
170  typedef T enc[n];
171 
172  typedef T coord;
173  enum { dim = n };
174 
175  vec();
176 
178  vec(const literal::zero_t&);
179  vec& operator=(const literal::zero_t&);
181 
182  vec(const vec<n, T>& rhs);
183 
184  template <typename U>
185  vec(const vec<n, U>& rhs);
186 
187  template <typename U>
188  vec& operator=(const vec<n, U>& rhs);
189 
190 
191  // Immersion of the vector into its homogeneous space.
192  algebra::h_vec<n, T> to_h_vec() const;
193 
194 
195  const T& operator[](unsigned i) const;
196 
197  T& operator[](unsigned i);
198 
199  void set_all(const T& val);
200 
201  unsigned size() const;
202 
203  const vec<n, T>& normalize();
204 
206  template <typename F>
207  vec(const Function_v2v<F>& f);
208 
210  static const vec<n, T> zero;
211 
213  static const vec<n, T> origin;
214  };
215 
216  } // end of namespace mln::metal
217 
218 
219  namespace trait
220  {
221 
222  // For unary traits.
223 
224  template < template <class> class Name,
225  unsigned n, typename T >
226  struct set_precise_unary_< Name, metal::vec<n, T> >
227  {
228  typedef mln_trait_unary(Name, T) V;
229  typedef metal::vec<n, V> ret;
230  };
231 
232  // For binary traits.
233 
234  template < template <class, class> class Name,
235  unsigned n, typename T,
236  typename U >
237  struct set_precise_binary_< Name,
238  metal::vec<n, T>, metal::vec<n, U> >
239  {
240  typedef mln_trait_binary(Name, T, U) V;
241  typedef metal::vec<n, V> ret;
242  };
243 
244  template < unsigned n, typename T,
245  typename U >
246  struct set_precise_binary_< op::times,
247  metal::vec<n, T>, metal::vec<n, U> >
248  {
249  typedef mln_sum_product(T,U) ret;
250  };
251 
252  template < template <class, class> class Name,
253  unsigned n, typename T,
254  typename S >
255  struct set_precise_binary_< Name,
256  metal::vec<n, T>, mln::value::scalar_<S> >
257  {
258  typedef mln_trait_binary(Name, T, S) V;
259  typedef metal::vec<n, V> ret;
260  };
261 
262  template < template<class, class> class Name,
263  unsigned n, typename T,
264  typename S >
265  struct set_binary_< Name,
266  mln::Object, metal::vec<n, T>,
267  mln::value::Scalar, S >
268  {
269  typedef mln_trait_binary(Name, T, S) V;
270  typedef metal::vec<n, V> ret;
271  };
272 
273  } // end of namespace mln::trait
274 
275 
276 
277  namespace metal
278  {
279 
280  // eq
281 
282  template <unsigned n, typename T, typename U>
283  bool operator==(const vec<n,T>& lhs, const vec<n,U>& rhs);
284 
285  // +
286 
287  template <unsigned n, typename T, typename U>
288  vec<n, mln_trait_op_plus(T,U)>
289  operator+(const vec<n,T>& lhs, const vec<n,U>& rhs);
290 
291  // -
292 
293  template <unsigned n, typename T, typename U>
294  vec<n, mln_trait_op_minus(T,U)>
295  operator-(const vec<n,T>& lhs, const vec<n,U>& rhs);
296 
297  // vec * vec
298 
299  template <unsigned n, typename T, typename U>
300  mln_sum_product(T,U)
301  operator*(const vec<n,T>& lhs, const vec<n,U>& rhs);
302 
303  // vec * s
304 
305  template <unsigned n, typename T, typename S>
306  vec<n, mln_trait_op_times(T, S)>
307  operator*(const vec<n,T>& lhs, const mln::value::scalar_<S>& s);
308 
309  // vec / s
310 
311  template <unsigned n, typename T, typename S>
312  vec<n, mln_trait_op_div(T, S)>
313  operator/(const vec<n,T>& lhs, const mln::value::scalar_<S>& s);
314 
315  // <<
316 
317  template <unsigned n, typename T>
318  std::ostream&
319  operator<<(std::ostream& ostr, const vec<n,T>& v);
320 
321  // vprod // FIXME: Generalize...
322 
323  template <typename T, typename U>
324  vec<3, mln_trait_op_times(T,U)> // FIXME: Sum of product...
325  vprod(const vec<3, T>& lhs, const vec<3, U>& rhs);
326 
327 
328 # ifndef MLN_INCLUDE_ONLY
329 
330  template <unsigned n, typename T>
331  inline
332  vec<n,T>::vec()
333  {
334  }
335 
336  template <unsigned n, typename T>
337  inline
338  vec<n,T>::vec(const literal::zero_t&)
339  {
340  this->set_all(0);
341  }
342 
343  template <unsigned n, typename T>
344  inline
345  vec<n,T>&
346  vec<n,T>::operator=(const literal::zero_t&)
347  {
348  this->set_all(0);
349  return *this;
350  }
351 
352  template <unsigned n, typename T>
353  inline
354  vec<n,T>::vec(const vec<n,T>& rhs)
355  : super_()
356  {
357  for (unsigned i = 0; i < n; ++i)
358  data_[i] = rhs[i];
359  }
360 
361  template <unsigned n, typename T>
362  template <typename U>
363  inline
364  vec<n,T>::vec(const vec<n, U>& rhs)
365  : super_()
366  {
367  for (unsigned i = 0; i < n; ++i)
368  data_[i] = rhs[i];
369  }
370 
371  template <unsigned n, typename T>
372  template <typename U>
373  inline
374  vec<n,T>& vec<n,T>::operator=(const vec<n, U>& rhs)
375  {
376  for (unsigned i = 0; i < n; ++i)
377  data_[i] = rhs[i];
378  return *this;
379  }
380 
381  template <unsigned n, typename T>
382  inline
383  const T& vec<n,T>::operator[](unsigned i) const
384  {
385  mln_precondition(i < dim);
386  return data_[i];
387  }
388 
389  template <unsigned n, typename T>
390  inline
391  T& vec<n,T>::operator[](unsigned i)
392  {
393  mln_precondition(i < dim);
394  return data_[i];
395  }
396 
397  template <unsigned n, typename T>
398  inline
399  void vec<n,T>::set_all(const T& val)
400  {
401  for (unsigned i = 0; i < n; ++i)
402  data_[i] = val;
403  }
404 
405  template <unsigned n, typename T>
406  inline
407  unsigned vec<n,T>::size() const
408  {
409  return n;
410  }
411 
412  template <unsigned n, typename T>
413  inline
414  const vec<n, T>& vec<n, T>::normalize()
415  {
416  float n_l2 = 0;
417  for (unsigned i = 0; i < n; ++i)
418  n_l2 += data_[i] * data_[i];
419  n_l2 = sqrt(n_l2);
420  for (unsigned i = 0; i < n; ++i)
421  data_[i] = T(data_[i] / n_l2);
422  return *this;
423  }
424 
425  template <unsigned n, typename T>
426  template <typename F>
427  inline
428  vec<n, T>::vec(const Function_v2v<F>& f_)
429  {
430  mlc_converts_to(mln_result(F), T)::check();
431  const F& f = exact(f_);
432  for (unsigned i = 0; i < n; ++i)
433  data_[i] = f(i);
434  }
435 
436 
437  template <unsigned n, typename T>
438  const vec<n, T> vec<n, T>::zero = all_to(0);
439 
440  template <unsigned n, typename T>
441  const vec<n, T> vec<n, T>::origin = all_to(0);
442 
443 
444  // Operators.
445 
446 
447  template <unsigned n, typename T, typename U>
448  inline
449  bool operator==(const vec<n,T>& lhs, const vec<n,U>& rhs)
450  {
451  for (unsigned i = 0; i < n; ++i)
452  if (lhs[i] != rhs[i])
453  return false;
454  return true;
455  }
456 
457 
458  template <unsigned n, typename T, typename U>
459  inline
460  vec<n, mln_trait_op_plus(T,U)>
461  operator+(const vec<n,T>& lhs, const vec<n,U>& rhs)
462  {
463  vec<n, mln_trait_op_plus(T,U)> tmp;
464  for (unsigned i = 0; i < n; ++i)
465  tmp[i] = lhs[i] + rhs[i];
466  return tmp;
467  }
468 
469  template <unsigned n, typename T, typename U>
470  inline
471  vec<n, mln_trait_op_minus(T,U)>
472  operator-(const vec<n,T>& lhs, const vec<n,U>& rhs)
473  {
474  vec<n, mln_trait_op_minus(T,U)> tmp;
475  for (unsigned i = 0; i < n; ++i)
476  tmp[i] = lhs[i] - rhs[i];
477  return tmp;
478  }
479 
480  template <unsigned n, typename T, typename U>
481  inline
482  mln_sum_product(T,U)
483  operator*(const vec<n,T>& lhs, const vec<n,U>& rhs)
484  {
485  mln_sum_product(T,U) tmp(literal::zero);
486  for (unsigned i = 0; i < n; ++i)
487  tmp += lhs[i] * rhs[i];
488  return tmp;
489  }
490 
491  template <unsigned n, typename T, typename S>
492  inline
493  vec<n, mln_trait_op_times(T, S)>
494  operator*(const vec<n,T>& lhs, const mln::value::scalar_<S>& s)
495  {
496  // FIXME: We made a choice here but is it correct?
497  // FIXME: We "un-scalar" s so that the scalar status do not propagate.
498 
499  // Think of the case: vec<mat> v * scalar(vec w) s
500  // It gives: for all i, v[i] * w so the i-th mat * vec w -> vec
501  // The result is a vec<vec>
502 
503  // If we really want to propage the "scalar" status then
504  // we shall allow for scalar(scalar(..)) !!! => FIXME
505 
506  vec<n, mln_trait_op_times(T, S)> tmp;
507  for (unsigned i = 0; i < n; ++i)
508  tmp[i] = lhs[i] * s.to_equiv();
509  return tmp;
510  }
511 
512  template <unsigned n, typename T, typename S>
513  inline
514  vec<n, mln_trait_op_div(T, S)>
515  operator/(const vec<n,T>& lhs, const mln::value::scalar_<S>& s)
516  {
517  mln_precondition(value::equiv(s) != literal::zero);
518  vec<n, mln_trait_op_div(T, S)> tmp;
519  for (unsigned i = 0; i < n; ++i)
520  tmp[i] = lhs[i] / s.to_equiv();
521  return tmp;
522  }
523 
524 
525  template <unsigned n, typename T>
526  inline
527  std::ostream&
528  operator<<(std::ostream& ostr, const vec<n,T>& v)
529  {
530  ostr << '(';
531  for (unsigned i = 0; i < n; ++i)
532  ostr << debug::format(v[i]) << (i == n - 1 ? ")" : ", ");
533  return ostr;
534  }
535 
536  // vprod
537 
538  template <typename T, typename U>
539  inline
540  vec<3, mln_trait_op_times(T,U)> // FIXME: typename binary_arith_trait<T, U>::ret>
541  vprod(const vec<3, T>& lhs, const vec<3, U>& rhs)
542  {
543  vec<3, mln_trait_op_times(T,U)> tmp; // FIXME: Likewise.
544  tmp[0] = lhs[1] * rhs[2] - lhs[2] * rhs[1];
545  tmp[1] = lhs[2] * rhs[0] - lhs[0] * rhs[2];
546  tmp[2] = lhs[0] * rhs[1] - lhs[1] * rhs[0];
547  return tmp;
548  }
549 
550 # endif // MLN_INCLUDE_ONLY
551 
552  } // end of namespace mln::metal
553 
554 } // end of namespace mln
555 
556 
557 # include <mln/make/vec.hh>
558 
559 
560 #endif // ! MLN_METAL_VEC_HH