Initial commit
This commit is contained in:
197
Lib/Include/CML/quaternion/conjugate.h
Normal file
197
Lib/Include/CML/quaternion/conjugate.h
Normal file
@@ -0,0 +1,197 @@
|
||||
/* -*- 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 Defines an operator for quaternion conjugation.
|
||||
*/
|
||||
|
||||
#ifndef conjugate_h
|
||||
#define conjugate_h
|
||||
|
||||
#include <cml/quaternion/quaternion_expr.h>
|
||||
|
||||
namespace cml {
|
||||
namespace et {
|
||||
|
||||
/** An expression node for conjugating a quaternion. */
|
||||
template<class ExprT>
|
||||
class ConjugateOp
|
||||
{
|
||||
public:
|
||||
|
||||
typedef ConjugateOp<ExprT> 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 ExprT::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<ExprT> 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 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 length_squared();
|
||||
}
|
||||
|
||||
/** Return square of the quaternion length. */
|
||||
value_type length_squared() const {
|
||||
return dot(
|
||||
QuaternionXpr<expr_type>(*this),
|
||||
QuaternionXpr<expr_type>(*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<expr_type>(*this));
|
||||
return q.normalize();
|
||||
}
|
||||
|
||||
/** Compute conjugated result at index i.
|
||||
*
|
||||
* The conjugate of quaternion s + v is s - v.
|
||||
*/
|
||||
value_type operator[](size_t i) const {
|
||||
return (i == W) ? m_expr[W] : - 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 ConjugateOp(expr_reference expr) : m_expr(expr) {}
|
||||
|
||||
/** Copy constructor. */
|
||||
ConjugateOp(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 ConjugateOp<>. */
|
||||
template<class ExprT>
|
||||
struct ExprTraits< ConjugateOp<ExprT> >
|
||||
{
|
||||
typedef ConjugateOp<ExprT> 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 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(); }
|
||||
};
|
||||
|
||||
} // namespace et
|
||||
|
||||
/** Conjugation of a quaternion. */
|
||||
template<typename E, class AT, class OT, class CT> inline
|
||||
et::QuaternionXpr< et::ConjugateOp< quaternion<E,AT,OT,CT> > >
|
||||
conjugate(const quaternion<E,AT,OT,CT>& arg)
|
||||
{
|
||||
typedef et::ConjugateOp< quaternion<E,AT,OT,CT> > ExprT;
|
||||
return et::QuaternionXpr<ExprT>(ExprT(arg));
|
||||
}
|
||||
|
||||
/** Conjugation of a QuaternionXpr. */
|
||||
template<class XprT> inline
|
||||
et::QuaternionXpr< et::ConjugateOp<XprT> >
|
||||
conjugate(QUATXPR_ARG_TYPE arg)
|
||||
{
|
||||
typedef et::ConjugateOp<XprT> ExprT;
|
||||
return et::QuaternionXpr<ExprT>(ExprT(arg.expression()));
|
||||
}
|
||||
|
||||
} // namespace cml
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// vim:ft=cpp
|
||||
268
Lib/Include/CML/quaternion/inverse.h
Normal file
268
Lib/Include/CML/quaternion/inverse.h
Normal file
@@ -0,0 +1,268 @@
|
||||
/* -*- 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 Defines an operator for quaternion inverse.
|
||||
*/
|
||||
|
||||
#ifndef quaternion_inverse_h
|
||||
#define quaternion_inverse_h
|
||||
|
||||
#include <cml/quaternion/quaternion_expr.h>
|
||||
#include <cml/quaternion/quaternion_functions.h>
|
||||
|
||||
namespace cml {
|
||||
namespace et {
|
||||
|
||||
/** An expression node for inverting a quaternion.
|
||||
*
|
||||
* This internally creates a ConjugateOp node to process the conjugate
|
||||
* of the given expression. The values produced by the ConjugateOp are then
|
||||
* divided by the Cayley norm of the expression on the fly.
|
||||
*/
|
||||
template<class ExprT>
|
||||
class QuaternionInverseOp
|
||||
{
|
||||
public:
|
||||
|
||||
typedef QuaternionInverseOp<ExprT> 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;
|
||||
|
||||
/* The subexpression is a ConjugateOp: */
|
||||
typedef et::ConjugateOp<ExprT> subexpression_type;
|
||||
typedef ExprTraits<subexpression_type> expr_traits;
|
||||
|
||||
/* Get traits for the ExprT: */
|
||||
typedef ExprTraits<ExprT> arg_traits;
|
||||
typedef typename arg_traits::const_reference arg_reference;
|
||||
|
||||
typedef typename subexpression_type::value_type value_type;
|
||||
typedef quaternion_result_tag result_tag;
|
||||
typedef typename subexpression_type::size_tag size_tag;
|
||||
|
||||
/* 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 m_expr.real()/m_norm;
|
||||
}
|
||||
|
||||
/** Return the vector part of the expression.
|
||||
*
|
||||
* @todo This could be returned as a VectorXpr also.
|
||||
*/
|
||||
imaginary_type imaginary() const {
|
||||
return m_expr.imaginary()/m_norm;
|
||||
}
|
||||
|
||||
/** 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<expr_type>(*this),
|
||||
QuaternionXpr<expr_type>(*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<expr_type>(*this));
|
||||
return q.normalize();
|
||||
}
|
||||
|
||||
/** Compute inverse result at index i.
|
||||
*
|
||||
* The inverse of a quaternion p is ~p/norm(p).
|
||||
*/
|
||||
value_type operator[](size_t i) const {
|
||||
return m_expr[i]/m_norm;
|
||||
}
|
||||
|
||||
|
||||
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 an input expression. */
|
||||
explicit QuaternionInverseOp(arg_reference arg)
|
||||
//: m_expr(arg), m_norm(cml::norm(arg)) {}
|
||||
: m_expr(arg), m_norm(arg.norm()) {}
|
||||
|
||||
/** Copy constructor. */
|
||||
QuaternionInverseOp(const expr_type& e)
|
||||
: m_expr(e.m_expr), m_norm(e.m_norm) {}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
subexpression_type m_expr;
|
||||
value_type m_norm;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/* Cannot be assigned to: */
|
||||
expr_type& operator=(const expr_type&);
|
||||
};
|
||||
|
||||
/** Expression traits class for QuaternionInverseOp<>. */
|
||||
template<class ExprT>
|
||||
struct ExprTraits< QuaternionInverseOp<ExprT> >
|
||||
{
|
||||
typedef QuaternionInverseOp<ExprT> 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 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(); }
|
||||
};
|
||||
|
||||
} // namespace et
|
||||
|
||||
/** Inverse of a quaternion. */
|
||||
template<typename E, class AT, class OrderT, class CrossT> inline
|
||||
et::QuaternionXpr< et::QuaternionInverseOp< quaternion<E,AT,OrderT,CrossT> > >
|
||||
inverse(const quaternion<E,AT,OrderT,CrossT>& arg)
|
||||
{
|
||||
typedef et::QuaternionInverseOp< quaternion<E,AT,OrderT,CrossT> > ExprT;
|
||||
return et::QuaternionXpr<ExprT>(ExprT(arg));
|
||||
}
|
||||
|
||||
/** Inverse of a QuaternionXpr. */
|
||||
template<class XprT> inline
|
||||
et::QuaternionXpr< et::QuaternionInverseOp<XprT> >
|
||||
inverse(QUATXPR_ARG_TYPE arg)
|
||||
{
|
||||
typedef et::QuaternionInverseOp<XprT> ExprT;
|
||||
return et::QuaternionXpr<ExprT>(ExprT(arg.expression()));
|
||||
}
|
||||
|
||||
/* NOTE: Quaternion division no longer supported, but I'm leaving the
|
||||
code here for reference (Jesse) */
|
||||
|
||||
#if 0
|
||||
/** Declare div taking two quaternion operands. */
|
||||
template<typename E1, class AT1, typename E2, class AT2, class OT, class CT>
|
||||
inline typename et::QuaternionPromote<
|
||||
quaternion<E1,AT1,OT,CT>, quaternion<E2,AT2,OT,CT>
|
||||
>::temporary_type
|
||||
operator/(
|
||||
const quaternion<E1,AT1,OT,CT>& left,
|
||||
const quaternion<E2,AT2,OT,CT>& right)
|
||||
{
|
||||
return left*inverse(right);
|
||||
}
|
||||
|
||||
/** Declare div taking a quaternion and a et::QuaternionXpr. */
|
||||
template<typename E, class AT, class OT, class CT, class XprT>
|
||||
inline typename et::QuaternionPromote<
|
||||
quaternion<E,AT,OT,CT>, typename XprT::result_type
|
||||
>::temporary_type
|
||||
operator/(
|
||||
const quaternion<E,AT,OT,CT>& left,
|
||||
QUATXPR_ARG_TYPE right)
|
||||
{
|
||||
return left*inverse(right);
|
||||
}
|
||||
|
||||
/** Declare div taking an et::QuaternionXpr and a quaternion. */
|
||||
template<class XprT, typename E, class AT, class OT, class CT>
|
||||
inline typename et::QuaternionPromote<
|
||||
typename XprT::result_type, quaternion<E,AT,OT,CT>
|
||||
>::temporary_type
|
||||
operator/(
|
||||
QUATXPR_ARG_TYPE left,
|
||||
const quaternion<E,AT,OT,CT>& right)
|
||||
{
|
||||
return left*inverse(right);
|
||||
}
|
||||
|
||||
/** Declare div taking two et::QuaternionXpr operands. */
|
||||
template<class XprT1, class XprT2>
|
||||
inline typename et::QuaternionPromote<
|
||||
typename XprT1::result_type, typename XprT2::result_type
|
||||
>::temporary_type
|
||||
operator/(
|
||||
QUATXPR_ARG_TYPE_N(1) left,
|
||||
QUATXPR_ARG_TYPE_N(2) right)
|
||||
{
|
||||
return left*inverse(right);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace cml
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// vim:ft=cpp
|
||||
526
Lib/Include/CML/quaternion/quaternion.h
Normal file
526
Lib/Include/CML/quaternion/quaternion.h
Normal file
@@ -0,0 +1,526 @@
|
||||
/* -*- 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
|
||||
*
|
||||
* @todo Return a VectorXpr adaptor from the imaginary() method of
|
||||
* quaternion and the expression node types.
|
||||
*
|
||||
* @todo swap multiplication order based upon template param
|
||||
*
|
||||
* @todo change element order based upon template param
|
||||
*/
|
||||
|
||||
#ifndef quaternion_h
|
||||
#define quaternion_h
|
||||
|
||||
#include <cml/mathlib/epsilon.h>
|
||||
#include <cml/quaternion/quaternion_expr.h>
|
||||
#include <cml/quaternion/quaternion_dot.h>
|
||||
#include <cml/util.h>
|
||||
|
||||
/* This is used below to create a more meaningful compile-time error when
|
||||
* the quaternion class is not created with a fixed-size 4-vector:
|
||||
*/
|
||||
struct quaternion_requires_fixed_size_array_type_error;
|
||||
|
||||
namespace cml {
|
||||
|
||||
/** A configurable quaternion type.
|
||||
*
|
||||
* @note Quaternions with two different orders cannot be used in the same
|
||||
* expression.
|
||||
*/
|
||||
template<
|
||||
typename Element,
|
||||
class ArrayType,
|
||||
class Order,
|
||||
class Cross
|
||||
>
|
||||
class quaternion
|
||||
{
|
||||
/* The ArrayType must be fixed<> or external<>: */
|
||||
CML_STATIC_REQUIRE_M(
|
||||
(same_type< ArrayType, fixed<> >::is_true
|
||||
|| same_type< ArrayType, external<> >::is_true),
|
||||
quaternion_requires_fixed_size_array_type_error);
|
||||
|
||||
public:
|
||||
|
||||
/* Shorthand for the array type generator: */
|
||||
typedef ArrayType storage_type;
|
||||
typedef typename ArrayType::template rebind<4>::other generator_type;
|
||||
|
||||
/* Vector representing the quaternion. Use the rebinding template to
|
||||
* set the vector size:
|
||||
*/
|
||||
typedef vector<Element, generator_type> vector_type;
|
||||
|
||||
/* Vector temporary type: */
|
||||
typedef typename vector_type::temporary_type vector_temporary;
|
||||
|
||||
/* Quaternion order: */
|
||||
typedef Order order_type;
|
||||
|
||||
/* Quaternion multiplication order: */
|
||||
typedef Cross cross_type;
|
||||
|
||||
/* Scalar type representing the scalar part: */
|
||||
typedef typename vector_type::value_type value_type;
|
||||
typedef typename vector_type::reference reference;
|
||||
typedef typename vector_type::const_reference const_reference;
|
||||
/* XXX Need to verify that this is a true scalar type. */
|
||||
|
||||
/* The quaternion type: */
|
||||
typedef quaternion<Element,storage_type,order_type,cross_type>
|
||||
quaternion_type;
|
||||
|
||||
/* For integration into the expression template code: */
|
||||
typedef quaternion_type expr_type;
|
||||
|
||||
/* For integration into the expression template code: */
|
||||
typedef quaternion<
|
||||
Element, typename vector_temporary::storage_type,
|
||||
order_type, cross_type> temporary_type;
|
||||
|
||||
/* For integration into the expression templates code: */
|
||||
typedef quaternion_type& expr_reference;
|
||||
typedef const quaternion_type& expr_const_reference;
|
||||
|
||||
/* For matching by storage type: */
|
||||
typedef typename vector_type::memory_tag memory_tag;
|
||||
|
||||
/* For matching by size type: */
|
||||
typedef typename vector_type::size_tag size_tag;
|
||||
|
||||
/* Get the imaginary part type: */
|
||||
typedef typename vector_temporary::subvector_type imaginary_type;
|
||||
|
||||
/* For matching by result-type: */
|
||||
typedef cml::et::quaternion_result_tag result_tag;
|
||||
|
||||
/* For matching by assignability: */
|
||||
typedef cml::et::assignable_tag assignable_tag;
|
||||
|
||||
|
||||
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 scalar part. */
|
||||
value_type real() const { return m_q[W]; }
|
||||
|
||||
/** Return the imaginary vector. */
|
||||
imaginary_type imaginary() const {
|
||||
/*
|
||||
imaginary_type v;
|
||||
v[0] = m_q[X]; v[1] = m_q[Y]; v[2] = m_q[Z];
|
||||
return v;
|
||||
*/
|
||||
return imaginary_type(m_q[X], m_q[Y], m_q[Z]);
|
||||
}
|
||||
|
||||
/** Return the vector representing the quaternion. */
|
||||
const vector_type& as_vector() const {
|
||||
return m_q;
|
||||
}
|
||||
|
||||
/** Return the Cayley norm of the quaternion. */
|
||||
value_type norm() const {
|
||||
return length_squared();
|
||||
}
|
||||
|
||||
/** Return square of the quaternion length. */
|
||||
value_type length_squared() const {
|
||||
return cml::dot(*this,*this);
|
||||
}
|
||||
|
||||
/** Return the quaternion length. */
|
||||
value_type length() const {
|
||||
return std::sqrt(length_squared());
|
||||
}
|
||||
|
||||
/** Normalize this quaternion (divide by its length).
|
||||
*
|
||||
* @todo Make this return a QuaternionXpr.
|
||||
*/
|
||||
quaternion_type& normalize() {
|
||||
return (*this /= length());
|
||||
}
|
||||
|
||||
/** Set this quaternion to the conjugate. */
|
||||
quaternion_type& conjugate() {
|
||||
return (*this) = cml::conjugate(*this);
|
||||
}
|
||||
|
||||
/** Set this quaternion to the inverse. */
|
||||
quaternion_type& inverse() {
|
||||
return (*this) = cml::inverse(*this);
|
||||
}
|
||||
|
||||
/** Set this quaternion to the multiplicative identity. */
|
||||
quaternion_type& identity() {
|
||||
m_q[W] = value_type(1);
|
||||
m_q[X] = value_type(0);
|
||||
m_q[Y] = value_type(0);
|
||||
m_q[Z] = value_type(0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Return the log of this quaternion. */
|
||||
temporary_type log(
|
||||
value_type tolerance = epsilon<value_type>::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 quaternion.
|
||||
*/
|
||||
temporary_type exp(
|
||||
value_type tolerance = epsilon<value_type>::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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Const access to the quaternion as a vector. */
|
||||
const_reference operator[](size_t i) const { return m_q[i]; }
|
||||
|
||||
/** Mutable access to the quaternion as a vector. */
|
||||
reference operator[](size_t i) { return m_q[i]; }
|
||||
|
||||
/** Fill quaternion with random elements.
|
||||
*
|
||||
* @warning This does not generate uniformly random rotations.
|
||||
*/
|
||||
void random(value_type min, value_type max) {
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
m_q[i] = random_real(min,max);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/** Default initializer.
|
||||
*
|
||||
* @note The default constructor cannot be used with an external<>
|
||||
* array type.
|
||||
*/
|
||||
quaternion() {}
|
||||
|
||||
/** Initializer for an external<> vector type. */
|
||||
quaternion(Element* const array) : m_q(array) {}
|
||||
|
||||
/** Copy construct from the same type of quaternion. */
|
||||
quaternion(const quaternion_type& q) : m_q(q.m_q) {}
|
||||
|
||||
/** Construct from a quaternion having a different array type. */
|
||||
template<typename E, class AT> quaternion(
|
||||
const quaternion<E,AT,order_type,cross_type>& q)
|
||||
: m_q(q.as_vector()) {}
|
||||
|
||||
/** Copy construct from a QuaternionXpr. */
|
||||
template<typename XprT> quaternion(QUATXPR_ARG_TYPE e) {
|
||||
typedef typename XprT::order_type arg_order;
|
||||
m_q[W] = e[arg_order::W];
|
||||
m_q[X] = e[arg_order::X];
|
||||
m_q[Y] = e[arg_order::Y];
|
||||
m_q[Z] = e[arg_order::Z];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Initialize from a 4-vector.
|
||||
*
|
||||
* If Order is scalar_first, then v[0] is the real part. Otherwise,
|
||||
* v[3] is the real part.
|
||||
*/
|
||||
quaternion(const vector_type& v) : m_q(v) {}
|
||||
|
||||
/** Initialize from an array of scalars.
|
||||
*
|
||||
* If Order is scalar_first, then v[0] is the real part. Otherwise,
|
||||
* v[3] is the real part.
|
||||
*
|
||||
* @note The target vector must have CML_VEC_COPY_FROM_ARRAY
|
||||
* implemented, so this cannot be used with external<> vectors.
|
||||
*/
|
||||
quaternion(const value_type v[4]) : m_q(v) {}
|
||||
|
||||
/** Initialize from 4 scalars.
|
||||
*
|
||||
* If Order is scalar_first, then a is the real part, and (b,c,d) is
|
||||
* the imaginary part. Otherwise, (a,b,c) is the imaginary part, and d
|
||||
* is the real part.
|
||||
*/
|
||||
quaternion(
|
||||
const value_type& a, const value_type& b,
|
||||
const value_type& c, const value_type& d)
|
||||
{
|
||||
/* Call the overloaded assignment function: */
|
||||
assign(a, b, c, d, Order());
|
||||
}
|
||||
|
||||
/** Initialize both the real and imaginary parts.
|
||||
*
|
||||
* The imaginary part is given by a 3-vector. Although the imaginary
|
||||
* part is specified first, the proper coefficient order (vector or
|
||||
* scalar first) is maintained.
|
||||
*/
|
||||
quaternion(const value_type& s, const imaginary_type& v) {
|
||||
m_q[W] = s; m_q[X] = v[0]; m_q[Y] = v[1]; m_q[Z] = v[2];
|
||||
}
|
||||
|
||||
/** Initialize both the real and imaginary parts.
|
||||
*
|
||||
* The imaginary part is given by a 3-vector. Although the imaginary
|
||||
* part is specified second, the proper coefficient order (vector or
|
||||
* scalar first) is maintained.
|
||||
*/
|
||||
quaternion(const imaginary_type& v, const value_type& s) {
|
||||
m_q[W] = s; m_q[X] = v[0]; m_q[Y] = v[1]; m_q[Z] = v[2];
|
||||
}
|
||||
|
||||
/** Initialize both the real and imaginary parts.
|
||||
*
|
||||
* The imaginary part is given by an array of scalars. Although the
|
||||
* imaginary part is specified first, the proper coefficient order
|
||||
* (vector or scalar first) is maintained.
|
||||
*/
|
||||
quaternion(const value_type v[3], const value_type& s) {
|
||||
m_q[W] = s; m_q[X] = v[0]; m_q[Y] = v[1]; m_q[Z] = v[2];
|
||||
}
|
||||
|
||||
/** Initialize both the real and imaginary parts.
|
||||
*
|
||||
* The imaginary part is given by an array of scalars. Although the
|
||||
* imaginary part is specified second, the proper coefficient order
|
||||
* (vector or scalar first) is maintained.
|
||||
*/
|
||||
quaternion(const value_type& s, const value_type v[3]) {
|
||||
m_q[W] = s; m_q[X] = v[0]; m_q[Y] = v[1]; m_q[Z] = v[2];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Initialize from a VectorXpr. */
|
||||
template<typename XprT>
|
||||
quaternion(VECXPR_ARG_TYPE e) : m_q(e) {}
|
||||
|
||||
/** Initialize both the real and imaginary parts.
|
||||
*
|
||||
* The imaginary part is initialized with a VectorXpr.
|
||||
*/
|
||||
template<typename XprT>
|
||||
quaternion(const value_type& s, VECXPR_ARG_TYPE e) {
|
||||
m_q[W] = s; m_q[X] = e[0]; m_q[Y] = e[1]; m_q[Z] = e[2];
|
||||
}
|
||||
|
||||
// @todo: Are we missing:
|
||||
|
||||
// quaternion(VECXPR_ARG_TYPE e, const value_type& s) {}
|
||||
|
||||
// Or is that covered elsewhere?
|
||||
|
||||
/** In-place op from a quaternion.
|
||||
*
|
||||
* This assumes that _op_ is defined for both the quaternion's vector
|
||||
* type and its scalar type.
|
||||
*/
|
||||
#define CML_QUAT_ASSIGN_FROM_QUAT(_op_) \
|
||||
template<typename E, class AT> const quaternion_type& \
|
||||
operator _op_ (const quaternion<E,AT,order_type,cross_type>& q) { \
|
||||
m_q[W] _op_ q[W]; \
|
||||
m_q[X] _op_ q[X]; \
|
||||
m_q[Y] _op_ q[Y]; \
|
||||
m_q[Z] _op_ q[Z]; \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
/** In-place op from a QuaternionXpr.
|
||||
*
|
||||
* This assumes that _op_ is defined for the quaternion's scalar type.
|
||||
*/
|
||||
#define CML_QUAT_ASSIGN_FROM_QUATXPR(_op_) \
|
||||
template<typename XprT> quaternion_type& \
|
||||
operator _op_ (QUATXPR_ARG_TYPE e) { \
|
||||
typedef typename XprT::order_type arg_order; \
|
||||
m_q[W] _op_ e[arg_order::W]; \
|
||||
m_q[X] _op_ e[arg_order::X]; \
|
||||
m_q[Y] _op_ e[arg_order::Y]; \
|
||||
m_q[Z] _op_ e[arg_order::Z]; \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
/** In-place op from a scalar type.
|
||||
*
|
||||
* This assumes that _op_ is defined for the quaternion's scalar type.
|
||||
*/
|
||||
#define CML_QUAT_ASSIGN_FROM_SCALAR(_op_,_op_name_) \
|
||||
quaternion_type& operator _op_ (const value_type& s) { \
|
||||
typedef _op_name_ <value_type,value_type> OpT; \
|
||||
OpT().apply(m_q[W],s); \
|
||||
OpT().apply(m_q[X],s); \
|
||||
OpT().apply(m_q[Y],s); \
|
||||
OpT().apply(m_q[Z],s); \
|
||||
return *this; \
|
||||
}
|
||||
|
||||
CML_QUAT_ASSIGN_FROM_QUAT(=)
|
||||
CML_QUAT_ASSIGN_FROM_QUAT(+=)
|
||||
CML_QUAT_ASSIGN_FROM_QUAT(-=)
|
||||
|
||||
CML_QUAT_ASSIGN_FROM_QUATXPR(=)
|
||||
CML_QUAT_ASSIGN_FROM_QUATXPR(+=)
|
||||
CML_QUAT_ASSIGN_FROM_QUATXPR(-=)
|
||||
|
||||
CML_QUAT_ASSIGN_FROM_SCALAR(*=, cml::et::OpMulAssign)
|
||||
CML_QUAT_ASSIGN_FROM_SCALAR(/=, cml::et::OpDivAssign)
|
||||
|
||||
#undef CML_QUAT_ASSIGN_FROM_QUAT
|
||||
#undef CML_QUAT_ASSIGN_FROM_QUATXPR
|
||||
#undef CML_QUAT_ASSIGN_FROM_SCALAR
|
||||
|
||||
/** Accumulated multiplication with a quaternion.
|
||||
*
|
||||
* Compute p = p * q for two quaternions p and q.
|
||||
*
|
||||
* @internal Using operator* here is okay, as long as cml/quaternion.h
|
||||
* is included before using this method (the only supported case for
|
||||
* end-user code). This is because modern compilers won't instantiate a
|
||||
* method in a template class until it is used, and including the main
|
||||
* header ensures all definitions are available before any possible use
|
||||
* of this method.
|
||||
*/
|
||||
quaternion_type& operator*=(const quaternion_type& q) {
|
||||
return (*this = *this * q);
|
||||
}
|
||||
|
||||
/** Accumulated multiplication with a quaternion expression.
|
||||
*
|
||||
* Compute p = p * e for a quaternion p and a quaternion expression e.
|
||||
*
|
||||
* @internal Using operator* here is okay, as long as cml/quaternion.h
|
||||
* is included before using this method (the only supported case for
|
||||
* end-user code). This is because modern compilers won't instantiate a
|
||||
* method in a template class until it is used, and including the main
|
||||
* header ensures all definitions are available before any possible use
|
||||
* of this method.
|
||||
*/
|
||||
template<typename XprT> quaternion_type& operator*=(QUATXPR_ARG_TYPE e) {
|
||||
return (*this = *this * e);
|
||||
}
|
||||
|
||||
/** Return access to the data as a raw pointer. */
|
||||
typename vector_type::pointer data() { return m_q.data(); }
|
||||
|
||||
/** Return access to the data as a const raw pointer. */
|
||||
const typename vector_type::pointer data() const { return m_q.data(); }
|
||||
|
||||
|
||||
/* NOTE: Quaternion division no longer supported, but I'm leaving the
|
||||
code here for reference (Jesse) */
|
||||
|
||||
#if 0
|
||||
/** Accumulated division with a quaternion.
|
||||
*
|
||||
* Compute p = p * inverse(q).
|
||||
*
|
||||
* @note Because quaternion multiplication is non-commutative, division
|
||||
* is ambiguous. This method assumes a multiplication order consistent
|
||||
* with the notational order; i.e. p = q / r means p = q*inverse(r).
|
||||
*
|
||||
* @internal Using operator* and cml::inverse here is okay, as long as
|
||||
* cml/quaternion.h is included before using this method (the only
|
||||
* supported case for end-user code). This is because modern compilers
|
||||
* won't instantiate a method in a template class until it is used, and
|
||||
* including the main header ensures all definitions are available
|
||||
* before any possible use of this method.
|
||||
*/
|
||||
quaternion_type& operator/=(const quaternion_type& q) {
|
||||
return (*this = *this * cml::inverse(q));
|
||||
}
|
||||
|
||||
/** Accumulated division with a quaternion expression.
|
||||
*
|
||||
* Compute p = p * inverse(q).
|
||||
*
|
||||
* @note Because quaternion multiplication is non-commutative, division
|
||||
* is ambiguous. This method assumes a multiplication order consistent
|
||||
* with the notational order; i.e. p = q / r means p = q*inverse(r).
|
||||
*
|
||||
* @internal Using operator* and cml::inverse here is okay, as long as
|
||||
* cml/quaternion.h is included before using this method (the only
|
||||
* supported case for end-user code). This is because modern compilers
|
||||
* won't instantiate a method in a template class until it is used, and
|
||||
* including the main header ensures all definitions are available
|
||||
* before any possible use of this method.
|
||||
*/
|
||||
template<typename XprT> quaternion_type& operator/=(QUATXPR_ARG_TYPE e) {
|
||||
return (*this = *this * cml::inverse(e));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/** Overloaded function to assign the quaternion from 4 scalars. */
|
||||
void assign(const value_type& a, const value_type& b,
|
||||
const value_type& c, const value_type& d, scalar_first)
|
||||
{
|
||||
m_q[W] = a; m_q[X] = b; m_q[Y] = c; m_q[Z] = d;
|
||||
}
|
||||
|
||||
/** Overloaded function to assign the quaternion from 4 scalars. */
|
||||
void assign(const value_type& a, const value_type& b,
|
||||
const value_type& c, const value_type& d, vector_first)
|
||||
{
|
||||
m_q[X] = a; m_q[Y] = b; m_q[Z] = c; m_q[W] = d;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
vector_type m_q;
|
||||
};
|
||||
|
||||
} // namespace cml
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// vim:ft=cpp
|
||||
216
Lib/Include/CML/quaternion/quaternion_comparison.h
Normal file
216
Lib/Include/CML/quaternion/quaternion_comparison.h
Normal file
@@ -0,0 +1,216 @@
|
||||
/* -*- 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_comparison_h
|
||||
#define quaternion_comparison_h
|
||||
|
||||
#include <cml/core/cml_assert.h>
|
||||
#include <cml/et/scalar_ops.h>
|
||||
|
||||
/* This is used below to create a more meaningful compile-time error when
|
||||
* quaternion_comparison is not provided with quaternion or QuaternionExpr arguments:
|
||||
*/
|
||||
struct quaternion_comparison_expects_quaternion_args_error;
|
||||
|
||||
#define CML_QUAT_QUAT_ORDER(_order_, _op_, _OpT_) \
|
||||
template< \
|
||||
typename E1, class AT1, typename E2, class AT2, class O, class C > \
|
||||
inline bool \
|
||||
_op_ ( \
|
||||
const quaternion<E1,AT1,O,C>& left, \
|
||||
const quaternion<E2,AT2,O,C>& right) \
|
||||
{ \
|
||||
return detail::quaternion_##_order_ (left, right, _OpT_ <E1,E2>()); \
|
||||
}
|
||||
|
||||
#define CML_QUAT_QUATXPR_ORDER(_order_, _op_, _OpT_) \
|
||||
template<typename E, class AT, class O, class C, class XprT> \
|
||||
inline bool \
|
||||
_op_ ( \
|
||||
const quaternion<E,AT,O,C>& left, \
|
||||
QUATXPR_ARG_TYPE right) \
|
||||
{ \
|
||||
return detail::quaternion_##_order_ (left, right, \
|
||||
_OpT_ <E, typename XprT::value_type>()); \
|
||||
}
|
||||
|
||||
#define CML_QUATXPR_QUAT_ORDER(_order_, _op_, _OpT_) \
|
||||
template<class XprT, typename E, class AT, class O, class C > \
|
||||
inline bool \
|
||||
_op_ ( \
|
||||
QUATXPR_ARG_TYPE left, \
|
||||
const quaternion<E,AT,O,C>& right) \
|
||||
{ \
|
||||
return detail::quaternion_##_order_ (left, right, \
|
||||
_OpT_ <typename XprT::value_type, E>()); \
|
||||
}
|
||||
|
||||
#define CML_QUATXPR_QUATXPR_ORDER(_order_, _op_, _OpT_) \
|
||||
template<class XprT1, class XprT2> \
|
||||
inline bool \
|
||||
_op_ ( \
|
||||
QUATXPR_ARG_TYPE_N(1) left, \
|
||||
QUATXPR_ARG_TYPE_N(2) right) \
|
||||
{ \
|
||||
return detail::quaternion_##_order_ (left, right, \
|
||||
_OpT_ < \
|
||||
typename XprT1::value_type, \
|
||||
typename XprT2::value_type>()); \
|
||||
}
|
||||
|
||||
|
||||
namespace cml {
|
||||
namespace detail {
|
||||
|
||||
/** Quaternion strict weak ordering relationship.
|
||||
*
|
||||
* OpT must implement a strict weak order on the quaternion element type.
|
||||
* operator< and operator> on integer and floating-point types are
|
||||
* examples.
|
||||
*/
|
||||
template<typename LeftT, typename RightT, typename OpT>
|
||||
inline bool
|
||||
quaternion_weak_order(const LeftT& left, const RightT& right, OpT)
|
||||
{
|
||||
/* Shorthand: */
|
||||
typedef et::ExprTraits<LeftT> left_traits;
|
||||
typedef et::ExprTraits<RightT> right_traits;
|
||||
|
||||
/* quaternion_comparison() requires quaternion expressions: */
|
||||
CML_STATIC_REQUIRE_M(
|
||||
(et::QuaternionExpressions<LeftT,RightT>::is_true),
|
||||
quaternion_comparison_expects_quaternion_args_error);
|
||||
/* Note: parens are required here so that the preprocessor ignores the
|
||||
* commas:
|
||||
*/
|
||||
|
||||
typedef typename et::QuaternionPromote<
|
||||
typename left_traits::result_type,
|
||||
typename right_traits::result_type
|
||||
>::type result_type;
|
||||
|
||||
for(ssize_t i = 0; i < result_type::array_size; ++ i) {
|
||||
|
||||
if(OpT().apply(
|
||||
left_traits().get(left,i),
|
||||
right_traits().get(right,i)
|
||||
))
|
||||
{
|
||||
/* If weak order (a < b) is satisfied, return true: */
|
||||
return true;
|
||||
} else if(OpT().apply(
|
||||
right_traits().get(right,i),
|
||||
left_traits().get(left,i)
|
||||
))
|
||||
{
|
||||
/* If !(b < a), then return false: */
|
||||
return false;
|
||||
} else {
|
||||
|
||||
/* Have !(a < b) && !(b < a) <=> (a >= b && b >= a) <=> (a == b).
|
||||
* so need to test next element:
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* XXX Can this be unrolled in any reasonable way? */
|
||||
|
||||
/* If we get here, then left == right: */
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Quaternion total order relationship.
|
||||
*
|
||||
* OpT must implement a total order on the quaternion element type. operator<=
|
||||
* and operator>= on integer and floating-point types are examples.
|
||||
*/
|
||||
template<typename LeftT, typename RightT, typename OpT>
|
||||
inline bool
|
||||
quaternion_total_order(const LeftT& left, const RightT& right, OpT)
|
||||
{
|
||||
/* Shorthand: */
|
||||
typedef et::ExprTraits<LeftT> left_traits;
|
||||
typedef et::ExprTraits<RightT> right_traits;
|
||||
|
||||
/* quaternion_comparison() requires quaternion expressions: */
|
||||
CML_STATIC_REQUIRE_M(
|
||||
(et::QuaternionExpressions<LeftT,RightT>::is_true),
|
||||
quaternion_comparison_expects_quaternion_args_error);
|
||||
/* Note: parens are required here so that the preprocessor ignores the
|
||||
* commas:
|
||||
*/
|
||||
|
||||
typedef typename et::QuaternionPromote<
|
||||
typename left_traits::result_type,
|
||||
typename right_traits::result_type
|
||||
>::type result_type;
|
||||
|
||||
for(ssize_t i = 0; i < result_type::array_size; ++ i) {
|
||||
|
||||
/* Test total order: */
|
||||
if(OpT().apply(
|
||||
left_traits().get(left,i),
|
||||
right_traits().get(right,i)
|
||||
))
|
||||
{
|
||||
/* Automatically true if weak order (a <= b) && !(b <= a) <=>
|
||||
* (a <= b) && (b > a) <=> (a < b) is satisfied:
|
||||
*/
|
||||
if(!OpT().apply(
|
||||
right_traits().get(right,i),
|
||||
left_traits().get(left,i)
|
||||
))
|
||||
return true;
|
||||
|
||||
/* Otherwise, have equality (a <= b) && (b <= a), so continue
|
||||
* to next element:
|
||||
*/
|
||||
else
|
||||
continue;
|
||||
|
||||
} else {
|
||||
|
||||
/* Total order isn't satisfied (a > b), so return false: */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/* XXX Can this be unrolled in any reasonable way? */
|
||||
|
||||
/* Total (==) or weak (<) order was satisfied, so return true: */
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* XXX There is a better way to handle these with operator traits... */
|
||||
|
||||
CML_QUAT_QUAT_ORDER( total_order, operator==, et::OpEqual)
|
||||
CML_QUATXPR_QUAT_ORDER( total_order, operator==, et::OpEqual)
|
||||
CML_QUAT_QUATXPR_ORDER( total_order, operator==, et::OpEqual)
|
||||
CML_QUATXPR_QUATXPR_ORDER( total_order, operator==, et::OpEqual)
|
||||
|
||||
CML_QUAT_QUAT_ORDER( weak_order, operator!=, et::OpNotEqual)
|
||||
CML_QUATXPR_QUAT_ORDER( weak_order, operator!=, et::OpNotEqual)
|
||||
CML_QUAT_QUATXPR_ORDER( weak_order, operator!=, et::OpNotEqual)
|
||||
CML_QUATXPR_QUATXPR_ORDER( weak_order, operator!=, et::OpNotEqual)
|
||||
|
||||
CML_QUAT_QUAT_ORDER( weak_order, operator<, et::OpLess)
|
||||
CML_QUATXPR_QUAT_ORDER( weak_order, operator<, et::OpLess)
|
||||
CML_QUAT_QUATXPR_ORDER( weak_order, operator<, et::OpLess)
|
||||
CML_QUATXPR_QUATXPR_ORDER( weak_order, operator<, et::OpLess)
|
||||
|
||||
} // namespace cml
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// vim:ft=cpp
|
||||
73
Lib/Include/CML/quaternion/quaternion_dot.h
Normal file
73
Lib/Include/CML/quaternion/quaternion_dot.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* -*- 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_dot_h
|
||||
#define quaternion_dot_h
|
||||
|
||||
#include <cml/vector/vector_products.h>
|
||||
#include <cml/quaternion/quaternion_expr.h>
|
||||
|
||||
namespace cml {
|
||||
namespace detail {
|
||||
|
||||
template<class LeftT, class RightT> inline
|
||||
typename detail::DotPromote<LeftT,RightT>::promoted_scalar
|
||||
quaternion_dot(const LeftT& p, const RightT& q)
|
||||
{
|
||||
return p[0]*q[0] + p[1]*q[1] + p[2]*q[2] + p[3]*q[3];
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename E1, class AT1, typename E2, class AT2, class OT, class CT>
|
||||
inline typename detail::DotPromote<
|
||||
quaternion<E1,AT1,OT,CT>, quaternion<E2,AT2,OT,CT>
|
||||
>::promoted_scalar
|
||||
dot(const quaternion<E1,AT1,OT,CT>& p,
|
||||
const quaternion<E2,AT2,OT,CT>& q)
|
||||
{
|
||||
return detail::quaternion_dot(p,q);
|
||||
}
|
||||
|
||||
template<typename E, class AT, class OT, class CT, class XprT>
|
||||
inline typename detail::DotPromote<
|
||||
quaternion<E,AT,OT,CT>, et::QuaternionXpr<XprT>
|
||||
>::promoted_scalar
|
||||
dot(const quaternion<E,AT,OT,CT>& p, QUATXPR_ARG_TYPE q)
|
||||
{
|
||||
return detail::quaternion_dot(p,q);
|
||||
}
|
||||
|
||||
template<class XprT, typename E, class AT, class OT, class CT>
|
||||
inline typename detail::DotPromote<
|
||||
et::QuaternionXpr<XprT>, quaternion<E,AT,OT,CT>
|
||||
>::promoted_scalar
|
||||
dot(QUATXPR_ARG_TYPE p, const quaternion<E,AT,OT,CT>& q)
|
||||
{
|
||||
return detail::quaternion_dot(p,q);
|
||||
}
|
||||
|
||||
template<class XprT1, class XprT2> inline
|
||||
typename detail::DotPromote<
|
||||
et::QuaternionXpr<XprT1>, et::QuaternionXpr<XprT2>
|
||||
>::promoted_scalar
|
||||
dot(QUATXPR_ARG_TYPE_N(1) p, QUATXPR_ARG_TYPE_N(2) q)
|
||||
{
|
||||
return detail::quaternion_dot(p,q);
|
||||
}
|
||||
|
||||
} // namespace cml
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// vim:ft=cpp
|
||||
614
Lib/Include/CML/quaternion/quaternion_expr.h
Normal file
614
Lib/Include/CML/quaternion/quaternion_expr.h
Normal file
@@ -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 <cml/et/size_checking.h>
|
||||
#include <cml/mathlib/epsilon.h>
|
||||
#include <cml/quaternion/quaternion_traits.h>
|
||||
#include <cml/quaternion/quaternion_promotions.h>
|
||||
#include <cml/util.h>
|
||||
|
||||
#define QUATXPR_ARG_TYPE const et::QuaternionXpr<XprT>&
|
||||
#define QUATXPR_ARG_TYPE_N(_N_) const et::QuaternionXpr<XprT##_N_>&
|
||||
|
||||
namespace cml {
|
||||
namespace et {
|
||||
|
||||
/** A placeholder for a quaternion expression in an expression tree. */
|
||||
template<class ExprT>
|
||||
class QuaternionXpr
|
||||
{
|
||||
public:
|
||||
|
||||
typedef QuaternionXpr<ExprT> 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<ExprT> 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<value_type>::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<value_type>::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<class ExprT>
|
||||
struct ExprTraits< QuaternionXpr<ExprT> >
|
||||
{
|
||||
typedef QuaternionXpr<ExprT> 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 ExprT, class OpT>
|
||||
class UnaryQuaternionOp
|
||||
{
|
||||
public:
|
||||
|
||||
typedef UnaryQuaternionOp<ExprT,OpT> 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<ExprT> 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<expr_type>(*this),
|
||||
QuaternionXpr<expr_type>(*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<expr_type>(*this));
|
||||
return q.normalize();
|
||||
}
|
||||
|
||||
/** Return the log of this expression. */
|
||||
temporary_type log(
|
||||
value_type tolerance = epsilon<value_type>::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<value_type>::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<class ExprT, class OpT>
|
||||
struct ExprTraits< UnaryQuaternionOp<ExprT,OpT> >
|
||||
{
|
||||
typedef UnaryQuaternionOp<ExprT,OpT> 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 LeftT, class RightT, class OpT>
|
||||
class BinaryQuaternionOp
|
||||
{
|
||||
public:
|
||||
|
||||
typedef BinaryQuaternionOp<LeftT,RightT,OpT> 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<LeftT> left_traits;
|
||||
typedef ExprTraits<RightT> 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<left_result,right_result>::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<LeftT,RightT,size_tag> 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<expr_type>(*this),
|
||||
QuaternionXpr<expr_type>(*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<expr_type>(*this));
|
||||
return q.normalize();
|
||||
}
|
||||
|
||||
/** Return the log of this expression. */
|
||||
temporary_type log(
|
||||
value_type tolerance = epsilon<value_type>::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<value_type>::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<class LeftT, class RightT, class OpT>
|
||||
struct ExprTraits< BinaryQuaternionOp<LeftT,RightT,OpT> >
|
||||
{
|
||||
typedef BinaryQuaternionOp<LeftT,RightT,OpT> 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<class LeftTraits, class RightTraits>
|
||||
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<left_result,et::quaternion_result_tag>::is_true
|
||||
&& same_type<right_result,et::quaternion_result_tag>::is_true) };
|
||||
};
|
||||
|
||||
} // namespace et
|
||||
} // namespace cml
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// vim:ft=cpp
|
||||
172
Lib/Include/CML/quaternion/quaternion_functions.h
Normal file
172
Lib/Include/CML/quaternion/quaternion_functions.h
Normal file
@@ -0,0 +1,172 @@
|
||||
/* -*- 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 Functions on quaternions.
|
||||
*
|
||||
* @todo The functions that return quaternions and vectors should be changed
|
||||
* to return quaternion expression nodes, as should the corresponding
|
||||
* class methods.
|
||||
*/
|
||||
|
||||
#ifndef quaternion_functions_h
|
||||
#define quaternion_functions_h
|
||||
|
||||
#include <cml/mathlib/checking.h> // For CheckQuat()
|
||||
#include <cml/mathlib/epsilon.h>
|
||||
#include <cml/util.h> // For acos_safe()
|
||||
|
||||
namespace cml {
|
||||
|
||||
/** Returns the real part of the quaternion. */
|
||||
template<typename E, class AT, class OT, class CT>
|
||||
inline typename quaternion<E,AT,OT,CT>::value_type
|
||||
real(const quaternion<E,AT,OT,CT>& q)
|
||||
{
|
||||
return q.real();
|
||||
}
|
||||
|
||||
/** Returns the real (scalar) part of the QuaternionXpr. */
|
||||
template<typename XprT>
|
||||
inline typename et::QuaternionXpr<XprT>::value_type
|
||||
real(const et::QuaternionXpr<XprT>& e)
|
||||
{
|
||||
return e.real();
|
||||
}
|
||||
|
||||
/** Returns the imaginary (vector) part of the quaternion. */
|
||||
template<typename E, class AT, class OT, class CT>
|
||||
inline typename quaternion<E,AT,OT,CT>::imaginary_type
|
||||
imaginary(const quaternion<E,AT,OT,CT>& q)
|
||||
{
|
||||
return q.imaginary();
|
||||
}
|
||||
|
||||
/** Returns the imaginary (vector) part of the QuaternionXpr. */
|
||||
template<typename XprT>
|
||||
//inline typename et::QuaternionXpr<XprT>::temporary_type
|
||||
inline typename et::QuaternionXpr<XprT>::imaginary_type
|
||||
imaginary(const et::QuaternionXpr<XprT>& e)
|
||||
{
|
||||
return e.imaginary();
|
||||
}
|
||||
|
||||
/** Cayley norm of a quaternion. */
|
||||
template<typename E, class AT, class OT, class CT>
|
||||
inline typename quaternion<E,AT,OT,CT>::value_type
|
||||
norm(const quaternion<E,AT,OT,CT>& arg)
|
||||
{
|
||||
return arg.length_squared();
|
||||
}
|
||||
|
||||
/** Cayley norm of a QuaternionXpr. */
|
||||
template<typename XprT>
|
||||
inline typename XprT::value_type
|
||||
norm(QUATXPR_ARG_TYPE arg)
|
||||
{
|
||||
return arg.length_squared();
|
||||
}
|
||||
|
||||
/** Squared length of a quaternion. */
|
||||
template<typename E, class AT, class OT, class CT>
|
||||
inline typename quaternion<E,AT,OT,CT>::value_type
|
||||
length_squared(const quaternion<E,AT,OT,CT>& arg)
|
||||
{
|
||||
return arg.length_squared();
|
||||
}
|
||||
|
||||
/** Squared length of a quaternion expr. */
|
||||
template<typename XprT>
|
||||
inline typename XprT::value_type
|
||||
length_squared(QUATXPR_ARG_TYPE arg)
|
||||
{
|
||||
return arg.length_squared();
|
||||
}
|
||||
|
||||
/** Length of a quaternion. */
|
||||
template<typename E, class AT, class OT, class CT>
|
||||
inline typename quaternion<E,AT,OT,CT>::value_type
|
||||
length(const quaternion<E,AT,OT,CT>& arg)
|
||||
{
|
||||
return arg.length();
|
||||
}
|
||||
|
||||
/** Length of a quaternion expr. */
|
||||
template<typename XprT>
|
||||
inline typename XprT::value_type
|
||||
length(QUATXPR_ARG_TYPE arg)
|
||||
{
|
||||
return arg.length();
|
||||
}
|
||||
|
||||
/** Normalize a quaternion.
|
||||
*
|
||||
* The input quaternion is not changed.
|
||||
*/
|
||||
template<typename E, class AT, class OT, class CT>
|
||||
inline quaternion<E,AT,OT,CT>
|
||||
normalize(const quaternion<E,AT,OT,CT>& arg)
|
||||
{
|
||||
typename quaternion<E,AT,OT,CT>::temporary_type result(arg);
|
||||
result.normalize();
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Normalize a quaternion expr. */
|
||||
template<typename XprT>
|
||||
inline typename XprT::temporary_type
|
||||
normalize(QUATXPR_ARG_TYPE arg)
|
||||
{
|
||||
return arg.normalize();
|
||||
}
|
||||
|
||||
/** Set a quaternion to the multiplicative identity.
|
||||
*
|
||||
* The input quaternion is not changed.
|
||||
*/
|
||||
template<typename E, class AT, class OT, class CT>
|
||||
inline quaternion<E,AT,OT,CT>
|
||||
identity(const quaternion<E,AT,OT,CT>& arg)
|
||||
{
|
||||
typename quaternion<E,AT,OT,CT>::temporary_type result(arg);
|
||||
result.identity();
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Log of a quaternion or quaternion expression.
|
||||
*/
|
||||
template < class QuatT >
|
||||
typename QuatT::temporary_type log(
|
||||
const QuatT& q,
|
||||
typename QuatT::value_type tolerance =
|
||||
epsilon<typename QuatT::value_type>::placeholder())
|
||||
{
|
||||
detail::CheckQuat(q);
|
||||
|
||||
return q.log();
|
||||
}
|
||||
|
||||
/** Exponential function of a quaternion or quaternion expression.
|
||||
*/
|
||||
template < class QuatT >
|
||||
typename QuatT::temporary_type exp(
|
||||
const QuatT& q,
|
||||
typename QuatT::value_type tolerance =
|
||||
epsilon<typename QuatT::value_type>::placeholder())
|
||||
{
|
||||
detail::CheckQuat(q);
|
||||
|
||||
return q.exp();
|
||||
}
|
||||
|
||||
} // namespace cml
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// vim:ft=cpp
|
||||
140
Lib/Include/CML/quaternion/quaternion_mul.h
Normal file
140
Lib/Include/CML/quaternion/quaternion_mul.h
Normal file
@@ -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 <cml/mathlib/checking.h>
|
||||
#include <cml/quaternion/quaternion_promotions.h>
|
||||
|
||||
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<cross_type, value_type> 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<typename E1, class AT1, typename E2, class AT2, class OT, class CT>
|
||||
inline typename et::QuaternionPromote<
|
||||
typename quaternion<E1,AT1,OT,CT>::temporary_type,
|
||||
typename quaternion<E2,AT2,OT,CT>::temporary_type
|
||||
>::temporary_type operator*(
|
||||
const quaternion<E1,AT1,OT,CT>& left,
|
||||
const quaternion<E2,AT2,OT,CT>& right)
|
||||
{
|
||||
return detail::QuaternionMult(left, right);
|
||||
}
|
||||
|
||||
/** Declare mul taking a quaternion and a et::QuaternionXpr. */
|
||||
template<typename E, class AT, class OT, class CT, class XprT>
|
||||
inline typename et::QuaternionPromote<
|
||||
typename quaternion<E,AT,OT,CT>::temporary_type,
|
||||
typename XprT::temporary_type
|
||||
>::temporary_type operator*(
|
||||
const quaternion<E,AT,OT,CT>& left,
|
||||
QUATXPR_ARG_TYPE right)
|
||||
{
|
||||
return detail::QuaternionMult(left, right);
|
||||
}
|
||||
|
||||
/** Declare mul taking an et::QuaternionXpr and a quaternion. */
|
||||
template<class XprT, typename E, class AT, class OT, class CT>
|
||||
inline typename et::QuaternionPromote<
|
||||
typename XprT::temporary_type,
|
||||
typename quaternion<E,AT,OT,CT>::temporary_type
|
||||
>::temporary_type operator*(
|
||||
QUATXPR_ARG_TYPE left,
|
||||
const quaternion<E,AT,OT,CT>& right)
|
||||
{
|
||||
return detail::QuaternionMult(left, right);
|
||||
}
|
||||
|
||||
/** Declare mul taking two et::QuaternionXpr operands. */
|
||||
template<class XprT1, class XprT2>
|
||||
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
|
||||
51
Lib/Include/CML/quaternion/quaternion_ops.h
Normal file
51
Lib/Include/CML/quaternion/quaternion_ops.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/* -*- 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 Defines the linear quaternion ops.
|
||||
*/
|
||||
|
||||
#ifndef quaternion_ops_h
|
||||
#define quaternion_ops_h
|
||||
|
||||
#include <cml/et/scalar_ops.h>
|
||||
#include <cml/quaternion/quaternion_expr.h>
|
||||
#include <cml/quaternion/quatop_macros.h>
|
||||
|
||||
namespace cml {
|
||||
|
||||
CML_QUAT_UNIOP( operator+, et::OpPos)
|
||||
CML_QUATXPR_UNIOP( operator+, et::OpPos)
|
||||
|
||||
CML_QUAT_UNIOP( operator-, et::OpNeg)
|
||||
CML_QUATXPR_UNIOP( operator-, et::OpNeg)
|
||||
|
||||
CML_QUAT_QUAT_BINOP( operator+, et::OpAdd)
|
||||
CML_QUATXPR_QUAT_BINOP( operator+, et::OpAdd)
|
||||
CML_QUAT_QUATXPR_BINOP( operator+, et::OpAdd)
|
||||
CML_QUATXPR_QUATXPR_BINOP( operator+, et::OpAdd)
|
||||
|
||||
CML_QUAT_QUAT_BINOP( operator-, et::OpSub)
|
||||
CML_QUATXPR_QUAT_BINOP( operator-, et::OpSub)
|
||||
CML_QUAT_QUATXPR_BINOP( operator-, et::OpSub)
|
||||
CML_QUATXPR_QUATXPR_BINOP( operator-, et::OpSub)
|
||||
|
||||
CML_QUAT_SCALAR_BINOP( operator*, et::OpMul)
|
||||
CML_SCALAR_QUAT_BINOP( operator*, et::OpMul)
|
||||
CML_QUATXPR_SCALAR_BINOP( operator*, et::OpMul)
|
||||
CML_SCALAR_QUATXPR_BINOP( operator*, et::OpMul)
|
||||
|
||||
CML_QUAT_SCALAR_BINOP( operator/, et::OpDiv)
|
||||
CML_QUATXPR_SCALAR_BINOP( operator/, et::OpDiv)
|
||||
|
||||
} // namespace cml
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// vim:ft=cpp
|
||||
90
Lib/Include/CML/quaternion/quaternion_print.h
Normal file
90
Lib/Include/CML/quaternion/quaternion_print.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/* -*- 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_print_h
|
||||
#define quaternion_print_h
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace cml {
|
||||
|
||||
/* NOTE: Made 'plain' quaternion output the default (Jesse) */
|
||||
|
||||
/* #if !defined(CML_PLAIN_QUATERNION_OUTPUT) */
|
||||
#if defined(CML_COMPLEX_QUATERNION_OUTPUT)
|
||||
|
||||
template<typename E, class AT, class CT> std::ostream&
|
||||
operator<<(std::ostream& os, const cml::quaternion<E,AT,scalar_first,CT>& q)
|
||||
{
|
||||
os << ((q[0] < 0)?" - ":"") << std::fabs(q[0]);
|
||||
os << ((q[1] < 0)?" - ":" + ") << std::fabs(q[1]) << "i";
|
||||
os << ((q[2] < 0)?" - ":" + ") << std::fabs(q[2]) << "j";
|
||||
os << ((q[3] < 0)?" - ":" + ") << std::fabs(q[3]) << "k";
|
||||
return os;
|
||||
}
|
||||
|
||||
template<typename E, class AT, class CT> std::ostream&
|
||||
operator<<(std::ostream& os, const cml::quaternion<E,AT,vector_first,CT>& q)
|
||||
{
|
||||
os << ((q[0] < 0)?" - ":"") << std::fabs(q[0]) << "i";
|
||||
os << ((q[1] < 0)?" - ":" + ") << std::fabs(q[1]) << "j";
|
||||
os << ((q[2] < 0)?" - ":" + ") << std::fabs(q[2]) << "k";
|
||||
os << ((q[3] < 0)?" - ":" + ") << std::fabs(q[3]);
|
||||
return os;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/** Output a quaternion to a std::ostream. */
|
||||
template<typename E, class AT, class OT, typename CT> std::ostream&
|
||||
operator<<(std::ostream& os, const cml::quaternion<E,AT,OT,CT>& q)
|
||||
{
|
||||
typedef typename cml::quaternion<E,AT,OT,CT>::order_type order_type;
|
||||
enum {
|
||||
W = order_type::W,
|
||||
X = order_type::X,
|
||||
Y = order_type::Y,
|
||||
Z = order_type::Z
|
||||
};
|
||||
|
||||
os << "[ "
|
||||
<< " " << q[W]
|
||||
<< " " << q[X]
|
||||
<< " " << q[Y]
|
||||
<< " " << q[Z]
|
||||
<< " ]";
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/** Output a quaternion expression to a std::ostream. */
|
||||
template< class XprT > inline std::ostream&
|
||||
operator<<(std::ostream& os, const et::QuaternionXpr<XprT>& q)
|
||||
{
|
||||
typedef typename et::QuaternionXpr<XprT>::result_type quaternion_type;
|
||||
|
||||
os << quaternion_type(q);
|
||||
/* XXX This temporary can be removed by templating the stream insertion
|
||||
* operators above.
|
||||
*/
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace cml
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// vim:ft=cpp
|
||||
140
Lib/Include/CML/quaternion/quaternion_promotions.h
Normal file
140
Lib/Include/CML/quaternion/quaternion_promotions.h
Normal file
@@ -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
|
||||
*/
|
||||
|
||||
#ifndef quaternion_promotions_h
|
||||
#define quaternion_promotions_h
|
||||
|
||||
#include <cml/et/scalar_promotions.h>
|
||||
#include <cml/vector/vector_promotions.h>
|
||||
|
||||
namespace cml {
|
||||
namespace et {
|
||||
|
||||
/* Default quaternion type promotion templates. */
|
||||
template<class LeftT, class RightT> struct QuaternionPromote;
|
||||
|
||||
/** Type promotion for two quaternion types. */
|
||||
template<typename E1, class AT1, typename E2, class AT2, class OT, class CT>
|
||||
struct QuaternionPromote<
|
||||
cml::quaternion<E1,AT1,OT,CT>,
|
||||
cml::quaternion<E2,AT2,OT,CT>
|
||||
>
|
||||
{
|
||||
/* The deduced vector type: */
|
||||
typedef typename VectorPromote<
|
||||
typename cml::quaternion<E1,AT1,OT,CT>::vector_type,
|
||||
typename cml::quaternion<E2,AT2,OT,CT>::vector_type
|
||||
>::type promoted_vector;
|
||||
|
||||
/* The deduced element and storage types: */
|
||||
typedef typename promoted_vector::value_type value_type;
|
||||
typedef typename promoted_vector::storage_type storage_type;
|
||||
|
||||
/* The deduced quaternion result type: */
|
||||
typedef cml::quaternion<value_type,storage_type,OT,CT> type;
|
||||
|
||||
/* The temporary type: */
|
||||
typedef typename type::temporary_type temporary_type;
|
||||
};
|
||||
|
||||
/**
|
||||
* NOTE: QuaternionPromote* are somewhat ad hoc, and were added to
|
||||
* simplify the code for quaternion slerp/squad/etc.
|
||||
*/
|
||||
|
||||
/** Type promotion for two quaternion types. */
|
||||
template < class Quat1_T, class Quat2_T >
|
||||
struct QuaternionPromote2
|
||||
{
|
||||
typedef typename QuaternionPromote<
|
||||
typename Quat1_T::temporary_type, typename Quat2_T::temporary_type
|
||||
>::temporary_type temporary_type;
|
||||
typedef typename temporary_type::value_type value_type;
|
||||
};
|
||||
|
||||
/** Type promotion for three quaternion types. */
|
||||
template < class Quat1_T, class Quat2_T, class Quat3_T >
|
||||
struct QuaternionPromote3
|
||||
{
|
||||
typedef typename QuaternionPromote<
|
||||
typename Quat1_T::temporary_type,
|
||||
typename QuaternionPromote<
|
||||
typename Quat2_T::temporary_type, typename Quat3_T::temporary_type
|
||||
>::temporary_type
|
||||
>::temporary_type temporary_type;
|
||||
typedef typename temporary_type::value_type value_type;
|
||||
};
|
||||
|
||||
/** Type promotion for four quaternion types. */
|
||||
template < class Quat1_T, class Quat2_T, class Quat3_T, class Quat4_T >
|
||||
struct QuaternionPromote4
|
||||
{
|
||||
typedef typename QuaternionPromote<
|
||||
typename Quat1_T::temporary_type,
|
||||
typename QuaternionPromote<
|
||||
typename Quat2_T::temporary_type,
|
||||
typename QuaternionPromote<
|
||||
typename Quat3_T::temporary_type,
|
||||
typename Quat4_T::temporary_type
|
||||
>::temporary_type
|
||||
>::temporary_type
|
||||
>::temporary_type temporary_type;
|
||||
typedef typename temporary_type::value_type value_type;
|
||||
};
|
||||
|
||||
/** Type promotion for a quaternion and a scalar. */
|
||||
template<typename E, class AT, class OT, class CT, typename S>
|
||||
struct QuaternionPromote<cml::quaternion<E,AT,OT,CT>, S>
|
||||
{
|
||||
/* The deduced vector type: */
|
||||
typedef typename VectorPromote<
|
||||
typename quaternion<E,AT,OT,CT>::vector_type, S
|
||||
>::type promoted_vector;
|
||||
|
||||
/* The deduced element and storage types: */
|
||||
typedef typename promoted_vector::value_type value_type;
|
||||
typedef typename promoted_vector::storage_type storage_type;
|
||||
|
||||
/* The deduced quaternion result type: */
|
||||
typedef cml::quaternion<value_type,storage_type,OT,CT> type;
|
||||
|
||||
/* The temporary type: */
|
||||
typedef typename type::temporary_type temporary_type;
|
||||
};
|
||||
|
||||
/** Type promotion for a scalar and a quaternion. */
|
||||
template<class S, typename E, class AT, class OT, class CT>
|
||||
struct QuaternionPromote<S, cml::quaternion<E,AT,OT,CT> >
|
||||
{
|
||||
/* The deduced vector type: */
|
||||
typedef typename VectorPromote<
|
||||
S, typename quaternion<E,AT,OT,CT>::vector_type
|
||||
>::type promoted_vector;
|
||||
|
||||
/* The deduced element and storage types: */
|
||||
typedef typename promoted_vector::value_type value_type;
|
||||
typedef typename promoted_vector::storage_type storage_type;
|
||||
|
||||
/* The deduced quaternion result type: */
|
||||
typedef cml::quaternion<value_type,storage_type,OT,CT> type;
|
||||
|
||||
/* The temporary type: */
|
||||
typedef typename type::temporary_type temporary_type;
|
||||
};
|
||||
|
||||
} // namespace et
|
||||
} // namespace cml
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// vim:ft=cpp
|
||||
45
Lib/Include/CML/quaternion/quaternion_traits.h
Normal file
45
Lib/Include/CML/quaternion/quaternion_traits.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/* -*- 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_traits_h
|
||||
#define quaternion_traits_h
|
||||
|
||||
#include <cml/et/traits.h>
|
||||
|
||||
namespace cml {
|
||||
namespace et {
|
||||
|
||||
/** Expression traits for a quaternion<> type. */
|
||||
template<typename E, class AT, class OT, class CT>
|
||||
struct ExprTraits< cml::quaternion<E,AT,OT,CT> >
|
||||
{
|
||||
typedef typename cml::quaternion<E,AT,OT,CT>::expr_type expr_type;
|
||||
typedef typename expr_type::value_type value_type;
|
||||
typedef typename expr_type::expr_reference reference;
|
||||
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::assignable_tag assignable_tag;
|
||||
typedef expr_type result_type;
|
||||
typedef expr_leaf_tag node_tag;
|
||||
|
||||
value_type get(const expr_type& v, size_t i) const { return v[i]; }
|
||||
size_t size(const expr_type& v) const { return 4; }
|
||||
};
|
||||
|
||||
} // namespace et
|
||||
} // namespace cml
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// vim:ft=cpp
|
||||
232
Lib/Include/CML/quaternion/quatop_macros.h
Normal file
232
Lib/Include/CML/quaternion/quatop_macros.h
Normal file
@@ -0,0 +1,232 @@
|
||||
/* -*- 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
|
||||
*
|
||||
* Create unary and binary operators with macros.
|
||||
*
|
||||
* These macros work just like those in cml/quaternion/vecop_macros.h.
|
||||
*/
|
||||
|
||||
#ifndef quatop_macros_h
|
||||
#define quatop_macros_h
|
||||
|
||||
/** Declare a unary operator taking a quaternion operand. */
|
||||
#define CML_QUAT_UNIOP(_op_, _OpT_) \
|
||||
template<typename E, class AT, class OT, class CT> \
|
||||
inline et::QuaternionXpr< \
|
||||
et::UnaryQuaternionOp< quaternion<E,AT,OT,CT>, _OpT_ <E> > \
|
||||
> \
|
||||
\
|
||||
_op_ (const quaternion<E,AT,OT,CT>& arg) \
|
||||
{ \
|
||||
typedef et::UnaryQuaternionOp< \
|
||||
quaternion<E,AT,OT,CT>, _OpT_ <E> \
|
||||
> ExprT; \
|
||||
return et::QuaternionXpr<ExprT>(ExprT(arg)); \
|
||||
}
|
||||
|
||||
|
||||
/** Declare a unary operator taking a et::QuaternionXpr operand. */
|
||||
#define CML_QUATXPR_UNIOP(_op_, _OpT_) \
|
||||
template<class XprT> \
|
||||
inline et::QuaternionXpr< \
|
||||
et::UnaryQuaternionOp< XprT, _OpT_ <typename XprT::value_type> > \
|
||||
> \
|
||||
\
|
||||
_op_ (QUATXPR_ARG_TYPE arg) \
|
||||
{ \
|
||||
typedef et::UnaryQuaternionOp< \
|
||||
XprT, _OpT_ <typename XprT::value_type> \
|
||||
> ExprT; \
|
||||
return et::QuaternionXpr<ExprT>(ExprT(arg.expression())); \
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Declare an operator taking two quaternion operands. */
|
||||
#define CML_QUAT_QUAT_BINOP(_op_, _OpT_) \
|
||||
template<typename E1, class AT1, typename E2, class AT2, \
|
||||
class OT, class CT> \
|
||||
inline et::QuaternionXpr< \
|
||||
et::BinaryQuaternionOp< \
|
||||
quaternion<E1,AT1,OT,CT>, quaternion<E2,AT2,OT,CT>, \
|
||||
_OpT_ <E1,E2> \
|
||||
> \
|
||||
> \
|
||||
\
|
||||
_op_ ( \
|
||||
const quaternion<E1,AT1,OT,CT>& left, \
|
||||
const quaternion<E2,AT2,OT,CT>& right) \
|
||||
{ \
|
||||
typedef et::BinaryQuaternionOp< \
|
||||
quaternion<E1,AT1,OT,CT>, quaternion<E2,AT2,OT,CT>, \
|
||||
_OpT_ <E1,E2> \
|
||||
> ExprT; \
|
||||
return et::QuaternionXpr<ExprT>(ExprT(left,right)); \
|
||||
}
|
||||
|
||||
|
||||
/** Declare an operator taking a quaternion and a et::QuaternionXpr. */
|
||||
#define CML_QUAT_QUATXPR_BINOP(_op_, _OpT_) \
|
||||
template<typename E, class AT, class OT, class CT, class XprT> \
|
||||
inline et::QuaternionXpr< \
|
||||
et::BinaryQuaternionOp< \
|
||||
quaternion<E,AT,OT,CT>, XprT, \
|
||||
_OpT_ <E, typename XprT::value_type> \
|
||||
> \
|
||||
> \
|
||||
\
|
||||
_op_ ( \
|
||||
const quaternion<E,AT,OT,CT>& left, \
|
||||
QUATXPR_ARG_TYPE right) \
|
||||
{ \
|
||||
typedef et::BinaryQuaternionOp< \
|
||||
quaternion<E,AT,OT,CT>, XprT, \
|
||||
_OpT_ <E, typename XprT::value_type> \
|
||||
> ExprT; \
|
||||
return et::QuaternionXpr<ExprT>(ExprT(left,right.expression())); \
|
||||
}
|
||||
|
||||
|
||||
/** Declare an operator taking an et::QuaternionXpr and a quaternion. */
|
||||
#define CML_QUATXPR_QUAT_BINOP(_op_, _OpT_) \
|
||||
template<class XprT, typename E, class AT, class OT, class CT> \
|
||||
inline et::QuaternionXpr< \
|
||||
et::BinaryQuaternionOp< \
|
||||
XprT, quaternion<E,AT,OT,CT>, \
|
||||
_OpT_ <typename XprT::value_type, E> \
|
||||
> \
|
||||
> \
|
||||
\
|
||||
_op_ ( \
|
||||
QUATXPR_ARG_TYPE left, \
|
||||
const quaternion<E,AT,OT,CT>& right) \
|
||||
{ \
|
||||
typedef et::BinaryQuaternionOp< \
|
||||
XprT, quaternion<E,AT,OT,CT>, \
|
||||
_OpT_ <typename XprT::value_type, E> \
|
||||
> ExprT; \
|
||||
return et::QuaternionXpr<ExprT>(ExprT(left.expression(),right)); \
|
||||
}
|
||||
|
||||
|
||||
/** Declare an operator taking two et::QuaternionXpr operands. */
|
||||
#define CML_QUATXPR_QUATXPR_BINOP(_op_, _OpT_) \
|
||||
template<class XprT1, class XprT2> \
|
||||
inline et::QuaternionXpr< \
|
||||
et::BinaryQuaternionOp< \
|
||||
XprT1, XprT2, \
|
||||
_OpT_ < \
|
||||
typename XprT1::value_type, \
|
||||
typename XprT2::value_type \
|
||||
> \
|
||||
> \
|
||||
> \
|
||||
\
|
||||
_op_ ( \
|
||||
QUATXPR_ARG_TYPE_N(1) left, \
|
||||
QUATXPR_ARG_TYPE_N(2) right) \
|
||||
{ \
|
||||
typedef et::BinaryQuaternionOp< \
|
||||
XprT1, XprT2, \
|
||||
_OpT_ < \
|
||||
typename XprT1::value_type, \
|
||||
typename XprT2::value_type> \
|
||||
> ExprT; \
|
||||
return et::QuaternionXpr<ExprT>( \
|
||||
ExprT(left.expression(),right.expression())); \
|
||||
}
|
||||
|
||||
|
||||
/** Declare an operator taking a quaternion and a scalar. */
|
||||
#define CML_QUAT_SCALAR_BINOP(_op_, _OpT_) \
|
||||
template<typename E, class AT, class OT, class CT, typename ScalarT> \
|
||||
inline et::QuaternionXpr< \
|
||||
et::BinaryQuaternionOp< \
|
||||
quaternion<E,AT,OT,CT>, ScalarT, \
|
||||
_OpT_ <E,ScalarT> \
|
||||
> \
|
||||
> \
|
||||
\
|
||||
_op_ ( \
|
||||
const quaternion<E,AT,OT,CT>& left, \
|
||||
SCALAR_ARG_TYPE right) \
|
||||
{ \
|
||||
typedef et::BinaryQuaternionOp< \
|
||||
quaternion<E,AT,OT,CT>, ScalarT, _OpT_ <E,ScalarT> \
|
||||
> ExprT; \
|
||||
return et::QuaternionXpr<ExprT>(ExprT(left,right)); \
|
||||
}
|
||||
|
||||
|
||||
/** Declare an operator taking a scalar and a quaternion. */
|
||||
#define CML_SCALAR_QUAT_BINOP(_op_, _OpT_) \
|
||||
template<typename ScalarT, typename E, class AT, class OT, class CT> \
|
||||
inline et::QuaternionXpr< \
|
||||
et::BinaryQuaternionOp< \
|
||||
ScalarT, quaternion<E,AT,OT,CT>, _OpT_ <ScalarT,E> \
|
||||
> \
|
||||
> \
|
||||
\
|
||||
_op_ ( \
|
||||
SCALAR_ARG_TYPE left, \
|
||||
const quaternion<E,AT,OT,CT>& right) \
|
||||
{ \
|
||||
typedef et::BinaryQuaternionOp< \
|
||||
ScalarT, quaternion<E,AT,OT,CT>, _OpT_ <ScalarT,E> \
|
||||
> ExprT; \
|
||||
return et::QuaternionXpr<ExprT>(ExprT(left,right)); \
|
||||
}
|
||||
|
||||
|
||||
/** Declare an operator taking a et::QuaternionXpr and a scalar. */
|
||||
#define CML_QUATXPR_SCALAR_BINOP(_op_, _OpT_) \
|
||||
template<class XprT, typename ScalarT> \
|
||||
inline et::QuaternionXpr< \
|
||||
et::BinaryQuaternionOp< \
|
||||
XprT, ScalarT, _OpT_ <typename XprT::value_type,ScalarT> \
|
||||
> \
|
||||
> \
|
||||
\
|
||||
_op_ ( \
|
||||
QUATXPR_ARG_TYPE left, \
|
||||
SCALAR_ARG_TYPE right) \
|
||||
{ \
|
||||
typedef et::BinaryQuaternionOp< \
|
||||
XprT, ScalarT, _OpT_ <typename XprT::value_type,ScalarT> \
|
||||
> ExprT; \
|
||||
return et::QuaternionXpr<ExprT>(ExprT(left.expression(),right)); \
|
||||
}
|
||||
|
||||
|
||||
/** Declare an operator taking a scalar and a et::QuaternionXpr. */
|
||||
#define CML_SCALAR_QUATXPR_BINOP(_op_, _OpT_) \
|
||||
template<typename ScalarT, class XprT> \
|
||||
inline et::QuaternionXpr< \
|
||||
et::BinaryQuaternionOp< \
|
||||
ScalarT, XprT, _OpT_ <ScalarT, typename XprT::value_type> \
|
||||
> \
|
||||
> \
|
||||
\
|
||||
_op_ ( \
|
||||
SCALAR_ARG_TYPE left, \
|
||||
QUATXPR_ARG_TYPE right) \
|
||||
{ \
|
||||
typedef et::BinaryQuaternionOp< \
|
||||
ScalarT, XprT, \
|
||||
_OpT_ <ScalarT, typename XprT::value_type> \
|
||||
> ExprT; \
|
||||
return et::QuaternionXpr<ExprT>(ExprT(left,right.expression())); \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// vim:ft=cpp
|
||||
Reference in New Issue
Block a user