27 #ifndef MLN_ALGEBRA_MAT_HH
28 # define MLN_ALGEBRA_MAT_HH
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>
55 template <
unsigned n,
unsigned m,
typename T>
class mat;
62 template <
unsigned n,
unsigned m,
typename T>
63 struct value_< algebra::
mat<n,m,T> >
65 typedef trait::value::nature::matrix
nature;
66 typedef trait::value::kind::data
kind;
69 nbits = n * m * mln_nbits(
T),
70 card = n * m * mln_card(
T)
72 typedef mln_value_quant_from_(card) quant;
74 typedef algebra::mat<n, m, mln_sum(
T)>
sum;
87 template <
unsigned n,
unsigned m,
typename T>
105 template <
typename U>
109 template <
typename F>
112 template <
typename U>
115 const T& operator()(
unsigned i,
unsigned j)
const;
117 T& operator()(
unsigned i,
unsigned j);
119 void set_all(
const T& val);
121 unsigned size()
const;
123 static mat identity();
149 template <
unsigned n,
unsigned m,
typename T >
150 struct set_precise_unary_< op::uminus,
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> >
162 typedef algebra::mat<n, m, mln_trait_op_plus(T, U)>
ret;
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> >
171 typedef algebra::mat<n, m, mln_trait_op_minus(T, U)>
ret;
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> >
181 typedef algebra::mat<n, m, mln_sum_product(T, U)>
ret;
184 template <
unsigned o,
typename T,
186 struct set_precise_binary_< op::
times,
187 algebra::mat<1,o,T>, algebra::mat<o,1,U> >
189 typedef mln_sum_product(
T, U)
ret;
194 template <
unsigned n,
unsigned m, typename
T,
196 struct set_precise_binary_< op::times,
197 algebra::mat<n,m,T>, algebra::vec<m,U> >
199 typedef algebra::vec<n, mln_sum_product(T, U)> ret;
202 template <
unsigned m,
typename T,
204 struct set_precise_binary_< op::
times,
205 algebra::mat<1,m,T>, algebra::vec<m,U> >
207 typedef mln_sum_product(
T, U)
ret;
212 template <
unsigned m, typename
T,
214 struct set_precise_binary_< op::times,
215 algebra::vec<m,T>, algebra::mat<1,m,U> >
217 typedef algebra::mat<m, m, mln_trait_op_times(T, U)> ret;
222 template <
unsigned n,
unsigned m,
typename T,
224 struct set_precise_binary_< op::
times,
227 typedef algebra::mat<n, m, mln_trait_op_times(T, S)>
ret;
242 template <
unsigned n,
unsigned m,
typename T,
244 struct set_precise_binary_< op::
div,
247 typedef algebra::mat<n, m, mln_trait_op_div(T, S)>
ret;
259 template <
unsigned n,
unsigned m,
typename T,
typename U>
265 template <
unsigned n,
unsigned m,
typename T>
266 mat<n, m, mln_trait_op_uminus(T)>
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);
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);
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);
288 template <
unsigned o,
typename T,
291 operator*(const mat<1,
o,
T>& lhs, const mat<o,1,U>&
rhs);
295 template <
unsigned n,
unsigned m, typename
T,
297 vec<n, mln_sum_product(T,U)>
298 operator*(const mat<n,m,T>& lhs, const vec<m,U>& rhs);
300 template <
unsigned m, typename T,
303 operator*(const mat<1,m,T>& lhs, const vec<m,U>& rhs);
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);
313 template <
unsigned n,
unsigned m, typename T,
315 mat<n, m, mln_trait_op_times(T,S)>
316 operator*(const mat<n,m,T>& lhs, const
value::scalar_<S>& s);
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);
326 template <
unsigned n,
unsigned m, typename T>
328 operator<<(std::ostream& ostr, const mat<n,m,T>& v);
335 template<
unsigned n, typename T>
337 tr(const mat<n,n,T>& m);
343 template<
unsigned n, typename T>
345 det(const mat<n,n,T>& m);
349 # ifndef MLN_INCLUDE_ONLY
354 template <
unsigned n,
typename T>
355 template <
typename U>
357 vec<n,T>::operator mat<n,1,U>()
const
359 mlc_converts_to(T, U)::check();
361 for (
unsigned i = 0; i < n; ++i)
362 tmp(i, 0) = data_[i];
369 template <
unsigned n,
typename T>
370 template <
typename U>
372 vec<n,T>::vec(
const mat<n, 1, U>& rhs)
374 mlc_converts_to(T, U)::check();
375 for (
unsigned i = 0; i < n; ++i)
376 data_[i] =
rhs(i, 0);
379 template <
unsigned n,
typename T>
380 template <
typename U>
383 vec<n,T>::operator=(
const mat<n, 1, U>& rhs)
385 mlc_converts_to(T, U)::check();
386 for (
unsigned i = 0; i < n; ++i)
387 data_[i] =
rhs(i, 0);
395 template <
unsigned n,
unsigned m,
typename T>
397 mat<n,m,T>::Id = mat<n,m,T>::identity();
399 template <
unsigned n,
unsigned m,
typename T>
402 mat<n,m,T>::identity()
404 static mat<n,m,T> id_;
405 static bool flower =
true;
408 for (
unsigned i = 0; i < n; ++i)
409 for (
unsigned j = 0; j < m; ++j)
410 id_(i, j) = (i == j);
416 template <
unsigned n,
unsigned m,
typename T>
422 template <
unsigned n,
unsigned m,
typename T>
424 mat<n,m,T>::mat(
const literal::zero_t&)
429 template <
unsigned n,
unsigned m,
typename T>
432 mat<n,m,T>::set_id_()
434 for (
unsigned i = 0; i < n; ++i)
435 for (
unsigned j = 0; j < m; ++j)
442 template <
unsigned n,
unsigned m,
typename T>
444 mat<n,m,T>::mat(
const literal::one_t&)
449 template <
unsigned n,
unsigned m,
typename T>
451 mat<n,m,T>::mat(
const literal::identity_t&)
456 template <
unsigned n,
unsigned m,
typename T>
457 template <
typename U>
459 mat<n,m,T>::mat(
const mat<n,m,U>& rhs)
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) );
466 template <
unsigned n,
unsigned m,
typename T>
467 template <
typename F>
469 mat<n,m,T>::mat(
const Function_v2v<F>& f_)
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) );
478 template <
unsigned n,
unsigned m,
typename T>
479 template <
typename U>
482 mat<n,m,T>::operator=(
const mat<n,m,U>& rhs)
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) );
490 template <
unsigned n,
unsigned m,
typename T>
493 mat<n,m,T>::operator()(
unsigned i,
unsigned j)
const
495 mln_precondition(i < n && j < m);
499 template <
unsigned n,
unsigned m,
typename T>
502 mat<n,m,T>::operator()(
unsigned i,
unsigned j)
504 mln_precondition(i < n && j < m);
508 template <
unsigned n,
unsigned m,
typename T>
510 void mat<n,m,T>::set_all(
const T& val)
512 for (
unsigned i = 0; i < n; ++i)
513 for (
unsigned j = 0; j < m; ++j)
517 template <
unsigned n,
unsigned m,
typename T>
519 unsigned mat<n,m,T>::size()
const
524 template <
unsigned n,
unsigned m,
typename T>
527 mat<n,m,T>::t()
const
530 for (
unsigned i = 0; i < n; ++i)
531 for (
unsigned j = 0; j < m; ++j)
532 tmp(j,i) = data_[i][j];
542 template <
typename T>
545 make(
const T& t00,
const T& t01,
546 const T& t10,
const T& t11)
549 tmp(0, 0) = t00; tmp(0, 1) = t01;
550 tmp(1, 0) = t10; tmp(1, 1) = t11;
554 template <
typename 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)
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;
571 template <
typename T>
574 inverse(
const mat<2,2,T>& 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 );
582 template <
typename T>
585 inverse(
const mat<3,3,T>& m)
588 mln_precondition(d != 0);
589 return make<float>(
det(make(m(1,1), m(1,2),
592 det(make(m(0,2), m(0,1),
595 det(make(m(0,1), m(0,2),
599 det(make(m(1,2), m(1,0),
602 det(make(m(0,0), m(0,2),
605 det(make(m(0,2), m(0,0),
608 det(make(m(1,0), m(1,1),
611 det(make(m(0,1), m(0,0),
614 det(make(m(0,0), m(0,1),
619 template <
typename T>
622 inverse(
const mat<4,4,T>& m)
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
696 for (
int i = 0; i < 4; i++)
697 for (
int j = 0; j < 4; j++)
705 template <
unsigned n,
unsigned m,
typename T>
708 mat<n,m,T>::_1()
const
710 mlc_bool(m == n)::check();
711 return internal::inverse(*
this);
718 template <
unsigned n,
unsigned m,
typename T,
typename U>
721 operator==(
const mat<n,m,T>& lhs,
const mat<n,m,U>& rhs)
723 for (
unsigned i = 0; i < n; ++i)
724 for (
unsigned j = 0; j < m; ++j)
725 if (lhs(i, j) !=
rhs(i, j))
730 template <
unsigned n,
unsigned m,
typename T,
typename U>
732 mat<n, m, mln_trait_op_plus(T,U)>
733 operator+(
const mat<n,m,T>& lhs,
const mat<n,m,U>& rhs)
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);
742 template <
unsigned n,
unsigned m,
typename T,
typename U>
744 mat<n,m, mln_trait_op_minus(T,U)>
745 operator-(
const mat<n,m,T>& lhs,
const mat<n,m,U>& rhs)
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);
754 template <
unsigned n,
unsigned m,
typename T>
756 mat<n,m, mln_trait_op_uminus(T)>
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);
768 template <
unsigned n,
unsigned o,
typename T,
769 unsigned m,
typename U>
771 mat<n, m, mln_sum_product(T,U)>
772 operator*(
const mat<n,o,T>& lhs,
const mat<o,m,U>& rhs)
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)
779 for (
unsigned k = 0; k <
o; ++k)
780 tmp(i, j) += lhs(i, k) *
rhs(k, j);
785 template <
unsigned o,
typename T,
789 operator*(const mat<1,o,T>& lhs, const mat<o,1,U>& rhs)
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);
799 template <
unsigned n,
unsigned m, typename T,
802 vec<n, mln_sum_product(T,U)>
803 operator*(const mat<n,m,T>& lhs, const vec<m,U>& rhs)
805 vec<n, mln_sum_product(T,U)> tmp;
806 for (
unsigned i = 0; i < n; ++i)
808 mln_sum_product(T,U)
sum(literal::zero);
809 for (
unsigned j = 0; j < m; ++j)
810 sum += lhs(i, j) * rhs[j];
816 template <
unsigned m, typename T,
820 operator*(const mat<1,m,T>& lhs, const vec<m,U>& rhs)
822 mln_sum_product(T,U) tmp(literal::zero);
823 for (
unsigned j = 0; j < m; ++j)
824 tmp += lhs(0, j) * rhs[j];
830 template <
unsigned m, typename T,
833 mat<m, m, mln_trait_op_times(T,U)>
834 operator*(const vec<m,T>& lhs, const mat<1,m,U>& rhs)
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);
845 template <
unsigned n,
unsigned m,
typename T,
typename S>
847 mat<n, m, mln_trait_op_times(T,S)>
848 operator*(
const mat<n,m,T>& lhs,
const value::scalar_<S>& s_)
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;
858 template <
unsigned n,
unsigned m,
typename T,
typename S>
860 mat<n,m, mln_trait_op_div(T,S)>
861 operator/(
const mat<n,m,T>& lhs,
const value::scalar_<S>& s_)
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;
873 template <
unsigned n,
unsigned m,
typename T>
876 operator<<(std::ostream& ostr, const mat<n,m,T>& v)
878 for (
unsigned i = 0; i < n; ++i)
881 for (
unsigned j = 0; j < m; ++j)
891 template<
unsigned n,
typename T>
894 tr(const mat<n,n,T>& m)
896 mln_sum(T) tr_ = literal::zero;
897 for (
unsigned i = 0; i < n; ++i)
908 template<
unsigned n,
typename T>
910 det(const mat<n,n,T>& )
913 mlc_abort(T)::check();
919 det(const mat<2,2,T>& m)
921 return m(0,0) * m(1,1) - m(0,1) * m(1,0);
927 det(const mat<3,3,T>& m)
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);
941 det(const mat<4,4,T>& m)
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);
960 template<
unsigned n,
typename T>
963 det(const mat<n,n,T>& m)
965 return mln::algebra::impl::det(m);
973 template <
unsigned n,
typename T>
979 for (
unsigned i = 0; i < n; ++i)
985 # endif // ! MLN_INCLUDE_ONLY
991 # include <mln/make/mat.hh>
993 #endif // ! MLN_ALGEBRA_MAT_HH