Milena (Olena)
User documentation 2.0a Id
|
00001 // Copyright (C) 2006, 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE) 00002 // 00003 // This file is part of Olena. 00004 // 00005 // Olena is free software: you can redistribute it and/or modify it under 00006 // the terms of the GNU General Public License as published by the Free 00007 // Software Foundation, version 2 of the License. 00008 // 00009 // Olena is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Olena. If not, see <http://www.gnu.org/licenses/>. 00016 // 00017 // As a special exception, you may use this file as part of a free 00018 // software project without restriction. Specifically, if other files 00019 // instantiate templates or use macros or inline functions from this 00020 // file, or you compile this file and link it with other files to produce 00021 // an executable, this file does not by itself cause the resulting 00022 // executable to be covered by the GNU General Public License. This 00023 // exception does not however invalidate any other reasons why the 00024 // executable file might be covered by the GNU General Public License. 00025 00026 #ifndef MLN_METAL_MAT_HH 00027 # define MLN_METAL_MAT_HH 00028 00035 # include <iostream> 00036 00037 # include <mln/core/concept/object.hh> 00038 # include <mln/core/concept/function.hh> 00039 # include <mln/core/contract.hh> 00040 # include <mln/trait/all.hh> 00041 # include <mln/trait/value_.hh> 00042 # include <mln/metal/vec.hh> 00043 00044 00045 // FIXME: Document. 00046 00047 00048 00049 namespace mln 00050 { 00051 00052 00053 // Fwd decl. 00054 namespace metal { 00055 template <unsigned n, unsigned m, typename T> class mat; 00056 } 00057 00058 00059 namespace trait 00060 { 00061 00062 template <unsigned n, unsigned m, typename T> 00063 struct value_< metal::mat<n,m,T> > 00064 { 00065 typedef trait::value::nature::matrix nature; 00066 typedef trait::value::kind::data kind; 00067 00068 enum { 00069 nbits = n * m * mln_nbits(T), 00070 card = n * m * mln_card(T) 00071 }; 00072 typedef mln_value_quant_from_(card) quant; 00073 00074 typedef metal::mat<n, m, mln_sum(T)> sum; 00075 }; 00076 00077 } // end of namespace mln::trait 00078 00079 00080 00081 namespace metal 00082 { 00083 00084 template <unsigned n, unsigned m, typename T> 00085 class mat : public Object< mat<n,m,T> > 00086 { 00087 public: 00088 00089 typedef T coord; 00090 enum { N = n, 00091 M = m, 00092 dim = n * m }; 00093 00094 static const mat<n,m,T> Id; 00095 00096 mat() 00097 { 00098 } 00099 00100 template <typename U> 00101 mat(const mat<n,m,U>& rhs); 00102 00104 template <typename F> 00105 mat(const Function_v2v<F>& f); 00106 00107 template <typename U> 00108 mat& operator=(const mat<n,m,U>& rhs); 00109 00110 const T& operator()(unsigned i, unsigned j) const; 00111 00112 T& operator()(unsigned i, unsigned j); 00113 00114 void set_all(const T& val); 00115 00116 unsigned size() const; 00117 00118 static mat identity(); 00119 00120 private: 00121 T data_[n][m]; 00122 }; 00123 00124 } 00125 00126 00127 namespace trait 00128 { 00129 00130 // Unarys. 00131 00132 template < template<class> class Name, 00133 unsigned n, unsigned m, typename T > 00134 struct set_precise_unary_< Name, metal::mat<n,m,T> > 00135 { 00136 typedef metal::mat<n, m, mln_trait_unary(Name, T)> ret; 00137 }; 00138 00139 // Default for binarys; works for (+), (-), comparisons, and promote. 00140 00141 template < template<class, class> class Name, 00142 unsigned n, unsigned m, typename T, typename U> 00143 struct set_precise_binary_< Name, metal::mat<n,m,T>, metal::mat<n,m,U> > 00144 { 00145 typedef metal::mat<n, m, mln_trait_binary(Name, T, U)> ret; 00146 }; 00147 00148 // mat * mat 00149 00150 template < unsigned n, unsigned o, typename T, 00151 unsigned m, typename U > 00152 struct set_precise_binary_< op::times, metal::mat<n,o,T>, metal::mat<o,m,U> > 00153 { 00154 typedef metal::mat<n, m, mln_sum_product(T, U)> ret; 00155 }; 00156 00157 template < unsigned n, typename T, typename U > 00158 struct set_precise_binary_< op::times, metal::mat<n,n,T>, metal::mat<n,n,U> > 00159 { // Disambiguate between both previous defs. 00160 typedef metal::mat<n, n, mln_sum_product(T, U)> ret; 00161 }; 00162 00163 // mat * vec 00164 00165 template < unsigned n, unsigned m, typename T, 00166 typename U > 00167 struct set_precise_binary_< op::times, metal::mat<n,m,T>, metal::vec<m,U> > 00168 { 00169 typedef metal::vec<n, mln_sum_product(T, U)> ret; 00170 }; 00171 00172 // mat * s 00173 00174 template < template<class, class> class Name, 00175 unsigned n, unsigned m, typename T, 00176 typename S > 00177 struct set_precise_binary_< Name, metal::mat<n,m,T>, mln::value::scalar_<S> > 00178 { 00179 typedef metal::mat<n, m, mln_trait_binary(Name, T, S)> ret; 00180 }; 00181 00182 template < template<class, class> class Name, 00183 unsigned n, unsigned m, typename T, 00184 typename S > 00185 struct set_binary_< Name, 00186 mln::Object, metal::mat<n,m,T>, 00187 mln::value::Scalar, S > 00188 { 00189 typedef metal::mat<n, m, mln_trait_binary(Name, T, S)> ret; 00190 }; 00191 00192 } // end of namespace mln::trait 00193 00194 00195 00196 namespace metal 00197 { 00198 00199 // == 00200 00201 template <unsigned n, unsigned m, typename T, typename U> 00202 bool 00203 operator==(mat<n,m,T>& lhs, const mat<n,m,U>& rhs); 00204 00205 // + 00206 00207 template <unsigned n, unsigned m, typename T, typename U> 00208 mat<n, m, mln_trait_op_plus(T,U)> 00209 operator+(mat<n,m,T>& lhs, const mat<n,m,U>& rhs); 00210 00211 // - 00212 00213 template <unsigned n, unsigned m, typename T, typename U> 00214 mat<n, m, mln_trait_op_minus(T,U)> 00215 operator-(const mat<n,m,T>& lhs, const mat<n,m,U>& rhs); 00216 00217 // - (unary) 00218 00219 template <unsigned n, unsigned m, typename T> 00220 mat<n, m, mln_trait_op_uminus(T)> 00221 operator-(const mat<n,m,T>& lhs); 00222 00223 // mat * mat 00224 00225 template <unsigned n, unsigned o, typename T, 00226 unsigned m, typename U> 00227 mat<n, m, mln_sum_product(T,U)> 00228 operator*(const mat<n,o,T>& lhs, const mat<o,m,U>& rhs); 00229 00230 // mat * vec 00231 00232 template <unsigned n, unsigned m, typename T, 00233 typename U> 00234 vec<n, mln_sum_product(T,U)> 00235 operator*(const mat<n,m,T>& lhs, const vec<m,U>& rhs); 00236 00237 // mat * s 00238 00239 template <unsigned n, unsigned m, typename T, 00240 typename S> 00241 mat<n, m, mln_trait_op_times(T,S)> 00242 operator*(const mat<n,m,T>& lhs, const value::scalar_<S>& s); 00243 00244 // mat / s 00245 00246 template <unsigned n, unsigned m, typename T, typename S> 00247 mat<n, m, mln_trait_op_div(T,S)> 00248 operator/(const mat<n,m,T>& lhs, const value::scalar_<S>& s); 00249 00250 // << 00251 00252 template <unsigned n, unsigned m, typename T> 00253 std::ostream& 00254 operator<<(std::ostream& ostr, const mat<n,m,T>& v); 00255 00256 00257 00258 # ifndef MLN_INCLUDE_ONLY 00259 00260 template <unsigned n, unsigned m, typename T> 00261 const mat<n,m,T> mat<n,m,T>::Id = mat<n,m,T>::identity(); 00262 00263 template <unsigned n, unsigned m, typename T> 00264 inline 00265 mat<n,m,T> mat<n,m,T>::identity() 00266 { 00267 static mat<n,m,T> id_; 00268 static bool flower = true; 00269 if (flower) 00270 { 00271 for (unsigned i = 0; i < n; ++i) 00272 for (unsigned j = 0; j < m; ++j) 00273 id_(i, j) = (i == j); 00274 flower = false; 00275 } 00276 return id_; 00277 } 00278 00279 template <unsigned n, unsigned m, typename T> 00280 template <typename U> 00281 inline 00282 mat<n,m,T>::mat(const mat<n,m,U>& rhs) 00283 { 00284 for (unsigned i = 0; i < n; ++i) 00285 for (unsigned j = 0; j < m; ++j) 00286 data_[i][j] = rhs(i, j); 00287 } 00288 00289 template <unsigned n, unsigned m, typename T> 00290 template <typename F> 00291 inline 00292 mat<n,m,T>::mat(const Function_v2v<F>& f_) 00293 { 00294 mlc_converts_to(mln_result(F), T)::check(); 00295 const F& f = exact(f_); 00296 for (unsigned i = 0; i < n; ++i) 00297 for (unsigned j = 0; j < m; ++j) 00298 data_[i][j] = f(i * n + j); 00299 } 00300 00301 template <unsigned n, unsigned m, typename T> 00302 template <typename U> 00303 inline 00304 mat<n,m,T>& 00305 mat<n,m,T>::operator=(const mat<n,m,U>& rhs) 00306 { 00307 for (unsigned i = 0; i < n; ++i) 00308 for (unsigned j = 0; j < m; ++j) 00309 data_[i][j] = rhs(i, j); 00310 return *this; 00311 } 00312 00313 template <unsigned n, unsigned m, typename T> 00314 inline 00315 const T& 00316 mat<n,m,T>::operator()(unsigned i, unsigned j) const 00317 { 00318 mln_precondition(i < n && j < m); 00319 return data_[i][j]; 00320 } 00321 00322 template <unsigned n, unsigned m, typename T> 00323 inline 00324 T& 00325 mat<n,m,T>::operator()(unsigned i, unsigned j) 00326 { 00327 mln_precondition(i < n && j < m); 00328 return data_[i][j]; 00329 } 00330 00331 template <unsigned n, unsigned m, typename T> 00332 inline 00333 void mat<n,m,T>::set_all(const T& val) 00334 { 00335 for (unsigned i = 0; i < n; ++i) 00336 for (unsigned j = 0; j < m; ++j) 00337 data_[i][j] = val; 00338 } 00339 00340 template <unsigned n, unsigned m, typename T> 00341 inline 00342 unsigned mat<n,m,T>::size() const 00343 { 00344 return n * m; 00345 } 00346 00347 00348 // Operators. 00349 00350 00351 template <unsigned n, unsigned m, typename T, typename U> 00352 inline 00353 bool 00354 operator==(const mat<n,m,T>& lhs, const mat<n,m,U>& rhs) 00355 { 00356 for (unsigned i = 0; i < n; ++i) 00357 for (unsigned j = 0; j < m; ++j) 00358 if (lhs(i, j) != rhs(i, j)) 00359 return false; 00360 return true; 00361 } 00362 00363 template <unsigned n, unsigned m, typename T, typename U> 00364 inline 00365 mat<n, m, mln_trait_op_plus(T,U)> 00366 operator+(const mat<n,m,T>& lhs, const mat<n,m,U>& rhs) 00367 { 00368 mat<n, m, mln_trait_op_plus(T,U)> tmp; 00369 for (unsigned i = 0; i < n; ++i) 00370 for (unsigned j = 0; j < m; ++j) 00371 tmp[i][j] = lhs(i, j) + rhs(i, j); 00372 return tmp; 00373 } 00374 00375 template <unsigned n, unsigned m, typename T, typename U> 00376 inline 00377 mat<n,m, mln_trait_op_minus(T,U)> 00378 operator-(const mat<n,m,T>& lhs, const mat<n,m,U>& rhs) 00379 { 00380 mat<n,m, mln_trait_op_minus(T,U)> tmp; 00381 for (unsigned i = 0; i < n; ++i) 00382 for (unsigned j = 0; j < m; ++j) 00383 tmp(i, j) = lhs(i, j) - rhs(i, j); 00384 return tmp; 00385 } 00386 00387 template <unsigned n, unsigned m, typename T> 00388 inline 00389 mat<n,m, mln_trait_op_uminus(T)> 00390 operator-(const mat<n,m,T>& rhs) 00391 { 00392 mat<n,m, mln_trait_op_uminus(T)> tmp; 00393 for (unsigned i = 0; i < n; ++i) 00394 for (unsigned j = 0; i < m; ++i) 00395 tmp(i, j) = - rhs(i, j); 00396 return tmp; 00397 } 00398 00399 template <unsigned n, unsigned o, typename T, 00400 unsigned m, typename U> 00401 inline 00402 mat<n, m, mln_sum_product(T,U)> 00403 operator*(const mat<n,o,T>& lhs, const mat<o,m,U>& rhs) 00404 { 00405 mat<n,m, mln_sum_product(T,U)> tmp; 00406 for (unsigned i = 0; i < n; ++i) 00407 for (unsigned j = 0; j < m; ++j) 00408 { 00409 tmp(i, j) = literal::zero; 00410 for (unsigned k = 0; k < o; ++k) 00411 tmp(i, j) += lhs(i, k) * rhs(k, j); 00412 } 00413 return tmp; 00414 } 00415 00416 template <unsigned n, unsigned m, typename T, 00417 typename U> 00418 inline 00419 vec<n, mln_sum_product(T,U)> 00420 operator*(const mat<n,m,T>& lhs, const vec<m,U>& rhs) 00421 { 00422 vec<n, mln_sum_product(T,U)> tmp; 00423 for (unsigned i = 0; i < n; ++i) 00424 { 00425 mln_sum_product(T,U) sum(literal::zero); 00426 for (unsigned j = 0; j < m; ++j) 00427 sum += lhs(i, j) * rhs[j]; 00428 tmp[i] = sum; 00429 } 00430 return tmp; 00431 } 00432 00433 template <unsigned n, unsigned m, typename T, typename S> 00434 inline 00435 mat<n, m, mln_trait_op_times(T,S)> 00436 operator*(const mat<n,m,T>& lhs, const value::scalar_<S>& s_) 00437 { 00438 S s = s_.to_equiv(); 00439 mat<n, m, mln_trait_op_times(T,S)> tmp; 00440 for (unsigned i = 0; i < n; ++i) 00441 for (unsigned j = 0; j < m; ++j) 00442 tmp(i, j) = lhs(i, j) * s; 00443 return tmp; 00444 } 00445 00446 template <unsigned n, unsigned m, typename T, typename S> 00447 inline 00448 mat<n,m, mln_trait_op_div(T,S)> 00449 operator/(const mat<n,m,T>& lhs, const value::scalar_<S>& s_) 00450 { 00451 S s = s_.to_equiv(); 00452 mat<n,m, mln_trait_op_times(T,S)> tmp; 00453 for (unsigned i = 0; i < n; ++i) 00454 for (unsigned j = 0; j < m; ++j) 00455 tmp[i][j] = lhs(i, j) / s; 00456 return tmp; 00457 } 00458 00459 // << 00460 00461 template <unsigned n, unsigned m, typename T> 00462 inline 00463 std::ostream& 00464 operator<<(std::ostream& ostr, const mat<n,m,T>& v) 00465 { 00466 for (unsigned i = 0; i < n; ++i) 00467 { 00468 ostr << '['; 00469 for (unsigned j = 0; j < m; ++j) 00470 ostr << debug::format(v(i, j)) << (j == m - 1 ? "]" : ", "); 00471 ostr << std::endl; 00472 } 00473 return ostr; 00474 } 00475 00476 # endif // ! MLN_INCLUDE_ONLY 00477 00478 } // end of namespace mln::metal 00479 00480 } // end of namespace mln 00481 00482 # include <mln/make/mat.hh> 00483 00484 #endif // ! MLN_METAL_MAT_HH