X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2Fcml%2Fquaternion%2Fquaternion_expr.h;fp=src%2FMoof%2Fcml%2Fquaternion%2Fquaternion_expr.h;h=dcec9fd68a3a2c158699382f7688471543c8d965;hp=0000000000000000000000000000000000000000;hb=c2321281bf12a7efaedde930422c7ddbc92080d4;hpb=87bc17e55b0c1dc73ecc66df856d3f08fd7a7724 diff --git a/src/Moof/cml/quaternion/quaternion_expr.h b/src/Moof/cml/quaternion/quaternion_expr.h new file mode 100644 index 0000000..dcec9fd --- /dev/null +++ b/src/Moof/cml/quaternion/quaternion_expr.h @@ -0,0 +1,614 @@ +/* -*- C++ -*- ------------------------------------------------------------ + +Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/ + +The Configurable Math Library (CML) is distributed under the terms of the +Boost Software License, v1.0 (see cml/LICENSE for details). + + *-----------------------------------------------------------------------*/ +/** @file + * @brief + */ + +#ifndef quaternion_expr_h +#define quaternion_expr_h + +#include +#include +#include +#include +#include + +#define QUATXPR_ARG_TYPE const et::QuaternionXpr& +#define QUATXPR_ARG_TYPE_N(_N_) const et::QuaternionXpr& + +namespace cml { +namespace et { + +/** A placeholder for a quaternion expression in an expression tree. */ +template +class QuaternionXpr +{ + public: + + typedef QuaternionXpr expr_type; + + /* Record ary-ness of the expression: */ + typedef typename ExprT::expr_ary expr_ary; + + /* Copy the expression by value into higher-up expressions: */ + typedef expr_type expr_const_reference; + + typedef typename ExprT::value_type value_type; + typedef quaternion_result_tag result_tag; + typedef typename ExprT::size_tag size_tag; + + /* Store the expression traits: */ + typedef ExprTraits expr_traits; + + /* Get the reference type: */ + typedef typename expr_traits::const_reference expr_reference; + + /* Get the result type: */ + typedef typename expr_traits::result_type result_type; + + /* Get the vector type: */ + typedef typename result_type::vector_type vector_type; + + /* Get the imaginary part type: */ + typedef typename vector_type::subvector_type imaginary_type; + + /* For matching by assignability: */ + typedef cml::et::not_assignable_tag assignable_tag; + + /* Get the temporary type: */ + typedef typename result_type::temporary_type temporary_type; + + /* Record the order type: */ + typedef typename result_type::order_type order_type; + + /* Record the cross type: */ + typedef typename result_type::cross_type cross_type; + + + public: + + /** Record result size as an enum. */ + enum { array_size = ExprT::array_size }; + + + public: + + /** Return the real part of the expression. */ + value_type real() const { + return m_expr.real(); + } + + /** Return the vector part of the expression. */ + imaginary_type imaginary() const { + return m_expr.imaginary(); + } + + /** Return the Cayley norm of the expression. */ + value_type norm() const { + return m_expr.length_squared(); + } + + /** Return square of the quaternion length. */ + value_type length_squared() const { + return m_expr.length_squared(); + } + + /** Return the quaternion length. */ + value_type length() const { + return m_expr.length(); + } + + /** Return the result as a normalized quaternion. */ + temporary_type normalize() const { + return m_expr.normalize(); + } + + /** Return the log of the expression. */ + temporary_type log( + value_type tolerance = epsilon::placeholder()) const + { + return m_expr.log(tolerance); + } + + /** + * Return the result of the exponential function as applied to + * this expression. + */ + temporary_type exp( + value_type tolerance = epsilon::placeholder()) const + { + return m_expr.exp(tolerance); + } + + /** Compute value at index i of the result quaternion. */ + value_type operator[](size_t i) const { + return m_expr[i]; + } + + + public: + + /** Return size of this expression (same as subexpression's size). */ + size_t size() const { + return m_expr.size(); + } + + /** Return reference to contained expression. */ + expr_reference expression() const { return m_expr; } + + + public: + + /** Construct from the subexpression to store. */ + explicit QuaternionXpr(expr_reference expr) : m_expr(expr) {} + + /** Copy constructor. */ + QuaternionXpr(const expr_type& e) : m_expr(e.m_expr) {} + + + protected: + + expr_reference m_expr; + + + private: + + /* Cannot be assigned to: */ + expr_type& operator=(const expr_type&); +}; + +/** Expression traits class for QuaternionXpr<>. */ +template +struct ExprTraits< QuaternionXpr > +{ + typedef QuaternionXpr expr_type; + typedef ExprT arg_type; + typedef typename expr_type::value_type value_type; + typedef typename expr_type::expr_const_reference const_reference; + typedef typename expr_type::result_tag result_tag; + typedef typename expr_type::size_tag size_tag; + typedef typename expr_type::result_type result_type; + typedef typename expr_type::assignable_tag not_assignable_tag; + typedef expr_node_tag node_tag; + + value_type get(const expr_type& v, size_t i) const { return v[i]; } + size_t size(const expr_type& e) const { return e.size(); } +}; + + +/** A unary quaternion expression. + * + * The operator's operator() method must take exactly one argument. + */ +template +class UnaryQuaternionOp +{ + public: + + typedef UnaryQuaternionOp expr_type; + + /* Record ary-ness of the expression: */ + typedef unary_expression expr_ary; + + /* Copy the expression by value into higher-up expressions: */ + typedef expr_type expr_const_reference; + + typedef typename OpT::value_type value_type; + typedef quaternion_result_tag result_tag; + typedef typename ExprT::size_tag size_tag; + + /* Store the expression traits for the subexpression: */ + typedef ExprTraits expr_traits; + + /* Reference type for the subexpression: */ + typedef typename expr_traits::const_reference expr_reference; + + /* Get the result type (same as for subexpression): */ + typedef typename expr_traits::result_type result_type; + + /* For matching by assignability: */ + typedef cml::et::not_assignable_tag assignable_tag; + + /* Get the temporary type: */ + typedef typename result_type::temporary_type temporary_type; + + /* Get the vector type: */ + typedef typename result_type::vector_type vector_type; + + /* Get the imaginary part type: */ + typedef typename vector_type::subvector_type imaginary_type; + + /* Record the order type: */ + typedef typename result_type::order_type order_type; + + + public: + + /** Record result size as an enum. */ + enum { array_size = ExprT::array_size }; + + /** Localize the ordering as an enum. */ + enum { + W = order_type::W, + X = order_type::X, + Y = order_type::Y, + Z = order_type::Z + }; + + + public: + + /** Return the real part of the expression. */ + value_type real() const { + return (*this)[W]; + } + + /** Return the vector part of the expression. */ + imaginary_type imaginary() const { + imaginary_type v; + v[0] = (*this)[X]; v[1] = (*this)[Y]; v[2] = (*this)[Z]; + return v; + } + + /** Return the Cayley norm of the expression. */ + value_type norm() const { + return length_squared(); + } + + /** Return square of the quaternion length. */ + value_type length_squared() const { + return dot( + QuaternionXpr(*this), + QuaternionXpr(*this)); + } + + /** Return the quaternion length. */ + value_type length() const { + return std::sqrt(length_squared()); + } + + /** Return the result as a normalized quaternion. */ + temporary_type normalize() const { + temporary_type q(QuaternionXpr(*this)); + return q.normalize(); + } + + /** Return the log of this expression. */ + temporary_type log( + value_type tolerance = epsilon::placeholder()) const + { + value_type a = acos_safe(real()); + value_type s = std::sin(a); + + if (s > tolerance) { + return temporary_type(value_type(0), imaginary() * (a / s)); + } else { + return temporary_type(value_type(0), imaginary()); + } + } + + /** + * Return the result of the exponential function as applied to + * this expression. + */ + temporary_type exp( + value_type tolerance = epsilon::placeholder()) const + { + imaginary_type v = imaginary(); + value_type a = cml::length(v); + + if (a > tolerance) { + return temporary_type(std::cos(a), v * (std::sin(a) / a)); + } else { + return temporary_type(std::cos(a), v); + } + } + + /** Compute value at index i of the result quaternion. */ + value_type operator[](size_t i) const { + + /* This uses the expression traits to figure out how to access the + * i'th index of the subexpression: + */ + return OpT().apply(expr_traits().get(m_expr,i)); + } + + + public: + + /** Return size of this expression (same as argument's size). */ + size_t size() const { + return m_expr.size(); + } + + /** Return reference to contained expression. */ + expr_reference expression() const { return m_expr; } + + + public: + + /** Construct from the subexpression. */ + explicit UnaryQuaternionOp(expr_reference expr) : m_expr(expr) {} + + /** Copy constructor. */ + UnaryQuaternionOp(const expr_type& e) : m_expr(e.m_expr) {} + + + protected: + + expr_reference m_expr; + + + private: + + /* Cannot be assigned to: */ + expr_type& operator=(const expr_type&); +}; + +/** Expression traits class for UnaryQuaternionOp<>. */ +template +struct ExprTraits< UnaryQuaternionOp > +{ + typedef UnaryQuaternionOp expr_type; + typedef ExprT arg_type; + + typedef typename expr_type::value_type value_type; + typedef typename expr_type::expr_const_reference const_reference; + typedef typename expr_type::result_tag result_tag; + typedef typename expr_type::size_tag size_tag; + typedef typename expr_type::result_type result_type; + typedef typename expr_type::assignable_tag not_assignable_tag; + typedef expr_node_tag node_tag; + + value_type get(const expr_type& v, size_t i) const { return v[i]; } + size_t size(const expr_type& e) const { return e.size(); } +}; + + +/** A binary quaternion expression. + * + * The operator's operator() method must take exactly two arguments. + */ +template +class BinaryQuaternionOp +{ + public: + + typedef BinaryQuaternionOp expr_type; + + /* Record ary-ness of the expression: */ + typedef binary_expression expr_ary; + + /* Copy the expression by value into higher-up expressions: */ + typedef expr_type expr_const_reference; + + typedef typename OpT::value_type value_type; + typedef quaternion_result_tag result_tag; + + /* Store the expression traits types for the two subexpressions: */ + typedef ExprTraits left_traits; + typedef ExprTraits right_traits; + + /* Reference types for the two subexpressions: */ + typedef typename left_traits::const_reference left_reference; + typedef typename right_traits::const_reference right_reference; + + /* Figure out the expression's resulting (quaternion) type: */ + typedef typename left_traits::result_type left_result; + typedef typename right_traits::result_type right_result; + typedef typename QuaternionPromote::type + result_type; + typedef typename result_type::size_tag size_tag; + + /* For matching by assignability: */ + typedef cml::et::not_assignable_tag assignable_tag; + + /* Get the temporary type: */ + typedef typename result_type::temporary_type temporary_type; + + /* Get the vector type: */ + typedef typename result_type::vector_type vector_type; + + /* Get the imaginary part type: */ + typedef typename vector_type::subvector_type imaginary_type; + + /* Record the order type: */ + typedef typename result_type::order_type order_type; + + /* Define a size checker: */ + typedef GetCheckedSize checked_size; + + + public: + + /** Record result size as an enum. */ + enum { array_size = 4 }; + + /** Localize the ordering as an enum. */ + enum { + W = order_type::W, + X = order_type::X, + Y = order_type::Y, + Z = order_type::Z + }; + + + public: + + /** Return the real part of the expression. */ + value_type real() const { + return (*this)[W]; + } + + /** Return the vector part of the expression. */ + imaginary_type imaginary() const { + imaginary_type v; + v[0] = (*this)[X]; v[1] = (*this)[Y]; v[2] = (*this)[Z]; + return v; + } + + /** Return the Cayley norm of the expression. */ + value_type norm() const { + return length_squared(); + } + + /** Return square of the quaternion length. */ + value_type length_squared() const { + return dot( + QuaternionXpr(*this), + QuaternionXpr(*this)); + } + + /** Return the quaternion length. */ + value_type length() const { + return std::sqrt(length_squared()); + } + + /** Return the result as a normalized quaternion. */ + temporary_type normalize() const { + temporary_type q(QuaternionXpr(*this)); + return q.normalize(); + } + + /** Return the log of this expression. */ + temporary_type log( + value_type tolerance = epsilon::placeholder()) const + { + value_type a = acos_safe(real()); + value_type s = std::sin(a); + + if (s > tolerance) { + return temporary_type(value_type(0), imaginary() * (a / s)); + } else { + return temporary_type(value_type(0), imaginary()); + } + } + + /** + * Return the result of the exponential function as applied to + * this expression. + */ + temporary_type exp( + value_type tolerance = epsilon::placeholder()) const + { + imaginary_type v = imaginary(); + value_type a = cml::length(v); + + if (a > tolerance) { + return temporary_type(std::cos(a), v * (std::sin(a) / a)); + } else { + return temporary_type(std::cos(a), v); + } + } + + /** Compute value at index i of the result quaternion. */ + value_type operator[](size_t i) const { + + /* This uses the expression traits to figure out how to access the + * i'th index of the two subexpressions: + */ + return OpT().apply( + left_traits().get(m_left,i), + right_traits().get(m_right,i)); + } + + + public: + + /** Return the size of the quaternion result. + * + * @throws std::invalid_argument if the expressions do not have the same + * size. + */ + size_t size() const { + /* Note: This actually does a check only if + * CML_CHECK_VECTOR_EXPR_SIZES is set: + */ + CheckedSize(m_left,m_right,size_tag()); + + /* The size is always 4: */ + return 4; + } + + /** Return reference to left expression. */ + left_reference left_expression() const { return m_left; } + + /** Return reference to right expression. */ + right_reference right_expression() const { return m_right; } + + + public: + + /** Construct from the two subexpressions. */ + explicit BinaryQuaternionOp(left_reference left, right_reference right) + : m_left(left), m_right(right) {} + + /** Copy constructor. */ + BinaryQuaternionOp(const expr_type& e) + : m_left(e.m_left), m_right(e.m_right) {} + + + protected: + + left_reference m_left; + right_reference m_right; + + + private: + + /* This ensures that a compile-time size check is executed: */ + typename checked_size::check_type _dummy; + + + private: + + /* Cannot be assigned to: */ + expr_type& operator=(const expr_type&); +}; + +/** Expression traits class for BinaryQuaternionOp<>. */ +template +struct ExprTraits< BinaryQuaternionOp > +{ + typedef BinaryQuaternionOp expr_type; + typedef LeftT left_type; + typedef RightT right_type; + + typedef typename expr_type::value_type value_type; + typedef typename expr_type::expr_const_reference const_reference; + typedef typename expr_type::result_tag result_tag; + typedef typename expr_type::size_tag size_tag; + typedef typename expr_type::result_type result_type; + typedef typename expr_type::imaginary_type imaginary_type; + typedef typename expr_type::assignable_tag not_assignable_tag; + typedef expr_node_tag node_tag; + + value_type get(const expr_type& v, size_t i) const { return v[i]; } + size_t size(const expr_type& e) const { return e.size(); } +}; + + +/* Helper struct to verify that both arguments are quaternion expressions: */ +template +struct QuaternionExpressions +{ + /* Require that both arguments are quaternion expressions: */ + typedef typename LeftTraits::result_tag left_result; + typedef typename RightTraits::result_tag right_result; + enum { is_true = (same_type::is_true + && same_type::is_true) }; +}; + +} // namespace et +} // namespace cml + +#endif + +// ------------------------------------------------------------------------- +// vim:ft=cpp