vector_expr.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  *-----------------------------------------------------------------------*/
00013 #ifndef vector_expr_h
00014 #define vector_expr_h
00015 
00016 #include <cmath>
00017 #include <cml/et/size_checking.h>
00018 #include <cml/vector/vector_traits.h>
00019 #include <cml/vector/vector_promotions.h>
00020 
00021 /* XXX Don't know which it should be just yet, since RVO seems to obviate need
00022  * for a reference type.  However, copy by value copies the *entire expression
00023  * tree rooted at the VectorXpr<>, so this choice is bound to affect
00024  * performace for some compiler or another:
00025  */
00026 #define VECXPR_ARG_TYPE  const et::VectorXpr<XprT>&
00027 #define VECXPR_ARG_TYPE_N(_N_)  const et::VectorXpr<XprT##_N_>&
00028 
00029 //#define VECXPR_ARG_TYPE         const et::VectorXpr<XprT>
00030 //#define VECXPR_ARG_TYPE_N(_N_)  const et::VectorXpr<XprT##_N_>
00031 
00032 namespace cml {
00033 namespace et {
00034 
00036 template<class ExprT>
00037 class VectorXpr
00038 {
00039   public:
00040 
00041     typedef VectorXpr<ExprT> expr_type;
00042 
00043     /* Record ary-ness of the expression: */
00044     typedef typename ExprT::expr_ary expr_ary;
00045 
00046     /* Copy the expression by value into higher-up expressions: */
00047     typedef expr_type expr_const_reference;
00048 
00049     typedef typename ExprT::value_type value_type;
00050     typedef vector_result_tag result_tag;
00051     typedef typename ExprT::size_tag size_tag;
00052 
00053     /* Store the expression traits: */
00054     typedef ExprTraits<ExprT> expr_traits;
00055 
00056     /* Get the reference type: */
00057     typedef typename expr_traits::const_reference expr_reference;
00058 
00059     /* Get the result type: */
00060     typedef typename expr_traits::result_type result_type;
00061 
00062     /* For matching by assignability: */
00063     typedef cml::et::not_assignable_tag assignable_tag;
00064 
00065     /* Get the temporary type: */
00066     typedef typename result_type::temporary_type temporary_type;
00067 
00068 
00069   public:
00070 
00072     enum { array_size = ExprT::array_size };
00073 
00074 
00075   public:
00076 
00078     value_type length_squared() const {
00079         return m_expr.length_squared();
00080     }
00081 
00083     value_type length() const {
00084         return m_expr.length();
00085     }
00086 
00088     result_type normalize() const {
00089         return m_expr.normalize();
00090     }
00091 
00093     value_type operator[](size_t i) const {
00094         return m_expr[i];
00095     }
00096 
00097 
00098   public:
00099 
00101     size_t size() const {
00102         return m_expr.size();
00103     }
00104 
00106     expr_reference expression() const { return m_expr; }
00107 
00108 
00109   public:
00110 
00112     explicit VectorXpr(expr_reference expr) : m_expr(expr) {}
00113 
00115     VectorXpr(const expr_type& e) : m_expr(e.m_expr) {}
00116 
00117 
00118   protected:
00119 
00120     expr_reference m_expr;
00121 
00122 
00123   private:
00124 
00125     /* Cannot be assigned to: */
00126     expr_type& operator=(const expr_type&);
00127 };
00128 
00130 template<class ExprT>
00131 struct ExprTraits< VectorXpr<ExprT> >
00132 {
00133     typedef VectorXpr<ExprT> expr_type;
00134     typedef ExprT arg_type;
00135     typedef typename expr_type::value_type value_type;
00136     typedef typename expr_type::expr_const_reference const_reference;
00137     typedef typename expr_type::result_tag result_tag;
00138     typedef typename expr_type::size_tag size_tag;
00139     typedef typename expr_type::result_type result_type;
00140     typedef typename expr_type::assignable_tag assignable_tag;
00141     typedef expr_node_tag node_tag;
00142 
00143     value_type get(const expr_type& v, size_t i) const { return v[i]; }
00144     size_t size(const expr_type& e) const { return e.size(); }
00145 };
00146 
00147 
00152 template<class ExprT, class OpT>
00153 class UnaryVectorOp
00154 {
00155   public:
00156 
00157     typedef UnaryVectorOp<ExprT,OpT> expr_type;
00158 
00159     /* Record ary-ness of the expression: */
00160     typedef unary_expression expr_ary;
00161 
00162     /* Copy the expression by value into higher-up expressions: */
00163     typedef expr_type expr_const_reference;
00164 
00165     typedef typename OpT::value_type value_type;
00166     typedef vector_result_tag result_tag;
00167     typedef typename ExprT::size_tag size_tag;
00168 
00169     /* Store the expression traits for the subexpression: */
00170     typedef ExprTraits<ExprT> expr_traits;
00171 
00172     /* Reference type for the subexpression: */
00173     typedef typename expr_traits::const_reference expr_reference;
00174 
00175     /* Get the result type (same as for subexpression): */
00176     typedef typename expr_traits::result_type result_type;
00177 
00178     /* For matching by assignability: */
00179     typedef cml::et::not_assignable_tag assignable_tag;
00180 
00181     /* Get the temporary type: */
00182     typedef typename result_type::temporary_type temporary_type;
00183 
00184 
00185   public:
00186 
00188     enum { array_size = ExprT::array_size };
00189 
00190 
00191   public:
00192 
00194     value_type length_squared() const {
00195         return dot(
00196                 VectorXpr<expr_type>(*this),
00197                 VectorXpr<expr_type>(*this));
00198     }
00199 
00201     value_type length() const {
00202         return std::sqrt(length_squared());
00203     }
00204 
00206     result_type normalize() const {
00207         result_type v(VectorXpr<expr_type>(*this));
00208         return v.normalize();
00209     }
00210 
00212     value_type operator[](size_t i) const {
00213 
00214         /* This uses the expression traits to figure out how to access the
00215          * i'th index of the subexpression:
00216          */
00217         return OpT().apply(expr_traits().get(m_expr,i));
00218     }
00219 
00220 
00221   public:
00222 
00224     size_t size() const {
00225         return m_expr.size();
00226     }
00227 
00229     expr_reference expression() const { return m_expr; }
00230 
00231 
00232   public:
00233 
00235     explicit UnaryVectorOp(expr_reference expr) : m_expr(expr) {}
00236 
00238     UnaryVectorOp(const expr_type& e) : m_expr(e.m_expr) {}
00239 
00240 
00241   protected:
00242 
00243     expr_reference m_expr;
00244 
00245 
00246   private:
00247 
00248     /* Cannot be assigned to: */
00249     expr_type& operator=(const expr_type&);
00250 };
00251 
00253 template<class ExprT, class OpT>
00254 struct ExprTraits< UnaryVectorOp<ExprT,OpT> >
00255 {
00256     typedef UnaryVectorOp<ExprT,OpT> expr_type;
00257     typedef ExprT arg_type;
00258 
00259     typedef typename expr_type::value_type value_type;
00260     typedef typename expr_type::expr_const_reference const_reference;
00261     typedef typename expr_type::result_tag result_tag;
00262     typedef typename expr_type::size_tag size_tag;
00263     typedef typename expr_type::result_type result_type;
00264     typedef typename expr_type::assignable_tag assignable_tag;
00265     typedef expr_node_tag node_tag;
00266 
00267     value_type get(const expr_type& v, size_t i) const { return v[i]; }
00268     size_t size(const expr_type& e) const { return e.size(); }
00269 };
00270 
00271 
00276 template<class LeftT, class RightT, class OpT>
00277 class BinaryVectorOp
00278 {
00279   public:
00280 
00281     typedef BinaryVectorOp<LeftT,RightT,OpT> expr_type;
00282 
00283     /* Record ary-ness of the expression: */
00284     typedef binary_expression expr_ary;
00285 
00286     /* Copy the expression by value into higher-up expressions: */
00287     typedef expr_type expr_const_reference;
00288 
00289     typedef typename OpT::value_type value_type;
00290     typedef vector_result_tag result_tag;
00291 
00292     /* Store the expression traits types for the two subexpressions: */
00293     typedef ExprTraits<LeftT> left_traits;
00294     typedef ExprTraits<RightT> right_traits;
00295 
00296     /* Reference types for the two subexpressions: */
00297     typedef typename left_traits::const_reference left_reference;
00298     typedef typename right_traits::const_reference right_reference;
00299 
00300     /* Figure out the expression's resulting (vector) type: */
00301     typedef typename left_traits::result_type left_result;
00302     typedef typename right_traits::result_type right_result;
00303     typedef typename VectorPromote<left_result,right_result>::type result_type;
00304     typedef typename result_type::size_tag size_tag;
00305 
00306     /* For matching by assignability: */
00307     typedef cml::et::not_assignable_tag assignable_tag;
00308 
00309     /* Get the temporary type: */
00310     typedef typename result_type::temporary_type temporary_type;
00311 
00312     /* Define a size checker: */
00313     typedef GetCheckedSize<LeftT,RightT,size_tag> checked_size;
00314 
00315 
00316   public:
00317 
00319     enum { array_size = result_type::array_size };
00320 
00321 
00322   public:
00323 
00325     value_type length_squared() const {
00326         return dot(
00327                 VectorXpr<expr_type>(*this),
00328                 VectorXpr<expr_type>(*this));
00329     }
00330 
00332     value_type length() const {
00333         return std::sqrt(length_squared());
00334     }
00335 
00337     result_type normalize() const {
00338         result_type v(VectorXpr<expr_type>(*this));
00339         return v.normalize();
00340     }
00341 
00343     value_type operator[](size_t i) const {
00344 
00345         /* This uses the expression traits to figure out how to access the
00346          * i'th index of the two subexpressions:
00347          */
00348         return OpT().apply(
00349                 left_traits().get(m_left,i),
00350                 right_traits().get(m_right,i));
00351     }
00352 
00353 
00354   public:
00355 
00361     size_t size() const {
00362         /* Note: This actually does a check only if
00363          * CML_CHECK_VECTOR_EXPR_SIZES is set:
00364          */
00365         return CheckedSize(m_left,m_right,size_tag());
00366     }
00367 
00369     left_reference left_expression() const { return m_left; }
00370 
00372     right_reference right_expression() const { return m_right; }
00373 
00374 
00375   public:
00376 
00378     explicit BinaryVectorOp(left_reference left, right_reference right)
00379         : m_left(left), m_right(right) {}
00380 
00382     BinaryVectorOp(const expr_type& e)
00383         : m_left(e.m_left), m_right(e.m_right) {}
00384 
00385 
00386   protected:
00387 
00388     left_reference m_left;
00389     right_reference m_right;
00390 
00391 
00392   private:
00393 
00394     /* This ensures that a compile-time size check is executed: */
00395     typename checked_size::check_type _dummy;
00396 
00397 
00398   private:
00399 
00400     /* Cannot be assigned to: */
00401     expr_type& operator=(const expr_type&);
00402 };
00403 
00405 template<class LeftT, class RightT, class OpT>
00406 struct ExprTraits< BinaryVectorOp<LeftT,RightT,OpT> >
00407 {
00408     typedef BinaryVectorOp<LeftT,RightT,OpT> expr_type;
00409     typedef LeftT left_type;
00410     typedef RightT right_type;
00411 
00412     typedef typename expr_type::value_type value_type;
00413     typedef typename expr_type::expr_const_reference const_reference;
00414     typedef typename expr_type::result_tag result_tag;
00415     typedef typename expr_type::size_tag size_tag;
00416     typedef typename expr_type::result_type result_type;
00417     typedef typename expr_type::assignable_tag assignable_tag;
00418     typedef expr_node_tag node_tag;
00419 
00420     value_type get(const expr_type& v, size_t i) const { return v[i]; }
00421     size_t size(const expr_type& e) const { return e.size(); }
00422 };
00423 
00424 /* Helper struct to verify that both arguments are vector expressions: */
00425 template<typename LeftTraits, typename RightTraits>
00426 struct VectorExpressions
00427 {
00428     /* Require that both arguments are vector expressions: */
00429     typedef typename LeftTraits::result_tag left_result;
00430     typedef typename RightTraits::result_tag right_result;
00431     enum { is_true = (same_type<left_result,et::vector_result_tag>::is_true
00432             && same_type<right_result,et::vector_result_tag>::is_true) };
00433 };
00434 
00435 namespace detail {
00436 
00437 template<typename VecT, typename RT, typename MT> inline
00438 void Resize(VecT&,size_t,RT,MT) {}
00439 
00440 template<typename VecT> inline
00441 void Resize(VecT& v, size_t S, resizable_tag, dynamic_memory_tag) {
00442     v.resize(S);
00443 }
00444 
00445 template<typename VecT> inline
00446 void Resize(VecT& v, size_t S) {
00447     Resize(v, S, typename VecT::resizing_tag(), typename VecT::memory_tag());
00448 }
00449 
00450 } // namespace detail
00451 
00452 } // namespace et
00453 } // namespace cml
00454 
00455 #endif
00456 
00457 // -------------------------------------------------------------------------
00458 // vim:ft=cpp

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