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