Milena (Olena)  User documentation 2.0a Id
vec.hh
00001 // Copyright (C) 2006, 2008, 2009, 2011 EPITA Research and Development
00002 // Laboratory (LRDE)
00003 //
00004 // This file is part of Olena.
00005 //
00006 // Olena is free software: you can redistribute it and/or modify it under
00007 // the terms of the GNU General Public License as published by the Free
00008 // Software Foundation, version 2 of the License.
00009 //
00010 // Olena is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Olena.  If not, see <http://www.gnu.org/licenses/>.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software project without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to produce
00022 // an executable, this file does not by itself cause the resulting
00023 // executable to be covered by the GNU General Public License.  This
00024 // exception does not however invalidate any other reasons why the
00025 // executable file might be covered by the GNU General Public License.
00026 
00027 #ifndef MLN_ALGEBRA_VEC_HH
00028 # define MLN_ALGEBRA_VEC_HH
00029 
00033 
00034 # include <iostream>
00035 # include <cmath>
00036 
00037 # include <mln/core/concept/object.hh>
00038 
00039 # include <mln/literal/zero.hh>
00040 # include <mln/literal/origin.hh>
00041 # include <mln/norm/l2.hh>
00042 # include <mln/trait/all.hh>
00043 # include <mln/trait/value_.hh>
00044 # include <mln/fun/i2v/all_to.hh>
00045 # include <mln/debug/format.hh>
00046 
00047 # include <mln/value/ops.hh>
00048 
00049 
00050 // FIXME: Document.
00051 
00052 
00053 namespace mln
00054 {
00055 
00056   // Forward declarations.
00057   namespace algebra {
00058     template <unsigned n, typename T> class vec;
00059     template <unsigned d, typename C> class h_vec;
00060     template <unsigned n, unsigned m, typename T> class mat;
00061   }
00062 
00063   namespace literal {
00064     struct zero_t;
00065   }
00066 
00067   namespace norm {
00068     template <unsigned n, typename C>
00069     mln_sum_product(C,C) l2(const algebra::vec<n,C>& vec);
00070   }
00071 
00072 
00073   namespace trait
00074   {
00075 
00076     template <unsigned n, typename T>
00077     struct value_< mln::algebra::vec<n,T> >
00078     {
00079       typedef trait::value::nature::vectorial nature;
00080       typedef trait::value::kind::data        kind;
00081 
00082       enum {
00083         dim   = n,
00084         nbits = n * mln_nbits(T),
00085         card  = n * mln_card(T)
00086       };
00087       typedef T comp;
00088       typedef mln_value_quant_from_(card) quant;
00089       typedef algebra::vec<n, mln_sum(T)> sum;
00090     };
00091 
00092     template <unsigned n, typename T>
00093     struct set_precise_unary_< op::ord, mln::algebra::vec<n,T> >
00094     {
00095       typedef mln::internal::ord_vec< mln::algebra::vec<n,T> > ret;
00096     };
00097 
00098   } // end of namespace mln::trait
00099 
00100 
00101 
00102   namespace algebra
00103   {
00104 
00105     namespace internal
00106     {
00107 
00108       template <unsigned n, typename T>
00109       class vec_base_ : public Object< vec<n,T> >
00110       {
00111       protected:
00112         T data_[n];
00113       };
00114 
00115       template <typename T>
00116       class vec_base_ <1, T> : public Object< vec<1,T> >
00117       {
00118       public:
00119         void set(const T& val0)
00120         {
00121           data_[0] = val0;
00122         }
00123       protected:
00124         T data_[1];
00125       };
00126 
00127       template <typename T>
00128       class vec_base_ <2, T> : public Object< vec<2,T> >
00129       {
00130       public:
00131         void set(const T& val0, const T& val1)
00132         {
00133           data_[0] = val0;
00134           data_[1] = val1;
00135         }
00136       protected:
00137         T data_[2];
00138       };
00139 
00140       template <typename T>
00141       class vec_base_ <3, T> : public Object< vec<3,T> >
00142       {
00143       public:
00144         void set(const T& val0, const T& val1, const T& val2)
00145         {
00146           data_[0] = val0;
00147           data_[1] = val1;
00148           data_[2] = val2;
00149         }
00150       protected:
00151         T data_[3];
00152       };
00153 
00154       template <typename T>
00155       class vec_base_ <4, T> : public Object< vec<4,T> >
00156       {
00157       public:
00158         void set(const T& val0, const T& val1, const T& val2, const T& val3)
00159         {
00160           data_[0] = val0;
00161           data_[1] = val1;
00162           data_[2] = val2;
00163           data_[3] = val3;
00164         }
00165       protected:
00166         T data_[4];
00167       };
00168 
00169 
00170     } // end of namespace mln::algebra::internal
00171 
00172 
00173 
00174     template <unsigned n, typename T>
00175     class vec : public internal::vec_base_<n, T>
00176     {
00177       typedef internal::vec_base_<n, T> super_;
00178 
00179     protected:
00180       using super_::data_;
00181 
00182     public:
00183 
00184       typedef T equiv[n];
00185       typedef T enc[n];
00186 
00187       typedef T coord;
00188       enum { dim = n };
00189 
00190       vec();
00191 
00193       vec(const literal::zero_t&);
00194       vec& operator=(const literal::zero_t&);
00196 
00198       vec(const literal::origin_t&);
00199       vec& operator=(const literal::origin_t&);
00201 
00202       vec(const vec<n, T>& rhs);
00203 
00204       template <typename U>
00205       vec(const vec<n, U>& rhs);
00206 
00207       template <typename U>
00208       vec& operator=(const vec<n, U>& rhs);
00209 
00210 
00211       // Immersion of the vector into its homogeneous space.
00212       algebra::h_vec<n, T> to_h_vec() const;
00213 
00214 
00215       const T& operator[](unsigned i) const;
00216 
00217       T& operator[](unsigned i);
00218 
00219       void set_all(const T& val);
00220 
00221       unsigned size() const;
00222 
00223       /* FIXME: What if the vector is null?  Even if we choose not to
00224          handle this case, we should *state* in the documentation the
00225          behavior of this method.
00226 
00227          I (Roland) have added an assertion to detect ``erroneous''
00228          cases, but we might want something different.
00229          ``Implementation defined'' or ``undefined behavior'' is fine
00230          by me, as long as the documentation mentions it.
00231 
00232          FWIW, Trimesh's developers chose to set all the coordinates
00233          of a vector being normalized to 1, when it norm is equal or
00234          lower (sic) to zero.  */
00235       const vec<n, T>& normalize();
00236 
00238       mat<1, n, T> t() const;
00239 
00241       template <typename F>
00242       vec(const Function_v2v<F>& f);
00243 
00245       static const vec<n, T> zero;
00246 
00248       static const vec<n, T> origin;
00249 
00250 
00252       template <typename U>
00253       operator mat<n, 1, U>() const;
00254 
00256       template <typename U>
00257       vec(const mat<n, 1, U>& rhs);
00258 
00260       template <typename U>
00261       vec& operator=(const mat<n, 1, U>& rhs);
00262     };
00263 
00264   } // end of namespace mln::algebra
00265 
00266 
00267 
00268   namespace trait
00269   {
00270 
00271     // For unary traits.
00272 
00273 
00274     template < template <class> class Name,
00275                unsigned n, typename T >
00276     struct set_precise_unary_< Name, algebra::vec<n, T> >
00277     {
00278       typedef mln_trait_unary(Name, T) V;
00279       typedef algebra::vec<n, V> ret;
00280     };
00281 
00282 
00283     // For binary traits.
00284 
00285 
00286     // vec + vec
00287 
00288     template < unsigned n, typename T,
00289                typename U >
00290     struct set_precise_binary_< op::plus,
00291                                 algebra::vec<n, T>, algebra::vec<n, U> >
00292     {
00293       typedef mln_trait_op_plus(T, U) V;
00294       typedef algebra::vec<n, V> ret;
00295     };
00296 
00297     // - vec
00298 
00299     template < unsigned n, typename T >
00300     struct set_precise_unary_< op::uminus,
00301                                algebra::vec<n, T> >
00302     {
00303       typedef mln_trait_op_uminus(T) V;
00304       typedef algebra::vec<n, V> ret;
00305     };
00306 
00307     // vec - vec
00308 
00309     template < unsigned n, typename T,
00310                typename U >
00311     struct set_precise_binary_< op::minus,
00312                                 algebra::vec<n, T>, algebra::vec<n, U> >
00313     {
00314       typedef mln_trait_op_minus(T, U) V;
00315       typedef algebra::vec<n, V> ret;
00316     };
00317 
00318     // vec * vec
00319 
00320     template < unsigned n, typename T,
00321                typename U >
00322     struct set_precise_binary_< op::times,
00323                                 algebra::vec<n, T>, algebra::vec<n, U> >
00324     {
00325       typedef mln_sum_product(T,U) ret;
00326     };
00327 
00328     // vec * s
00329 
00330     template < unsigned n, typename T,
00331                typename S >
00332     struct set_precise_binary_< op::times,
00333                                 algebra::vec<n, T>, mln::value::scalar_<S> >
00334     {
00335       typedef mln_trait_op_times(T, S) V;
00336       typedef algebra::vec<n, V> ret;
00337     };
00338 
00339     // vec / s
00340 
00341     template < unsigned n, typename T,
00342                typename S >
00343     struct set_precise_binary_< op::div,
00344                                 algebra::vec<n, T>, mln::value::scalar_<S> >
00345     {
00346       typedef mln_trait_op_div(T, S) V;
00347       typedef algebra::vec<n, V> ret;
00348     };
00349 
00350 //     template < template<class, class> class Name,
00351 //             unsigned n, typename T,
00352 //             typename S >
00353 //     struct set_binary_< Name,
00354 //                      mln::Object, algebra::vec<n, T>,
00355 //                      mln::value::Scalar, S >
00356 //     {
00357 //       typedef mln_trait_binary(Name, T, S) V;
00358 //       typedef algebra::vec<n, V> ret;
00359 //     };
00360 
00361   } // end of namespace mln::trait
00362 
00363 
00364 
00365   namespace algebra
00366   {
00367 
00368     // vec == vec
00369 
00370     template <unsigned n, typename T, typename U>
00371     bool
00372     operator==(const vec<n,T>& lhs, const vec<n,U>& rhs);
00373 
00374     // vec + vec
00375 
00376     template <unsigned n, typename T, typename U>
00377     vec<n, mln_trait_op_plus(T,U)>
00378     operator+(const vec<n,T>& lhs, const vec<n,U>& rhs);
00379 
00380     // - vec
00381 
00382     template <unsigned n, typename T>
00383     vec<n, mln_trait_op_uminus(T)>
00384     operator-(const vec<n,T>& rhs);
00385 
00386     // vec - vec
00387 
00388     template <unsigned n, typename T, typename U>
00389     vec<n, mln_trait_op_minus(T,U)>
00390     operator-(const vec<n,T>& lhs, const vec<n,U>& rhs);
00391 
00392     // vec * vec
00393 
00395     template <unsigned n, typename T, typename U>
00396     mln_sum_product(T,U)
00397     operator*(const vec<n,T>& lhs, const vec<n,U>& rhs);
00398 
00399     // vec * s
00400 
00401     template <unsigned n, typename T, typename S>
00402     vec<n, mln_trait_op_times(T, S)>
00403     operator*(const vec<n,T>& lhs, const mln::value::scalar_<S>& s);
00404 
00405     // vec / s
00406 
00407     template <unsigned n, typename T, typename S>
00408     vec<n, mln_trait_op_div(T, S)>
00409     operator/(const vec<n,T>& lhs, const mln::value::scalar_<S>& s);
00410 
00411     // <<
00412 
00413     template <unsigned n, typename T>
00414     std::ostream&
00415     operator<<(std::ostream& ostr, const vec<n,T>& v);
00416 
00417     // >>
00418 
00419     template <unsigned n, typename T>
00420     std::istream&
00421     operator>>(std::istream& istr, vec<n,T>& v);
00422 
00423     // vprod // FIXME: Generalize...
00424 
00426     template <typename T, typename U>
00427     vec<3, mln_trait_op_times(T,U)> // FIXME: Sum of product...
00428     vprod(const vec<3, T>& lhs, const vec<3, U>& rhs);
00429 
00430   } // end of namespace mln::algebra
00431 
00432 
00433 
00434 
00435 # ifndef MLN_INCLUDE_ONLY
00436 
00437   namespace algebra
00438   {
00439 
00440     template <unsigned n, typename T>
00441     inline
00442     vec<n,T>::vec()
00443     {
00444     }
00445 
00446     template <unsigned n, typename T>
00447     inline
00448     vec<n,T>::vec(const literal::zero_t&)
00449     {
00450       this->set_all(0);
00451     }
00452 
00453     template <unsigned n, typename T>
00454     inline
00455     vec<n,T>&
00456     vec<n,T>::operator=(const literal::zero_t&)
00457     {
00458       this->set_all(0);
00459       return *this;
00460     }
00461 
00462     template <unsigned n, typename T>
00463     inline
00464     vec<n,T>::vec(const literal::origin_t&)
00465     {
00466       this->set_all(0);
00467     }
00468 
00469     template <unsigned n, typename T>
00470     inline
00471     vec<n,T>&
00472     vec<n,T>::operator=(const literal::origin_t&)
00473     {
00474       this->set_all(0);
00475       return *this;
00476     }
00477 
00478     template <unsigned n, typename T>
00479     inline
00480     vec<n,T>::vec(const vec<n,T>& rhs)
00481       : super_()
00482     {
00483       for (unsigned i = 0; i < n; ++i)
00484         data_[i] = rhs[i];
00485     }
00486 
00487     template <unsigned n, typename T>
00488     template <typename U>
00489     inline
00490     vec<n,T>::vec(const vec<n, U>& rhs)
00491       : super_()
00492     {
00493       mlc_converts_to(U, T)::check();
00494       for (unsigned i = 0; i < n; ++i)
00495         data_[i] = static_cast<T>(rhs[i]);
00496     }
00497 
00498     template <unsigned n, typename T>
00499     template <typename U>
00500     inline
00501     vec<n,T>& vec<n,T>::operator=(const vec<n, U>& rhs)
00502     {
00503       mlc_converts_to(U, T)::check();
00504       for (unsigned i = 0; i < n; ++i)
00505         data_[i] = static_cast<T>(rhs[i]);
00506       return *this;
00507     }
00508 
00509     template <unsigned n, typename T>
00510     inline
00511     const T& vec<n,T>::operator[](unsigned i) const
00512     {
00513       mln_precondition(i < dim);
00514       return data_[i];
00515     }
00516 
00517     template <unsigned n, typename T>
00518     inline
00519     T& vec<n,T>::operator[](unsigned i)
00520     {
00521       mln_precondition(i < dim);
00522       return data_[i];
00523     }
00524 
00525     template <unsigned n, typename T>
00526     inline
00527     void vec<n,T>::set_all(const T& val)
00528     {
00529       for (unsigned i = 0; i < n; ++i)
00530         data_[i] = val;
00531     }
00532 
00533     template <unsigned n, typename T>
00534     inline
00535     unsigned vec<n,T>::size() const
00536     {
00537       return n;
00538     }
00539 
00540     template <unsigned n, typename T>
00541     inline
00542     const vec<n, T>& vec<n, T>::normalize()
00543     {
00544       mln_sum_product(T,T) l2_norm = norm::l2(*this);
00545       mln_assertion(l2_norm > mln_sum_product(T,T)(0));
00546       for (unsigned i = 0; i < n; ++i)
00547         data_[i] = static_cast<T>(data_[i] / l2_norm);
00548       return *this;
00549     }
00550 
00551     template <unsigned n, typename T>
00552     template <typename F>
00553     inline
00554     vec<n, T>::vec(const Function_v2v<F>& f_)
00555     {
00556       mlc_converts_to(mln_result(F), T)::check();
00557       const F& f = exact(f_);
00558       for (unsigned i = 0; i < n; ++i)
00559         data_[i] = static_cast<T>(f(i));
00560     }
00561 
00562 
00563     template <unsigned n, typename T>
00564     const vec<n, T> vec<n, T>::zero = all_to(0);
00565 
00566     template <unsigned n, typename T>
00567     const vec<n, T> vec<n, T>::origin = all_to(0);
00568 
00569 
00570 
00571     // Operators.
00572 
00573 
00574     // vec == vec
00575 
00576     template <unsigned n, typename T, typename U>
00577     inline
00578     bool operator==(const vec<n,T>& lhs, const vec<n,U>& rhs)
00579     {
00580       for (unsigned i = 0; i < n; ++i)
00581         if (lhs[i] != rhs[i])
00582           return false;
00583       return true;
00584     }
00585 
00586     // vec + vec
00587 
00588     template <unsigned n, typename T, typename U>
00589     inline
00590     vec<n, mln_trait_op_plus(T,U)>
00591     operator+(const vec<n,T>& lhs, const vec<n,U>& rhs)
00592     {
00593       typedef mln_trait_op_plus(T,U) R;
00594       vec<n, R> tmp;
00595       for (unsigned i = 0; i < n; ++i)
00596         tmp[i] = lhs[i] + rhs[i];
00597       return tmp;
00598     }
00599 
00600     // - vec
00601 
00602     template <unsigned n, typename T>
00603     inline
00604     vec<n, mln_trait_op_uminus(T)>
00605     operator-(const vec<n,T>& rhs)
00606     {
00607       typedef mln_trait_op_uminus(T) R;
00608       vec<n, R> tmp;
00609       for (unsigned i = 0; i < n; ++i)
00610         tmp[i] = - rhs[i];
00611       return tmp;
00612     }
00613 
00614     // vec - vec
00615 
00616     template <unsigned n, typename T, typename U>
00617     inline
00618     vec<n, mln_trait_op_minus(T,U)>
00619     operator-(const vec<n,T>& lhs, const vec<n,U>& rhs)
00620     {
00621       typedef mln_trait_op_minus(T,U) R;
00622       vec<n, R> tmp;
00623       for (unsigned i = 0; i < n; ++i)
00624         tmp[i] = lhs[i] - rhs[i];
00625       return tmp;
00626     }
00627 
00628     // vec * vec
00629 
00630     template <unsigned n, typename T, typename U>
00631     inline
00632     mln_sum_product(T,U)
00633     operator*(const vec<n,T>& lhs, const vec<n,U>& rhs)
00634     {
00635       typedef mln_sum_product(T,U) R;
00636       mln_sum_product(T,U) tmp(literal::zero);
00637       for (unsigned i = 0; i < n; ++i)
00638         tmp += lhs[i] * rhs[i];
00639       return tmp;
00640     }
00641 
00642     // vec * s
00643 
00644     template <unsigned n, typename T, typename S>
00645     inline
00646     vec<n, mln_trait_op_times(T, S)>
00647     operator*(const vec<n,T>& lhs, const mln::value::scalar_<S>& s)
00648     {
00649       // FIXME: We made a choice here but is it correct?
00650       // FIXME: We "un-scalar" s so that the scalar status do not propagate.
00651 
00652       // Think of the case: vec<mat> v * scalar(vec w) s
00653       // It gives: for all i, v[i] * w  so  the i-th mat * vec w -> vec
00654       // The result is a vec<vec>
00655 
00656       // If we really want to propage the "scalar" status then
00657       // we shall allow for scalar(scalar(..)) !!!  => FIXME
00658 
00659       typedef mln_trait_op_times(T, S) R;
00660       vec<n, R> tmp;
00661       for (unsigned i = 0; i < n; ++i)
00662         tmp[i] = lhs[i] * s.to_equiv();
00663       return tmp;
00664     }
00665 
00666     // vec / s
00667 
00668     template <unsigned n, typename T, typename S>
00669     inline
00670     vec<n, mln_trait_op_div(T, S)>
00671     operator/(const vec<n,T>& lhs, const mln::value::scalar_<S>& s)
00672     {
00673       mln_precondition(value::equiv(s) != (S)(literal::zero));
00674       typedef mln_trait_op_div(T, S) R;
00675       vec<n, R> tmp;
00676       for (unsigned i = 0; i < n; ++i)
00677         tmp[i] = lhs[i] / s.to_equiv();
00678       return tmp;
00679     }
00680 
00681 
00682     // << v
00683 
00684     template <unsigned n, typename T>
00685     inline
00686     std::ostream&
00687     operator<<(std::ostream& ostr, const vec<n,T>& v)
00688     {
00689       ostr << '(';
00690       for (unsigned i = 0; i < n; ++i)
00691         ostr << debug::format(v[i]) << (i == n - 1 ? ")" : ", ");
00692       return ostr;
00693     }
00694 
00695 
00696     // >> v
00697 
00698     template <unsigned n, typename T>
00699     inline
00700     std::istream&
00701     operator>>(std::istream& istr, vec<n,T>& v)
00702     {
00703       for (unsigned i = 0; i < n; ++i)
00704         istr >> v[i];
00705       return istr;
00706     }
00707 
00708 
00709     // vprod
00710 
00711     template <typename T, typename U>
00712     inline
00713     vec<3, mln_trait_op_times(T,U)> // FIXME: typename binary_arith_trait<T, U>::ret>
00714     vprod(const vec<3, T>& lhs, const vec<3, U>& rhs)
00715     {
00716       vec<3, mln_trait_op_times(T,U)> tmp; // FIXME: Likewise.
00717       tmp[0] = lhs[1] * rhs[2] - lhs[2] * rhs[1];
00718       tmp[1] = lhs[2] * rhs[0] - lhs[0] * rhs[2];
00719       tmp[2] = lhs[0] * rhs[1] - lhs[1] * rhs[0];
00720       return tmp;
00721     }
00722 
00723 
00724     template <typename P>
00725     inline
00726     P
00727     to_point(const vec<P::dim,float>& v)
00728     {
00729       P tmp;
00730       for (unsigned i = 0; i < P::dim; ++i)
00731         tmp[i] = round(v[i]);
00732       return tmp;
00733     }
00734 
00735 
00736   } // end of namespace mln::algebra
00737 
00738 
00739 # endif // MLN_INCLUDE_ONLY
00740 
00741 } // end of namespace mln
00742 
00743 
00744 # include <mln/make/vec.hh>
00745 # include <mln/algebra/mat.hh>
00746 
00747 
00748 #endif // ! MLN_ALGEBRA_VEC_HH
 All Classes Namespaces Functions Variables Typedefs Enumerator