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