algebramix_doc 0.3
|
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