$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
algebra/vec.hh
1 // Copyright (C) 2006, 2008, 2009, 2011, 2012 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_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  namespace value {
73  template <unsigned n> struct rgb;
74  }
75 
76  template <typename G, typename C> struct point;
77  template <typename E> struct Gpoint;
78  // end of forward declarations
79 
80 
81  namespace trait
82  {
83 
84  template <unsigned n, typename T>
85  struct value_< mln::algebra::vec<n,T> >
86  {
87  typedef trait::value::nature::vectorial nature;
88  typedef trait::value::kind::data kind;
89 
90  enum {
91  dim = n,
92  nbits = n * mln_nbits(T),
93  card = n * mln_card(T)
94  };
95  typedef T comp;
96  typedef mln_value_quant_from_(card) quant;
97  typedef algebra::vec<n, mln_sum(T)> sum;
98  };
99 
100  template <unsigned n, typename T>
101  struct set_precise_unary_< op::ord, mln::algebra::vec<n,T> >
102  {
104  };
105 
106  } // end of namespace mln::trait
107 
108 
109 
110  namespace algebra
111  {
112 
113  namespace internal
114  {
115 
116  template <unsigned n, typename T>
117  class vec_base_ : public Object< vec<n,T> >
118  {
119  protected:
120  T data_[n];
121  };
122 
123  template <typename T>
124  class vec_base_ <1, T> : public Object< vec<1,T> >
125  {
126  public:
127  void set(const T& val0)
128  {
129  data_[0] = val0;
130  }
131  protected:
132  T data_[1];
133  };
134 
135  template <typename T>
136  class vec_base_ <2, T> : public Object< vec<2,T> >
137  {
138  public:
139  void set(const T& val0, const T& val1)
140  {
141  data_[0] = val0;
142  data_[1] = val1;
143  }
144  protected:
145  T data_[2];
146  };
147 
148  template <typename T>
149  class vec_base_ <3, T> : public Object< vec<3,T> >
150  {
151  public:
152  void set(const T& val0, const T& val1, const T& val2)
153  {
154  data_[0] = val0;
155  data_[1] = val1;
156  data_[2] = val2;
157  }
158  protected:
159  T data_[3];
160  };
161 
162  template <typename T>
163  class vec_base_ <4, T> : public Object< vec<4,T> >
164  {
165  public:
166  void set(const T& val0, const T& val1, const T& val2, const T& val3)
167  {
168  data_[0] = val0;
169  data_[1] = val1;
170  data_[2] = val2;
171  data_[3] = val3;
172  }
173  protected:
174  T data_[4];
175  };
176 
177 
178  } // end of namespace mln::algebra::internal
179 
180 
184  template <unsigned n, typename T>
185  class vec : public internal::vec_base_<n, T>
186  {
188 
189  protected:
190  using super_::data_;
191 
192  public:
193 
194  typedef T equiv[n];
195  typedef T enc[n];
196 
197  typedef T coord;
198  enum { dim = n };
199 
200  vec();
201 
203  vec(const literal::zero_t&);
204  vec& operator=(const literal::zero_t&);
206 
208  vec(const literal::origin_t&);
209  vec& operator=(const literal::origin_t&);
211 
212  vec(const vec<n, T>& rhs);
213 
214  template <typename U>
215  vec(const vec<n, U>& rhs);
216 
217  template <typename U>
218  vec& operator=(const vec<n, U>& rhs);
219 
220 
221  // Immersion of the vector into its homogeneous space.
222  algebra::h_vec<n, T> to_h_vec() const;
223 
224 
225  const T& operator[](unsigned i) const;
226 
227  T& operator[](unsigned i);
228 
229  void set_all(const T& val);
230 
231  unsigned size() const;
232 
233  /* FIXME: What if the vector is null? Even if we choose not to
234  handle this case, we should *state* in the documentation the
235  behavior of this method.
236 
237  I (Roland) have added an assertion to detect ``erroneous''
238  cases, but we might want something different.
239  ``Implementation defined'' or ``undefined behavior'' is fine
240  by me, as long as the documentation mentions it.
241 
242  FWIW, Trimesh's developers chose to set all the coordinates
243  of a vector being normalized to 1, when it norm is equal or
244  lower (sic) to zero. */
245  const vec<n, T>& normalize();
246 
248  mat<1, n, T> t() const;
249 
251  template <typename F>
252  vec(const Function_v2v<F>& f);
253 
255  static const vec<n, T> zero;
256 
258  static const vec<n, T> origin;
259 
260 
262  template <typename U>
263  operator mat<n, 1, U>() const;
264 
266  template <typename U>
267  vec(const mat<n, 1, U>& rhs);
268 
270  template <typename U>
271  vec& operator=(const mat<n, 1, U>& rhs);
272  };
273 
274 
276  template <typename T, unsigned m>
277  void from_to_(const vec<3,T>& from, value::rgb<m>& to_);
278 
280  template <typename C1, typename G, typename C2>
281  inline
282  void
283  from_to_(const vec<1,C1>& from, point<G,C2>& to);
284 
286  template <unsigned n, typename C1, typename G, typename C2>
287  void
288  from_to_(const vec<n,C1>& from, point<G,C2>& to);
289 
291  template <typename C1, typename G>
292  inline
293  void
294  from_to_(const vec<1,C1>& from, point<G,C1>& to);
295 
297  template <unsigned n, typename C1, typename G>
298  void
299  from_to_(const vec<n,C1>& from, point<G,C1>& to);
300 
302  template <unsigned n, typename T, typename P>
303  void
304  from_to_(const vec<n,T>& from, Gpoint<P>& to);
305 
306  } // end of namespace mln::algebra
307 
308 
309 
310  namespace trait
311  {
312 
313  // For unary traits.
314 
315 
316  template < template <class> class Name,
317  unsigned n, typename T >
318  struct set_precise_unary_< Name, algebra::vec<n, T> >
319  {
320  typedef mln_trait_unary(Name, T) V;
321  typedef algebra::vec<n, V> ret;
322  };
323 
324 
325  // For binary traits.
326 
327 
328  // vec + vec
329 
330  template < unsigned n, typename T,
331  typename U >
332  struct set_precise_binary_< op::plus,
333  algebra::vec<n, T>, algebra::vec<n, U> >
334  {
335  typedef mln_trait_op_plus(T, U) V;
336  typedef algebra::vec<n, V> ret;
337  };
338 
339  // - vec
340 
341  template < unsigned n, typename T >
342  struct set_precise_unary_< op::uminus,
343  algebra::vec<n, T> >
344  {
345  typedef mln_trait_op_uminus(T) V;
346  typedef algebra::vec<n, V> ret;
347  };
348 
349  // vec - vec
350 
351  template < unsigned n, typename T,
352  typename U >
353  struct set_precise_binary_< op::minus,
354  algebra::vec<n, T>, algebra::vec<n, U> >
355  {
356  typedef mln_trait_op_minus(T, U) V;
357  typedef algebra::vec<n, V> ret;
358  };
359 
360  // vec * vec
361 
362  template < unsigned n, typename T,
363  typename U >
364  struct set_precise_binary_< op::times,
365  algebra::vec<n, T>, algebra::vec<n, U> >
366  {
367  typedef mln_sum_product(T,U) ret;
368  };
369 
370  // vec * s
371 
372  template < unsigned n, typename T,
373  typename S >
374  struct set_precise_binary_< op::times,
375  algebra::vec<n, T>, mln::value::scalar_<S> >
376  {
377  typedef mln_trait_op_times(T, S) V;
378  typedef algebra::vec<n, V> ret;
379  };
380 
381  // vec / s
382 
383  template < unsigned n, typename T,
384  typename S >
385  struct set_precise_binary_< op::div,
386  algebra::vec<n, T>, mln::value::scalar_<S> >
387  {
388  typedef mln_trait_op_div(T, S) V;
389  typedef algebra::vec<n, V> ret;
390  };
391 
392 // template < template<class, class> class Name,
393 // unsigned n, typename T,
394 // typename S >
395 // struct set_binary_< Name,
396 // mln::Object, algebra::vec<n, T>,
397 // mln::value::Scalar, S >
398 // {
399 // typedef mln_trait_binary(Name, T, S) V;
400 // typedef algebra::vec<n, V> ret;
401 // };
402 
403  } // end of namespace mln::trait
404 
405 
406 
407  namespace algebra
408  {
409 
410  // vec == vec
411 
412  template <unsigned n, typename T, typename U>
413  bool
414  operator==(const vec<n,T>& lhs, const vec<n,U>& rhs);
415 
416  // vec + vec
417 
418  template <unsigned n, typename T, typename U>
419  vec<n, mln_trait_op_plus(T,U)>
420  operator+(const vec<n,T>& lhs, const vec<n,U>& rhs);
421 
422  // - vec
423 
424  template <unsigned n, typename T>
425  vec<n, mln_trait_op_uminus(T)>
426  operator-(const vec<n,T>& rhs);
427 
428  // vec - vec
429 
430  template <unsigned n, typename T, typename U>
431  vec<n, mln_trait_op_minus(T,U)>
432  operator-(const vec<n,T>& lhs, const vec<n,U>& rhs);
433 
434  // vec * vec
435 
437  template <unsigned n, typename T, typename U>
438  mln_sum_product(T,U)
439  operator*(const vec<n,T>& lhs, const vec<n,U>& rhs);
440 
441  // vec * s
442 
443  template <unsigned n, typename T, typename S>
444  vec<n, mln_trait_op_times(T, S)>
445  operator*(const vec<n,T>& lhs, const mln::value::scalar_<S>& s);
446 
447  // vec / s
448 
449  template <unsigned n, typename T, typename S>
450  vec<n, mln_trait_op_div(T, S)>
451  operator/(const vec<n,T>& lhs, const mln::value::scalar_<S>& s);
452 
453  // <<
454 
455  template <unsigned n, typename T>
456  std::ostream&
457  operator<<(std::ostream& ostr, const vec<n,T>& v);
458 
459  // >>
460 
461  template <unsigned n, typename T>
462  std::istream&
463  operator>>(std::istream& istr, vec<n,T>& v);
464 
465  // vprod // FIXME: Generalize...
466 
468  template <typename T, typename U>
469  vec<3, mln_trait_op_times(T,U)> // FIXME: Sum of product...
470  vprod(const vec<3, T>& lhs, const vec<3, U>& rhs);
471 
472  } // end of namespace mln::algebra
473 
474 
475 
476 
477 # ifndef MLN_INCLUDE_ONLY
478 
479  namespace internal
480  {
481 
482  template <typename C, typename C2>
483  inline
484  C
485  convert_data_(metal::bool_<false>, const C2& v)
486  {
487  return static_cast<C>(v);
488  }
489 
490  template <typename C, typename C2>
491  inline
492  C
493  convert_data_(metal::bool_<true>, const C2& v)
494  {
495  return static_cast<C>(round(v));
496  }
497 
498  template <typename C, typename C2>
499  inline
500  C
501  convert_data(const C2& v)
502  {
503  // If (C != float && C != double) && (C2 == float || C2 == double)
504  // => We want to round the value.
505  // Otherwise we can just statically cast.
506  //
507  return convert_data_<C>(
508  typename mlc_and(
509  mlc_and(mlc_is_not(C,float),
510  mlc_is_not(C,double)),
511  mlc_or(mlc_is(C2,float),
512  mlc_is(C2, double)))::eval(), v);
513  }
514 
515  } // end of namespace mln::internal
516 
517 
518 
519  namespace algebra
520  {
521 
522  template <unsigned n, typename T>
523  inline
524  vec<n,T>::vec()
525  {
526  }
527 
528  template <unsigned n, typename T>
529  inline
530  vec<n,T>::vec(const literal::zero_t&)
531  {
532  this->set_all(0);
533  }
534 
535  template <unsigned n, typename T>
536  inline
537  vec<n,T>&
538  vec<n,T>::operator=(const literal::zero_t&)
539  {
540  this->set_all(0);
541  return *this;
542  }
543 
544  template <unsigned n, typename T>
545  inline
546  vec<n,T>::vec(const literal::origin_t&)
547  {
548  this->set_all(0);
549  }
550 
551  template <unsigned n, typename T>
552  inline
553  vec<n,T>&
554  vec<n,T>::operator=(const literal::origin_t&)
555  {
556  this->set_all(0);
557  return *this;
558  }
559 
560  template <unsigned n, typename T>
561  inline
562  vec<n,T>::vec(const vec<n,T>& rhs)
563  : super_()
564  {
565  for (unsigned i = 0; i < n; ++i)
566  data_[i] = rhs[i];
567  }
568 
569  template <unsigned n, typename T>
570  template <typename U>
571  inline
572  vec<n,T>::vec(const vec<n, U>& rhs)
573  : super_()
574  {
575  mlc_converts_to(U, T)::check();
576  for (unsigned i = 0; i < n; ++i)
577  data_[i] = static_cast<T>(rhs[i]);
578  }
579 
580  template <unsigned n, typename T>
581  template <typename U>
582  inline
583  vec<n,T>& vec<n,T>::operator=(const vec<n, U>& rhs)
584  {
585  mlc_converts_to(U, T)::check();
586  for (unsigned i = 0; i < n; ++i)
587  data_[i] = static_cast<T>(rhs[i]);
588  return *this;
589  }
590 
591  template <unsigned n, typename T>
592  inline
593  const T& vec<n,T>::operator[](unsigned i) const
594  {
595  mln_precondition(i < dim);
596  return data_[i];
597  }
598 
599  template <unsigned n, typename T>
600  inline
601  T& vec<n,T>::operator[](unsigned i)
602  {
603  mln_precondition(i < dim);
604  return data_[i];
605  }
606 
607  template <unsigned n, typename T>
608  inline
609  void vec<n,T>::set_all(const T& val)
610  {
611  for (unsigned i = 0; i < n; ++i)
612  data_[i] = val;
613  }
614 
615  template <unsigned n, typename T>
616  inline
617  unsigned vec<n,T>::size() const
618  {
619  return n;
620  }
621 
622  template <unsigned n, typename T>
623  inline
624  const vec<n, T>& vec<n, T>::normalize()
625  {
626  mln_sum_product(T,T) l2_norm = norm::l2(*this);
627  mln_assertion(l2_norm > mln_sum_product(T,T)(0));
628  for (unsigned i = 0; i < n; ++i)
629  data_[i] = static_cast<T>(data_[i] / l2_norm);
630  return *this;
631  }
632 
633  template <unsigned n, typename T>
634  template <typename F>
635  inline
636  vec<n, T>::vec(const Function_v2v<F>& f_)
637  {
638  mlc_converts_to(mln_result(F), T)::check();
639  const F& f = exact(f_);
640  for (unsigned i = 0; i < n; ++i)
641  data_[i] = static_cast<T>(f(i));
642  }
643 
644 
645  template <unsigned n, typename T>
646  const vec<n, T> vec<n, T>::zero = all_to(0);
647 
648  template <unsigned n, typename T>
649  const vec<n, T> vec<n, T>::origin = all_to(0);
650 
651 
652 
653  // Operators.
654 
655 
656  // vec == vec
657 
658  template <unsigned n, typename T, typename U>
659  inline
660  bool operator==(const vec<n,T>& lhs, const vec<n,U>& rhs)
661  {
662  for (unsigned i = 0; i < n; ++i)
663  if (lhs[i] != rhs[i])
664  return false;
665  return true;
666  }
667 
668  // vec + vec
669 
670  template <unsigned n, typename T, typename U>
671  inline
672  vec<n, mln_trait_op_plus(T,U)>
673  operator+(const vec<n,T>& lhs, const vec<n,U>& rhs)
674  {
675  typedef mln_trait_op_plus(T,U) R;
676  vec<n, R> tmp;
677  for (unsigned i = 0; i < n; ++i)
678  tmp[i] = lhs[i] + rhs[i];
679  return tmp;
680  }
681 
682  // - vec
683 
684  template <unsigned n, typename T>
685  inline
686  vec<n, mln_trait_op_uminus(T)>
687  operator-(const vec<n,T>& rhs)
688  {
689  typedef mln_trait_op_uminus(T) R;
690  vec<n, R> tmp;
691  for (unsigned i = 0; i < n; ++i)
692  tmp[i] = - rhs[i];
693  return tmp;
694  }
695 
696  // vec - vec
697 
698  template <unsigned n, typename T, typename U>
699  inline
700  vec<n, mln_trait_op_minus(T,U)>
701  operator-(const vec<n,T>& lhs, const vec<n,U>& rhs)
702  {
703  typedef mln_trait_op_minus(T,U) R;
704  vec<n, R> tmp;
705  for (unsigned i = 0; i < n; ++i)
706  tmp[i] = lhs[i] - rhs[i];
707  return tmp;
708  }
709 
710  // vec * vec
711 
712  template <unsigned n, typename T, typename U>
713  inline
714  mln_sum_product(T,U)
715  operator*(const vec<n,T>& lhs, const vec<n,U>& rhs)
716  {
717  typedef mln_sum_product(T,U) R;
718  mln_sum_product(T,U) tmp(literal::zero);
719  for (unsigned i = 0; i < n; ++i)
720  tmp += lhs[i] * rhs[i];
721  return tmp;
722  }
723 
724  // vec * s
725 
726  template <unsigned n, typename T, typename S>
727  inline
728  vec<n, mln_trait_op_times(T, S)>
729  operator*(const vec<n,T>& lhs, const mln::value::scalar_<S>& s)
730  {
731  // FIXME: We made a choice here but is it correct?
732  // FIXME: We "un-scalar" s so that the scalar status do not propagate.
733 
734  // Think of the case: vec<mat> v * scalar(vec w) s
735  // It gives: for all i, v[i] * w so the i-th mat * vec w -> vec
736  // The result is a vec<vec>
737 
738  // If we really want to propage the "scalar" status then
739  // we shall allow for scalar(scalar(..)) !!! => FIXME
740 
741  typedef mln_trait_op_times(T, S) R;
742  vec<n, R> tmp;
743  for (unsigned i = 0; i < n; ++i)
744  tmp[i] = lhs[i] * s.to_equiv();
745  return tmp;
746  }
747 
748  // vec / s
749 
750  template <unsigned n, typename T, typename S>
751  inline
752  vec<n, mln_trait_op_div(T, S)>
753  operator/(const vec<n,T>& lhs, const mln::value::scalar_<S>& s)
754  {
755  mln_precondition(value::equiv(s) != (S)(literal::zero));
756  typedef mln_trait_op_div(T, S) R;
757  vec<n, R> tmp;
758  for (unsigned i = 0; i < n; ++i)
759  tmp[i] = lhs[i] / s.to_equiv();
760  return tmp;
761  }
762 
763 
764  // << v
765 
766  template <unsigned n, typename T>
767  inline
768  std::ostream&
769  operator<<(std::ostream& ostr, const vec<n,T>& v)
770  {
771  ostr << '(';
772  for (unsigned i = 0; i < n; ++i)
773  ostr << debug::format(v[i]) << (i == n - 1 ? ")" : ", ");
774  return ostr;
775  }
776 
777 
778  // >> v
779 
780  template <unsigned n, typename T>
781  inline
782  std::istream&
783  operator>>(std::istream& istr, vec<n,T>& v)
784  {
785  for (unsigned i = 0; i < n; ++i)
786  istr >> v[i];
787  return istr;
788  }
789 
790 
791  // vprod
792 
793  template <typename T, typename U>
794  inline
795  vec<3, mln_trait_op_times(T,U)> // FIXME: typename binary_arith_trait<T, U>::ret>
796  vprod(const vec<3, T>& lhs, const vec<3, U>& rhs)
797  {
798  vec<3, mln_trait_op_times(T,U)> tmp; // FIXME: Likewise.
799  tmp[0] = lhs[1] * rhs[2] - lhs[2] * rhs[1];
800  tmp[1] = lhs[2] * rhs[0] - lhs[0] * rhs[2];
801  tmp[2] = lhs[0] * rhs[1] - lhs[1] * rhs[0];
802  return tmp;
803  }
804 
805 
806  template <typename P>
807  inline
808  P
809  to_point(const vec<P::dim,float>& v)
810  {
811  P tmp;
812  for (unsigned i = 0; i < P::dim; ++i)
813  tmp[i] = round(v[i]);
814  return tmp;
815  }
816 
817 
818  // Conversions
819 
820 
821  template <typename T, unsigned m>
822  inline
823  void
824  from_to_(const vec<3,T>& from, value::rgb<m>& to)
825  {
826  algebra::vec<3, unsigned> tmp;
827  for (unsigned i = 0; i < 3; ++i)
828  tmp[i] = static_cast<unsigned>(from[i]); // FIXME: Use from_to_ instead of cast.
829 
830  to = value::rgb<m>(tmp);
831  }
832 
833  template <unsigned n, typename C1, typename G, typename C2>
834  inline
835  void
836  from_to_(const mln::algebra::vec<n,C1>& from, point<G,C2>& to)
837  {
838  mlc_converts_to(C1, C2)::check();
839  enum { dim = G::dim };
840  mlc_bool(G::dim == n)::check();
841 
842  unsigned j = 0;
843  for (unsigned i = dim - 2; i < dim; ++i)
844  to[i] = mln::internal::convert_data<C2>(from[j++]);
845  for (unsigned i = 2; i < dim; ++i, ++j)
846  to[i-j] = mln::internal::convert_data<C2>(from[j]);
847  }
848 
849  template <typename C1, typename G, typename C2>
850  inline
851  void
852  from_to_(const mln::algebra::vec<1,C1>& from, point<G,C2>& to)
853  {
854  mlc_converts_to(C1, C2)::check();
855  enum { dim = G::dim };
856  mlc_bool(G::dim == 1)::check();
857 
858  to[0] = mln::internal::convert_data<C2>(from[0]);
859  }
860 
861  template <unsigned n, typename C1, typename G>
862  inline
863  void
864  from_to_(const mln::algebra::vec<n,C1>& from, point<G,C1>& to)
865  {
866  enum { dim = G::dim };
867  mlc_bool(G::dim == n)::check();
868 
869  unsigned j = 0;
870  for (unsigned i = dim - 2; i < dim; ++i)
871  to[i] = from[j++];
872  for (unsigned i = 2; i < dim; ++i, ++j)
873  to[i-j] = from[j];
874  }
875 
876  template <typename C1, typename G>
877  inline
878  void
879  from_to_(const mln::algebra::vec<1,C1>& from, point<G,C1>& to)
880  {
881  enum { dim = G::dim };
882  mlc_bool(G::dim == 1)::check();
883 
884  to[0] = from[0];
885  }
886 
887  template <unsigned n, typename T, typename P>
888  inline
889  void
890  from_to_(const vec<n,T>& from, Gpoint<P>& to_)
891  {
892  mlc_bool(P::dim == n)::check();
893  P& to = exact(to_);
894  for (unsigned i = 0; i < n; ++i)
895  to[i] = static_cast< typename P::coord >(from[i]); // FIXME: cast -> best effort...
896  }
897 
898 
899  } // end of namespace mln::algebra
900 
901 
902 # endif // MLN_INCLUDE_ONLY
903 
904 } // end of namespace mln
905 
906 
907 # include <mln/make/vec.hh>
908 # include <mln/algebra/mat.hh>
909 
910 
911 #endif // ! MLN_ALGEBRA_VEC_HH