$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
metal/mat.hh
1 // Copyright (C) 2006, 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE)
2 //
3 // This file is part of Olena.
4 //
5 // Olena is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation, version 2 of the License.
8 //
9 // Olena is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // As a special exception, you may use this file as part of a free
18 // software project without restriction. Specifically, if other files
19 // instantiate templates or use macros or inline functions from this
20 // file, or you compile this file and link it with other files to produce
21 // an executable, this file does not by itself cause the resulting
22 // executable to be covered by the GNU General Public License. This
23 // exception does not however invalidate any other reasons why the
24 // executable file might be covered by the GNU General Public License.
25 
26 #ifndef MLN_METAL_MAT_HH
27 # define MLN_METAL_MAT_HH
28 
35 # include <iostream>
36 
37 # include <mln/core/concept/object.hh>
38 # include <mln/core/concept/function.hh>
39 # include <mln/core/contract.hh>
40 # include <mln/trait/all.hh>
41 # include <mln/trait/value_.hh>
42 # include <mln/metal/vec.hh>
43 
44 
45 // FIXME: Document.
46 
47 
48 
49 namespace mln
50 {
51 
52 
53  // Fwd decl.
54  namespace metal {
55  template <unsigned n, unsigned m, typename T> class mat;
56  }
57 
58 
59  namespace trait
60  {
61 
62  template <unsigned n, unsigned m, typename T>
63  struct value_< metal::mat<n,m,T> >
64  {
65  typedef trait::value::nature::matrix nature;
66  typedef trait::value::kind::data kind;
67 
68  enum {
69  nbits = n * m * mln_nbits(T),
70  card = n * m * mln_card(T)
71  };
72  typedef mln_value_quant_from_(card) quant;
73 
74  typedef metal::mat<n, m, mln_sum(T)> sum;
75  };
76 
77  } // end of namespace mln::trait
78 
79 
80 
81  namespace metal
82  {
83 
84  template <unsigned n, unsigned m, typename T>
85  class mat : public Object< mat<n,m,T> >
86  {
87  public:
88 
89  typedef T coord;
90  enum { N = n,
91  M = m,
92  dim = n * m };
93 
94  static const mat<n,m,T> Id;
95 
96  mat()
97  {
98  }
99 
100  template <typename U>
101  mat(const mat<n,m,U>& rhs);
102 
104  template <typename F>
105  mat(const Function_v2v<F>& f);
106 
107  template <typename U>
108  mat& operator=(const mat<n,m,U>& rhs);
109 
110  const T& operator()(unsigned i, unsigned j) const;
111 
112  T& operator()(unsigned i, unsigned j);
113 
114  void set_all(const T& val);
115 
116  unsigned size() const;
117 
118  static mat identity();
119 
120  private:
121  T data_[n][m];
122  };
123 
124  }
125 
126 
127  namespace trait
128  {
129 
130  // Unarys.
131 
132  template < template<class> class Name,
133  unsigned n, unsigned m, typename T >
134  struct set_precise_unary_< Name, metal::mat<n,m,T> >
135  {
136  typedef metal::mat<n, m, mln_trait_unary(Name, T)> ret;
137  };
138 
139  // Default for binarys; works for (+), (-), comparisons, and promote.
140 
141  template < template<class, class> class Name,
142  unsigned n, unsigned m, typename T, typename U>
143  struct set_precise_binary_< Name, metal::mat<n,m,T>, metal::mat<n,m,U> >
144  {
145  typedef metal::mat<n, m, mln_trait_binary(Name, T, U)> ret;
146  };
147 
148  // mat * mat
149 
150  template < unsigned n, unsigned o, typename T,
151  unsigned m, typename U >
152  struct set_precise_binary_< op::times, metal::mat<n,o,T>, metal::mat<o,m,U> >
153  {
154  typedef metal::mat<n, m, mln_sum_product(T, U)> ret;
155  };
156 
157  template < unsigned n, typename T, typename U >
158  struct set_precise_binary_< op::times, metal::mat<n,n,T>, metal::mat<n,n,U> >
159  { // Disambiguate between both previous defs.
160  typedef metal::mat<n, n, mln_sum_product(T, U)> ret;
161  };
162 
163  // mat * vec
164 
165  template < unsigned n, unsigned m, typename T,
166  typename U >
167  struct set_precise_binary_< op::times, metal::mat<n,m,T>, metal::vec<m,U> >
168  {
169  typedef metal::vec<n, mln_sum_product(T, U)> ret;
170  };
171 
172  // mat * s
173 
174  template < template<class, class> class Name,
175  unsigned n, unsigned m, typename T,
176  typename S >
177  struct set_precise_binary_< Name, metal::mat<n,m,T>, mln::value::scalar_<S> >
178  {
179  typedef metal::mat<n, m, mln_trait_binary(Name, T, S)> ret;
180  };
181 
182  template < template<class, class> class Name,
183  unsigned n, unsigned m, typename T,
184  typename S >
185  struct set_binary_< Name,
186  mln::Object, metal::mat<n,m,T>,
187  mln::value::Scalar, S >
188  {
189  typedef metal::mat<n, m, mln_trait_binary(Name, T, S)> ret;
190  };
191 
192  } // end of namespace mln::trait
193 
194 
195 
196  namespace metal
197  {
198 
199  // ==
200 
201  template <unsigned n, unsigned m, typename T, typename U>
202  bool
203  operator==(mat<n,m,T>& lhs, const mat<n,m,U>& rhs);
204 
205  // +
206 
207  template <unsigned n, unsigned m, typename T, typename U>
208  mat<n, m, mln_trait_op_plus(T,U)>
209  operator+(mat<n,m,T>& lhs, const mat<n,m,U>& rhs);
210 
211  // -
212 
213  template <unsigned n, unsigned m, typename T, typename U>
214  mat<n, m, mln_trait_op_minus(T,U)>
215  operator-(const mat<n,m,T>& lhs, const mat<n,m,U>& rhs);
216 
217  // - (unary)
218 
219  template <unsigned n, unsigned m, typename T>
220  mat<n, m, mln_trait_op_uminus(T)>
221  operator-(const mat<n,m,T>& lhs);
222 
223  // mat * mat
224 
225  template <unsigned n, unsigned o, typename T,
226  unsigned m, typename U>
227  mat<n, m, mln_sum_product(T,U)>
228  operator*(const mat<n,o,T>& lhs, const mat<o,m,U>& rhs);
229 
230  // mat * vec
231 
232  template <unsigned n, unsigned m, typename T,
233  typename U>
234  vec<n, mln_sum_product(T,U)>
235  operator*(const mat<n,m,T>& lhs, const vec<m,U>& rhs);
236 
237  // mat * s
238 
239  template <unsigned n, unsigned m, typename T,
240  typename S>
241  mat<n, m, mln_trait_op_times(T,S)>
242  operator*(const mat<n,m,T>& lhs, const value::scalar_<S>& s);
243 
244  // mat / s
245 
246  template <unsigned n, unsigned m, typename T, typename S>
247  mat<n, m, mln_trait_op_div(T,S)>
248  operator/(const mat<n,m,T>& lhs, const value::scalar_<S>& s);
249 
250  // <<
251 
252  template <unsigned n, unsigned m, typename T>
253  std::ostream&
254  operator<<(std::ostream& ostr, const mat<n,m,T>& v);
255 
256 
257 
258 # ifndef MLN_INCLUDE_ONLY
259 
260  template <unsigned n, unsigned m, typename T>
261  const mat<n,m,T> mat<n,m,T>::Id = mat<n,m,T>::identity();
262 
263  template <unsigned n, unsigned m, typename T>
264  inline
265  mat<n,m,T> mat<n,m,T>::identity()
266  {
267  static mat<n,m,T> id_;
268  static bool flower = true;
269  if (flower)
270  {
271  for (unsigned i = 0; i < n; ++i)
272  for (unsigned j = 0; j < m; ++j)
273  id_(i, j) = (i == j);
274  flower = false;
275  }
276  return id_;
277  }
278 
279  template <unsigned n, unsigned m, typename T>
280  template <typename U>
281  inline
282  mat<n,m,T>::mat(const mat<n,m,U>& rhs)
283  {
284  for (unsigned i = 0; i < n; ++i)
285  for (unsigned j = 0; j < m; ++j)
286  data_[i][j] = rhs(i, j);
287  }
288 
289  template <unsigned n, unsigned m, typename T>
290  template <typename F>
291  inline
292  mat<n,m,T>::mat(const Function_v2v<F>& f_)
293  {
294  mlc_converts_to(mln_result(F), T)::check();
295  const F& f = exact(f_);
296  for (unsigned i = 0; i < n; ++i)
297  for (unsigned j = 0; j < m; ++j)
298  data_[i][j] = f(i * n + j);
299  }
300 
301  template <unsigned n, unsigned m, typename T>
302  template <typename U>
303  inline
304  mat<n,m,T>&
305  mat<n,m,T>::operator=(const mat<n,m,U>& rhs)
306  {
307  for (unsigned i = 0; i < n; ++i)
308  for (unsigned j = 0; j < m; ++j)
309  data_[i][j] = rhs(i, j);
310  return *this;
311  }
312 
313  template <unsigned n, unsigned m, typename T>
314  inline
315  const T&
316  mat<n,m,T>::operator()(unsigned i, unsigned j) const
317  {
318  mln_precondition(i < n && j < m);
319  return data_[i][j];
320  }
321 
322  template <unsigned n, unsigned m, typename T>
323  inline
324  T&
325  mat<n,m,T>::operator()(unsigned i, unsigned j)
326  {
327  mln_precondition(i < n && j < m);
328  return data_[i][j];
329  }
330 
331  template <unsigned n, unsigned m, typename T>
332  inline
333  void mat<n,m,T>::set_all(const T& val)
334  {
335  for (unsigned i = 0; i < n; ++i)
336  for (unsigned j = 0; j < m; ++j)
337  data_[i][j] = val;
338  }
339 
340  template <unsigned n, unsigned m, typename T>
341  inline
342  unsigned mat<n,m,T>::size() const
343  {
344  return n * m;
345  }
346 
347 
348  // Operators.
349 
350 
351  template <unsigned n, unsigned m, typename T, typename U>
352  inline
353  bool
354  operator==(const mat<n,m,T>& lhs, const mat<n,m,U>& rhs)
355  {
356  for (unsigned i = 0; i < n; ++i)
357  for (unsigned j = 0; j < m; ++j)
358  if (lhs(i, j) != rhs(i, j))
359  return false;
360  return true;
361  }
362 
363  template <unsigned n, unsigned m, typename T, typename U>
364  inline
365  mat<n, m, mln_trait_op_plus(T,U)>
366  operator+(const mat<n,m,T>& lhs, const mat<n,m,U>& rhs)
367  {
368  mat<n, m, mln_trait_op_plus(T,U)> tmp;
369  for (unsigned i = 0; i < n; ++i)
370  for (unsigned j = 0; j < m; ++j)
371  tmp[i][j] = lhs(i, j) + rhs(i, j);
372  return tmp;
373  }
374 
375  template <unsigned n, unsigned m, typename T, typename U>
376  inline
377  mat<n,m, mln_trait_op_minus(T,U)>
378  operator-(const mat<n,m,T>& lhs, const mat<n,m,U>& rhs)
379  {
380  mat<n,m, mln_trait_op_minus(T,U)> tmp;
381  for (unsigned i = 0; i < n; ++i)
382  for (unsigned j = 0; j < m; ++j)
383  tmp(i, j) = lhs(i, j) - rhs(i, j);
384  return tmp;
385  }
386 
387  template <unsigned n, unsigned m, typename T>
388  inline
389  mat<n,m, mln_trait_op_uminus(T)>
390  operator-(const mat<n,m,T>& rhs)
391  {
392  mat<n,m, mln_trait_op_uminus(T)> tmp;
393  for (unsigned i = 0; i < n; ++i)
394  for (unsigned j = 0; i < m; ++i)
395  tmp(i, j) = - rhs(i, j);
396  return tmp;
397  }
398 
399  template <unsigned n, unsigned o, typename T,
400  unsigned m, typename U>
401  inline
402  mat<n, m, mln_sum_product(T,U)>
403  operator*(const mat<n,o,T>& lhs, const mat<o,m,U>& rhs)
404  {
405  mat<n,m, mln_sum_product(T,U)> tmp;
406  for (unsigned i = 0; i < n; ++i)
407  for (unsigned j = 0; j < m; ++j)
408  {
409  tmp(i, j) = literal::zero;
410  for (unsigned k = 0; k < o; ++k)
411  tmp(i, j) += lhs(i, k) * rhs(k, j);
412  }
413  return tmp;
414  }
415 
416  template <unsigned n, unsigned m, typename T,
417  typename U>
418  inline
419  vec<n, mln_sum_product(T,U)>
420  operator*(const mat<n,m,T>& lhs, const vec<m,U>& rhs)
421  {
422  vec<n, mln_sum_product(T,U)> tmp;
423  for (unsigned i = 0; i < n; ++i)
424  {
425  mln_sum_product(T,U) sum(literal::zero);
426  for (unsigned j = 0; j < m; ++j)
427  sum += lhs(i, j) * rhs[j];
428  tmp[i] = sum;
429  }
430  return tmp;
431  }
432 
433  template <unsigned n, unsigned m, typename T, typename S>
434  inline
435  mat<n, m, mln_trait_op_times(T,S)>
436  operator*(const mat<n,m,T>& lhs, const value::scalar_<S>& s_)
437  {
438  S s = s_.to_equiv();
439  mat<n, m, mln_trait_op_times(T,S)> tmp;
440  for (unsigned i = 0; i < n; ++i)
441  for (unsigned j = 0; j < m; ++j)
442  tmp(i, j) = lhs(i, j) * s;
443  return tmp;
444  }
445 
446  template <unsigned n, unsigned m, typename T, typename S>
447  inline
448  mat<n,m, mln_trait_op_div(T,S)>
449  operator/(const mat<n,m,T>& lhs, const value::scalar_<S>& s_)
450  {
451  S s = s_.to_equiv();
452  mat<n,m, mln_trait_op_times(T,S)> tmp;
453  for (unsigned i = 0; i < n; ++i)
454  for (unsigned j = 0; j < m; ++j)
455  tmp[i][j] = lhs(i, j) / s;
456  return tmp;
457  }
458 
459  // <<
460 
461  template <unsigned n, unsigned m, typename T>
462  inline
463  std::ostream&
464  operator<<(std::ostream& ostr, const mat<n,m,T>& v)
465  {
466  for (unsigned i = 0; i < n; ++i)
467  {
468  ostr << '[';
469  for (unsigned j = 0; j < m; ++j)
470  ostr << debug::format(v(i, j)) << (j == m - 1 ? "]" : ", ");
471  ostr << std::endl;
472  }
473  return ostr;
474  }
475 
476 # endif // ! MLN_INCLUDE_ONLY
477 
478  } // end of namespace mln::metal
479 
480 } // end of namespace mln
481 
482 # include <mln/make/mat.hh>
483 
484 #endif // ! MLN_METAL_MAT_HH