algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/matrix.hpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : matrix.hpp
00004 * DESCRIPTION: Dense matrices
00005 * COPYRIGHT  : (C) 2004--2007  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license and comes WITHOUT
00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details.
00009 * If you don't have this file, write to the Free Software Foundation, Inc.,
00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00011 ******************************************************************************/
00012 
00013 #ifndef __MMX_MATRIX_HPP
00014 #define __MMX_MATRIX_HPP
00015 #include <basix/iterator.hpp>
00016 #include <basix/vector.hpp>
00017 #include <algebramix/permutation.hpp>
00018 #include <algebramix/matrix_naive.hpp>
00019 
00020 namespace mmx {
00021 #define Matrix_variant(C) matrix_variant_helper<C>::MV
00022 #define TMPL_DEF template<typename C, typename V= typename Matrix_variant(C)>
00023 #define TMPL template<typename C, typename V>
00024 #define TMPLK template<typename C, typename V, typename K>
00025 #define Format format<C>
00026 #define Matrix matrix<C,V>
00027 #define Matrix_rep matrix_rep<C,V>
00028 #define Abs_matrix matrix<Abs_type(C),V>
00029 #define Real_matrix matrix<Real_type(C),V>
00030 #define Center_matrix matrix<Center_type(C),V>
00031 #define Radius_matrix matrix<Radius_type(C),V>
00032 TMPL class matrix_rep;
00033 TMPL class matrix;
00034 TMPL inline nat cols (const Matrix& m);
00035 TMPL inline nat rows (const Matrix& m);
00036 TMPL inline bool is_a_scalar   (const Matrix& m);
00037 TMPL inline bool is_non_scalar (const Matrix& m);
00038 TMPL inline C* tab (Matrix& m);
00039 TMPL inline const C* tab (const Matrix& m);
00040 
00041 /******************************************************************************
00042 * Dense matrices of arbitrary sizes
00043 ******************************************************************************/
00044 
00045 TMPL_DEF
00046 class matrix_rep REP_STRUCT_1(C) {
00047   C*   a;
00048   nat  nr;
00049   nat  nc;
00050   bool scalar_flag;
00051 public:
00052   inline matrix_rep (C* a2, nat nr2, nat nc2, bool flag, const Format& fm):
00053     Format (fm), a (a2), nr (nr2), nc (nc2), scalar_flag (flag) {}
00054   inline ~matrix_rep () { mmx_delete<C> (a, aligned_size<C,V> (nr * nc)); }
00055   friend class Matrix;
00056   friend nat cols LESSGTR (const Matrix& m);
00057   friend nat rows LESSGTR (const Matrix& m);
00058   friend C* tab LESSGTR (Matrix& m);
00059   friend const C* tab LESSGTR (const Matrix& m);
00060   friend bool is_a_scalar   LESSGTR (const Matrix& m);
00061   friend bool is_non_scalar LESSGTR (const Matrix& m);
00062 };
00063 
00064 TMPL_DEF
00065 class matrix {
00066 INDIRECT_PROTO_2 (matrix, matrix_rep, C, V)
00067 public:
00068   typedef implementation<vector_linear,V> Vec;
00069   typedef implementation<matrix_linear,V> Mat;
00070 private:
00071   static C zero;
00072 public:
00073   matrix (const Format& fm= Format (no_format ())) {
00074     nat nc = Mat::def_rows;
00075     nat nr = Mat::def_cols;
00076     nat l  = aligned_size<C,V> (nr * nc);
00077     C*  tab= mmx_formatted_new<C> (l, fm);
00078     rep= new Matrix_rep (tab, nr, nc, false, fm);
00079   }
00080 
00081   template<typename T>
00082   matrix (const T& c) {
00083     Format fm= get_format (as<C> (c));
00084     nat nr = Mat::init_rows;
00085     nat nc = Mat::init_cols;
00086     nat l  = aligned_size<C,V> (nr * nc);
00087     C*  tab= mmx_formatted_new<C> (l, fm);
00088     rep= new Matrix_rep (tab, nr, nc, true, fm);
00089     Mat::set (rep->a, C(c), nr, nc);
00090   }
00091 
00092   template<typename T>
00093   matrix (const T& c, const Format& fm) {
00094     nat nr = Mat::init_rows;
00095     nat nc = Mat::init_cols;
00096     nat l  = aligned_size<C,V> (nr * nc);
00097     C*  tab= mmx_formatted_new<C> (l, fm);
00098     rep= new Matrix_rep (tab, nr, nc, true, fm);
00099     Mat::set (rep->a, C(c), nr, nc);
00100   }
00101 
00102   template<typename T, typename W>
00103   matrix (const matrix<T,W>& m) {
00104     Format fm= as<Format > (CF(m));
00105     nat l= aligned_size<C,V> (rows(m) * cols(m));
00106     C*  t= mmx_formatted_new<C> (l, fm);
00107     rep= new Matrix_rep (t, rows(m), cols(m), is_a_scalar (m), fm);
00108     Vec::cast (rep->a, tab(m), rows(m) * cols(m));
00109   }
00110 
00111   template<typename T, typename W>
00112   matrix (const matrix<T,W>& m, const Format& fm) {
00113     nat l= aligned_size<C,V> (rows(m) * cols(m));
00114     C*  t= mmx_formatted_new<C> (l, fm);
00115     rep= new Matrix_rep (t, rows(m), cols(m), is_a_scalar (m), fm);
00116     Vec::cast (rep->a, tab(m), rows(m) * cols(m));
00117   }
00118 
00119   matrix (const C& x) {
00120     Format fm= get_format (x);
00121     nat nr = Mat::init_rows;
00122     nat nc = Mat::init_cols;
00123     nat l  = aligned_size<C,V> (nr * nc);
00124     C*  tab= mmx_formatted_new<C> (l, fm);
00125     rep= new Matrix_rep (tab, nr, nc, true, fm);
00126     Mat::set (rep->a, x, nr, nc);
00127   }
00128 
00129   matrix (const C& x, nat nr, nat nc) {
00130     Format fm= get_format (x);
00131     nat l  = aligned_size<C,V> (nr * nc);
00132     C*  tab= mmx_formatted_new<C> (l, fm);
00133     rep= new Matrix_rep (tab, nr, nc, false, fm);
00134     Mat::set (rep->a, x, nr, nc);
00135   }
00136 
00137   matrix (C* tab, nat nr, nat nc, const Format& fm) {
00138     rep= new Matrix_rep (tab, nr, nc, false, fm);
00139   }
00140 
00141   matrix (C* tab, nat nr, nat nc, bool flag, const Format& fm) {
00142     rep= new Matrix_rep (tab, nr, nc, flag, fm);
00143   }
00144 
00145   matrix (const iterator<C>& it) {
00146     Format fm= CF(it);
00147     nat i, j, nr= Mat::def_rows, nc= Mat::def_cols;
00148     if (nr==0) nr=1;
00149     nat l  = aligned_size<C,V> (nr * nc);
00150     C*  tab= mmx_formatted_new<C> (l, fm);
00151     for (i=0; i<nr; i++, ++it)
00152       for (j=0; j<nc; j++, ++it)
00153         tab[Mat::index (i, j, nr, nc)]= *it;
00154     rep= new Matrix_rep (tab, nc, nr, false, fm);
00155   }
00156 
00157   inline const C& operator () (nat i, nat j) const {
00158     VERIFY (is_non_scalar (*this), "non-scalar matrix expected");
00159     VERIFY (i<rep->nr, "row out of range");
00160     VERIFY (j<rep->nc, "column out of range");
00161     return rep->a[Mat::index (i, j, rows (*this), cols(*this))]; }
00162   inline C& operator () (nat i, nat j) {
00163     VERIFY (is_non_scalar (*this), "non-scalar matrix expected");
00164     VERIFY (i<rep->nr, "row out of range");
00165     VERIFY (j<rep->nc, "column out of range");
00166     return rep->a[Mat::index (i, j, rows (*this), cols(*this))]; }
00167   inline C scalar () const {
00168     VERIFY (is_a_scalar (*this), "scalar matrix expected");
00169     return rep->a[0]; }
00170   inline C& scalar () {
00171     VERIFY (is_a_scalar (*this), "scalar matrix expected");
00172     return rep->a[0]; }
00173 };
00174 INDIRECT_IMPL_2 (matrix, matrix_rep, typename C, C, typename V, V)
00175 DEFINE_UNARY_FORMAT_2 (matrix)
00176 
00177 TMPL C Matrix::zero= C(0);
00178 TMPL inline nat rows (const Matrix& m) { return m->nr; }
00179 TMPL inline nat cols (const Matrix& m) { return m->nc; }
00180 TMPL inline nat nbcol (const Matrix& m) {return cols(m);}
00181 TMPL inline nat nbrow (const Matrix& m) {return rows(m);} 
00182 TMPL inline nat N (const Matrix& m) { return rows (m) * cols (m); } 
00183 TMPL inline Format CF (const Matrix& m) { return m->tfm (); }
00184 TMPL inline bool is_a_scalar (const Matrix& m) { return m->scalar_flag; }
00185 TMPL inline bool is_non_scalar (const Matrix& m) { return !m->scalar_flag; }
00186 TMPL inline bool is_square_matrix (const Matrix& m) {
00187   return rows (m) == cols (m); }
00188 TMPL inline const C& read (const Matrix& m, nat i, nat j) { return m(i,j); }
00189 TMPL inline const C* tab (const Matrix& m) { return m->a; }
00190 TMPL inline C* tab (Matrix& m) {
00191   VERIFY (is_non_scalar (m), "non-scalar matrix expected");
00192   m.secure(); return m->a; }
00193 template<typename C, typename V, typename C2, typename V2> inline Matrix
00194 extend (const Matrix& m, const matrix<C2,V2>& n) {
00195   VERIFY (is_a_scalar (m), "scalar matrix expected");
00196   VERIFY (is_non_scalar (n), "non-scalar matrix expected");
00197   return Matrix (m.scalar(), rows (n), cols (n)); }
00198 
00199 STYPE_TO_TYPE(TMPL,scalar_type,Matrix,C);
00200 UNARY_RETURN_TYPE(TMPL,abs_op,Matrix,Abs_matrix);
00201 UNARY_RETURN_TYPE(TMPL,Re_op,Matrix,Real_matrix);
00202 UNARY_RETURN_TYPE(TMPL,center_op,Matrix,Center_matrix);
00203 UNARY_RETURN_TYPE(TMPL,radius_op,Matrix,Radius_matrix);
00204 
00205 TMPL
00206 struct fast_helper<Matrix > {
00207   typedef Fast_type(C) FC;
00208   typedef matrix<FC> fast_type;
00209   typedef typename Matrix_variant(FC) FV;
00210   static inline fast_type dd (const Matrix& m) {
00211     typedef implementation<vector_linear,FV> FVec;
00212     format<FC> fm= fast (CF(m));
00213     nat l= aligned_size<FC,FV> (rows (m) * cols (m));
00214     FC* r= mmx_formatted_new<FC> (l, fm);
00215     FVec::template vec_unary<fast_op> (r, tab (m), rows (m) * cols (m));
00216     return fast_type (r, rows (m), cols (m), is_a_scalar (m), fm); }
00217   static inline Matrix uu (const fast_type& m) {
00218     typedef implementation<vector_linear,V> Vec;
00219     Format fm= slow<C> (CF(m));
00220     nat l= aligned_size<C,V> (rows (m) * cols (m));
00221     C*  r= mmx_formatted_new<C> (l, fm);
00222     Vec::template vec_unary<slow_op> (r, tab (m), rows (m) * cols (m));
00223     return Matrix (r, rows (m), cols (m), is_a_scalar (m), fm); }
00224 };
00225 
00226 template<typename T, typename F, typename TV, typename FV>
00227 struct as_helper<matrix<T,TV>,matrix<F,FV> > {
00228   static inline matrix<T,TV>
00229   cv (const matrix<F,FV>& m) {
00230     format<T> fm= as<format<T> > (CF(m));
00231     nat n= rows(m) * cols(m);
00232     nat l= aligned_size<T,TV> (rows (m) * cols (m));
00233     const F* sm= tab (m);
00234     T* c= mmx_formatted_new<T> (l, fm);
00235     for (nat i=0; i<n; i++) c[i]= as<T> (sm[i]);
00236     return matrix<T,TV> (c, rows (m), cols (m), is_a_scalar (m), fm); }
00237 };
00238 
00239 template<typename T, typename F, typename TV, typename FV> inline void
00240 set_as (matrix<T,TV>& r, const matrix<F,FV>& m) {
00241   r= matrix<T,TV> (m, CF(r));
00242 }
00243 
00244 template<typename C, typename V, typename T> inline void
00245 set_as (Matrix& r, const T& x) {
00246   r= Matrix (x, CF(r));
00247 }
00248 
00249 /******************************************************************************
00250 * Fixed size dense matrices
00251 ******************************************************************************/
00252 
00253 template<typename V, typename RS, typename CS>
00254 struct matrix_fixed: public V {
00255   typedef implementation<vector_linear,V> Vec;
00256   typedef matrix_fixed<typename V::Naive,RS,CS> Naive;
00257   typedef matrix_fixed<typename V::Positive,RS,CS> Positive;
00258   typedef matrix_fixed<typename V::No_simd,RS,CS> No_simd;
00259   typedef matrix_fixed<typename V::No_thread,RS,CS> No_thread;
00260   typedef matrix_fixed<typename V::No_scaled,RS,CS> No_scaled;
00261 };
00262 
00263 template<typename F, typename V, typename RS, typename CS>
00264 struct implementation<F,matrix_fixed<V,RS,CS> >:
00265   public implementation<F,V> {};
00266 
00267 template<typename V, typename RS, typename CS>
00268 struct implementation<matrix_defaults,matrix_fixed<V,RS,CS> > {
00269   static const nat def_rows = RS::val;
00270   static const nat def_cols = CS::val;
00271   static const nat init_rows= RS::val;
00272   static const nat init_cols= CS::val;
00273 };
00274 
00275 #define FMatrix matrix<C,matrix_fixed<V,RS,CS> >
00276 #define FMatrix_rep matrix_rep<C,matrix_fixed<V,RS,CS> >
00277 
00278 template<typename C, typename V, typename RS, typename CS>
00279 class FMatrix_rep REP_STRUCT_1(C) {
00280   C* a;
00281 public:
00282   inline matrix_rep (C* a2, nat, nat, bool, const Format& fm):
00283     Format (fm), a (a2) {}
00284   inline virtual ~matrix_rep () { mmx_delete<C> (a, RS::val * CS::val); }
00285   friend class FMatrix;
00286   friend nat cols LESSGTR (const FMatrix& m);
00287   friend nat rows LESSGTR (const FMatrix& m);
00288   friend C*  tab  LESSGTR (const FMatrix& m);
00289   friend bool is_a_scalar   LESSGTR (const Matrix& m);
00290   friend bool is_non_scalar LESSGTR (const Matrix& m);
00291 };
00292 
00293 template<typename C, typename V, typename RS, typename CS> inline nat
00294 cols (const FMatrix& m) { return CS::val; }
00295 template<typename C, typename V, typename RS, typename CS> inline nat
00296 rows (const FMatrix& m) { return RS::val; }
00297 template<typename C, typename V, typename RS, typename CS> inline bool
00298 is_a_scalar (const FMatrix& m) { (void) m; return false; }
00299 template<typename C, typename V, typename RS, typename CS> inline bool
00300 is_non_scalar (const FMatrix& m) { (void) m; return true; }
00301 
00302 #undef FMatrix
00303 #undef FMatrix_rep
00304 
00305 /******************************************************************************
00306 * Matrix iteration
00307 ******************************************************************************/
00308 
00309 TMPL_DEF
00310 class matrix_iterator_rep: public iterator_rep<C> {
00311 public:
00312   typedef implementation<matrix_linear,V> Mat;
00313 private:
00314   const Matrix m;  // the matrix to traverse
00315   nat i;           // current row
00316   nat j;           // current column
00317   nat nc;
00318 protected:
00319   bool is_busy () { return i < rows(m); }
00320   void advance () { j++; if (j >= cols(m)) { j=0; i++; } }
00321   C current () {return m (i, j); }
00322 public:
00323   matrix_iterator_rep (const Matrix& m2, nat c = Mat::def_cols):
00324     iterator_rep<C> (CF(m)), m(m2), i(0), j(0), nc(c) {}
00325 };
00326 
00327 TMPL iterator<C>
00328 iterate (const Matrix& m) {
00329   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
00330   return iterator<C> (new matrix_iterator_rep<C,V> (m));
00331 }
00332 
00333 /******************************************************************************
00334 * Hashing and generic output routines for matrices
00335 ******************************************************************************/
00336 
00337 TMPL syntactic
00338 flatten (const Matrix& m) {
00339   if (is_a_scalar (m)) return flatten (m.scalar());
00340   int i, j, nr= rows(m), nc= cols(m);
00341   vector<syntactic> v;
00342   for (i=0; i<nr; i++) {
00343     vector<syntactic> h;
00344     for (j=0; j<nc; j++)
00345       h << flatten (m (i, j));
00346     v << apply (GEN_ROW, h);
00347   }
00348   return apply (GEN_SQTUPLE, v);
00349 }
00350 
00351 TMPL
00352 struct binary_helper<Matrix >: public void_binary_helper<Matrix > {
00353   static inline string short_type_name () {
00354     return "M" * Short_type_name (C); }
00355   static inline generic full_type_name () {
00356     return gen ("Matrix", Full_type_name (C)); }
00357   static generic disassemble (const Matrix& m) {
00358     if (is_a_scalar (m)) return as<generic> (m.scalar ());
00359     vector<generic> v= vec (as<generic> (rows (m)), as<generic> (cols (m)));
00360     for (nat i=0; i<rows(m)*cols(m); i++)
00361       v << as<generic> (tab(m)[i]);
00362     return as<generic> (v); }
00363   static Matrix assemble (const generic& x) {
00364     // FIXME: what to do with the format?
00365     if (!is<vector<generic> > (x)) return Matrix (as<C> (x));
00366     vector<generic> v= as<vector<generic> > (x);
00367     nat rs= as<nat> (v[0]);
00368     nat cs= as<nat> (v[1]);
00369     nat l = aligned_size<C,V> (rs*cs);
00370     C*  r = mmx_new<C> (l);
00371     for (nat i=0; i<rs*cs; i++)
00372       r[i]= as<C> (v[i+2]);
00373     return Matrix (r, rs, cs, Format ()); }
00374   static void write (const port& out, const Matrix& m) {
00375     binary_write<Format > (out, CF (m));
00376     binary_write<bool> (out, is_a_scalar (m));
00377     if (is_a_scalar (m)) binary_write<C> (out, m.scalar ());
00378     else {
00379       binary_write<nat> (out, rows(m));
00380       binary_write<nat> (out, cols(m));
00381       for (nat i=0; i<rows(m)*cols(m); i++)
00382         binary_write<C> (out, tab(m)[i]); } }
00383   static Matrix read (const port& in) {
00384     Format fm= binary_read<Format > (in);
00385     bool sc= binary_read<bool> (in);
00386     if (sc) return Matrix (binary_read<C> (in), fm);
00387     else {
00388       nat rs= binary_read<nat> (in);
00389       nat cs= binary_read<nat> (in);
00390       nat l = aligned_size<C,V> (rs*cs);
00391       C*  r = mmx_formatted_new<C> (l, fm);
00392       for (nat i=0; i<rs*cs; i++)
00393         r[i]= binary_read<C> (in);
00394       return Matrix (r, rs, cs, fm); } }
00395 };
00396 
00397 /******************************************************************************
00398 * Abstract routines on dense matrices
00399 ******************************************************************************/
00400 
00401 template<typename Op, typename C, typename V> nat
00402 unary_hash (const matrix<C,V>& m) {
00403   register nat i, j, h= 214365, nr= rows (m), nc= cols (m);
00404   for (i=0; i<nr; i++)
00405     for (j=0; j<nc; j++)
00406       h= (h<<1) ^ (h<<5) ^ (h>>27) ^ Op::op (m (i, j));
00407   return h;
00408 }
00409 
00410 template<typename Op, typename C, typename V>
00411 matrix<Unary_return_type(Op,C),V>
00412 unary_map (const matrix<C,V>& m) {
00413   typedef implementation<vector_linear,V> Vec;
00414   typedef Unary_return_type(Op,C) T;
00415   format<T> fm= unary_map<Op> (CF(m));
00416   if (is_a_scalar (m)) return matrix<T,V> (Op::op (m.scalar()));
00417   nat nrows= rows (m);
00418   nat ncols= cols (m);
00419   nat l= aligned_size<T,V> (nrows * ncols);
00420   T*  r= mmx_formatted_new<T> (l, fm);
00421   Vec::template vec_unary<Op> (r, tab (m), nrows*ncols);
00422   return matrix<T,V> (r, nrows, ncols, fm);
00423 }
00424 
00425 template<typename Op, typename C1, typename C2, typename V>
00426 matrix<Binary_return_type(Op,C1,C2),V>
00427 binary_map (const matrix<C1,V>& m, const matrix<C2,V>& n) {
00428   typedef implementation<vector_linear,V> Vec;
00429   typedef Binary_return_type(Op,C1,C2) T;
00430   format<T> fm= binary_map<Op> (CF(m), CF(n));
00431   if (is_a_scalar (m) || is_a_scalar (n)) {
00432     if (is_non_scalar (m)) return binary_map<Op> (m, extend (n, m));
00433     if (is_non_scalar (n)) return binary_map<Op> (extend (m, n), n);
00434     return matrix<T,V> (Op::op (m.scalar(), n.scalar()));
00435   }
00436   nat nrows= rows (m);
00437   nat ncols= cols (m);
00438   ASSERT (rows (n) == nrows, "unequal number of rows");
00439   ASSERT (cols (n) == ncols, "unequal number of columns");
00440   nat l= aligned_size<T,V> (nrows * ncols);
00441   T*  r= mmx_formatted_new<T> (l, fm);
00442   Vec::template vec_binary<Op> (r, tab (m), tab (n), nrows*ncols);
00443   return matrix<T,V> (r, nrows, ncols, fm);
00444 }
00445 
00446 template<typename Op, typename C, typename V, typename X>
00447 matrix<Binary_return_type(Op,C,X),V>
00448 binary_map_scalar (const matrix<C,V>& m, const X& x) {
00449   typedef implementation<vector_linear,V> Vec;
00450   typedef Binary_return_type(Op,C,X) T;
00451   format<T> fm= binary_map_scalar<C> (CF(m), x);
00452   if (is_a_scalar (m)) return matrix<T,V> (Op::op (m.scalar(), x));
00453   nat nrows= rows (m);
00454   nat ncols= cols (m);
00455   nat l= aligned_size<T,V> (nrows * ncols);
00456   T*  r= mmx_formatted_new<T> (l, fm);
00457   Vec::template vec_binary_scalar<Op> (r, tab (m), x, nrows*ncols);
00458   return matrix<T,V> (r, nrows, ncols, fm);
00459 }
00460 
00461 template<typename Op, typename C, typename V> matrix<C,V>&
00462 nullary_set (matrix<C,V>& m) {
00463   typedef implementation<vector_linear,V> Vec;
00464   Vec::template vec_nullary<Op> (tab (m), rows (m) * cols (m));
00465   return m;
00466 }
00467 
00468 template<typename Op, typename T, typename C, typename V> matrix<T,V>&
00469 unary_set (matrix<T,V>& m, const matrix<C,V>& n) {
00470   typedef implementation<vector_linear,V> Vec;
00471   if (is_a_scalar (m) || is_a_scalar (n)) {
00472     if (is_non_scalar (m))
00473       return unary_set<Op> (m, extend (n, m));
00474     else if (is_non_scalar (n))
00475       m= extend (m, n);
00476     else {
00477       Op::set_op (m.scalar(), n.scalar());
00478       return m;
00479     }
00480   }
00481   nat nrows= rows (m);
00482   nat ncols= cols (m);
00483   ASSERT (rows (n) == nrows, "unequal number of rows");
00484   ASSERT (cols (n) == ncols, "unequal number of columns");
00485   Vec::template vec_unary<Op> (tab (m), tab (n), nrows*ncols);
00486   return m;
00487 }
00488 
00489 template<typename Op, typename T, typename V, typename X> matrix<T,V>&
00490 unary_set_scalar (matrix<T,V>& m, const X& x) {
00491   typedef implementation<vector_linear,V> Vec;
00492   if (is_a_scalar (m)) {
00493     Op::set_op (m.scalar(), x);
00494     return m;
00495   }
00496   nat nrows= rows (m);
00497   nat ncols= cols (m);
00498   Vec::template vec_unary_scalar<Op> (tab (m), x, nrows*ncols);
00499   return m;
00500 }
00501 
00502 template<typename Op, typename C1, typename C2, typename V> bool
00503 binary_test (const matrix<C1,V>& m, const matrix<C2,V>& n) {
00504   typedef implementation<vector_linear,V> Vec;
00505   if (is_a_scalar (m) || is_a_scalar (n)) {
00506     if (is_non_scalar (m)) return binary_test<Op> (m, extend (n, m));
00507     if (is_non_scalar (n)) return binary_test<Op> (extend (m, n), n);
00508     return Op::op (m.scalar(), n.scalar());
00509   }
00510   nat nrows= rows (m);
00511   nat ncols= cols (m);
00512   if (rows (n) != nrows || cols (n) != ncols) return false;
00513   return Vec::template vec_binary_test<Op> (tab (m), tab (n), nrows*ncols);
00514 }
00515 
00516 template<typename Op, typename C, typename V> Unary_return_type(Op,C)
00517 big (const matrix<C,V>& m) {
00518   typedef implementation<vector_linear,V> Vec;
00519   ASSERT (is_non_scalar (m), "non scalar matrix expected");
00520   return Vec::template vec_unary_big<Op> (tab (m), rows (m) * cols (m));
00521 }
00522 
00523 /******************************************************************************
00524 * Dynamic mappers
00525 ******************************************************************************/
00526 
00527 template<typename S1, typename D> matrix<D>
00528 map (const function_1<D,Argument(S1) >& fun,
00529      const matrix<S1>& m, const format<D>& fm)
00530 {
00531   nat n= rows(m) * cols(m);
00532   nat l= default_aligned_size<D> (n);
00533   D* r= mmx_formatted_new<D> (l, fm);
00534   const S1* src= tab (m);
00535   for (nat i=0; i<n; i++) r[i]= fun (src[i]);
00536   return matrix<D> (r, rows(m), cols(m), fm);
00537 }
00538 
00539 template<typename S1, typename D> inline matrix<D>
00540 map (D (*fun) (const S1&),
00541      const matrix<S1>& x1, const format<D>& fm) {
00542   return map (function_1<D,Argument(S1) > (fun), x1, fm);
00543 }
00544 
00545 /******************************************************************************
00546 * Constants
00547 ******************************************************************************/
00548 
00549 TMPL void set_pi (Matrix& m) { nullary_set<pi_as_op> (m); }
00550 TMPL void set_log2 (Matrix& m) { nullary_set<log2_as_op> (m); }
00551 TMPL void set_euler (Matrix& m) { nullary_set<euler_as_op> (m); }
00552 TMPL void set_catalan (Matrix& m) { nullary_set<catalan_as_op> (m); }
00553 TMPL void set_imaginary (Matrix& m) { nullary_set<imaginary_as_op> (m); }
00554 TMPL void set_nan (Matrix& m) { nullary_set<nan_as_op> (m); }
00555 TMPL void set_fuzz (Matrix& m) { nullary_set<fuzz_as_op> (m); }
00556 TMPL void set_smallest (Matrix& m) { nullary_set<smallest_as_op> (m); }
00557 TMPL void set_largest (Matrix& m) { nullary_set<largest_as_op> (m); }
00558 TMPL void set_accuracy (Matrix& m) { nullary_set<accuracy_as_op> (m); }
00559 TMPL void set_infinity (Matrix& m) { nullary_set<infinity_as_op> (m); }
00560 TMPL void set_maximal (Matrix& m) { nullary_set<maximal_as_op> (m); }
00561 TMPL void set_minimal (Matrix& m) { nullary_set<minimal_as_op> (m); }
00562 
00563 /******************************************************************************
00564 * Instantiations of abstract routines on matrices
00565 ******************************************************************************/
00566 
00567 TMPL Matrix copy (const Matrix& m) {
00568   return unary_map<id_op> (m); }
00569 TMPL Matrix duplicate (const Matrix& m) {
00570   return unary_map<duplicate_op> (m); }
00571 
00572 TMPL Matrix operator - (const Matrix& m) {
00573   return unary_map<neg_op> (m); }
00574 TMPL Matrix operator + (const Matrix& m, const Matrix& n) {
00575   return binary_map<add_op> (m, n); }
00576 TMPL Matrix operator + (const Matrix& m, const C& n) {
00577   return binary_map<add_op> (m, Matrix (n)); }
00578 TMPL Matrix operator + (const C& m, const Matrix& n) {
00579   return binary_map<add_op> (Matrix (m), n); }
00580 TMPL Matrix operator - (const Matrix& m, const Matrix& n) {
00581   return binary_map<sub_op> (m, n); }
00582 TMPL Matrix operator - (const Matrix& m, const C& n) {
00583   return binary_map<sub_op> (m, Matrix (n)); }
00584 TMPL Matrix operator - (const C& m, const Matrix& n) {
00585   return binary_map<sub_op> (Matrix (m), n); }
00586 TMPL Matrix operator * (const Matrix& m, const C& c) {
00587   return binary_map_scalar<rmul_op> (m, c); }
00588 TMPL Matrix operator * (const C& c, const Matrix& m) {
00589   return binary_map_scalar<lmul_op> (m, c); }
00590 TMPL Matrix operator / (const Matrix& m, const C& c) {
00591   return binary_map_scalar<rdiv_op> (m, c); }
00592 TMPL Matrix quo (const Matrix& m, const C& c) {
00593   return binary_map_scalar<rquo_op> (m, c); }
00594 TMPL Matrix rem (const Matrix& m, const C& c) {
00595   return binary_map_scalar<rrem_op> (m, c); }
00596 TMPL Matrix& operator += (Matrix& m, const Matrix& n) {
00597   return unary_set<add_op> (m, n); }
00598 TMPL Matrix& operator -= (Matrix& m, const Matrix& n) {
00599   return unary_set<sub_op> (m, n); }
00600 TMPL Matrix& operator *= (Matrix& m, const C& x) {
00601   return unary_set_scalar<rmul_op> (m, x); }
00602 TMPL Matrix& operator /= (Matrix& m, const C& x) {
00603   return unary_set_scalar<rdiv_op> (m, x); }
00604 TMPL bool operator <= (const Matrix& m, const Matrix& n) {
00605   return binary_test<lesseq_op> (m, n); }
00606 TMPL bool operator >= (const Matrix& m, const Matrix& n) {
00607   return binary_test<gtreq_op> (m, n); }
00608 template<typename C, typename V, typename K> bool
00609 operator == (const Matrix& m, const K& c) {
00610   return m == Matrix (c, rows (m), cols (m)); }
00611 template<typename C, typename V, typename K> bool
00612 operator != (const Matrix& m, const K& c) {
00613   return m != Matrix (c, rows (m), cols (m)); }
00614 template<typename C, typename V, typename K> bool
00615 operator <= (const Matrix& m, const C& c) {
00616   return m <= Matrix (c, rows (m), cols (m)); }
00617 template<typename C, typename V, typename K> bool
00618 operator >= (const Matrix& m, const C& c) {
00619   return m >= Matrix (c, rows (m), cols (m)); }
00620 
00621 TRUE_IDENTITY_OP_SUGAR(TMPL,Matrix)
00622 EXACT_IDENTITY_OP_SUGAR(TMPL,Matrix)
00623 ARITH_SCALAR_INT_SUGAR(TMPL,Matrix);
00624 STRICT_COMPARE_SUGAR(TMPL,Matrix)
00625 
00626 TMPL Matrix derive (const Matrix& m) {
00627   return unary_map<derive_op> (m); }
00628 TMPL Matrix integrate (const Matrix& m) {
00629   return unary_map<integrate_op> (m); }
00630 
00631 TMPL inline C big_add (const Matrix& m) { return big<add_op> (m); }
00632 TMPL inline C big_sup (const Matrix& m) { return big<sup_op> (m); }
00633 TMPL inline C big_max (const Matrix& m) { return big<max_op> (m); }
00634 
00635 /******************************************************************************
00636 * Floating point related functions
00637 ******************************************************************************/
00638 
00639 TMPL inline bool is_finite (const Matrix& m) {
00640   if (is_a_scalar (m)) return is_finite (m.scalar());
00641   return big<and_is_finite_op> (m); }
00642 TMPL inline bool is_nan (const Matrix& m) {
00643   if (is_a_scalar (m)) return is_nan (m.scalar());
00644   return big<or_is_nan_op> (m); }
00645 TMPL inline bool is_infinite (const Matrix& m) {
00646   if (is_a_scalar (m)) return is_infinite (m.scalar());
00647   return !is_nan (m) && big<or_is_infinite_op> (m); }
00648 TMPL inline bool is_fuzz (const Matrix& m) {
00649   if (is_a_scalar (m)) return is_fuzz (m.scalar());
00650   return !is_nan (m) && big<or_is_fuzz_op> (m); }
00651 TMPL inline bool is_reliable (const Matrix& m) {
00652   if (is_a_scalar (m)) return is_reliable (m.scalar());
00653   return is_reliable (C (0)); }
00654 
00655 TMPL inline Matrix change_precision (const Matrix& m, xnat p) {
00656   return binary_map_scalar<change_precision_op> (m, p); }
00657 TMPL inline xnat precision (const Matrix& m) {
00658   return big<min_precision_op> (m); }
00659 
00660 TMPL inline xint exponent (const Matrix& m) {
00661   return big<max_exponent_op> (m); }
00662 TMPL inline double magnitude (const Matrix& m) {
00663   return big<max_magnitude_op> (m); }
00664 
00665 /******************************************************************************
00666 * Complex and ball matrices
00667 ******************************************************************************/
00668 
00669 TMPL Abs_matrix abs (const Matrix& m) { return unary_map<abs_op> (m); }
00670 TMPL Real_matrix Re (const Matrix& m) { return unary_map<Re_op> (m); }
00671 TMPL Real_matrix Im (const Matrix& m) { return unary_map<Im_op> (m); }
00672 TMPL Matrix conj (const Matrix& m) { return unary_map<conj_op> (m); }
00673 
00674 TMPL Center_matrix center (const Matrix& m) {
00675   return unary_map<center_op> (m); }
00676 TMPL Radius_matrix radius (const Matrix& m) {
00677   return unary_map<radius_op> (m); }
00678 TMPL Center_matrix lower (const Matrix& m) {
00679   return unary_map<lower_op> (m); }
00680 TMPL Center_matrix upper (const Matrix& m) {
00681   return unary_map<upper_op> (m); }
00682 TMPL inline Matrix sharpen (const Matrix& m) {
00683   return unary_map<sharpen_op> (m); }
00684 TMPLK inline Matrix blur (const Matrix& m, const K& x) {
00685   return binary_map_scalar<blur_op> (m, x); }
00686 template<typename C, typename V, typename C2, typename V2> inline Matrix
00687 blur (const Matrix& m, const matrix<C2,V2>& n) {
00688   return binary_map<blur_op> (m, n); }
00689 
00690 /******************************************************************************
00691 * Explicit matrices
00692 ******************************************************************************/
00693 
00694 template<typename C> matrix<C>
00695 identity_matrix (const int& n, const format<C>& fm= format<C> ()) {
00696   return matrix<C> (promote (1, fm), n, n);
00697 }
00698 
00699 template<typename C> matrix<C>
00700 fill_matrix (const C& x, const int& r, const int& c) {
00701   matrix<C> m (promote (0, x), (nat) r, (nat) c);
00702   for (nat i=0; i<((nat) r); i++)
00703     for (nat j=0; j<((nat) c); j++)
00704       m (i, j)= x;
00705   return m;
00706 }
00707 
00708 template<typename C> matrix<C>
00709 tensor_matrix (const vector<C>& v, const vector<C>& w) {
00710   ASSERT (is_non_scalar (v), "non-scalar vector expected");
00711   ASSERT (is_non_scalar (w), "non-scalar vector expected");
00712   matrix<C> m (promote (0, CF(v)), N(v), N(w));
00713   for (nat i=0; i<N(v); i++)
00714     for (nat j=0; j<N(w); j++)
00715       m (i, j)= v[i] * w[j];
00716   return m;
00717 }
00718 
00719 template<typename C> matrix<C>
00720 hilbert_matrix (const int& n, const format<C>& fm= format<C> ()) {
00721   matrix<C> m (promote (0, fm), n, n);
00722   for (nat i=0; i<(nat) n; i++)
00723     for (nat j=0; j<(nat) n; j++)
00724       m (i, j)= 1 / promote (1 + i + j, fm);
00725   return m;
00726 }
00727 
00728 template<typename C> matrix<C>
00729 vandermonde (const vector<C>& v) {
00730   ASSERT (is_non_scalar (v), "non-scalar vector expected");
00731   matrix<C> m (promote (0, CF(v)), N(v), N(v));
00732   for (nat i=0; i<N(v); i++) {
00733     C p= promote (1, CF(v));
00734     for (nat j=0; j<N(v); j++, p *= v[i])
00735       m (i, j)= p;
00736   }
00737   return m;
00738 }
00739 
00740 template<typename C> matrix<C>
00741 jordan_matrix (const C& c, const int& n) {
00742   matrix<C> m (c, n, n);
00743   for (nat i=0; i<((nat) (n-1)); i++)
00744     m (i, i+1)= promote (1, c);
00745   return m;
00746 }
00747 
00748 template<typename C> matrix<C>
00749 toeplitz_matrix (const vector<C>& v) {
00750   ASSERT ((N(v)&1) == 1, "odd dimension expected");
00751   nat n= (N(v) >> 1) + 1;
00752   matrix<C> m (promote (0, CF(v)), n, n);
00753   for (nat i=0; i<n; i++)
00754     for (nat j=0; j<n; j++)
00755       m (i, j)= v [n-1 + i-j];
00756   return m;
00757 }
00758 
00759 template<typename C> matrix<C>
00760 hankel_matrix (const vector<C>& v) {
00761   ASSERT ((N(v)&1) == 1, "odd dimension expected");
00762   nat n= (N(v) >> 1) + 1;
00763   matrix<C> m (promote (0, CF(v)), n, n);
00764   for (nat i=0; i<n; i++)
00765     for (nat j=0; j<n; j++)
00766       m (i, j)= v [i+j];
00767   return m;
00768 }
00769 
00770 /******************************************************************************
00771 * Further routines on matrices
00772 ******************************************************************************/
00773 
00774 TMPL Matrix
00775 horizontal_join (const Matrix& m1, const Matrix& m2) {
00776   ASSERT (is_non_scalar (m1) || is_non_scalar (m2),
00777           "non-scalar matrix expected");
00778   if (!is_non_scalar (m1))
00779     return horizontal_join (Matrix (m1.scalar(), rows (m2), rows (m2)), m2);
00780   if (!is_non_scalar (m2))
00781     return horizontal_join (m1, Matrix (m2.scalar(), rows (m1), rows (m1)));
00782   ASSERT (rows (m1) == rows (m2), "unequal number of rows");
00783   Matrix r (promote (0, CF(m1)), rows (m1), cols (m1) + cols (m2));
00784   for (nat i=0; i<rows(m1); i++) {
00785     for (nat j=0; j<cols(m1); j++)
00786       r(i,j)= m1(i,j);
00787     for (nat j=0; j<cols(m2); j++)
00788       r(i,j+cols(m1))= m2(i,j);
00789   }
00790   return r;
00791 }
00792 
00793 TMPL Matrix
00794 vertical_join (const Matrix& m1, const Matrix& m2) {
00795   ASSERT (is_non_scalar (m1) || is_non_scalar (m2),
00796           "non-scalar matrix expected");
00797   if (!is_non_scalar (m1))
00798     return vertical_join (Matrix (m1.scalar(), cols (m2), cols (m2)), m2);
00799   if (!is_non_scalar (m2))
00800     return vertical_join (m1, Matrix (m2.scalar(), cols (m1), cols (m1)));
00801   ASSERT (cols (m1) == cols (m2), "unequal number of columns");
00802   Matrix r (promote (0, CF(m1)), rows (m1) + rows (m2), cols (m1));
00803   for (nat j=0; j<cols(m1); j++) {
00804     for (nat i=0; i<rows(m1); i++)
00805       r(i,j)= m1(i,j);
00806     for (nat i=0; i<rows(m2); i++)
00807       r(i+rows(m1),j)= m2(i,j);
00808   }
00809   return r;
00810 }
00811 
00812 TMPL Matrix
00813 transpose (const Matrix & m) {
00814   typedef implementation<matrix_linear,V> Mat;
00815   if (is_a_scalar (m)) return m;
00816   nat nrows= rows (m), ncols= cols (m);
00817   nat l= aligned_size<C,V> (nrows * ncols);
00818   C*  r= mmx_formatted_new<C> (l, CF(m));
00819   Mat::transpose (r, tab (m), nrows, ncols);
00820   return Matrix (r, ncols, nrows, CF(m));
00821 }
00822 
00823 TMPL inline Matrix
00824 range (const Matrix& m, nat r1, nat c1, nat r2, nat c2) {
00825   typedef implementation<matrix_linear,V> Mat;
00826   if (is_a_scalar (m)) return Matrix (m.scalar(), r2-r1, c2-c1);
00827   nat nrows= rows (m), ncols= cols (m);
00828   nat l= aligned_size<C,V> ((r2-r1) * (c2-c1));
00829   C*  r= mmx_formatted_new<C> (l, CF(m));
00830   Mat::get_range (r, tab (m), r1, c1, r2, c2, nrows, ncols);
00831   return Matrix (r, r2-r1, c2-c1, CF(m));
00832 }
00833 
00834 TMPL inline Matrix
00835 delete_row (const Matrix& m, nat r) {
00836   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
00837   ASSERT (r < rows (m), "index out of range");
00838   Matrix d (promote (0, CF(m)), rows (m) - 1, cols (m));
00839   for (nat i= 0; i < r; i++)
00840     for (nat j= 0; j < cols (m); j++) d(i,j)= m(i,j);
00841   for (nat i= r+1; i < rows (m); i++)
00842     for (nat j= 0; j < cols (m); j++) d(i-1,j)= m(i,j);
00843   return d;
00844 }
00845   
00846 TMPL Matrix
00847 delete_col (const Matrix& m, nat c) {
00848   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
00849   ASSERT (c < cols (m), "index out of range");
00850   Matrix d (promote (0, CF(m)), rows (m), cols (m) - 1);
00851   for (nat j= 0; j < c; j++)
00852     for (nat i= 0; i < rows (m); i++) d(i,j)= m(i,j);
00853   for (nat j= c+1; j < cols (m); j++)
00854     for (nat i= 0; i < rows (m); i++) d(i,j-1)= m(i,j);
00855   return d;
00856 }
00857   
00858 TMPL Matrix
00859 operator * (const Matrix& m, const Matrix& n) {
00860   typedef implementation<matrix_multiply,V> Mat;
00861   if (is_a_scalar (m) || is_a_scalar (n)) {
00862     if (is_non_scalar (m)) return m * n.scalar();
00863     if (is_non_scalar (n)) return m.scalar() * n;
00864     return Matrix (m.scalar() * n.scalar());
00865   }
00866   nat mrows= rows (m), mcols= cols (m), nrows= rows(n), ncols= cols(n);
00867   ASSERT (nrows == mcols, "numbers of rows and columns don't match");
00868   nat l= aligned_size<C,V> (mrows * ncols);
00869   C*  r= mmx_formatted_new<C> (l, CF(m));
00870   Mat::mul (r, tab (m), tab (n), mrows, mcols, ncols);
00871   return Matrix (r, mrows, ncols, CF(m));
00872 }
00873 
00874 template<typename C, typename V, typename W> vector<C,W>
00875 operator * (const matrix<C,V>& m, const vector<C,W>& v) {
00876   typedef implementation<vector_linear,W> Vec;
00877   typedef implementation<matrix_linear,V> Mat;
00878   if (is_a_scalar (m)) return m.scalar() * v;
00879   ASSERT (is_non_scalar (v), "non-scalar vector expected");
00880   nat rr= rows (m), cc= cols (m);
00881   ASSERT (cc == N(v), "sizes don't match");
00882   nat l= aligned_size<C,W> (rr);
00883   C*  a= mmx_formatted_new<C> (l, CF(m));
00884   for (nat i=0; i<rr; i++)
00885     a[i]= Vec::template vec_binary_big_stride<mul_add_op>
00886       (tab (m) + Mat::index (i, 0, rr, cc), Mat::index (0, 1, rr, cc),
00887        seg (v), 1, cc);
00888   return vector<C,W> (a, rr, l, CF(m));
00889 }
00890 
00891 template<typename C, typename V, typename W> vector<C,W>
00892 operator * (const vector<C,W>& v, const matrix<C,V>& m) {
00893   typedef implementation<vector_linear,W> Vec;
00894   typedef implementation<matrix_linear,V> Mat;
00895   if (is_a_scalar (m)) return v * m.scalar();
00896   ASSERT (is_non_scalar (v), "non-scalar vector expected");
00897   nat rr= rows (m), cc= cols (m);
00898   ASSERT (rr == N(v), "sizes don't match");
00899   nat l= aligned_size<C,W> (cc);
00900   C*  a= mmx_formatted_new<C> (l, CF(m));
00901   for (nat i=0; i<cc; i++)
00902     a[i]= Vec::template vec_binary_big_stride<mul_add_op>
00903       (seg (v), 1,
00904        tab (m) + Mat::index (0, i, rr, cc), Mat::index (1, 0, rr, cc), rr);
00905   return vector<C,W> (a, cc, l, CF(m));
00906 }
00907 
00908 /******************************************************************************
00909 * Operations on rows or columns
00910 ******************************************************************************/
00911 
00912 TMPL vector<C>
00913 row (const Matrix& m, nat i) {
00914   nat n= cols (m);
00915   nat l= default_aligned_size<C> (n);
00916   C*  a= mmx_formatted_new<C> (l, CF(m));
00917   for (nat j=0; j<n; j++) a[j]= m(i,j);
00918   return vector<C> (a, n, l, CF(m));
00919 }
00920 
00921 TMPL vector<C>
00922 column (const Matrix& m, nat j) {
00923   nat n= rows (m);
00924   nat l= default_aligned_size<C> (n);
00925   C*  a= mmx_formatted_new<C> (l, CF(m));
00926   for (nat i=0; i<n; i++) a[i]= m(i,j);
00927   return vector<C> (a, n, l, CF(m));
00928 }
00929 
00930 template<typename C> vector<vector<C> >
00931 row_vectors (const matrix<C>& m) {
00932   vector<vector<C> > v=  fill<vector<C> > (rows (m));
00933   for (nat i=0; i<rows(m); i++)
00934     v[i]= row (m, i);
00935   return v;
00936 }
00937 
00938 template<typename C> matrix<C>
00939 row_matrix (const vector<vector<C> >& v) {
00940   if (N(v) == 0) return matrix<C> (0);
00941   matrix<C> r (promote (0, get_format1 (CF(v))), N(v), N(v[0]));
00942   for (nat i=0; N(v)>i; i++) {
00943     ASSERT (N(v[i]) == N(v[0]), "unequal row lengths");
00944     for (nat j=0; j<N(v[0]); j++)
00945       r (i, j)= v[i][j];
00946   }
00947   return r;
00948 }
00949 
00950 TMPL void
00951 swap_row (Matrix& m, nat i, nat j) {
00952   typedef implementation<matrix_linear,V> Mat;
00953   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
00954   nat mrows= rows (m), mcols= cols (m);
00955   ASSERT (i < mrows && j < mrows, "out of range");
00956   Mat::row_swap (tab (m), i, j, mrows, mcols);
00957 }
00958 
00959 TMPL void
00960 swap_col (Matrix& m, nat i, nat j) {
00961   typedef implementation<matrix_linear,V> Mat;
00962   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
00963   nat mrows= rows (m), mcols= cols (m);
00964   ASSERT (i < mcols && j < mcols, "out of range");
00965   Mat::col_swap (tab (m), i, j, mrows, mcols);
00966 }
00967 
00968 TMPL void
00969 reverse_cols (Matrix& m) {
00970   typedef implementation<matrix_linear,V> Mat;
00971   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
00972   Mat::col_reverse (tab (m), rows (m), cols (m));
00973 }
00974 
00975 #define INLINE_SCAL_LINE_OP(name1,name2)                        \
00976 TMPL void name1 (Matrix& m, C c, nat i) {                       \
00977   typedef implementation<matrix_linear,V> Mat;                  \
00978   ASSERT (is_non_scalar (m), "non-scalar matrix expected");     \
00979   nat mrows=rows(m), mcols=cols(m);                             \
00980   Mat::name2 (tab(m), c, i, mrows, mcols);                      \
00981 }
00982 
00983 #define INLINE_LINES_OP(name1, name2)                           \
00984 TMPL void name1 (Matrix& m, nat i, C ci, nat j, C cj) {         \
00985   typedef implementation<matrix_linear,V> Mat;                  \
00986   ASSERT (is_non_scalar (m), "non-scalar matrix expected");     \
00987   nat mrows=rows(m), mcols=cols(m);                             \
00988   Mat::name2 (tab(m), i, ci, j, cj, mrows, mcols);              \
00989 }
00990 
00991 INLINE_SCAL_LINE_OP(row_mul, row_mul);
00992 INLINE_SCAL_LINE_OP(row_div, row_div);
00993 INLINE_SCAL_LINE_OP(col_mul, col_mul);
00994 INLINE_SCAL_LINE_OP(col_div, col_div);
00995 INLINE_LINES_OP(rows_linsub,row_combine_sub);
00996 INLINE_LINES_OP(cols_linsub,col_combine_sub);
00997 
00998 /******************************************************************************
00999 * Permutations
01000 ******************************************************************************/
01001 
01002 TMPL matrix<C>
01003 as_matrix (const permutation& p, const Format& fm= Format ()) {
01004   nat n= N(p);
01005   matrix<C> m (promote (0, fm), n, n);
01006   for (nat i=0; i<n; i++)
01007     for (nat j=0; j<n; j++)
01008       m (i, j) = promote (i == p (j) ? 1 : 0, fm);
01009   return m;
01010 }
01011 
01012 TMPL void
01013 permute_columns (Matrix& m, const permutation& p) {
01014   // replace m by m * as_matrix (p)
01015   typedef implementation<matrix_permute,V> Mat;
01016   if (is_a_scalar (m)) return;
01017   nat rs= rows (m), cs= cols (m);
01018   Mat::col_permute (tab (m), seg (*p), rs, cs);
01019 }
01020 
01021 TMPL void
01022 permute_rows (Matrix& m, const permutation& p) {
01023   // replace m by transpose (as_matrix (p)) * m
01024   typedef implementation<matrix_permute,V> Mat;
01025   if (is_a_scalar (m)) return;
01026   nat rs= rows (m), cs= cols (m);
01027   Mat::row_permute (tab (m), seg (*p), rs, cs);
01028 }
01029 
01030 TMPL Matrix
01031 operator * (const Matrix& m, const permutation& p) {
01032   // returns m * as_matrix (p)
01033   typedef implementation<matrix_permute,V> Mat;
01034   if (is_a_scalar (m)) return m;
01035   nat rs= rows (m), cs= cols (m);
01036   Matrix dest (promote (0, CF(m)), rs, cs);
01037   Mat::col_permute (tab (dest), tab (m), seg (*p), rs, cs);
01038   return dest;
01039 }
01040 
01041 TMPL Matrix
01042 operator * (const permutation& p, const Matrix& m) {
01043   // returns transpose (as_matrix (p)) * m
01044   typedef implementation<matrix_permute,V> Mat;
01045   if (is_a_scalar (m)) return m;
01046   nat rs= rows (m), cs= cols (m);
01047   Matrix dest (promote (0, CF(m)), rs, cs);
01048   Mat::row_permute (tab (dest), tab (m), seg (*p), rs, cs);
01049   return dest;
01050 }
01051 
01052 /******************************************************************************
01053 * Echelon forms
01054 ******************************************************************************/
01055 
01056 TMPL Matrix
01057 column_echelon (const Matrix& m, bool reduced= false) {
01058   typedef implementation<matrix_echelon,V> Mat;
01059   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
01060   Matrix c= copy (m);
01061   C* k= NULL;
01062   Mat::col_echelon (tab(c), k, rows(m), cols(m), reduced);
01063   return c;
01064 }
01065 
01066 TMPL Matrix
01067 column_reduced_echelon (const Matrix& m) {
01068   return column_echelon (m, true);
01069 }
01070 
01071 TMPL Matrix
01072 column_reduced_echelon (const Matrix& m, permutation& permut) {
01073   typedef implementation<matrix_echelon,V> Mat;
01074   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
01075   Matrix c= copy (m);
01076   C* k= NULL;
01077   nat* buf= mmx_new<nat> (default_aligned_size<nat> (cols(m)));
01078   Mat::col_echelon (tab(c), k, rows(m), cols(m), true, buf);
01079   permut= permutation (vector<nat> (buf, cols(m), format<nat> ()));
01080   return c;
01081 }
01082 
01083 TMPL Matrix
01084 column_echelon (const Matrix& m, Matrix& k, bool reduced= false) {
01085   typedef implementation<matrix_echelon,V> Mat;
01086   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
01087   Matrix c= copy (m);
01088   k= Matrix (promote (0, CF(m)), cols(m), cols(m));
01089   Mat::col_echelon (tab(c), tab(k), rows(m), cols(m), false);
01090   return c;
01091 }
01092 
01093 TMPL Matrix
01094 column_reduced_echelon (const Matrix& m, Matrix& k) {
01095   return column_echelon (m, k, true);
01096 }
01097 
01098 TMPL inline Matrix
01099 row_echelon (const Matrix& m, bool reduced= false) {
01100   return transpose (column_echelon (transpose (m), reduced));
01101 }
01102 
01103 TMPL Matrix
01104 row_reduced_echelon (const Matrix& m) {
01105   return row_echelon (m, true);
01106 }
01107 
01108 TMPL inline Matrix
01109 row_echelon (const Matrix& m, Matrix& k, bool reduced= false) {
01110   Matrix c= column_echelon (transpose (m), k, reduced);
01111   k= transpose (k);
01112   return transpose (c);
01113 }
01114 
01115 TMPL Matrix
01116 row_reduced_echelon (const Matrix& m, Matrix& k) {
01117   return row_echelon (m, k, true);
01118 }
01119 
01120 /******************************************************************************
01121 * System solving
01122 ******************************************************************************/
01123 
01124 TMPL inline C
01125 det (const Matrix& m) {
01126   typedef implementation<matrix_determinant,V> Mat;
01127   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
01128   ASSERT (cols(m) == rows(m), "square matrix expected");
01129   C r= promote (1, CF(m));
01130   Mat::det (r, tab(m), rows(m));
01131   return r;
01132 }
01133 
01134 TMPL inline C
01135 first_minor (const Matrix& m, nat i, nat j) {
01136   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
01137   ASSERT (cols(m) == rows(m), "square matrix expected");
01138   ASSERT (i < rows(m), "index out of range");
01139   ASSERT (j < cols(m), "index out of range");
01140   return det (delete_col (delete_row (m, i), j));
01141 }
01142 
01143 TMPL inline C
01144 cofactor (const Matrix& m, nat i, nat j) {
01145   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
01146   ASSERT (cols(m) == rows(m), "square matrix expected");
01147   ASSERT (i < rows(m), "index out of range");
01148   ASSERT (j < cols(m), "index out of range");
01149   C c= first_minor (m, i, j);
01150   return ((i + j) & 1) ? -c : c;
01151 }
01152 
01153 TMPL Matrix
01154 invert (const Matrix& m) {
01155   typedef implementation<matrix_invert,V> Mat;
01156   if (is_a_scalar (m)) return Matrix (invert (m.scalar()));
01157   ASSERT (cols(m) == rows(m), "square matrix expected");
01158   Matrix a (promote (1, CF(m)), rows(m), cols(m));
01159   Mat::invert (tab(a), tab(m), rows(m));
01160   return a;
01161 }
01162 
01163 TMPL Matrix operator / (const C& c, const Matrix& m) {
01164   return c * invert (m); }
01165 
01166 /******************************************************************************
01167 * Kernel, image and rank
01168 ******************************************************************************/
01169 
01170 TMPL Matrix
01171 kernel (const Matrix& m) {
01172   typedef implementation<matrix_kernel,V> Mat;
01173   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
01174   Matrix k (promote (0, CF(m)), cols(m), cols(m));
01175   nat dim= Mat::kernel (tab(k), tab(m), rows(m), cols(m));
01176   return range (k, 0, 0, cols(m), dim);
01177 }
01178 
01179 TMPL Matrix
01180 image (const Matrix& m) {
01181   typedef implementation<matrix_image,V> Mat;
01182   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
01183   Matrix k (promote (0, CF(m)), rows(m), rows(m));
01184   nat dim= Mat::image (tab(k), tab(m), rows(m), cols(m));
01185   return range (k, 0, 0, rows(m), dim);
01186 }
01187 
01188 TMPL nat
01189 rank (const Matrix& m) {
01190   typedef implementation<matrix_image,V> Mat;
01191   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
01192   return Mat::rank (tab(m), rows(m), cols(m));
01193 }
01194 
01195 TMPL Matrix
01196 krylov (const Matrix& m, const Matrix& v) {
01197   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
01198   ASSERT (is_square_matrix (m), "square matrix expected");
01199   Matrix r= image (v);
01200   Matrix p= m;
01201   while (true) {
01202     nat rk= rows (r);
01203     r= image (vertical_join (r, r*p));
01204     if (rows (r) <= rk) return r;
01205     p= p*p;
01206   }
01207 }
01208 
01209 /******************************************************************************
01210 * Gram Schmidt and related decompositions
01211 ******************************************************************************/
01212 
01213 TMPL inline Matrix
01214 row_orthogonalization (const Matrix& m) {
01215   typedef implementation<matrix_orthogonalization,V> Mat;
01216   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
01217   Matrix c= copy (m);
01218   vector<C> n (promote (0, CF(m)), rows(m));
01219   Mat::row_orthogonalize (tab(c), rows(m), cols(m), seg(n));
01220   return c;
01221 }  
01222 
01223 TMPL inline Matrix
01224 column_orthogonalization (const Matrix& m) {
01225   typedef implementation<matrix_orthogonalization,V> Mat;
01226   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
01227   Matrix c= copy (m);
01228   vector<C> n (promote (0, CF(m)), cols(m));
01229   Mat::col_orthogonalize (tab(c), rows(m), cols(m), seg(n));
01230   return c;
01231 }  
01232 
01233 TMPL inline Matrix
01234 row_orthogonalization (const Matrix& m, Matrix& l) {
01235   typedef implementation<matrix_orthogonalization,V> Mat;
01236   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
01237   Matrix c= copy (m);
01238   vector<C> n (promote (0, CF(m)), rows(m));
01239   l= Matrix (promote (0, CF(m)), rows(m), rows(m));
01240   Mat::row_orthogonalize (tab(c), rows(m), cols(m), tab(l), seg(n));
01241   return c;
01242 }  
01243 
01244 TMPL inline Matrix
01245 column_orthogonalization (const Matrix& m, Matrix& l) {
01246   typedef implementation<matrix_orthogonalization,V> Mat;
01247   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
01248   Matrix c= copy (m);
01249   vector<C> n (promote (0, CF(m)), cols(m));
01250   l= Matrix (promote (0, CF(m)), cols(m), cols(m));
01251   Mat::col_orthogonalize (tab(c), rows(m), cols(m), tab(l), seg(n));
01252   return c;
01253 }  
01254 
01255 TMPL inline Matrix
01256 row_orthonormalization (const Matrix& m) {
01257   typedef implementation<matrix_orthogonalization,V> Mat;
01258   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
01259   Matrix c= copy (m);
01260   Mat::row_orthonormalize (tab(c), rows(m), cols(m));
01261   return c;
01262 }  
01263 
01264 TMPL inline Matrix
01265 column_orthonormalization (const Matrix& m) {
01266   typedef implementation<matrix_orthogonalization,V> Mat;
01267   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
01268   Matrix c= copy (m);
01269   Mat::col_orthonormalize (tab(c), rows(m), cols(m));
01270   return c;
01271 }  
01272 
01273 TMPL inline Matrix
01274 row_orthonormalization (const Matrix& m, Matrix& l) {
01275   typedef implementation<matrix_orthogonalization,V> Mat;
01276   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
01277   Matrix c= copy (m);
01278   l= Matrix (promote (0, CF(m)), rows(m), rows(m));
01279   Mat::row_orthonormalize (tab(c), rows(m), cols(m), tab(l));
01280   return c;
01281 }  
01282 
01283 TMPL inline Matrix
01284 column_orthonormalization (const Matrix& m, Matrix& l) {
01285   typedef implementation<matrix_orthogonalization,V> Mat;
01286   ASSERT (is_non_scalar (m), "non-scalar matrix expected");
01287   Matrix c= copy (m);
01288   l= Matrix (promote (0, CF(m)), cols(m), cols(m));
01289   Mat::col_orthonormalize (tab(c), rows(m), cols(m), tab(l));
01290   return c;
01291 }  
01292 
01293 #undef TMPL_DEF
01294 #undef TMPL
01295 #undef TMPLK
01296 #undef Format
01297 #undef Matrix
01298 #undef Matrix_rep
01299 #undef Abs_matrix
01300 #undef Real_matrix
01301 #undef Center_matrix
01302 #undef Radius_matrix
01303 } // namespace mmx
01304 #endif // __MMX_MATRIX_HPP
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines