X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2Fcml%2Fquaternion%2Fquaternion_mul.h;fp=src%2Fcml%2Fquaternion%2Fquaternion_mul.h;h=bfb533b801d86604ac4d1806d0889a6debcf9f33;hp=0000000000000000000000000000000000000000;hb=6b0a0d0efafe34d48ab344fca3b479553bd4e62c;hpb=85783316365181491a3e3c0c63659972477cebba diff --git a/src/cml/quaternion/quaternion_mul.h b/src/cml/quaternion/quaternion_mul.h new file mode 100644 index 0000000..bfb533b --- /dev/null +++ b/src/cml/quaternion/quaternion_mul.h @@ -0,0 +1,140 @@ +/* -*- 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 Multiplication of two quaternions, p*q. + * + * This uses the expression tree, since the result is closed-form and can be + * computed by index. + */ + +#ifndef quaternion_mul_h +#define quaternion_mul_h + +#include +#include + +namespace cml { +namespace detail { + +template < class CrossType, class Real > struct SumOp; + +template < class Real > struct SumOp< positive_cross, Real > { + Real operator()(Real a, Real b) const { + return a + b; + } +}; + +template < class Real > struct SumOp< negative_cross, Real > { + Real operator()(Real a, Real b) const { + return a - b; + } +}; + +template < class Quat1_T, class Quat2_T > +typename et::QuaternionPromote< + typename Quat1_T::temporary_type, typename Quat2_T::temporary_type +>::temporary_type +QuaternionMult(const Quat1_T& q1, const Quat2_T& q2) +{ + detail::CheckQuat(q1); + detail::CheckQuat(q2); + + typedef typename et::QuaternionPromote< + typename Quat1_T::temporary_type, typename Quat2_T::temporary_type + >::temporary_type temporary_type; + + typedef typename temporary_type::value_type value_type; + typedef typename temporary_type::order_type order_type; + typedef typename temporary_type::cross_type cross_type; + + typedef detail::SumOp sum_op; + + enum { + W = order_type::W, + X = order_type::X, + Y = order_type::Y, + Z = order_type::Z + }; + + temporary_type result; + + /* s1*s2-dot(v1,v2): */ + result[W] = + q1[W]*q2[W] - q1[X]*q2[X] - q1[Y]*q2[Y] - q1[Z]*q2[Z]; + + /* (s1*v2 + s2*v1 + v1^v2) i: */ + result[X] = + sum_op()(q1[W]*q2[X] + q2[W]*q1[X], q1[Y]*q2[Z] - q1[Z]*q2[Y]); + + /* (s1*v2 + s2*v1 + v1^v2) j: */ + result[Y] = + sum_op()(q1[W]*q2[Y] + q2[W]*q1[Y], q1[Z]*q2[X] - q1[X]*q2[Z]); + + /* (s1*v2 + s2*v1 + v1^v2) k: */ + result[Z] = + sum_op()(q1[W]*q2[Z] + q2[W]*q1[Z], q1[X]*q2[Y] - q1[Y]*q2[X]); + + return result; +} + +} // namespace detail + +/** Declare mul taking two quaternion operands. */ +template +inline typename et::QuaternionPromote< + typename quaternion::temporary_type, + typename quaternion::temporary_type +>::temporary_type operator*( + const quaternion& left, + const quaternion& right) +{ + return detail::QuaternionMult(left, right); +} + +/** Declare mul taking a quaternion and a et::QuaternionXpr. */ +template +inline typename et::QuaternionPromote< + typename quaternion::temporary_type, + typename XprT::temporary_type +>::temporary_type operator*( + const quaternion& left, + QUATXPR_ARG_TYPE right) +{ + return detail::QuaternionMult(left, right); +} + +/** Declare mul taking an et::QuaternionXpr and a quaternion. */ +template +inline typename et::QuaternionPromote< + typename XprT::temporary_type, + typename quaternion::temporary_type +>::temporary_type operator*( + QUATXPR_ARG_TYPE left, + const quaternion& right) +{ + return detail::QuaternionMult(left, right); +} + +/** Declare mul taking two et::QuaternionXpr operands. */ +template +inline typename et::QuaternionPromote< + typename XprT1::temporary_type, typename XprT2::temporary_type +>::temporary_type operator*( + QUATXPR_ARG_TYPE_N(1) left, + QUATXPR_ARG_TYPE_N(2) right) +{ + return detail::QuaternionMult(left, right); +} + +} // namespace cml + +#endif + +// ------------------------------------------------------------------------- +// vim:ft=cpp