]> Dogcows Code - chaz/yoink/blob - src/cml/quaternion/quaternion_expr.h
now using cml for vectors and math stuff
[chaz/yoink] / src / cml / quaternion / quaternion_expr.h
1 /* -*- C++ -*- ------------------------------------------------------------
2
3 Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
4
5 The Configurable Math Library (CML) is distributed under the terms of the
6 Boost Software License, v1.0 (see cml/LICENSE for details).
7
8 *-----------------------------------------------------------------------*/
9 /** @file
10 * @brief
11 */
12
13 #ifndef quaternion_expr_h
14 #define quaternion_expr_h
15
16 #include <cml/et/size_checking.h>
17 #include <cml/mathlib/epsilon.h>
18 #include <cml/quaternion/quaternion_traits.h>
19 #include <cml/quaternion/quaternion_promotions.h>
20 #include <cml/util.h>
21
22 #define QUATXPR_ARG_TYPE const et::QuaternionXpr<XprT>&
23 #define QUATXPR_ARG_TYPE_N(_N_) const et::QuaternionXpr<XprT##_N_>&
24
25 namespace cml {
26 namespace et {
27
28 /** A placeholder for a quaternion expression in an expression tree. */
29 template<class ExprT>
30 class QuaternionXpr
31 {
32 public:
33
34 typedef QuaternionXpr<ExprT> expr_type;
35
36 /* Record ary-ness of the expression: */
37 typedef typename ExprT::expr_ary expr_ary;
38
39 /* Copy the expression by value into higher-up expressions: */
40 typedef expr_type expr_const_reference;
41
42 typedef typename ExprT::value_type value_type;
43 typedef quaternion_result_tag result_tag;
44 typedef typename ExprT::size_tag size_tag;
45
46 /* Store the expression traits: */
47 typedef ExprTraits<ExprT> expr_traits;
48
49 /* Get the reference type: */
50 typedef typename expr_traits::const_reference expr_reference;
51
52 /* Get the result type: */
53 typedef typename expr_traits::result_type result_type;
54
55 /* Get the vector type: */
56 typedef typename result_type::vector_type vector_type;
57
58 /* Get the imaginary part type: */
59 typedef typename vector_type::subvector_type imaginary_type;
60
61 /* For matching by assignability: */
62 typedef cml::et::not_assignable_tag assignable_tag;
63
64 /* Get the temporary type: */
65 typedef typename result_type::temporary_type temporary_type;
66
67 /* Record the order type: */
68 typedef typename result_type::order_type order_type;
69
70 /* Record the cross type: */
71 typedef typename result_type::cross_type cross_type;
72
73
74 public:
75
76 /** Record result size as an enum. */
77 enum { array_size = ExprT::array_size };
78
79
80 public:
81
82 /** Return the real part of the expression. */
83 value_type real() const {
84 return m_expr.real();
85 }
86
87 /** Return the vector part of the expression. */
88 imaginary_type imaginary() const {
89 return m_expr.imaginary();
90 }
91
92 /** Return the Cayley norm of the expression. */
93 value_type norm() const {
94 return m_expr.length_squared();
95 }
96
97 /** Return square of the quaternion length. */
98 value_type length_squared() const {
99 return m_expr.length_squared();
100 }
101
102 /** Return the quaternion length. */
103 value_type length() const {
104 return m_expr.length();
105 }
106
107 /** Return the result as a normalized quaternion. */
108 temporary_type normalize() const {
109 return m_expr.normalize();
110 }
111
112 /** Return the log of the expression. */
113 temporary_type log(
114 value_type tolerance = epsilon<value_type>::placeholder()) const
115 {
116 return m_expr.log(tolerance);
117 }
118
119 /**
120 * Return the result of the exponential function as applied to
121 * this expression.
122 */
123 temporary_type exp(
124 value_type tolerance = epsilon<value_type>::placeholder()) const
125 {
126 return m_expr.exp(tolerance);
127 }
128
129 /** Compute value at index i of the result quaternion. */
130 value_type operator[](size_t i) const {
131 return m_expr[i];
132 }
133
134
135 public:
136
137 /** Return size of this expression (same as subexpression's size). */
138 size_t size() const {
139 return m_expr.size();
140 }
141
142 /** Return reference to contained expression. */
143 expr_reference expression() const { return m_expr; }
144
145
146 public:
147
148 /** Construct from the subexpression to store. */
149 explicit QuaternionXpr(expr_reference expr) : m_expr(expr) {}
150
151 /** Copy constructor. */
152 QuaternionXpr(const expr_type& e) : m_expr(e.m_expr) {}
153
154
155 protected:
156
157 expr_reference m_expr;
158
159
160 private:
161
162 /* Cannot be assigned to: */
163 expr_type& operator=(const expr_type&);
164 };
165
166 /** Expression traits class for QuaternionXpr<>. */
167 template<class ExprT>
168 struct ExprTraits< QuaternionXpr<ExprT> >
169 {
170 typedef QuaternionXpr<ExprT> expr_type;
171 typedef ExprT arg_type;
172 typedef typename expr_type::value_type value_type;
173 typedef typename expr_type::expr_const_reference const_reference;
174 typedef typename expr_type::result_tag result_tag;
175 typedef typename expr_type::size_tag size_tag;
176 typedef typename expr_type::result_type result_type;
177 typedef typename expr_type::assignable_tag not_assignable_tag;
178 typedef expr_node_tag node_tag;
179
180 value_type get(const expr_type& v, size_t i) const { return v[i]; }
181 size_t size(const expr_type& e) const { return e.size(); }
182 };
183
184
185 /** A unary quaternion expression.
186 *
187 * The operator's operator() method must take exactly one argument.
188 */
189 template<class ExprT, class OpT>
190 class UnaryQuaternionOp
191 {
192 public:
193
194 typedef UnaryQuaternionOp<ExprT,OpT> expr_type;
195
196 /* Record ary-ness of the expression: */
197 typedef unary_expression expr_ary;
198
199 /* Copy the expression by value into higher-up expressions: */
200 typedef expr_type expr_const_reference;
201
202 typedef typename OpT::value_type value_type;
203 typedef quaternion_result_tag result_tag;
204 typedef typename ExprT::size_tag size_tag;
205
206 /* Store the expression traits for the subexpression: */
207 typedef ExprTraits<ExprT> expr_traits;
208
209 /* Reference type for the subexpression: */
210 typedef typename expr_traits::const_reference expr_reference;
211
212 /* Get the result type (same as for subexpression): */
213 typedef typename expr_traits::result_type result_type;
214
215 /* For matching by assignability: */
216 typedef cml::et::not_assignable_tag assignable_tag;
217
218 /* Get the temporary type: */
219 typedef typename result_type::temporary_type temporary_type;
220
221 /* Get the vector type: */
222 typedef typename result_type::vector_type vector_type;
223
224 /* Get the imaginary part type: */
225 typedef typename vector_type::subvector_type imaginary_type;
226
227 /* Record the order type: */
228 typedef typename result_type::order_type order_type;
229
230
231 public:
232
233 /** Record result size as an enum. */
234 enum { array_size = ExprT::array_size };
235
236 /** Localize the ordering as an enum. */
237 enum {
238 W = order_type::W,
239 X = order_type::X,
240 Y = order_type::Y,
241 Z = order_type::Z
242 };
243
244
245 public:
246
247 /** Return the real part of the expression. */
248 value_type real() const {
249 return (*this)[W];
250 }
251
252 /** Return the vector part of the expression. */
253 imaginary_type imaginary() const {
254 imaginary_type v;
255 v[0] = (*this)[X]; v[1] = (*this)[Y]; v[2] = (*this)[Z];
256 return v;
257 }
258
259 /** Return the Cayley norm of the expression. */
260 value_type norm() const {
261 return length_squared();
262 }
263
264 /** Return square of the quaternion length. */
265 value_type length_squared() const {
266 return dot(
267 QuaternionXpr<expr_type>(*this),
268 QuaternionXpr<expr_type>(*this));
269 }
270
271 /** Return the quaternion length. */
272 value_type length() const {
273 return std::sqrt(length_squared());
274 }
275
276 /** Return the result as a normalized quaternion. */
277 temporary_type normalize() const {
278 temporary_type q(QuaternionXpr<expr_type>(*this));
279 return q.normalize();
280 }
281
282 /** Return the log of this expression. */
283 temporary_type log(
284 value_type tolerance = epsilon<value_type>::placeholder()) const
285 {
286 value_type a = acos_safe(real());
287 value_type s = std::sin(a);
288
289 if (s > tolerance) {
290 return temporary_type(value_type(0), imaginary() * (a / s));
291 } else {
292 return temporary_type(value_type(0), imaginary());
293 }
294 }
295
296 /**
297 * Return the result of the exponential function as applied to
298 * this expression.
299 */
300 temporary_type exp(
301 value_type tolerance = epsilon<value_type>::placeholder()) const
302 {
303 imaginary_type v = imaginary();
304 value_type a = cml::length(v);
305
306 if (a > tolerance) {
307 return temporary_type(std::cos(a), v * (std::sin(a) / a));
308 } else {
309 return temporary_type(std::cos(a), v);
310 }
311 }
312
313 /** Compute value at index i of the result quaternion. */
314 value_type operator[](size_t i) const {
315
316 /* This uses the expression traits to figure out how to access the
317 * i'th index of the subexpression:
318 */
319 return OpT().apply(expr_traits().get(m_expr,i));
320 }
321
322
323 public:
324
325 /** Return size of this expression (same as argument's size). */
326 size_t size() const {
327 return m_expr.size();
328 }
329
330 /** Return reference to contained expression. */
331 expr_reference expression() const { return m_expr; }
332
333
334 public:
335
336 /** Construct from the subexpression. */
337 explicit UnaryQuaternionOp(expr_reference expr) : m_expr(expr) {}
338
339 /** Copy constructor. */
340 UnaryQuaternionOp(const expr_type& e) : m_expr(e.m_expr) {}
341
342
343 protected:
344
345 expr_reference m_expr;
346
347
348 private:
349
350 /* Cannot be assigned to: */
351 expr_type& operator=(const expr_type&);
352 };
353
354 /** Expression traits class for UnaryQuaternionOp<>. */
355 template<class ExprT, class OpT>
356 struct ExprTraits< UnaryQuaternionOp<ExprT,OpT> >
357 {
358 typedef UnaryQuaternionOp<ExprT,OpT> expr_type;
359 typedef ExprT arg_type;
360
361 typedef typename expr_type::value_type value_type;
362 typedef typename expr_type::expr_const_reference const_reference;
363 typedef typename expr_type::result_tag result_tag;
364 typedef typename expr_type::size_tag size_tag;
365 typedef typename expr_type::result_type result_type;
366 typedef typename expr_type::assignable_tag not_assignable_tag;
367 typedef expr_node_tag node_tag;
368
369 value_type get(const expr_type& v, size_t i) const { return v[i]; }
370 size_t size(const expr_type& e) const { return e.size(); }
371 };
372
373
374 /** A binary quaternion expression.
375 *
376 * The operator's operator() method must take exactly two arguments.
377 */
378 template<class LeftT, class RightT, class OpT>
379 class BinaryQuaternionOp
380 {
381 public:
382
383 typedef BinaryQuaternionOp<LeftT,RightT,OpT> expr_type;
384
385 /* Record ary-ness of the expression: */
386 typedef binary_expression expr_ary;
387
388 /* Copy the expression by value into higher-up expressions: */
389 typedef expr_type expr_const_reference;
390
391 typedef typename OpT::value_type value_type;
392 typedef quaternion_result_tag result_tag;
393
394 /* Store the expression traits types for the two subexpressions: */
395 typedef ExprTraits<LeftT> left_traits;
396 typedef ExprTraits<RightT> right_traits;
397
398 /* Reference types for the two subexpressions: */
399 typedef typename left_traits::const_reference left_reference;
400 typedef typename right_traits::const_reference right_reference;
401
402 /* Figure out the expression's resulting (quaternion) type: */
403 typedef typename left_traits::result_type left_result;
404 typedef typename right_traits::result_type right_result;
405 typedef typename QuaternionPromote<left_result,right_result>::type
406 result_type;
407 typedef typename result_type::size_tag size_tag;
408
409 /* For matching by assignability: */
410 typedef cml::et::not_assignable_tag assignable_tag;
411
412 /* Get the temporary type: */
413 typedef typename result_type::temporary_type temporary_type;
414
415 /* Get the vector type: */
416 typedef typename result_type::vector_type vector_type;
417
418 /* Get the imaginary part type: */
419 typedef typename vector_type::subvector_type imaginary_type;
420
421 /* Record the order type: */
422 typedef typename result_type::order_type order_type;
423
424 /* Define a size checker: */
425 typedef GetCheckedSize<LeftT,RightT,size_tag> checked_size;
426
427
428 public:
429
430 /** Record result size as an enum. */
431 enum { array_size = 4 };
432
433 /** Localize the ordering as an enum. */
434 enum {
435 W = order_type::W,
436 X = order_type::X,
437 Y = order_type::Y,
438 Z = order_type::Z
439 };
440
441
442 public:
443
444 /** Return the real part of the expression. */
445 value_type real() const {
446 return (*this)[W];
447 }
448
449 /** Return the vector part of the expression. */
450 imaginary_type imaginary() const {
451 imaginary_type v;
452 v[0] = (*this)[X]; v[1] = (*this)[Y]; v[2] = (*this)[Z];
453 return v;
454 }
455
456 /** Return the Cayley norm of the expression. */
457 value_type norm() const {
458 return length_squared();
459 }
460
461 /** Return square of the quaternion length. */
462 value_type length_squared() const {
463 return dot(
464 QuaternionXpr<expr_type>(*this),
465 QuaternionXpr<expr_type>(*this));
466 }
467
468 /** Return the quaternion length. */
469 value_type length() const {
470 return std::sqrt(length_squared());
471 }
472
473 /** Return the result as a normalized quaternion. */
474 temporary_type normalize() const {
475 temporary_type q(QuaternionXpr<expr_type>(*this));
476 return q.normalize();
477 }
478
479 /** Return the log of this expression. */
480 temporary_type log(
481 value_type tolerance = epsilon<value_type>::placeholder()) const
482 {
483 value_type a = acos_safe(real());
484 value_type s = std::sin(a);
485
486 if (s > tolerance) {
487 return temporary_type(value_type(0), imaginary() * (a / s));
488 } else {
489 return temporary_type(value_type(0), imaginary());
490 }
491 }
492
493 /**
494 * Return the result of the exponential function as applied to
495 * this expression.
496 */
497 temporary_type exp(
498 value_type tolerance = epsilon<value_type>::placeholder()) const
499 {
500 imaginary_type v = imaginary();
501 value_type a = cml::length(v);
502
503 if (a > tolerance) {
504 return temporary_type(std::cos(a), v * (std::sin(a) / a));
505 } else {
506 return temporary_type(std::cos(a), v);
507 }
508 }
509
510 /** Compute value at index i of the result quaternion. */
511 value_type operator[](size_t i) const {
512
513 /* This uses the expression traits to figure out how to access the
514 * i'th index of the two subexpressions:
515 */
516 return OpT().apply(
517 left_traits().get(m_left,i),
518 right_traits().get(m_right,i));
519 }
520
521
522 public:
523
524 /** Return the size of the quaternion result.
525 *
526 * @throws std::invalid_argument if the expressions do not have the same
527 * size.
528 */
529 size_t size() const {
530 /* Note: This actually does a check only if
531 * CML_CHECK_VECTOR_EXPR_SIZES is set:
532 */
533 CheckedSize(m_left,m_right,size_tag());
534
535 /* The size is always 4: */
536 return 4;
537 }
538
539 /** Return reference to left expression. */
540 left_reference left_expression() const { return m_left; }
541
542 /** Return reference to right expression. */
543 right_reference right_expression() const { return m_right; }
544
545
546 public:
547
548 /** Construct from the two subexpressions. */
549 explicit BinaryQuaternionOp(left_reference left, right_reference right)
550 : m_left(left), m_right(right) {}
551
552 /** Copy constructor. */
553 BinaryQuaternionOp(const expr_type& e)
554 : m_left(e.m_left), m_right(e.m_right) {}
555
556
557 protected:
558
559 left_reference m_left;
560 right_reference m_right;
561
562
563 private:
564
565 /* This ensures that a compile-time size check is executed: */
566 typename checked_size::check_type _dummy;
567
568
569 private:
570
571 /* Cannot be assigned to: */
572 expr_type& operator=(const expr_type&);
573 };
574
575 /** Expression traits class for BinaryQuaternionOp<>. */
576 template<class LeftT, class RightT, class OpT>
577 struct ExprTraits< BinaryQuaternionOp<LeftT,RightT,OpT> >
578 {
579 typedef BinaryQuaternionOp<LeftT,RightT,OpT> expr_type;
580 typedef LeftT left_type;
581 typedef RightT right_type;
582
583 typedef typename expr_type::value_type value_type;
584 typedef typename expr_type::expr_const_reference const_reference;
585 typedef typename expr_type::result_tag result_tag;
586 typedef typename expr_type::size_tag size_tag;
587 typedef typename expr_type::result_type result_type;
588 typedef typename expr_type::imaginary_type imaginary_type;
589 typedef typename expr_type::assignable_tag not_assignable_tag;
590 typedef expr_node_tag node_tag;
591
592 value_type get(const expr_type& v, size_t i) const { return v[i]; }
593 size_t size(const expr_type& e) const { return e.size(); }
594 };
595
596
597 /* Helper struct to verify that both arguments are quaternion expressions: */
598 template<class LeftTraits, class RightTraits>
599 struct QuaternionExpressions
600 {
601 /* Require that both arguments are quaternion expressions: */
602 typedef typename LeftTraits::result_tag left_result;
603 typedef typename RightTraits::result_tag right_result;
604 enum { is_true = (same_type<left_result,et::quaternion_result_tag>::is_true
605 && same_type<right_result,et::quaternion_result_tag>::is_true) };
606 };
607
608 } // namespace et
609 } // namespace cml
610
611 #endif
612
613 // -------------------------------------------------------------------------
614 // vim:ft=cpp
This page took 0.05932 seconds and 4 git commands to generate.