quaternion_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 quaternion_expr_h
00014 #define quaternion_expr_h
00015 
00016 #include <cml/et/size_checking.h>
00017 #include <cml/mathlib/epsilon.h>
00018 #include <cml/quaternion/quaternion_traits.h>
00019 #include <cml/quaternion/quaternion_promotions.h>
00020 #include <cml/util.h>
00021 
00022 #define QUATXPR_ARG_TYPE  const et::QuaternionXpr<XprT>&
00023 #define QUATXPR_ARG_TYPE_N(_N_)  const et::QuaternionXpr<XprT##_N_>&
00024 
00025 namespace cml {
00026 namespace et {
00027 
00029 template<class ExprT>
00030 class QuaternionXpr
00031 {
00032   public:
00033 
00034     typedef QuaternionXpr<ExprT> expr_type;
00035 
00036     /* Record ary-ness of the expression: */
00037     typedef typename ExprT::expr_ary expr_ary;
00038 
00039     /* Copy the expression by value into higher-up expressions: */
00040     typedef expr_type expr_const_reference;
00041 
00042     typedef typename ExprT::value_type value_type;
00043     typedef quaternion_result_tag result_tag;
00044     typedef typename ExprT::size_tag size_tag;
00045 
00046     /* Store the expression traits: */
00047     typedef ExprTraits<ExprT> expr_traits;
00048 
00049     /* Get the reference type: */
00050     typedef typename expr_traits::const_reference expr_reference;
00051 
00052     /* Get the result type: */
00053     typedef typename expr_traits::result_type result_type;
00054 
00055     /* Get the vector type: */
00056     typedef typename result_type::vector_type vector_type;
00057 
00058     /* Get the imaginary part type: */
00059     typedef typename vector_type::subvector_type imaginary_type;
00060 
00061     /* For matching by assignability: */
00062     typedef cml::et::not_assignable_tag assignable_tag;
00063 
00064     /* Get the temporary type: */
00065     typedef typename result_type::temporary_type temporary_type;
00066 
00067     /* Record the order type: */
00068     typedef typename result_type::order_type order_type;
00069     
00070     /* Record the cross type: */
00071     typedef typename result_type::cross_type cross_type;
00072 
00073 
00074   public:
00075 
00077     enum { array_size = ExprT::array_size };
00078 
00079 
00080   public:
00081 
00083     value_type real() const {
00084         return m_expr.real();
00085     }
00086 
00088     imaginary_type imaginary() const {
00089         return m_expr.imaginary();
00090     }
00091 
00093     value_type norm() const {
00094         return m_expr.length_squared();
00095     }
00096 
00098     value_type length_squared() const {
00099         return m_expr.length_squared();
00100     }
00101 
00103     value_type length() const {
00104         return m_expr.length();
00105     }
00106 
00108     temporary_type normalize() const {
00109         return m_expr.normalize();
00110     }
00111 
00113     temporary_type log(
00114         value_type tolerance = epsilon<value_type>::placeholder()) const
00115     {
00116         return m_expr.log(tolerance);
00117     }
00118 
00123     temporary_type exp(
00124         value_type tolerance = epsilon<value_type>::placeholder()) const
00125     {
00126         return m_expr.exp(tolerance);
00127     }
00128 
00130     value_type operator[](size_t i) const {
00131         return m_expr[i];
00132     }
00133 
00134 
00135   public:
00136 
00138     size_t size() const {
00139         return m_expr.size();
00140     }
00141 
00143     expr_reference expression() const { return m_expr; }
00144 
00145 
00146   public:
00147 
00149     explicit QuaternionXpr(expr_reference expr) : m_expr(expr) {}
00150 
00152     QuaternionXpr(const expr_type& e) : m_expr(e.m_expr) {}
00153 
00154 
00155   protected:
00156 
00157     expr_reference m_expr;
00158 
00159 
00160   private:
00161 
00162     /* Cannot be assigned to: */
00163     expr_type& operator=(const expr_type&);
00164 };
00165 
00167 template<class ExprT>
00168 struct ExprTraits< QuaternionXpr<ExprT> >
00169 {
00170     typedef QuaternionXpr<ExprT> expr_type;
00171     typedef ExprT arg_type;
00172     typedef typename expr_type::value_type value_type;
00173     typedef typename expr_type::expr_const_reference const_reference;
00174     typedef typename expr_type::result_tag result_tag;
00175     typedef typename expr_type::size_tag size_tag;
00176     typedef typename expr_type::result_type result_type;
00177     typedef typename expr_type::assignable_tag not_assignable_tag;
00178     typedef expr_node_tag node_tag;
00179 
00180     value_type get(const expr_type& v, size_t i) const { return v[i]; }
00181     size_t size(const expr_type& e) const { return e.size(); }
00182 };
00183 
00184 
00189 template<class ExprT, class OpT>
00190 class UnaryQuaternionOp
00191 {
00192   public:
00193 
00194     typedef UnaryQuaternionOp<ExprT,OpT> expr_type;
00195 
00196     /* Record ary-ness of the expression: */
00197     typedef unary_expression expr_ary;
00198 
00199     /* Copy the expression by value into higher-up expressions: */
00200     typedef expr_type expr_const_reference;
00201 
00202     typedef typename OpT::value_type value_type;
00203     typedef quaternion_result_tag result_tag;
00204     typedef typename ExprT::size_tag size_tag;
00205 
00206     /* Store the expression traits for the subexpression: */
00207     typedef ExprTraits<ExprT> expr_traits;
00208 
00209     /* Reference type for the subexpression: */
00210     typedef typename expr_traits::const_reference expr_reference;
00211 
00212     /* Get the result type (same as for subexpression): */
00213     typedef typename expr_traits::result_type result_type;
00214 
00215     /* For matching by assignability: */
00216     typedef cml::et::not_assignable_tag assignable_tag;
00217 
00218     /* Get the temporary type: */
00219     typedef typename result_type::temporary_type temporary_type;
00220 
00221     /* Get the vector type: */
00222     typedef typename result_type::vector_type vector_type;
00223 
00224     /* Get the imaginary part type: */
00225     typedef typename vector_type::subvector_type imaginary_type;
00226 
00227     /* Record the order type: */
00228     typedef typename result_type::order_type order_type;
00229 
00230 
00231   public:
00232 
00234     enum { array_size = ExprT::array_size };
00235 
00237     enum {
00238         W = order_type::W,
00239         X = order_type::X,
00240         Y = order_type::Y,
00241         Z = order_type::Z
00242     };
00243 
00244 
00245   public:
00246 
00248     value_type real() const {
00249         return (*this)[W];
00250     }
00251 
00253     imaginary_type imaginary() const {
00254         imaginary_type v;
00255         v[0] = (*this)[X]; v[1] = (*this)[Y]; v[2] = (*this)[Z];
00256         return v;
00257     }
00258 
00260     value_type norm() const {
00261         return length_squared();
00262     }
00263 
00265     value_type length_squared() const {
00266         return dot(
00267                 QuaternionXpr<expr_type>(*this),
00268                 QuaternionXpr<expr_type>(*this));
00269     }
00270 
00272     value_type length() const {
00273         return std::sqrt(length_squared());
00274     }
00275 
00277     temporary_type normalize() const {
00278         temporary_type q(QuaternionXpr<expr_type>(*this));
00279         return q.normalize();
00280     }
00281 
00283     temporary_type log(
00284         value_type tolerance = epsilon<value_type>::placeholder()) const
00285     {
00286         value_type a = acos_safe(real());
00287         value_type s = std::sin(a);
00288         
00289         if (s > tolerance) {
00290             return temporary_type(value_type(0), imaginary() * (a / s));
00291         } else {
00292             return temporary_type(value_type(0), imaginary());
00293         }
00294     }
00295     
00300     temporary_type exp(
00301         value_type tolerance = epsilon<value_type>::placeholder()) const
00302     {
00303         imaginary_type v = imaginary();
00304         value_type a = cml::length(v);
00305         
00306         if (a > tolerance) {
00307             return temporary_type(std::cos(a), v * (std::sin(a) / a));
00308         } else {
00309             return temporary_type(std::cos(a), v);
00310         }
00311     }
00312 
00314     value_type operator[](size_t i) const {
00315 
00316         /* This uses the expression traits to figure out how to access the
00317          * i'th index of the subexpression:
00318          */
00319         return OpT().apply(expr_traits().get(m_expr,i));
00320     }
00321 
00322 
00323   public:
00324 
00326     size_t size() const {
00327         return m_expr.size();
00328     }
00329 
00331     expr_reference expression() const { return m_expr; }
00332 
00333 
00334   public:
00335 
00337     explicit UnaryQuaternionOp(expr_reference expr) : m_expr(expr) {}
00338 
00340     UnaryQuaternionOp(const expr_type& e) : m_expr(e.m_expr) {}
00341 
00342 
00343   protected:
00344 
00345     expr_reference m_expr;
00346 
00347 
00348   private:
00349 
00350     /* Cannot be assigned to: */
00351     expr_type& operator=(const expr_type&);
00352 };
00353 
00355 template<class ExprT, class OpT>
00356 struct ExprTraits< UnaryQuaternionOp<ExprT,OpT> >
00357 {
00358     typedef UnaryQuaternionOp<ExprT,OpT> expr_type;
00359     typedef ExprT arg_type;
00360 
00361     typedef typename expr_type::value_type value_type;
00362     typedef typename expr_type::expr_const_reference const_reference;
00363     typedef typename expr_type::result_tag result_tag;
00364     typedef typename expr_type::size_tag size_tag;
00365     typedef typename expr_type::result_type result_type;
00366     typedef typename expr_type::assignable_tag not_assignable_tag;
00367     typedef expr_node_tag node_tag;
00368 
00369     value_type get(const expr_type& v, size_t i) const { return v[i]; }
00370     size_t size(const expr_type& e) const { return e.size(); }
00371 };
00372 
00373 
00378 template<class LeftT, class RightT, class OpT>
00379 class BinaryQuaternionOp
00380 {
00381   public:
00382 
00383     typedef BinaryQuaternionOp<LeftT,RightT,OpT> expr_type;
00384 
00385     /* Record ary-ness of the expression: */
00386     typedef binary_expression expr_ary;
00387 
00388     /* Copy the expression by value into higher-up expressions: */
00389     typedef expr_type expr_const_reference;
00390 
00391     typedef typename OpT::value_type value_type;
00392     typedef quaternion_result_tag result_tag;
00393 
00394     /* Store the expression traits types for the two subexpressions: */
00395     typedef ExprTraits<LeftT> left_traits;
00396     typedef ExprTraits<RightT> right_traits;
00397 
00398     /* Reference types for the two subexpressions: */
00399     typedef typename left_traits::const_reference left_reference;
00400     typedef typename right_traits::const_reference right_reference;
00401 
00402     /* Figure out the expression's resulting (quaternion) type: */
00403     typedef typename left_traits::result_type left_result;
00404     typedef typename right_traits::result_type right_result;
00405     typedef typename QuaternionPromote<left_result,right_result>::type
00406         result_type;
00407     typedef typename result_type::size_tag size_tag;
00408 
00409     /* For matching by assignability: */
00410     typedef cml::et::not_assignable_tag assignable_tag;
00411 
00412     /* Get the temporary type: */
00413     typedef typename result_type::temporary_type temporary_type;
00414 
00415     /* Get the vector type: */
00416     typedef typename result_type::vector_type vector_type;
00417 
00418     /* Get the imaginary part type: */
00419     typedef typename vector_type::subvector_type imaginary_type;
00420 
00421     /* Record the order type: */
00422     typedef typename result_type::order_type order_type;
00423 
00424     /* Define a size checker: */
00425     typedef GetCheckedSize<LeftT,RightT,size_tag> checked_size;
00426 
00427 
00428   public:
00429 
00431     enum { array_size = 4 };
00432 
00434     enum {
00435         W = order_type::W,
00436         X = order_type::X,
00437         Y = order_type::Y,
00438         Z = order_type::Z
00439     };
00440 
00441 
00442   public:
00443 
00445     value_type real() const {
00446         return (*this)[W];
00447     }
00448 
00450     imaginary_type imaginary() const {
00451         imaginary_type v;
00452         v[0] = (*this)[X]; v[1] = (*this)[Y]; v[2] = (*this)[Z];
00453         return v;
00454     }
00455 
00457     value_type norm() const {
00458         return length_squared();
00459     }
00460 
00462     value_type length_squared() const {
00463         return dot(
00464                 QuaternionXpr<expr_type>(*this),
00465                 QuaternionXpr<expr_type>(*this));
00466     }
00467 
00469     value_type length() const {
00470         return std::sqrt(length_squared());
00471     }
00472 
00474     temporary_type normalize() const {
00475         temporary_type q(QuaternionXpr<expr_type>(*this));
00476         return q.normalize();
00477     }
00478 
00480     temporary_type log(
00481         value_type tolerance = epsilon<value_type>::placeholder()) const
00482     {
00483         value_type a = acos_safe(real());
00484         value_type s = std::sin(a);
00485         
00486         if (s > tolerance) {
00487             return temporary_type(value_type(0), imaginary() * (a / s));
00488         } else {
00489             return temporary_type(value_type(0), imaginary());
00490         }
00491     }
00492     
00497     temporary_type exp(
00498         value_type tolerance = epsilon<value_type>::placeholder()) const
00499     {
00500         imaginary_type v = imaginary();
00501         value_type a = cml::length(v);
00502         
00503         if (a > tolerance) {
00504             return temporary_type(std::cos(a), v * (std::sin(a) / a));
00505         } else {
00506             return temporary_type(std::cos(a), v);
00507         }
00508     }
00509 
00511     value_type operator[](size_t i) const {
00512 
00513         /* This uses the expression traits to figure out how to access the
00514          * i'th index of the two subexpressions:
00515          */
00516         return OpT().apply(
00517                 left_traits().get(m_left,i),
00518                 right_traits().get(m_right,i));
00519     }
00520 
00521 
00522   public:
00523 
00529     size_t size() const {
00530         /* Note: This actually does a check only if
00531          * CML_CHECK_VECTOR_EXPR_SIZES is set:
00532          */
00533         CheckedSize(m_left,m_right,size_tag());
00534 
00535         /* The size is always 4: */
00536         return 4;
00537     }
00538 
00540     left_reference left_expression() const { return m_left; }
00541 
00543     right_reference right_expression() const { return m_right; }
00544 
00545 
00546   public:
00547 
00549     explicit BinaryQuaternionOp(left_reference left, right_reference right)
00550         : m_left(left), m_right(right) {}
00551 
00553     BinaryQuaternionOp(const expr_type& e)
00554         : m_left(e.m_left), m_right(e.m_right) {}
00555 
00556 
00557   protected:
00558 
00559     left_reference m_left;
00560     right_reference m_right;
00561 
00562 
00563   private:
00564 
00565     /* This ensures that a compile-time size check is executed: */
00566     typename checked_size::check_type _dummy;
00567 
00568 
00569   private:
00570 
00571     /* Cannot be assigned to: */
00572     expr_type& operator=(const expr_type&);
00573 };
00574 
00576 template<class LeftT, class RightT, class OpT>
00577 struct ExprTraits< BinaryQuaternionOp<LeftT,RightT,OpT> >
00578 {
00579     typedef BinaryQuaternionOp<LeftT,RightT,OpT> expr_type;
00580     typedef LeftT left_type;
00581     typedef RightT right_type;
00582 
00583     typedef typename expr_type::value_type value_type;
00584     typedef typename expr_type::expr_const_reference const_reference;
00585     typedef typename expr_type::result_tag result_tag;
00586     typedef typename expr_type::size_tag size_tag;
00587     typedef typename expr_type::result_type result_type;
00588     typedef typename expr_type::imaginary_type imaginary_type;
00589     typedef typename expr_type::assignable_tag not_assignable_tag;
00590     typedef expr_node_tag node_tag;
00591 
00592     value_type get(const expr_type& v, size_t i) const { return v[i]; }
00593     size_t size(const expr_type& e) const { return e.size(); }
00594 };
00595 
00596 
00597 /* Helper struct to verify that both arguments are quaternion expressions: */
00598 template<class LeftTraits, class RightTraits>
00599 struct QuaternionExpressions
00600 {
00601     /* Require that both arguments are quaternion expressions: */
00602     typedef typename LeftTraits::result_tag left_result;
00603     typedef typename RightTraits::result_tag right_result;
00604     enum { is_true = (same_type<left_result,et::quaternion_result_tag>::is_true
00605             && same_type<right_result,et::quaternion_result_tag>::is_true) };
00606 };
00607 
00608 } // namespace et
00609 } // namespace cml
00610 
00611 #endif
00612 
00613 // -------------------------------------------------------------------------
00614 // vim:ft=cpp

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