// // $COPYRIGHT$ // #ifndef MTL_BLAIS_H #define MTL_BLAIS_H /* * Basic Linear Algebra Instruction Set (BLAIS) */ #include #include "mtl/mtl_iterator.h" #include "mtl/mtl_config.h" #include "mtl/matrix_traits.h" #include "mtl/fast.h" #include "mtl/scaled1D.h" /* * Level 1 */ namespace blais_v { //: Set elements of vector x to alpha //!tparam: N - static length of x //!category: blais //!component: type template struct set { template inline set(Vector x, const T& alpha) { fast::fill(x.begin(), fast::count(), alpha); } }; } /* blais_v */ namespace blais_vv { using namespace mtl; //: Copy y <- x // Copies vector x into vector y //!tparam: N - the length of the vectors //!category: blais //!component: type template struct copy { template inline copy(Vec1 x, Vec2 y) { fast::copy(x.begin(), fast::count(), y.begin()); } }; //: Add y <- x + y // This adds vector x into vector y. //!example: blais_add.cc //!tparam: N - the length of the vectors //!category: blais //!component: type template struct add { template inline add(Vec1 x, Vec2 y) { typedef typename linalg_traits::value_type T; fast::transform(x.begin(), fast::count(), y.begin(), y.begin(), std::plus()); } }; //: Dot Product s <- x . y //!tparam: N - the length of the vectors //!category: blais //!component: type template struct dot { template inline dot(Vec1 x, Vec2 y, T& prod) { prod = fast::inner_product(x.begin(), fast::count(), y.begin(), prod); } }; } /* blais_vv namespace */ namespace blais_m { //: blah //!noindex: template struct __recur_set { template inline __recur_set(TwoDIter i, const T& alpha) { blais_v::set(*i, alpha); __recur_set(++i, alpha); } }; //: blah //!noindex: template struct __recur_set<0,N> { template inline __recur_set(TwoDIter, const T&) { } }; //: Set matrix A to alpha // //!category: blais //!component: type template struct set { template inline set(Matrix A, const T& alpha) { __recur_set(A.begin(), alpha); } }; } /* Matrix-Vector Algorithms */ namespace blais_mv { using namespace mtl; //: blah //!noindex: template struct __mult { }; /* row major version (dot product) */ //: blah //!noindex: template struct __mult { template inline __mult(ARowIter A_2Diter, VecX x, IterY y) { typedef typename std::iterator_traits::value_type T; blais_vv::dot(*A_2Diter, x, *y); blais_mv::__mult(++A_2Diter, x, ++y); } }; //: blah //!noindex: template struct __mult<0, N, row_tag> { template inline __mult(AIter A_2Diter, VecX x, IterY y) { /* do nothing */ } }; /* column major version (axpy) */ //: blah //!noindex: template struct __mult { template inline __mult(AColIter Aiter, IterX x, VecY y) { typedef typename AColIter::value_type OneD; // KCC choking on the LOO for this scaled1D object mtl::scaled1D sa(*Aiter, *x); blais_vv::add(sa, y); blais_mv::__mult(++Aiter, ++x, y); } }; //: blah //!noindex: template struct __mult { template inline __mult(AColIter A_2Diter, IterX x, VecY y) { /* do nothing */ } }; //: Multiplication y <- A x + y //!tparam: M - Number of rows in A //!tparam: N - Number of columns in A //!category: blais //!component: type template struct mult { template inline mult(const Matrix& A, VecX x, VecY y) { typedef typename matrix_traits::orientation Orien; do_mult(A, x, y, Orien()); } template inline void do_mult(const Matrix& A, VecX x, VecY y, row_tag) { blais_mv::__mult(A.begin(), x, y.begin()); } template inline void do_mult(const Matrix& A, VecX x, VecY y, column_tag) { blais_mv::__mult(A.begin(), x.begin(), y); // blais_mv::__mult(rows(A).begin(), x, y.begin()); } }; //: blah //!noindex: template struct __rank_one { }; //: blah //!noindex: template struct __rank_one { template inline __rank_one(Row2Diter Arow, IterX x, VecY y) { mtl::scaled1D sy(y, *x); blais_vv::add(sy, *Arow); __rank_one(++Arow, ++x, y); } }; //: blah //!noindex: template struct __rank_one<0, N, row_tag> { template inline __rank_one(Row2Diter Arow, IterX x, VecY y) { /* do nothing */ } }; //: blah //!noindex: template struct __rank_one { template inline __rank_one(Col2Diter Acol, VecX x, IterY y) { mtl::scaled1D sx(x, *y); blais_vv::add(sx, *Acol); __rank_one(++Acol, x, ++y); } }; //: blah //!noindex: template struct __rank_one { template inline __rank_one(Col2Diter Acol, VecX x, IterY y) { /* do nothing */ } }; //: Rank One Update A <- A + x * y^T // // //!tparam: M - Number of rows in A //!tparam: N - Number of columns in A //!category: blais //!component: type template struct rank_one { template inline rank_one(Matrix& A, VecX x, VecY y) { typedef typename matrix_traits::orientation Orien; do_update(A, x, y, Orien()); } template inline void do_update(Matrix& A, VecX x, VecY y, row_tag) { __rank_one(A.begin(), x.begin(), y); } template inline void do_update(Matrix& A, VecX x, VecY y, column_tag) { __rank_one(A.begin(), x, y.begin()); } }; } /* matvec namespace */ /* Level 3 */ namespace blais_mm { using namespace mtl; //: blah //!noindex: template struct __copy { template inline __copy(IterA Aiter, IterB Biter) { blais_vv::copy(*Aiter, *Biter); blais_mm::__copy(++Aiter, ++Biter); } }; //: blah //!noindex: template struct __copy<0, N> { template inline __copy(IterA Aiter, IterB Biter) { /* do nothing */ } }; //: Copy B <- A // //!tparam: M - Number of rows in A //!tparam: N - Number of columns in A //!category: blais //!component: type template struct copy { template inline copy(const MatrixA& A, MatrixB& B) { typedef typename matrix_traits::orientation Orien; do_copy(A, B, Orien()); } template inline void do_copy(const MatrixA& A, MatrixB& B, row_tag) { blais_mm::__copy(A.begin(), rows(B).begin()); } template inline void do_copy(const MatrixA& A, MatrixB& B, column_tag) { blais_mm::__copy(A.begin(), columns(B).begin()); } }; //: blah //!noindex: template struct __mult { template inline __mult(const MatrixA& A, ColIterB Bcol, ColIterC Ccol) { blais_mv::mult(A, *Bcol, *Ccol); blais_mm::__mult(A, ++Bcol, ++Ccol); } }; //: blah //!noindex: template struct __mult { template inline __mult(const MatrixA& A, Col2DIterB Bcol, Col2DIterC Ccol) { /* do nothing */ } }; //: Multiplication C <- A * B //!tparam: M - Number of rows in A and C //!tparam: N - Number of columns in B and rows in C //!tparam: K - Number of columns in A and rows in B //!category: blais //!component: type template struct mult { template inline mult(const MatrixA& A, const MatrixB& B, MatrixC& C) { blais_mm::__mult(A, columns(B).begin(), columns(C).begin()); } }; } /* matmat namespace */ #endif #if 0 struct take1st { template inline T operator()(const T& t, const U& u) { return t; } }; template class add_op { public: add_op(IterY& y_) : y(y_) { } template IterY operator()(const Col& a, const T& x) { #ifdef __GNUC__ /* parse error :( */ blais::blais_scaled_iter scl_a(a.begin(), x); blais_vv::add(scl_a, y); return y; #else blais_vv::add(blais::scl(a.begin(),x), y); return y; #endif } protected: const IterY& y; }; /* wow, this is highly critical use reference to y to aid in small object optimization */ template struct __mult { template inline __mult(const Matrix& A, IterX x, IterY y) { fast::inner_product(A.begin_columns(), fast::count(), x, y, take1st(), add_op(y)); } }; #endif #if 0 /* Multiply, Fixed M, Nonfixed N */ template struct __mult_fixn { template inline __mult_fixn(TwoDIter Arow, VecX& x, IterY& y) { *y = vecvec::dot((*Arow).begin(), x); __mult_fixn(++Arow, x, ++y); } }; template <> struct __mult_fixn<0> { template inline __mult_fixn(const Matrix& A, VecX& x, VecY& y) { // do nothing } }; template struct mult_fixn { template inline mult_fixn(const Matrix& A, VecX& x, VecY& y) { __mult_fixn(A.begin_rows(), x, y.begin()); } }; #endif