1 /* -*- C++ -*- ------------------------------------------------------------
3 Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
5 The Configurable Math Library (CML) is distributed under the terms of the
6 Boost Software License, v1.0 (see cml/LICENSE for details).
8 *-----------------------------------------------------------------------*/
10 * @brief Defines an operator for quaternion inverse.
13 #ifndef quaternion_inverse_h
14 #define quaternion_inverse_h
16 #include <cml/quaternion/quaternion_expr.h>
17 #include <cml/quaternion/quaternion_functions.h>
22 /** An expression node for inverting a quaternion.
24 * This internally creates a ConjugateOp node to process the conjugate
25 * of the given expression. The values produced by the ConjugateOp are then
26 * divided by the Cayley norm of the expression on the fly.
29 class QuaternionInverseOp
33 typedef QuaternionInverseOp
<ExprT
> expr_type
;
35 /* Record ary-ness of the expression: */
36 typedef unary_expression expr_ary
;
38 /* Copy the expression by value into higher-up expressions: */
39 typedef expr_type expr_const_reference
;
41 /* The subexpression is a ConjugateOp: */
42 typedef et::ConjugateOp
<ExprT
> subexpression_type
;
43 typedef ExprTraits
<subexpression_type
> expr_traits
;
45 /* Get traits for the ExprT: */
46 typedef ExprTraits
<ExprT
> arg_traits
;
47 typedef typename
arg_traits::const_reference arg_reference
;
49 typedef typename
subexpression_type::value_type value_type
;
50 typedef quaternion_result_tag result_tag
;
51 typedef typename
subexpression_type::size_tag size_tag
;
53 /* Reference type for the subexpression: */
54 typedef typename
expr_traits::const_reference expr_reference
;
56 /* Get the result type (same as for subexpression): */
57 typedef typename
expr_traits::result_type result_type
;
59 /* For matching by assignability: */
60 typedef cml::et::not_assignable_tag assignable_tag
;
62 /* Get the temporary type: */
63 typedef typename
result_type::temporary_type temporary_type
;
65 /* Get the vector type: */
66 typedef typename
result_type::vector_type vector_type
;
68 /* Get the imaginary part type: */
69 typedef typename
vector_type::subvector_type imaginary_type
;
71 /* Record the order type: */
72 typedef typename
result_type::order_type order_type
;
77 /** Record result size as an enum. */
78 enum { array_size
= ExprT::array_size
};
80 /** Localize the ordering as an enum. */
91 /** Return the real part of the expression. */
92 value_type
real() const {
93 return m_expr
.real()/m_norm
;
96 /** Return the vector part of the expression.
98 * @todo This could be returned as a VectorXpr also.
100 imaginary_type
imaginary() const {
101 return m_expr
.imaginary()/m_norm
;
104 /** Return the Cayley norm of the expression. */
105 value_type
norm() const {
106 return length_squared();
109 /** Return square of the quaternion length. */
110 value_type
length_squared() const {
112 QuaternionXpr
<expr_type
>(*this),
113 QuaternionXpr
<expr_type
>(*this));
116 /** Return the quaternion length. */
117 value_type
length() const {
118 return std::sqrt(length_squared());
121 /** Return the result as a normalized quaternion. */
122 temporary_type
normalize() const {
123 temporary_type
q(QuaternionXpr
<expr_type
>(*this));
124 return q
.normalize();
127 /** Compute inverse result at index i.
129 * The inverse of a quaternion p is ~p/norm(p).
131 value_type
operator[](size_t i
) const {
132 return m_expr
[i
]/m_norm
;
138 /** Return size of this expression (same as argument's size). */
139 size_t size() const {
140 return m_expr
.size();
143 /** Return reference to contained expression. */
144 expr_reference
expression() const { return m_expr
; }
149 /** Construct from an input expression. */
150 explicit QuaternionInverseOp(arg_reference arg
)
151 //: m_expr(arg), m_norm(cml::norm(arg)) {}
152 : m_expr(arg
), m_norm(arg
.norm()) {}
154 /** Copy constructor. */
155 QuaternionInverseOp(const expr_type
& e
)
156 : m_expr(e
.m_expr
), m_norm(e
.m_norm
) {}
161 subexpression_type m_expr
;
167 /* Cannot be assigned to: */
168 expr_type
& operator=(const expr_type
&);
171 /** Expression traits class for QuaternionInverseOp<>. */
172 template<class ExprT
>
173 struct ExprTraits
< QuaternionInverseOp
<ExprT
> >
175 typedef QuaternionInverseOp
<ExprT
> expr_type
;
176 typedef ExprT arg_type
;
178 typedef typename
expr_type::value_type value_type
;
179 typedef typename
expr_type::expr_const_reference const_reference
;
180 typedef typename
expr_type::result_tag result_tag
;
181 typedef typename
expr_type::size_tag size_tag
;
182 typedef typename
expr_type::result_type result_type
;
183 typedef typename
expr_type::assignable_tag assignable_tag
;
184 typedef expr_node_tag node_tag
;
186 value_type
get(const expr_type
& v
, size_t i
) const { return v
[i
]; }
187 size_t size(const expr_type
& e
) const { return e
.size(); }
192 /** Inverse of a quaternion. */
193 template<typename E
, class AT
, class OrderT
, class CrossT
> inline
194 et::QuaternionXpr
< et::QuaternionInverseOp
< quaternion
<E
,AT
,OrderT
,CrossT
> > >
195 inverse(const quaternion
<E
,AT
,OrderT
,CrossT
>& arg
)
197 typedef et::QuaternionInverseOp
< quaternion
<E
,AT
,OrderT
,CrossT
> > ExprT
;
198 return et::QuaternionXpr
<ExprT
>(ExprT(arg
));
201 /** Inverse of a QuaternionXpr. */
202 template<class XprT
> inline
203 et::QuaternionXpr
< et::QuaternionInverseOp
<XprT
> >
204 inverse(QUATXPR_ARG_TYPE arg
)
206 typedef et::QuaternionInverseOp
<XprT
> ExprT
;
207 return et::QuaternionXpr
<ExprT
>(ExprT(arg
.expression()));
210 /* NOTE: Quaternion division no longer supported, but I'm leaving the
211 code here for reference (Jesse) */
214 /** Declare div taking two quaternion operands. */
215 template<typename E1
, class AT1
, typename E2
, class AT2
, class OT
, class CT
>
216 inline typename
et::QuaternionPromote
<
217 quaternion
<E1
,AT1
,OT
,CT
>, quaternion
<E2
,AT2
,OT
,CT
>
220 const quaternion
<E1
,AT1
,OT
,CT
>& left
,
221 const quaternion
<E2
,AT2
,OT
,CT
>& right
)
223 return left
*inverse(right
);
226 /** Declare div taking a quaternion and a et::QuaternionXpr. */
227 template<typename E
, class AT
, class OT
, class CT
, class XprT
>
228 inline typename
et::QuaternionPromote
<
229 quaternion
<E
,AT
,OT
,CT
>, typename
XprT::result_type
232 const quaternion
<E
,AT
,OT
,CT
>& left
,
233 QUATXPR_ARG_TYPE right
)
235 return left
*inverse(right
);
238 /** Declare div taking an et::QuaternionXpr and a quaternion. */
239 template<class XprT
, typename E
, class AT
, class OT
, class CT
>
240 inline typename
et::QuaternionPromote
<
241 typename
XprT::result_type
, quaternion
<E
,AT
,OT
,CT
>
244 QUATXPR_ARG_TYPE left
,
245 const quaternion
<E
,AT
,OT
,CT
>& right
)
247 return left
*inverse(right
);
250 /** Declare div taking two et::QuaternionXpr operands. */
251 template<class XprT1
, class XprT2
>
252 inline typename
et::QuaternionPromote
<
253 typename
XprT1::result_type
, typename
XprT2::result_type
256 QUATXPR_ARG_TYPE_N(1) left
,
257 QUATXPR_ARG_TYPE_N(2) right
)
259 return left
*inverse(right
);
267 // -------------------------------------------------------------------------