Milena (Olena)
User documentation 2.0a Id
|
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