matvec_mul.h

Go to the documentation of this file.
00001 /* -*- C++ -*- ------------------------------------------------------------
00002  
00003 Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
00004 
00005 The Configurable Math Library (CML) is distributed under the terms of the
00006 Boost Software License, v1.0 (see cml/LICENSE for details).
00007 
00008  *-----------------------------------------------------------------------*/
00023 #ifndef matvec_mul_h
00024 #define matvec_mul_h
00025 
00026 #include <cml/core/cml_meta.h>
00027 #include <cml/vector/vector_expr.h>
00028 #include <cml/matrix/matrix_expr.h>
00029 #include <cml/matvec/matvec_promotions.h>
00030 
00031 /* This is used below to create a more meaningful compile-time error when
00032  * mat-vec mul is not provided with the right arguments:
00033  */
00034 struct mvmul_expects_one_matrix_and_one_vector_arg_error;
00035 struct mvmul_expects_one_vector_and_one_matrix_arg_error;
00036 
00037 namespace cml {
00038 namespace detail {
00039 
00040 /* For choosing the proper multiplication order: */
00041 typedef true_type mul_Ax;
00042 typedef false_type mul_xA;
00043 
00045 template<typename LeftT, typename RightT> inline
00046 typename et::MatVecPromote<
00047     typename et::ExprTraits<LeftT>::result_type,
00048     typename et::ExprTraits<RightT>::result_type
00049 >::temporary_type
00050 mul(const LeftT& A, const RightT& x, mul_Ax)
00051 {
00052     /* Shorthand: */
00053     typedef et::ExprTraits<LeftT> left_traits;
00054     typedef et::ExprTraits<RightT> right_traits;
00055     typedef typename left_traits::result_tag left_result;
00056     typedef typename right_traits::result_tag right_result;
00057 
00058     /* mul()[A*x] requires a matrix and a vector expression: */
00059     CML_STATIC_REQUIRE_M(
00060         (same_type<left_result, et::matrix_result_tag>::is_true
00061          && same_type<right_result, et::vector_result_tag>::is_true),
00062         mvmul_expects_one_matrix_and_one_vector_arg_error);
00063     /* Note: parens are required here so that the preprocessor ignores the
00064      * commas.
00065      */
00066 
00067     /* Get result type: */
00068     typedef typename et::MatVecPromote<
00069         typename left_traits::result_type,
00070         typename right_traits::result_type
00071     >::temporary_type result_type;
00072 
00073     /* Record size type: */
00074     typedef typename result_type::size_tag size_tag;
00075 
00076     /* Check the size: */
00077     size_t N = et::CheckedSize(A, x, size_tag());
00078 
00079     /* Initialize the new vector: */
00080     result_type y; cml::et::detail::Resize(y, N);
00081 
00082     /* Compute y = A*x: */
00083     typedef typename result_type::value_type sum_type;
00084     for(size_t i = 0; i < N; ++i) {
00085         /* XXX This should be unrolled. */
00086         sum_type sum(A(i,0)*x[0]);
00087         for(size_t k = 1; k < x.size(); ++k) {
00088             sum += (A(i,k)*x[k]);
00089         }
00090         y[i] = sum;
00091     }
00092 
00093     return y;
00094 }
00095 
00097 template<typename LeftT, typename RightT> inline
00098 typename et::MatVecPromote<
00099     typename et::ExprTraits<LeftT>::result_type,
00100     typename et::ExprTraits<RightT>::result_type
00101 >::temporary_type
00102 mul(const LeftT& x, const RightT& A, mul_xA)
00103 {
00104     /* Shorthand: */
00105     typedef et::ExprTraits<LeftT> left_traits;
00106     typedef et::ExprTraits<RightT> right_traits;
00107     typedef typename left_traits::result_tag left_result;
00108     typedef typename right_traits::result_tag right_result;
00109 
00110     /* mul()[x*A] requires a vector and a matrix expression: */
00111     CML_STATIC_REQUIRE_M(
00112         (same_type<left_result, et::vector_result_tag>::is_true
00113          && same_type<right_result, et::matrix_result_tag>::is_true),
00114         mvmul_expects_one_vector_and_one_matrix_arg_error);
00115     /* Note: parens are required here so that the preprocessor ignores the
00116      * commas.
00117      */
00118 
00119     /* Get result type: */
00120     typedef typename et::MatVecPromote<
00121         typename left_traits::result_type,
00122         typename right_traits::result_type
00123     >::temporary_type result_type;
00124 
00125     /* Record size type: */
00126     typedef typename result_type::size_tag size_tag;
00127 
00128     /* Check the size: */
00129     size_t N = et::CheckedSize(x, A, size_tag());
00130 
00131     /* Initialize the new vector: */
00132     result_type y; cml::et::detail::Resize(y, N);
00133 
00134     /* Compute y = x*A: */
00135     typedef typename result_type::value_type sum_type;
00136     for(size_t i = 0; i < N; ++i) {
00137         /* XXX This should be unrolled. */
00138         sum_type sum(x[0]*A(0,i));
00139         for(size_t k = 1; k < x.size(); ++k) {
00140             sum += (x[k]*A(k,i));
00141         }
00142         y[i] = sum;
00143     }
00144 
00145     return y;
00146 }
00147 
00148 } // namespace detail
00149 
00150 
00152 template<typename E1, class AT1, typename BO, class L,
00153          typename E2, class AT2>
00154 inline typename et::MatVecPromote<
00155     matrix<E1,AT1,BO,L>, vector<E2,AT2>
00156 >::temporary_type
00157 operator*(const matrix<E1,AT1,BO,L>& left,
00158           const vector<E2,AT2>& right)
00159 {
00160     return detail::mul(left,right,detail::mul_Ax());
00161 }
00162 
00164 template<typename E, class AT, class L, typename BO, typename XprT>
00165 inline typename et::MatVecPromote<
00166     matrix<E,AT,BO,L>, typename XprT::result_type
00167 >::temporary_type
00168 operator*(const matrix<E,AT,BO,L>& left,
00169           const et::VectorXpr<XprT>& right)
00170 {
00171     /* Generate a temporary, and compute the right-hand expression: */
00172     typename et::VectorXpr<XprT>::temporary_type right_tmp;
00173     cml::et::detail::Resize(right_tmp,right.size());
00174     right_tmp = right;
00175 
00176     return detail::mul(left,right_tmp,detail::mul_Ax());
00177 }
00178 
00180 template<typename XprT, typename E, class AT>
00181 inline typename et::MatVecPromote<
00182     typename XprT::result_type, vector<E,AT>
00183 >::temporary_type
00184 operator*(const et::MatrixXpr<XprT>& left,
00185           const vector<E,AT>& right)
00186 {
00187     /* Generate a temporary, and compute the left-hand expression: */
00188     typename et::MatrixXpr<XprT>::temporary_type left_tmp;
00189     cml::et::detail::Resize(left_tmp,left.rows(),left.cols());
00190     left_tmp = left;
00191 
00192     return detail::mul(left_tmp,right,detail::mul_Ax());
00193 }
00194 
00196 template<typename XprT1, typename XprT2>
00197 inline typename et::MatVecPromote<
00198     typename XprT1::result_type, typename XprT2::result_type
00199 >::temporary_type
00200 operator*(const et::MatrixXpr<XprT1>& left,
00201           const et::VectorXpr<XprT2>& right)
00202 {
00203     /* Generate a temporary, and compute the left-hand expression: */
00204     typename et::MatrixXpr<XprT1>::temporary_type left_tmp;
00205     cml::et::detail::Resize(left_tmp,left.rows(),left.cols());
00206     left_tmp = left;
00207 
00208     /* Generate a temporary, and compute the right-hand expression: */
00209     typename et::VectorXpr<XprT2>::temporary_type right_tmp;
00210     cml::et::detail::Resize(right_tmp,right.size());
00211     right_tmp = right;
00212 
00213     return detail::mul(left_tmp,right_tmp,detail::mul_Ax());
00214 }
00215 
00217 template<typename E1, class AT1, typename E2, class AT2, typename BO, class L>
00218 inline typename et::MatVecPromote<
00219     vector<E1,AT1>, matrix<E2,AT2,BO,L>
00220 >::temporary_type
00221 operator*(const vector<E1,AT1>& left,
00222           const matrix<E2,AT2,BO,L>& right)
00223 {
00224     return detail::mul(left,right,detail::mul_xA());
00225 }
00226 
00228 template<typename XprT, typename E, class AT>
00229 inline typename et::MatVecPromote<
00230     typename XprT::result_type, vector<E,AT>
00231 >::temporary_type
00232 operator*(const vector<E,AT>& left,
00233           const et::MatrixXpr<XprT>& right)
00234 {
00235     /* Generate a temporary, and compute the right-hand expression: */
00236     typename et::MatrixXpr<XprT>::temporary_type right_tmp;
00237     cml::et::detail::Resize(right_tmp,right.rows(),right.cols());
00238     right_tmp = right;
00239 
00240     return detail::mul(left,right_tmp,detail::mul_xA());
00241 }
00242 
00244 template<typename XprT, typename E, class AT, typename BO, class L>
00245 inline typename et::MatVecPromote<
00246     typename XprT::result_type, matrix<E,AT,BO,L>
00247 >::temporary_type
00248 operator*(const et::VectorXpr<XprT>& left,
00249           const matrix<E,AT,BO,L>& right)
00250 {
00251     /* Generate a temporary, and compute the left-hand expression: */
00252     typename et::VectorXpr<XprT>::temporary_type left_tmp;
00253     cml::et::detail::Resize(left_tmp,left.size());
00254     left_tmp = left;
00255 
00256     return detail::mul(left_tmp,right,detail::mul_xA());
00257 }
00258 
00260 template<typename XprT1, typename XprT2>
00261 inline typename et::MatVecPromote<
00262     typename XprT1::result_type, typename XprT2::result_type
00263 >::temporary_type
00264 operator*(const et::VectorXpr<XprT1>& left,
00265           const et::MatrixXpr<XprT2>& right)
00266 {
00267     /* Generate a temporary, and compute the left-hand expression: */
00268     typename et::VectorXpr<XprT1>::temporary_type left_tmp;
00269     cml::et::detail::Resize(left_tmp,left.size());
00270     left_tmp = left;
00271 
00272     /* Generate a temporary, and compute the right-hand expression: */
00273     typename et::MatrixXpr<XprT2>::temporary_type right_tmp;
00274     cml::et::detail::Resize(right_tmp,right.rows(),right.cols());
00275     right_tmp = right;
00276 
00277     return detail::mul(left_tmp,right_tmp,detail::mul_xA());
00278 }
00279 
00280 } // namespace cml
00281 
00282 #endif
00283 
00284 // -------------------------------------------------------------------------
00285 // vim:ft=cpp

Generated on Sat Jul 18 19:35:27 2009 for CML 1.0 by  doxygen 1.5.9