$extrastylesheet
Olena  User documentation 2.1
An Image Processing Platform
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
algebra/mat.hh
1 // Copyright (C) 2006, 2008, 2009, 2012, 2013 EPITA Research and Development
2 // 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_MAT_HH
28 # define MLN_ALGEBRA_MAT_HH
29 
33 
34 # include <iostream>
35 
36 # include <mln/core/concept/object.hh>
37 # include <mln/core/concept/function.hh>
38 # include <mln/core/contract.hh>
39 # include <mln/trait/all.hh>
40 # include <mln/trait/value_.hh>
41 # include <mln/algebra/vec.hh>
42 # include <mln/literal/identity.hh>
43 
44 
45 // FIXME: Document.
46 
47 
48 
49 namespace mln
50 {
51 
52 
53  // Forward declaration.
54  namespace algebra {
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_< algebra::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 algebra::mat<n, m, mln_sum(T)> sum;
75  };
76 
77  } // end of namespace mln::trait
78 
79 
80 
81  namespace algebra
82  {
83 
87  template <unsigned n, unsigned m, typename T>
88  class mat : public Object< mat<n,m,T> >
89  {
90  public:
91 
92  typedef T coord;
93  enum { N = n,
94  M = m,
95  dim = n * m };
96 
97  static const mat<n,m,T> Id;
98 
99  mat();
100 
101  mat(const literal::zero_t&);
102  mat(const literal::one_t&);
103  mat(const literal::identity_t&);
104 
105  template <typename U>
106  mat(const mat<n,m,U>& rhs);
107 
109  template <typename F>
110  mat(const Function_v2v<F>& f);
111 
112  template <typename U>
113  mat& operator=(const mat<n,m,U>& rhs);
114 
115  const T& operator()(unsigned i, unsigned j) const;
116 
117  T& operator()(unsigned i, unsigned j);
118 
119  void set_all(const T& val);
120 
121  unsigned size() const;
122 
123  static mat identity();
124 
126  mat<m,n,T> t() const;
127 
130  mat<n,m,T> _1() const;
131 
132  private:
133 
134  T data_[n][m];
135 
136  void set_id_();
137  };
138 
139 
140  } // end of namespace algebra
141 
142 
143 
144  namespace trait
145  {
146 
147  // - mat
148 
149  template < unsigned n, unsigned m, typename T >
150  struct set_precise_unary_< op::uminus,
151  algebra::mat<n,m,T> >
152  {
154  };
155 
156  // mat + mat
157 
158  template < unsigned n, unsigned m, typename T, typename U >
159  struct set_precise_binary_< op::plus,
160  algebra::mat<n,m,T>, algebra::mat<n,m,U> >
161  {
162  typedef algebra::mat<n, m, mln_trait_op_plus(T, U)> ret;
163  };
164 
165  // mat - mat
166 
167  template < unsigned n, unsigned m, typename T, typename U >
168  struct set_precise_binary_< op::minus,
169  algebra::mat<n,m,T>, algebra::mat<n,m,U> >
170  {
171  typedef algebra::mat<n, m, mln_trait_op_minus(T, U)> ret;
172  };
173 
174  // mat * mat
175 
176  template < unsigned n, unsigned o, typename T,
177  unsigned m, typename U >
178  struct set_precise_binary_< op::times,
179  algebra::mat<n,o,T>, algebra::mat<o,m,U> >
180  {
181  typedef algebra::mat<n, m, mln_sum_product(T, U)> ret;
182  };
183 
184  template < unsigned o, typename T,
185  typename U >
186  struct set_precise_binary_< op::times,
187  algebra::mat<1,o,T>, algebra::mat<o,1,U> >
188  {
189  typedef mln_sum_product(T, U) ret;
190  };
191 
192  // mat * vec
193 
194  template < unsigned n, unsigned m, typename T,
195  typename U >
196  struct set_precise_binary_< op::times,
197  algebra::mat<n,m,T>, algebra::vec<m,U> >
198  {
199  typedef algebra::vec<n, mln_sum_product(T, U)> ret;
200  };
201 
202  template < unsigned m, typename T,
203  typename U >
204  struct set_precise_binary_< op::times,
205  algebra::mat<1,m,T>, algebra::vec<m,U> >
206  {
207  typedef mln_sum_product(T, U) ret; // a scalar
208  };
209 
210  // vec * mat
211 
212  template < unsigned m, typename T,
213  typename U >
214  struct set_precise_binary_< op::times,
215  algebra::vec<m,T>, algebra::mat<1,m,U> >
216  {
217  typedef algebra::mat<m, m, mln_trait_op_times(T, U)> ret;
218  };
219 
220  // mat * s
221 
222  template < unsigned n, unsigned m, typename T,
223  typename S >
224  struct set_precise_binary_< op::times,
225  algebra::mat<n,m,T>, mln::value::scalar_<S> >
226  {
227  typedef algebra::mat<n, m, mln_trait_op_times(T, S)> ret;
228  };
229 
230  // template < template<class, class> class Name,
231  // unsigned n, unsigned m, typename T,
232  // typename S >
233  // struct set_binary_< Name,
234  // mln::Object, algebra::mat<n,m,T>,
235  // mln::value::Scalar, S >
236  // {
237  // typedef algebra::mat<n, m, mln_trait_binary(Name, T, S)> ret;
238  // };
239 
240  // mat / s
241 
242  template < unsigned n, unsigned m, typename T,
243  typename S >
244  struct set_precise_binary_< op::div,
245  algebra::mat<n,m,T>, mln::value::scalar_<S> >
246  {
247  typedef algebra::mat<n, m, mln_trait_op_div(T, S)> ret;
248  };
249 
250  } // end of namespace mln::trait
251 
252 
253 
254  namespace algebra
255  {
256 
257  // ==
258 
259  template <unsigned n, unsigned m, typename T, typename U>
260  bool
261  operator==(const mat<n,m,T>& lhs, const mat<n,m,U>& rhs);
262 
263  // - mat
264 
265  template <unsigned n, unsigned m, typename T>
266  mat<n, m, mln_trait_op_uminus(T)>
267  operator-(const mat<n,m,T>& lhs);
268 
269  // mat + mat
270 
271  template <unsigned n, unsigned m, typename T, typename U>
272  mat<n, m, mln_trait_op_plus(T,U)>
273  operator+(const mat<n,m,T>& lhs, const mat<n,m,U>& rhs);
274 
275  // mat - mat
276 
277  template <unsigned n, unsigned m, typename T, typename U>
278  mat<n, m, mln_trait_op_minus(T,U)>
279  operator-(const mat<n,m,T>& lhs, const mat<n,m,U>& rhs);
280 
281  // mat * mat
282 
283  template <unsigned n, unsigned o, typename T,
284  unsigned m, typename U>
285  mat<n, m, mln_sum_product(T,U)>
286  operator*(const mat<n,o,T>& lhs, const mat<o,m,U>& rhs);
287 
288  template <unsigned o, typename T,
289  typename U>
290  mln_sum_product(T,U)
291  operator*(const mat<1,o,T>& lhs, const mat<o,1,U>& rhs);
292 
293  // mat * vec
294 
295  template <unsigned n, unsigned m, typename T,
296  typename U>
297  vec<n, mln_sum_product(T,U)>
298  operator*(const mat<n,m,T>& lhs, const vec<m,U>& rhs);
299 
300  template <unsigned m, typename T,
301  typename U>
302  mln_sum_product(T,U) // scalar
303  operator*(const mat<1,m,T>& lhs, const vec<m,U>& rhs);
304 
305  // vec * mat
306 
307  template <unsigned m, typename T, typename U>
308  mat<m, m, mln_trait_op_times(T,U)>
309  operator*(const vec<m,T>& lhs, const mat<1,m,U>& rhs);
310 
311  // mat * s
312 
313  template <unsigned n, unsigned m, typename T,
314  typename S>
315  mat<n, m, mln_trait_op_times(T,S)>
316  operator*(const mat<n,m,T>& lhs, const value::scalar_<S>& s);
317 
318  // mat / s
319 
320  template <unsigned n, unsigned m, typename T, typename S>
321  mat<n, m, mln_trait_op_div(T,S)>
322  operator/(const mat<n,m,T>& lhs, const value::scalar_<S>& s);
323 
324  // <<
325 
326  template <unsigned n, unsigned m, typename T>
327  std::ostream&
328  operator<<(std::ostream& ostr, const mat<n,m,T>& v);
329 
330 
331 
332  // Trace.
333 
335  template<unsigned n, typename T>
336  mln_sum(T)
337  tr(const mat<n,n,T>& m);
338 
339 
340  // Determinant.
341 
343  template<unsigned n, typename T>
344  mln_sum_product(T,T)
345  det(const mat<n,n,T>& m);
346 
347 
348 
349 # ifndef MLN_INCLUDE_ONLY
350 
351 
352  // vec -> mat
353 
354  template <unsigned n, typename T>
355  template <typename U>
356  inline
357  vec<n,T>::operator mat<n,1,U>() const
358  {
359  mlc_converts_to(T, U)::check();
360  mat<n,1,U> tmp;
361  for (unsigned i = 0; i < n; ++i)
362  tmp(i, 0) = data_[i];
363  return tmp;
364  }
365 
366 
367  // mat -> vec
368 
369  template <unsigned n, typename T>
370  template <typename U>
371  inline
372  vec<n,T>::vec(const mat<n, 1, U>& rhs)
373  {
374  mlc_converts_to(T, U)::check();
375  for (unsigned i = 0; i < n; ++i)
376  data_[i] = rhs(i, 0);
377  }
378 
379  template <unsigned n, typename T>
380  template <typename U>
381  inline
382  vec<n,T>&
383  vec<n,T>::operator=(const mat<n, 1, U>& rhs)
384  {
385  mlc_converts_to(T, U)::check();
386  for (unsigned i = 0; i < n; ++i)
387  data_[i] = rhs(i, 0);
388  return *this;
389  }
390 
391 
392 
393  // Id
394 
395  template <unsigned n, unsigned m, typename T>
396  const mat<n,m,T>
397  mat<n,m,T>::Id = mat<n,m,T>::identity();
398 
399  template <unsigned n, unsigned m, typename T>
400  inline
401  mat<n,m,T>
402  mat<n,m,T>::identity()
403  {
404  static mat<n,m,T> id_;
405  static bool flower = true;
406  if (flower)
407  {
408  for (unsigned i = 0; i < n; ++i)
409  for (unsigned j = 0; j < m; ++j)
410  id_(i, j) = (i == j);
411  flower = false;
412  }
413  return id_;
414  }
415 
416  template <unsigned n, unsigned m, typename T>
417  inline
418  mat<n,m,T>::mat()
419  {
420  }
421 
422  template <unsigned n, unsigned m, typename T>
423  inline
424  mat<n,m,T>::mat(const literal::zero_t&)
425  {
426  this->set_all(0);
427  }
428 
429  template <unsigned n, unsigned m, typename T>
430  inline
431  void
432  mat<n,m,T>::set_id_()
433  {
434  for (unsigned i = 0; i < n; ++i)
435  for (unsigned j = 0; j < m; ++j)
436  if (i == j)
437  data_[i][j] = literal::one;
438  else
439  data_[i][j] = literal::zero;
440  }
441 
442  template <unsigned n, unsigned m, typename T>
443  inline
444  mat<n,m,T>::mat(const literal::one_t&)
445  {
446  this->set_id_();
447  }
448 
449  template <unsigned n, unsigned m, typename T>
450  inline
451  mat<n,m,T>::mat(const literal::identity_t&)
452  {
453  this->set_id_();
454  }
455 
456  template <unsigned n, unsigned m, typename T>
457  template <typename U>
458  inline
459  mat<n,m,T>::mat(const mat<n,m,U>& rhs)
460  {
461  for (unsigned i = 0; i < n; ++i)
462  for (unsigned j = 0; j < m; ++j)
463  data_[i][j] = static_cast<T>( rhs(i, j) );
464  }
465 
466  template <unsigned n, unsigned m, typename T>
467  template <typename F>
468  inline
469  mat<n,m,T>::mat(const Function_v2v<F>& f_)
470  {
471  mlc_converts_to(mln_result(F), T)::check();
472  const F& f = exact(f_);
473  for (unsigned i = 0; i < n; ++i)
474  for (unsigned j = 0; j < m; ++j)
475  data_[i][j] = static_cast<T>( f(i * n + j) );
476  }
477 
478  template <unsigned n, unsigned m, typename T>
479  template <typename U>
480  inline
481  mat<n,m,T>&
482  mat<n,m,T>::operator=(const mat<n,m,U>& rhs)
483  {
484  for (unsigned i = 0; i < n; ++i)
485  for (unsigned j = 0; j < m; ++j)
486  data_[i][j] = static_cast<T>( rhs(i, j) );
487  return *this;
488  }
489 
490  template <unsigned n, unsigned m, typename T>
491  inline
492  const T&
493  mat<n,m,T>::operator()(unsigned i, unsigned j) const
494  {
495  mln_precondition(i < n && j < m);
496  return data_[i][j];
497  }
498 
499  template <unsigned n, unsigned m, typename T>
500  inline
501  T&
502  mat<n,m,T>::operator()(unsigned i, unsigned j)
503  {
504  mln_precondition(i < n && j < m);
505  return data_[i][j];
506  }
507 
508  template <unsigned n, unsigned m, typename T>
509  inline
510  void mat<n,m,T>::set_all(const T& val)
511  {
512  for (unsigned i = 0; i < n; ++i)
513  for (unsigned j = 0; j < m; ++j)
514  data_[i][j] = val;
515  }
516 
517  template <unsigned n, unsigned m, typename T>
518  inline
519  unsigned mat<n,m,T>::size() const
520  {
521  return n * m;
522  }
523 
524  template <unsigned n, unsigned m, typename T>
525  inline
526  mat<m,n,T>
527  mat<n,m,T>::t() const
528  {
529  mat<m,n,T> tmp;
530  for (unsigned i = 0; i < n; ++i)
531  for (unsigned j = 0; j < m; ++j)
532  tmp(j,i) = data_[i][j];
533  return tmp;
534  }
535 
536 
537  namespace internal
538  {
539 
540  // "Make" routines.
541 
542  template <typename T>
543  inline
544  mat<2,2,T>
545  make(const T& t00, const T& t01,
546  const T& t10, const T& t11)
547  {
548  mat<2,2,T> tmp;
549  tmp(0, 0) = t00; tmp(0, 1) = t01;
550  tmp(1, 0) = t10; tmp(1, 1) = t11;
551  return tmp;
552  }
553 
554  template <typename T>
555  inline
556  mat<3,3,T>
557  make(const T& t00, const T& t01, const T& t02,
558  const T& t10, const T& t11, const T& t12,
559  const T& t20, const T& t21, const T& t22)
560  {
561  mat<3,3,T> tmp;
562  tmp(0, 0) = t00; tmp(0, 1) = t01; tmp(0, 2) = t02;
563  tmp(1, 0) = t10; tmp(1, 1) = t11; tmp(1, 2) = t12;
564  tmp(2, 0) = t20; tmp(2, 1) = t21; tmp(2, 2) = t22;
565  return tmp;
566  }
567 
568 
569  // Inverse routines.
570 
571  template <typename T>
572  inline
573  mat<2,2,float>
574  inverse(const mat<2,2,T>& m)
575  {
576  float d = det(m);
577  mln_precondition(d != 0);
578  return make<float>( + m(1,1) / d, - m(0,1) / d,
579  - m(1,0) / d, + m(0,0) / d );
580  }
581 
582  template <typename T>
583  inline
584  mat<3,3,float>
585  inverse(const mat<3,3,T>& m)
586  {
587  float d = det(m);
588  mln_precondition(d != 0);
589  return make<float>( det(make(m(1,1), m(1,2),
590  m(2,1), m(2,2))),
591 
592  det(make(m(0,2), m(0,1),
593  m(2,2), m(2,1))),
594 
595  det(make(m(0,1), m(0,2),
596  m(1,1), m(1,2))),
597 
598 
599  det(make(m(1,2), m(1,0),
600  m(2,2), m(2,0))),
601 
602  det(make(m(0,0), m(0,2),
603  m(2,0), m(2,2))),
604 
605  det(make(m(0,2), m(0,0),
606  m(1,2), m(1,0))),
607 
608  det(make(m(1,0), m(1,1),
609  m(2,0), m(2,1))),
610 
611  det(make(m(0,1), m(0,0),
612  m(2,1), m(2,0))),
613 
614  det(make(m(0,0), m(0,1),
615  m(1,0), m(1,1)))
616  ) / d;
617  }
618 
619  template <typename T>
620  inline
621  mat<4,4,float>
622  inverse(const mat<4,4,T>& m)
623  {
624  mat<4,4,T> mo;
625 
626  // Based on MESA implementation of the GLU library.
627  mo(0,0) = m(1,1) * m(2,2) * m(3,3) - m(1,1) * m(2,3) * m(3,2) -
628  m(2,1) * m(1,2) * m(3,3) + m(2,1) * m(1,3) * m(3,2) +
629  m(3,1) * m(1,2) * m(2,3) - m(3,1) * m(1,3) * m(2,2);
630 
631  mo(1,0) = -m(1,0) * m(2,2) * m(3,3) + m(1,0) * m(2,3) * m(3,2) +
632  m(2,0) * m(1,2) * m(3,3) - m(2,0) * m(1,3) * m(3,2) -
633  m(3,0) * m(1,2) * m(2,3) + m(3,0) * m(1,3) * m(2,2);
634 
635  mo(2,0) = m(1,0) * m(2,1) * m(3,3) - m(1,0) * m(2,3) * m(3,1) -
636  m(2,0) * m(1,1) * m(3,3) + m(2,0) * m(1,3) * m(3,1) +
637  m(3,0) * m(1,1) * m(2,3) - m(3,0) * m(1,3) * m(2,1);
638 
639  mo(3,0) = -m(1,0) * m(2,1) * m(3,2) + m(1,0) * m(2,2) * m(3,1) +
640  m(2,0) * m(1,1) * m(3,2) - m(2,0) * m(1,2) * m(3,1) -
641  m(3,0) * m(1,1) * m(2,2) + m(3,0) * m(1,2) * m(2,1);
642 
643  mo(0,1) = -m(0,1) * m(2,2) * m(3,3) + m(0,1) * m(2,3) * m(3,2) +
644  m(2,1) * m(0,2) * m(3,3) - m(2,1) * m(0,3) * m(3,2) -
645  m(3,1) * m(0,2) * m(2,3) + m(3,1) * m(0,3) * m(2,2);
646 
647  mo(1,1) = m(0,0) * m(2,2) * m(3,3) - m(0,0) * m(2,3) * m(3,2) -
648  m(2,0) * m(0,2) * m(3,3) + m(2,0) * m(0,3) * m(3,2) +
649  m(3,0) * m(0,2) * m(2,3) - m(3,0) * m(0,3) * m(2,2);
650 
651  mo(2,1) = -m(0,0) * m(2,1) * m(3,3) + m(0,0) * m(2,3) * m(3,1) +
652  m(2,0) * m(0,1) * m(3,3) - m(2,0) * m(0,3) * m(3,1) -
653  m(3,0) * m(0,1) * m(2,3) + m(3,0) * m(0,3) * m(2,1);
654 
655  mo(3,1) = m(0,0) * m(2,1) * m(3,2) - m(0,0) * m(2,2) * m(3,1) -
656  m(2,0) * m(0,1) * m(3,2) + m(2,0) * m(0,2) * m(3,1) +
657  m(3,0) * m(0,1) * m(2,2) - m(3,0) * m(0,2) * m(2,1);
658 
659  mo(0,2) = m(0,1) * m(1,2) * m(3,3) - m(0,1) * m(1,3) * m(3,2) -
660  m(1,1) * m(0,2) * m(3,3) + m(1,1) * m(0,3) * m(3,2) +
661  m(3,1) * m(0,2) * m(1,3) - m(3,1) * m(0,3) * m(1,2);
662 
663  mo(1,2) = -m(0,0) * m(1,2) * m(3,3) + m(0,0) * m(1,3) * m(3,2) +
664  m(1,0) * m(0,2) * m(3,3) - m(1,0) * m(0,3) * m(3,2) -
665  m(3,0) * m(0,2) * m(1,3) + m(3,0) * m(0,3) * m(1,2);
666 
667  mo(2,2) = m(0,0) * m(1,1) * m(3,3) - m(0,0) * m(1,3) * m(3,1) -
668  m(1,0) * m(0,1) * m(3,3) + m(1,0) * m(0,3) * m(3,1) +
669  m(3,0) * m(0,1) * m(1,3) - m(3,0) * m(0,3) * m(1,1);
670 
671  mo(3,2) = -m(0,0) * m(1,1) * m(3,2) + m(0,0) * m(1,2) * m(3,1) +
672  m(1,0) * m(0,1) * m(3,2) - m(1,0) * m(0,2) * m(3,1) -
673  m(3,0) * m(0,1) * m(1,2) + m(3,0) * m(0,2) * m(1,1);
674 
675  mo(0,3) = -m(0,1) * m(1,2) * m(2,3) + m(0,1) * m(1,3) * m(2,2) +
676  m(1,1) * m(0,2) * m(2,3) - m(1,1) * m(0,3) * m(2,2) -
677  m(2,1) * m(0,2) * m(1,3) + m(2,1) * m(0,3) * m(1,2);
678 
679  mo(1,3) = m(0,0) * m(1,2) * m(2,3) - m(0,0) * m(1,3) * m(2,2) -
680  m(1,0) * m(0,2) * m(2,3) + m(1,0) * m(0,3) * m(2,2) +
681  m(2,0) * m(0,2) * m(1,3) - m(2,0) * m(0,3) * m(1,2);
682 
683  mo(2,3) = -m(0,0) * m(1,1) * m(2,3) + m(0,0) * m(1,3) * m(2,1) +
684  m(1,0) * m(0,1) * m(2,3) - m(1,0) * m(0,3) * m(2,1) -
685  m(2,0) * m(0,1) * m(1,3) + m(2,0) * m(0,3) * m(1,1);
686 
687  mo(3,3) = m(0,0) * m(1,1) * m(2,2) - m(0,0) * m(1,2) * m(2,1) -
688  m(1,0) * m(0,1) * m(2,2) + m(1,0) * m(0,2) * m(2,1) +
689  m(2,0) * m(0,1) * m(1,2) - m(2,0) * m(0,2) * m(1,1);
690 
691  double det = m(0,0) * mo(0,0) + m(0,1) * mo(1,0) + m(0,2) * mo(2,0) + m(0,3) * mo(0,3);
692  mln_precondition(det != 0);
693 
694  det = 1.0 / det;
695 
696  for (int i = 0; i < 4; i++)
697  for (int j = 0; j < 4; j++)
698  mo(i,j) *= det;
699 
700  return mo;
701  }
702 
703  } // end of namespace algebra::internal
704 
705  template <unsigned n, unsigned m, typename T>
706  inline
707  mat<n,m,T>
708  mat<n,m,T>::_1() const
709  {
710  mlc_bool(m == n)::check();
711  return internal::inverse(*this);
712  }
713 
714 
715 
716  // Operators.
717 
718  template <unsigned n, unsigned m, typename T, typename U>
719  inline
720  bool
721  operator==(const mat<n,m,T>& lhs, const mat<n,m,U>& rhs)
722  {
723  for (unsigned i = 0; i < n; ++i)
724  for (unsigned j = 0; j < m; ++j)
725  if (lhs(i, j) != rhs(i, j))
726  return false;
727  return true;
728  }
729 
730  template <unsigned n, unsigned m, typename T, typename U>
731  inline
732  mat<n, m, mln_trait_op_plus(T,U)>
733  operator+(const mat<n,m,T>& lhs, const mat<n,m,U>& rhs)
734  {
735  mat<n, m, mln_trait_op_plus(T,U)> tmp;
736  for (unsigned i = 0; i < n; ++i)
737  for (unsigned j = 0; j < m; ++j)
738  tmp(i, j) = lhs(i, j) + rhs(i, j);
739  return tmp;
740  }
741 
742  template <unsigned n, unsigned m, typename T, typename U>
743  inline
744  mat<n,m, mln_trait_op_minus(T,U)>
745  operator-(const mat<n,m,T>& lhs, const mat<n,m,U>& rhs)
746  {
747  mat<n,m, mln_trait_op_minus(T,U)> tmp;
748  for (unsigned i = 0; i < n; ++i)
749  for (unsigned j = 0; j < m; ++j)
750  tmp(i, j) = lhs(i, j) - rhs(i, j);
751  return tmp;
752  }
753 
754  template <unsigned n, unsigned m, typename T>
755  inline
756  mat<n,m, mln_trait_op_uminus(T)>
757  operator-(const mat<n,m,T>& rhs)
758  {
759  mat<n,m, mln_trait_op_uminus(T)> tmp;
760  for (unsigned i = 0; i < n; ++i)
761  for (unsigned j = 0; i < m; ++i)
762  tmp(i, j) = - rhs(i, j);
763  return tmp;
764  }
765 
766  // mat * mat
767 
768  template <unsigned n, unsigned o, typename T,
769  unsigned m, typename U>
770  inline
771  mat<n, m, mln_sum_product(T,U)>
772  operator*(const mat<n,o,T>& lhs, const mat<o,m,U>& rhs)
773  {
774  mat<n,m, mln_sum_product(T,U)> tmp;
775  for (unsigned i = 0; i < n; ++i)
776  for (unsigned j = 0; j < m; ++j)
777  {
778  tmp(i, j) = literal::zero;
779  for (unsigned k = 0; k < o; ++k)
780  tmp(i, j) += lhs(i, k) * rhs(k, j);
781  }
782  return tmp;
783  }
784 
785  template <unsigned o, typename T,
786  typename U>
787  inline
788  mln_sum_product(T,U)
789  operator*(const mat<1,o,T>& lhs, const mat<o,1,U>& rhs)
790  {
791  mln_sum_product(T,U) tmp(literal::zero);
792  for (unsigned k = 0; k < o; ++k)
793  tmp += lhs(0, k) * rhs(k, 0);
794  return tmp;
795  }
796 
797  // mat * vec
798 
799  template <unsigned n, unsigned m, typename T,
800  typename U>
801  inline
802  vec<n, mln_sum_product(T,U)>
803  operator*(const mat<n,m,T>& lhs, const vec<m,U>& rhs)
804  {
805  vec<n, mln_sum_product(T,U)> tmp;
806  for (unsigned i = 0; i < n; ++i)
807  {
808  mln_sum_product(T,U) sum(literal::zero);
809  for (unsigned j = 0; j < m; ++j)
810  sum += lhs(i, j) * rhs[j];
811  tmp[i] = sum;
812  }
813  return tmp;
814  }
815 
816  template <unsigned m, typename T,
817  typename U>
818  inline
819  mln_sum_product(T,U) // scalar
820  operator*(const mat<1,m,T>& lhs, const vec<m,U>& rhs)
821  {
822  mln_sum_product(T,U) tmp(literal::zero);
823  for (unsigned j = 0; j < m; ++j)
824  tmp += lhs(0, j) * rhs[j];
825  return tmp;
826  }
827 
828  // vec * mat
829 
830  template <unsigned m, typename T,
831  typename U>
832  inline
833  mat<m, m, mln_trait_op_times(T,U)>
834  operator*(const vec<m,T>& lhs, const mat<1,m,U>& rhs)
835  {
836  mat<m, m, mln_trait_op_times(T,U)> tmp;
837  for (unsigned i = 0; i < m; ++i)
838  for (unsigned j = 0; j < m; ++j)
839  tmp(i, j) = lhs[i] * rhs(0, j);
840  return tmp;
841  }
842 
843  // mat * s
844 
845  template <unsigned n, unsigned m, typename T, typename S>
846  inline
847  mat<n, m, mln_trait_op_times(T,S)>
848  operator*(const mat<n,m,T>& lhs, const value::scalar_<S>& s_)
849  {
850  S s = s_.to_equiv();
851  mat<n, m, mln_trait_op_times(T,S)> tmp;
852  for (unsigned i = 0; i < n; ++i)
853  for (unsigned j = 0; j < m; ++j)
854  tmp(i, j) = lhs(i, j) * s;
855  return tmp;
856  }
857 
858  template <unsigned n, unsigned m, typename T, typename S>
859  inline
860  mat<n,m, mln_trait_op_div(T,S)>
861  operator/(const mat<n,m,T>& lhs, const value::scalar_<S>& s_)
862  {
863  S s = s_.to_equiv();
864  mat<n,m, mln_trait_op_times(T,S)> tmp;
865  for (unsigned i = 0; i < n; ++i)
866  for (unsigned j = 0; j < m; ++j)
867  tmp(i,j) = lhs(i, j) / s;
868  return tmp;
869  }
870 
871  // <<
872 
873  template <unsigned n, unsigned m, typename T>
874  inline
875  std::ostream&
876  operator<<(std::ostream& ostr, const mat<n,m,T>& v)
877  {
878  for (unsigned i = 0; i < n; ++i)
879  {
880  ostr << '[';
881  for (unsigned j = 0; j < m; ++j)
882  ostr << debug::format(v(i, j)) << (j == m - 1 ? "]" : ", ");
883  ostr << std::endl;
884  }
885  return ostr;
886  }
887 
888 
889  // Trace.
890 
891  template<unsigned n, typename T>
892  inline
893  mln_sum(T)
894  tr(const mat<n,n,T>& m)
895  {
896  mln_sum(T) tr_ = literal::zero;
897  for (unsigned i = 0; i < n; ++i)
898  tr_ += m(i,i);
899  return tr_;
900  }
901 
902 
903  // Determinant.
904 
905  namespace impl
906  {
907 
908  template<unsigned n, typename T>
909  mln_sum_product(T,T)
910  det(const mat<n,n,T>& /* m */)
911  {
912  // Not implemented.
913  mlc_abort(T)::check();
914  }
915 
916  template<typename T>
917  inline
918  mln_sum_product(T,T)
919  det(const mat<2,2,T>& m)
920  {
921  return m(0,0) * m(1,1) - m(0,1) * m(1,0);
922  }
923 
924  template<typename T>
925  inline
926  mln_sum_product(T,T)
927  det(const mat<3,3,T>& m)
928  {
929  return
930  + m(0,0) * m(1,1) * m(2,2)
931  - m(0,0) * m(1,2) * m(2,1)
932  - m(0,1) * m(1,0) * m(2,2)
933  + m(0,1) * m(1,2) * m(2,0)
934  + m(0,2) * m(1,0) * m(2,1)
935  - m(0,2) * m(1,1) * m(2,0);
936  }
937 
938  template<typename T>
939  inline
940  mln_sum_product(T,T)
941  det(const mat<4,4,T>& m)
942  {
943  return m(0,3) * m(1,2) * m(2,1) * m(3,0) - m(0,2) * m(1,3) * m(2,1) * m(3,0) -
944  m(0,3) * m(1,1) * m(2,2) * m(3,0) + m(0,1) * m(1,3) * m(2,2) * m(3,0) +
945  m(0,2) * m(1,1) * m(2,3) * m(3,0) - m(0,1) * m(1,2) * m(2,3) * m(3,0) -
946  m(0,3) * m(1,2) * m(2,0) * m(3,1) + m(0,2) * m(1,3) * m(2,0) * m(3,1) +
947  m(0,3) * m(1,0) * m(2,2) * m(3,1) - m(0,0) * m(1,3) * m(2,2) * m(3,1) -
948  m(0,2) * m(1,0) * m(2,3) * m(3,1) + m(0,0) * m(1,2) * m(2,3) * m(3,1) +
949  m(0,3) * m(1,1) * m(2,0) * m(3,2) - m(0,1) * m(1,3) * m(2,0) * m(3,2) -
950  m(0,3) * m(1,0) * m(2,1) * m(3,2) + m(0,0) * m(1,3) * m(2,1) * m(3,2) +
951  m(0,1) * m(1,0) * m(2,3) * m(3,2) - m(0,0) * m(1,1) * m(2,3) * m(3,2) -
952  m(0,2) * m(1,1) * m(2,0) * m(3,3) + m(0,1) * m(1,2) * m(2,0) * m(3,3) +
953  m(0,2) * m(1,0) * m(2,1) * m(3,3) - m(0,0) * m(1,2) * m(2,1) * m(3,3) -
954  m(0,1) * m(1,0) * m(2,2) * m(3,3) + m(0,0) * m(1,1) * m(2,2) * m(3,3);
955  }
956 
957  } // end of namespace mln::algebra::impl
958 
959 
960  template<unsigned n, typename T>
961  inline
962  mln_sum_product(T,T)
963  det(const mat<n,n,T>& m)
964  {
965  return mln::algebra::impl::det(m);
966  }
967 
968 
969 
970 
971  // vec methods.
972 
973  template <unsigned n, typename T>
974  inline
975  mat<1,n,T>
976  vec<n,T>::t() const
977  {
978  mat<1,n,T> tmp;
979  for (unsigned i = 0; i < n; ++i)
980  tmp(0,i) = data_[i];
981  return tmp;
982  }
983 
984 
985 # endif // ! MLN_INCLUDE_ONLY
986 
987  } // end of namespace mln::algebra
988 
989 } // end of namespace mln
990 
991 # include <mln/make/mat.hh>
992 
993 #endif // ! MLN_ALGEBRA_MAT_HH