Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
algebra/vec.hh
1 // Copyright (C) 2006, 2008, 2009, 2011 EPITA Research and Development
2 // 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_ALGEBRA_VEC_HH
28 # define MLN_ALGEBRA_VEC_HH
29 
33 
34 # include <iostream>
35 # include <cmath>
36 
37 # include <mln/core/concept/object.hh>
38 
39 # include <mln/literal/zero.hh>
40 # include <mln/literal/origin.hh>
41 # include <mln/norm/l2.hh>
42 # include <mln/trait/all.hh>
43 # include <mln/trait/value_.hh>
44 # include <mln/fun/i2v/all_to.hh>
45 # include <mln/debug/format.hh>
46 
47 # include <mln/value/ops.hh>
48 
49 
50 // FIXME: Document.
51 
52 
53 namespace mln
54 {
55 
56  // Forward declarations.
57  namespace algebra {
58  template <unsigned n, typename T> class vec;
59  template <unsigned d, typename C> class h_vec;
60  template <unsigned n, unsigned m, typename T> class mat;
61  }
62 
63  namespace literal {
64  struct zero_t;
65  }
66 
67  namespace norm {
68  template <unsigned n, typename C>
69  mln_sum_product(C,C) l2(const algebra::vec<n,C>& vec);
70  }
71 
72 
73  namespace trait
74  {
75 
76  template <unsigned n, typename T>
77  struct value_< mln::algebra::vec<n,T> >
78  {
79  typedef trait::value::nature::vectorial nature;
80  typedef trait::value::kind::data kind;
81 
82  enum {
83  dim = n,
84  nbits = n * mln_nbits(T),
85  card = n * mln_card(T)
86  };
87  typedef T comp;
88  typedef mln_value_quant_from_(card) quant;
89  typedef algebra::vec<n, mln_sum(T)> sum;
90  };
91 
92  template <unsigned n, typename T>
93  struct set_precise_unary_< op::ord, mln::algebra::vec<n,T> >
94  {
95  typedef mln::internal::ord_vec< mln::algebra::vec<n,T> > ret;
96  };
97 
98  } // end of namespace mln::trait
99 
100 
101 
102  namespace algebra
103  {
104 
105  namespace internal
106  {
107 
108  template <unsigned n, typename T>
109  class vec_base_ : public Object< vec<n,T> >
110  {
111  protected:
112  T data_[n];
113  };
114 
115  template <typename T>
116  class vec_base_ <1, T> : public Object< vec<1,T> >
117  {
118  public:
119  void set(const T& val0)
120  {
121  data_[0] = val0;
122  }
123  protected:
124  T data_[1];
125  };
126 
127  template <typename T>
128  class vec_base_ <2, T> : public Object< vec<2,T> >
129  {
130  public:
131  void set(const T& val0, const T& val1)
132  {
133  data_[0] = val0;
134  data_[1] = val1;
135  }
136  protected:
137  T data_[2];
138  };
139 
140  template <typename T>
141  class vec_base_ <3, T> : public Object< vec<3,T> >
142  {
143  public:
144  void set(const T& val0, const T& val1, const T& val2)
145  {
146  data_[0] = val0;
147  data_[1] = val1;
148  data_[2] = val2;
149  }
150  protected:
151  T data_[3];
152  };
153 
154  template <typename T>
155  class vec_base_ <4, T> : public Object< vec<4,T> >
156  {
157  public:
158  void set(const T& val0, const T& val1, const T& val2, const T& val3)
159  {
160  data_[0] = val0;
161  data_[1] = val1;
162  data_[2] = val2;
163  data_[3] = val3;
164  }
165  protected:
166  T data_[4];
167  };
168 
169 
170  } // end of namespace mln::algebra::internal
171 
172 
173 
174  template <unsigned n, typename T>
175  class vec : public internal::vec_base_<n, T>
176  {
177  typedef internal::vec_base_<n, T> super_;
178 
179  protected:
180  using super_::data_;
181 
182  public:
183 
184  typedef T equiv[n];
185  typedef T enc[n];
186 
187  typedef T coord;
188  enum { dim = n };
189 
190  vec();
191 
193  vec(const literal::zero_t&);
194  vec& operator=(const literal::zero_t&);
196 
198  vec(const literal::origin_t&);
199  vec& operator=(const literal::origin_t&);
201 
202  vec(const vec<n, T>& rhs);
203 
204  template <typename U>
205  vec(const vec<n, U>& rhs);
206 
207  template <typename U>
208  vec& operator=(const vec<n, U>& rhs);
209 
210 
211  // Immersion of the vector into its homogeneous space.
212  algebra::h_vec<n, T> to_h_vec() const;
213 
214 
215  const T& operator[](unsigned i) const;
216 
217  T& operator[](unsigned i);
218 
219  void set_all(const T& val);
220 
221  unsigned size() const;
222 
223  /* FIXME: What if the vector is null? Even if we choose not to
224  handle this case, we should *state* in the documentation the
225  behavior of this method.
226 
227  I (Roland) have added an assertion to detect ``erroneous''
228  cases, but we might want something different.
229  ``Implementation defined'' or ``undefined behavior'' is fine
230  by me, as long as the documentation mentions it.
231 
232  FWIW, Trimesh's developers chose to set all the coordinates
233  of a vector being normalized to 1, when it norm is equal or
234  lower (sic) to zero. */
235  const vec<n, T>& normalize();
236 
238  mat<1, n, T> t() const;
239 
241  template <typename F>
242  vec(const Function_v2v<F>& f);
243 
245  static const vec<n, T> zero;
246 
248  static const vec<n, T> origin;
249 
250 
252  template <typename U>
253  operator mat<n, 1, U>() const;
254 
256  template <typename U>
257  vec(const mat<n, 1, U>& rhs);
258 
260  template <typename U>
261  vec& operator=(const mat<n, 1, U>& rhs);
262  };
263 
264  } // end of namespace mln::algebra
265 
266 
267 
268  namespace trait
269  {
270 
271  // For unary traits.
272 
273 
274  template < template <class> class Name,
275  unsigned n, typename T >
276  struct set_precise_unary_< Name, algebra::vec<n, T> >
277  {
278  typedef mln_trait_unary(Name, T) V;
279  typedef algebra::vec<n, V> ret;
280  };
281 
282 
283  // For binary traits.
284 
285 
286  // vec + vec
287 
288  template < unsigned n, typename T,
289  typename U >
290  struct set_precise_binary_< op::plus,
291  algebra::vec<n, T>, algebra::vec<n, U> >
292  {
293  typedef mln_trait_op_plus(T, U) V;
294  typedef algebra::vec<n, V> ret;
295  };
296 
297  // - vec
298 
299  template < unsigned n, typename T >
300  struct set_precise_unary_< op::uminus,
301  algebra::vec<n, T> >
302  {
303  typedef mln_trait_op_uminus(T) V;
304  typedef algebra::vec<n, V> ret;
305  };
306 
307  // vec - vec
308 
309  template < unsigned n, typename T,
310  typename U >
311  struct set_precise_binary_< op::minus,
312  algebra::vec<n, T>, algebra::vec<n, U> >
313  {
314  typedef mln_trait_op_minus(T, U) V;
315  typedef algebra::vec<n, V> ret;
316  };
317 
318  // vec * vec
319 
320  template < unsigned n, typename T,
321  typename U >
322  struct set_precise_binary_< op::times,
323  algebra::vec<n, T>, algebra::vec<n, U> >
324  {
325  typedef mln_sum_product(T,U) ret;
326  };
327 
328  // vec * s
329 
330  template < unsigned n, typename T,
331  typename S >
332  struct set_precise_binary_< op::times,
333  algebra::vec<n, T>, mln::value::scalar_<S> >
334  {
335  typedef mln_trait_op_times(T, S) V;
336  typedef algebra::vec<n, V> ret;
337  };
338 
339  // vec / s
340 
341  template < unsigned n, typename T,
342  typename S >
343  struct set_precise_binary_< op::div,
344  algebra::vec<n, T>, mln::value::scalar_<S> >
345  {
346  typedef mln_trait_op_div(T, S) V;
347  typedef algebra::vec<n, V> ret;
348  };
349 
350 // template < template<class, class> class Name,
351 // unsigned n, typename T,
352 // typename S >
353 // struct set_binary_< Name,
354 // mln::Object, algebra::vec<n, T>,
355 // mln::value::Scalar, S >
356 // {
357 // typedef mln_trait_binary(Name, T, S) V;
358 // typedef algebra::vec<n, V> ret;
359 // };
360 
361  } // end of namespace mln::trait
362 
363 
364 
365  namespace algebra
366  {
367 
368  // vec == vec
369 
370  template <unsigned n, typename T, typename U>
371  bool
372  operator==(const vec<n,T>& lhs, const vec<n,U>& rhs);
373 
374  // vec + vec
375 
376  template <unsigned n, typename T, typename U>
377  vec<n, mln_trait_op_plus(T,U)>
378  operator+(const vec<n,T>& lhs, const vec<n,U>& rhs);
379 
380  // - vec
381 
382  template <unsigned n, typename T>
383  vec<n, mln_trait_op_uminus(T)>
384  operator-(const vec<n,T>& rhs);
385 
386  // vec - vec
387 
388  template <unsigned n, typename T, typename U>
389  vec<n, mln_trait_op_minus(T,U)>
390  operator-(const vec<n,T>& lhs, const vec<n,U>& rhs);
391 
392  // vec * vec
393 
395  template <unsigned n, typename T, typename U>
396  mln_sum_product(T,U)
397  operator*(const vec<n,T>& lhs, const vec<n,U>& rhs);
398 
399  // vec * s
400 
401  template <unsigned n, typename T, typename S>
402  vec<n, mln_trait_op_times(T, S)>
403  operator*(const vec<n,T>& lhs, const mln::value::scalar_<S>& s);
404 
405  // vec / s
406 
407  template <unsigned n, typename T, typename S>
408  vec<n, mln_trait_op_div(T, S)>
409  operator/(const vec<n,T>& lhs, const mln::value::scalar_<S>& s);
410 
411  // <<
412 
413  template <unsigned n, typename T>
414  std::ostream&
415  operator<<(std::ostream& ostr, const vec<n,T>& v);
416 
417  // >>
418 
419  template <unsigned n, typename T>
420  std::istream&
421  operator>>(std::istream& istr, vec<n,T>& v);
422 
423  // vprod // FIXME: Generalize...
424 
426  template <typename T, typename U>
427  vec<3, mln_trait_op_times(T,U)> // FIXME: Sum of product...
428  vprod(const vec<3, T>& lhs, const vec<3, U>& rhs);
429 
430  } // end of namespace mln::algebra
431 
432 
433 
434 
435 # ifndef MLN_INCLUDE_ONLY
436 
437  namespace algebra
438  {
439 
440  template <unsigned n, typename T>
441  inline
442  vec<n,T>::vec()
443  {
444  }
445 
446  template <unsigned n, typename T>
447  inline
448  vec<n,T>::vec(const literal::zero_t&)
449  {
450  this->set_all(0);
451  }
452 
453  template <unsigned n, typename T>
454  inline
455  vec<n,T>&
456  vec<n,T>::operator=(const literal::zero_t&)
457  {
458  this->set_all(0);
459  return *this;
460  }
461 
462  template <unsigned n, typename T>
463  inline
464  vec<n,T>::vec(const literal::origin_t&)
465  {
466  this->set_all(0);
467  }
468 
469  template <unsigned n, typename T>
470  inline
471  vec<n,T>&
472  vec<n,T>::operator=(const literal::origin_t&)
473  {
474  this->set_all(0);
475  return *this;
476  }
477 
478  template <unsigned n, typename T>
479  inline
480  vec<n,T>::vec(const vec<n,T>& rhs)
481  : super_()
482  {
483  for (unsigned i = 0; i < n; ++i)
484  data_[i] = rhs[i];
485  }
486 
487  template <unsigned n, typename T>
488  template <typename U>
489  inline
490  vec<n,T>::vec(const vec<n, U>& rhs)
491  : super_()
492  {
493  mlc_converts_to(U, T)::check();
494  for (unsigned i = 0; i < n; ++i)
495  data_[i] = static_cast<T>(rhs[i]);
496  }
497 
498  template <unsigned n, typename T>
499  template <typename U>
500  inline
501  vec<n,T>& vec<n,T>::operator=(const vec<n, U>& rhs)
502  {
503  mlc_converts_to(U, T)::check();
504  for (unsigned i = 0; i < n; ++i)
505  data_[i] = static_cast<T>(rhs[i]);
506  return *this;
507  }
508 
509  template <unsigned n, typename T>
510  inline
511  const T& vec<n,T>::operator[](unsigned i) const
512  {
513  mln_precondition(i < dim);
514  return data_[i];
515  }
516 
517  template <unsigned n, typename T>
518  inline
519  T& vec<n,T>::operator[](unsigned i)
520  {
521  mln_precondition(i < dim);
522  return data_[i];
523  }
524 
525  template <unsigned n, typename T>
526  inline
527  void vec<n,T>::set_all(const T& val)
528  {
529  for (unsigned i = 0; i < n; ++i)
530  data_[i] = val;
531  }
532 
533  template <unsigned n, typename T>
534  inline
535  unsigned vec<n,T>::size() const
536  {
537  return n;
538  }
539 
540  template <unsigned n, typename T>
541  inline
542  const vec<n, T>& vec<n, T>::normalize()
543  {
544  mln_sum_product(T,T) l2_norm = norm::l2(*this);
545  mln_assertion(l2_norm > mln_sum_product(T,T)(0));
546  for (unsigned i = 0; i < n; ++i)
547  data_[i] = static_cast<T>(data_[i] / l2_norm);
548  return *this;
549  }
550 
551  template <unsigned n, typename T>
552  template <typename F>
553  inline
554  vec<n, T>::vec(const Function_v2v<F>& f_)
555  {
556  mlc_converts_to(mln_result(F), T)::check();
557  const F& f = exact(f_);
558  for (unsigned i = 0; i < n; ++i)
559  data_[i] = static_cast<T>(f(i));
560  }
561 
562 
563  template <unsigned n, typename T>
564  const vec<n, T> vec<n, T>::zero = all_to(0);
565 
566  template <unsigned n, typename T>
567  const vec<n, T> vec<n, T>::origin = all_to(0);
568 
569 
570 
571  // Operators.
572 
573 
574  // vec == vec
575 
576  template <unsigned n, typename T, typename U>
577  inline
578  bool operator==(const vec<n,T>& lhs, const vec<n,U>& rhs)
579  {
580  for (unsigned i = 0; i < n; ++i)
581  if (lhs[i] != rhs[i])
582  return false;
583  return true;
584  }
585 
586  // vec + vec
587 
588  template <unsigned n, typename T, typename U>
589  inline
590  vec<n, mln_trait_op_plus(T,U)>
591  operator+(const vec<n,T>& lhs, const vec<n,U>& rhs)
592  {
593  typedef mln_trait_op_plus(T,U) R;
594  vec<n, R> tmp;
595  for (unsigned i = 0; i < n; ++i)
596  tmp[i] = lhs[i] + rhs[i];
597  return tmp;
598  }
599 
600  // - vec
601 
602  template <unsigned n, typename T>
603  inline
604  vec<n, mln_trait_op_uminus(T)>
605  operator-(const vec<n,T>& rhs)
606  {
607  typedef mln_trait_op_uminus(T) R;
608  vec<n, R> tmp;
609  for (unsigned i = 0; i < n; ++i)
610  tmp[i] = - rhs[i];
611  return tmp;
612  }
613 
614  // vec - vec
615 
616  template <unsigned n, typename T, typename U>
617  inline
618  vec<n, mln_trait_op_minus(T,U)>
619  operator-(const vec<n,T>& lhs, const vec<n,U>& rhs)
620  {
621  typedef mln_trait_op_minus(T,U) R;
622  vec<n, R> tmp;
623  for (unsigned i = 0; i < n; ++i)
624  tmp[i] = lhs[i] - rhs[i];
625  return tmp;
626  }
627 
628  // vec * vec
629 
630  template <unsigned n, typename T, typename U>
631  inline
632  mln_sum_product(T,U)
633  operator*(const vec<n,T>& lhs, const vec<n,U>& rhs)
634  {
635  typedef mln_sum_product(T,U) R;
636  mln_sum_product(T,U) tmp(literal::zero);
637  for (unsigned i = 0; i < n; ++i)
638  tmp += lhs[i] * rhs[i];
639  return tmp;
640  }
641 
642  // vec * s
643 
644  template <unsigned n, typename T, typename S>
645  inline
646  vec<n, mln_trait_op_times(T, S)>
647  operator*(const vec<n,T>& lhs, const mln::value::scalar_<S>& s)
648  {
649  // FIXME: We made a choice here but is it correct?
650  // FIXME: We "un-scalar" s so that the scalar status do not propagate.
651 
652  // Think of the case: vec<mat> v * scalar(vec w) s
653  // It gives: for all i, v[i] * w so the i-th mat * vec w -> vec
654  // The result is a vec<vec>
655 
656  // If we really want to propage the "scalar" status then
657  // we shall allow for scalar(scalar(..)) !!! => FIXME
658 
659  typedef mln_trait_op_times(T, S) R;
660  vec<n, R> tmp;
661  for (unsigned i = 0; i < n; ++i)
662  tmp[i] = lhs[i] * s.to_equiv();
663  return tmp;
664  }
665 
666  // vec / s
667 
668  template <unsigned n, typename T, typename S>
669  inline
670  vec<n, mln_trait_op_div(T, S)>
671  operator/(const vec<n,T>& lhs, const mln::value::scalar_<S>& s)
672  {
673  mln_precondition(value::equiv(s) != (S)(literal::zero));
674  typedef mln_trait_op_div(T, S) R;
675  vec<n, R> tmp;
676  for (unsigned i = 0; i < n; ++i)
677  tmp[i] = lhs[i] / s.to_equiv();
678  return tmp;
679  }
680 
681 
682  // << v
683 
684  template <unsigned n, typename T>
685  inline
686  std::ostream&
687  operator<<(std::ostream& ostr, const vec<n,T>& v)
688  {
689  ostr << '(';
690  for (unsigned i = 0; i < n; ++i)
691  ostr << debug::format(v[i]) << (i == n - 1 ? ")" : ", ");
692  return ostr;
693  }
694 
695 
696  // >> v
697 
698  template <unsigned n, typename T>
699  inline
700  std::istream&
701  operator>>(std::istream& istr, vec<n,T>& v)
702  {
703  for (unsigned i = 0; i < n; ++i)
704  istr >> v[i];
705  return istr;
706  }
707 
708 
709  // vprod
710 
711  template <typename T, typename U>
712  inline
713  vec<3, mln_trait_op_times(T,U)> // FIXME: typename binary_arith_trait<T, U>::ret>
714  vprod(const vec<3, T>& lhs, const vec<3, U>& rhs)
715  {
716  vec<3, mln_trait_op_times(T,U)> tmp; // FIXME: Likewise.
717  tmp[0] = lhs[1] * rhs[2] - lhs[2] * rhs[1];
718  tmp[1] = lhs[2] * rhs[0] - lhs[0] * rhs[2];
719  tmp[2] = lhs[0] * rhs[1] - lhs[1] * rhs[0];
720  return tmp;
721  }
722 
723 
724  template <typename P>
725  inline
726  P
727  to_point(const vec<P::dim,float>& v)
728  {
729  P tmp;
730  for (unsigned i = 0; i < P::dim; ++i)
731  tmp[i] = round(v[i]);
732  return tmp;
733  }
734 
735 
736  } // end of namespace mln::algebra
737 
738 
739 # endif // MLN_INCLUDE_ONLY
740 
741 } // end of namespace mln
742 
743 
744 # include <mln/make/vec.hh>
745 # include <mln/algebra/mat.hh>
746 
747 
748 #endif // ! MLN_ALGEBRA_VEC_HH