00001
00002
00003
00004
00005
00006
00007
00008
00013 #ifndef quaternion_expr_h
00014 #define quaternion_expr_h
00015
00016 #include <cml/et/size_checking.h>
00017 #include <cml/mathlib/epsilon.h>
00018 #include <cml/quaternion/quaternion_traits.h>
00019 #include <cml/quaternion/quaternion_promotions.h>
00020 #include <cml/util.h>
00021
00022 #define QUATXPR_ARG_TYPE const et::QuaternionXpr<XprT>&
00023 #define QUATXPR_ARG_TYPE_N(_N_) const et::QuaternionXpr<XprT##_N_>&
00024
00025 namespace cml {
00026 namespace et {
00027
00029 template<class ExprT>
00030 class QuaternionXpr
00031 {
00032 public:
00033
00034 typedef QuaternionXpr<ExprT> expr_type;
00035
00036
00037 typedef typename ExprT::expr_ary expr_ary;
00038
00039
00040 typedef expr_type expr_const_reference;
00041
00042 typedef typename ExprT::value_type value_type;
00043 typedef quaternion_result_tag result_tag;
00044 typedef typename ExprT::size_tag size_tag;
00045
00046
00047 typedef ExprTraits<ExprT> expr_traits;
00048
00049
00050 typedef typename expr_traits::const_reference expr_reference;
00051
00052
00053 typedef typename expr_traits::result_type result_type;
00054
00055
00056 typedef typename result_type::vector_type vector_type;
00057
00058
00059 typedef typename vector_type::subvector_type imaginary_type;
00060
00061
00062 typedef cml::et::not_assignable_tag assignable_tag;
00063
00064
00065 typedef typename result_type::temporary_type temporary_type;
00066
00067
00068 typedef typename result_type::order_type order_type;
00069
00070
00071 typedef typename result_type::cross_type cross_type;
00072
00073
00074 public:
00075
00077 enum { array_size = ExprT::array_size };
00078
00079
00080 public:
00081
00083 value_type real() const {
00084 return m_expr.real();
00085 }
00086
00088 imaginary_type imaginary() const {
00089 return m_expr.imaginary();
00090 }
00091
00093 value_type norm() const {
00094 return m_expr.length_squared();
00095 }
00096
00098 value_type length_squared() const {
00099 return m_expr.length_squared();
00100 }
00101
00103 value_type length() const {
00104 return m_expr.length();
00105 }
00106
00108 temporary_type normalize() const {
00109 return m_expr.normalize();
00110 }
00111
00113 temporary_type log(
00114 value_type tolerance = epsilon<value_type>::placeholder()) const
00115 {
00116 return m_expr.log(tolerance);
00117 }
00118
00123 temporary_type exp(
00124 value_type tolerance = epsilon<value_type>::placeholder()) const
00125 {
00126 return m_expr.exp(tolerance);
00127 }
00128
00130 value_type operator[](size_t i) const {
00131 return m_expr[i];
00132 }
00133
00134
00135 public:
00136
00138 size_t size() const {
00139 return m_expr.size();
00140 }
00141
00143 expr_reference expression() const { return m_expr; }
00144
00145
00146 public:
00147
00149 explicit QuaternionXpr(expr_reference expr) : m_expr(expr) {}
00150
00152 QuaternionXpr(const expr_type& e) : m_expr(e.m_expr) {}
00153
00154
00155 protected:
00156
00157 expr_reference m_expr;
00158
00159
00160 private:
00161
00162
00163 expr_type& operator=(const expr_type&);
00164 };
00165
00167 template<class ExprT>
00168 struct ExprTraits< QuaternionXpr<ExprT> >
00169 {
00170 typedef QuaternionXpr<ExprT> expr_type;
00171 typedef ExprT arg_type;
00172 typedef typename expr_type::value_type value_type;
00173 typedef typename expr_type::expr_const_reference const_reference;
00174 typedef typename expr_type::result_tag result_tag;
00175 typedef typename expr_type::size_tag size_tag;
00176 typedef typename expr_type::result_type result_type;
00177 typedef typename expr_type::assignable_tag not_assignable_tag;
00178 typedef expr_node_tag node_tag;
00179
00180 value_type get(const expr_type& v, size_t i) const { return v[i]; }
00181 size_t size(const expr_type& e) const { return e.size(); }
00182 };
00183
00184
00189 template<class ExprT, class OpT>
00190 class UnaryQuaternionOp
00191 {
00192 public:
00193
00194 typedef UnaryQuaternionOp<ExprT,OpT> expr_type;
00195
00196
00197 typedef unary_expression expr_ary;
00198
00199
00200 typedef expr_type expr_const_reference;
00201
00202 typedef typename OpT::value_type value_type;
00203 typedef quaternion_result_tag result_tag;
00204 typedef typename ExprT::size_tag size_tag;
00205
00206
00207 typedef ExprTraits<ExprT> expr_traits;
00208
00209
00210 typedef typename expr_traits::const_reference expr_reference;
00211
00212
00213 typedef typename expr_traits::result_type result_type;
00214
00215
00216 typedef cml::et::not_assignable_tag assignable_tag;
00217
00218
00219 typedef typename result_type::temporary_type temporary_type;
00220
00221
00222 typedef typename result_type::vector_type vector_type;
00223
00224
00225 typedef typename vector_type::subvector_type imaginary_type;
00226
00227
00228 typedef typename result_type::order_type order_type;
00229
00230
00231 public:
00232
00234 enum { array_size = ExprT::array_size };
00235
00237 enum {
00238 W = order_type::W,
00239 X = order_type::X,
00240 Y = order_type::Y,
00241 Z = order_type::Z
00242 };
00243
00244
00245 public:
00246
00248 value_type real() const {
00249 return (*this)[W];
00250 }
00251
00253 imaginary_type imaginary() const {
00254 imaginary_type v;
00255 v[0] = (*this)[X]; v[1] = (*this)[Y]; v[2] = (*this)[Z];
00256 return v;
00257 }
00258
00260 value_type norm() const {
00261 return length_squared();
00262 }
00263
00265 value_type length_squared() const {
00266 return dot(
00267 QuaternionXpr<expr_type>(*this),
00268 QuaternionXpr<expr_type>(*this));
00269 }
00270
00272 value_type length() const {
00273 return std::sqrt(length_squared());
00274 }
00275
00277 temporary_type normalize() const {
00278 temporary_type q(QuaternionXpr<expr_type>(*this));
00279 return q.normalize();
00280 }
00281
00283 temporary_type log(
00284 value_type tolerance = epsilon<value_type>::placeholder()) const
00285 {
00286 value_type a = acos_safe(real());
00287 value_type s = std::sin(a);
00288
00289 if (s > tolerance) {
00290 return temporary_type(value_type(0), imaginary() * (a / s));
00291 } else {
00292 return temporary_type(value_type(0), imaginary());
00293 }
00294 }
00295
00300 temporary_type exp(
00301 value_type tolerance = epsilon<value_type>::placeholder()) const
00302 {
00303 imaginary_type v = imaginary();
00304 value_type a = cml::length(v);
00305
00306 if (a > tolerance) {
00307 return temporary_type(std::cos(a), v * (std::sin(a) / a));
00308 } else {
00309 return temporary_type(std::cos(a), v);
00310 }
00311 }
00312
00314 value_type operator[](size_t i) const {
00315
00316
00317
00318
00319 return OpT().apply(expr_traits().get(m_expr,i));
00320 }
00321
00322
00323 public:
00324
00326 size_t size() const {
00327 return m_expr.size();
00328 }
00329
00331 expr_reference expression() const { return m_expr; }
00332
00333
00334 public:
00335
00337 explicit UnaryQuaternionOp(expr_reference expr) : m_expr(expr) {}
00338
00340 UnaryQuaternionOp(const expr_type& e) : m_expr(e.m_expr) {}
00341
00342
00343 protected:
00344
00345 expr_reference m_expr;
00346
00347
00348 private:
00349
00350
00351 expr_type& operator=(const expr_type&);
00352 };
00353
00355 template<class ExprT, class OpT>
00356 struct ExprTraits< UnaryQuaternionOp<ExprT,OpT> >
00357 {
00358 typedef UnaryQuaternionOp<ExprT,OpT> expr_type;
00359 typedef ExprT arg_type;
00360
00361 typedef typename expr_type::value_type value_type;
00362 typedef typename expr_type::expr_const_reference const_reference;
00363 typedef typename expr_type::result_tag result_tag;
00364 typedef typename expr_type::size_tag size_tag;
00365 typedef typename expr_type::result_type result_type;
00366 typedef typename expr_type::assignable_tag not_assignable_tag;
00367 typedef expr_node_tag node_tag;
00368
00369 value_type get(const expr_type& v, size_t i) const { return v[i]; }
00370 size_t size(const expr_type& e) const { return e.size(); }
00371 };
00372
00373
00378 template<class LeftT, class RightT, class OpT>
00379 class BinaryQuaternionOp
00380 {
00381 public:
00382
00383 typedef BinaryQuaternionOp<LeftT,RightT,OpT> expr_type;
00384
00385
00386 typedef binary_expression expr_ary;
00387
00388
00389 typedef expr_type expr_const_reference;
00390
00391 typedef typename OpT::value_type value_type;
00392 typedef quaternion_result_tag result_tag;
00393
00394
00395 typedef ExprTraits<LeftT> left_traits;
00396 typedef ExprTraits<RightT> right_traits;
00397
00398
00399 typedef typename left_traits::const_reference left_reference;
00400 typedef typename right_traits::const_reference right_reference;
00401
00402
00403 typedef typename left_traits::result_type left_result;
00404 typedef typename right_traits::result_type right_result;
00405 typedef typename QuaternionPromote<left_result,right_result>::type
00406 result_type;
00407 typedef typename result_type::size_tag size_tag;
00408
00409
00410 typedef cml::et::not_assignable_tag assignable_tag;
00411
00412
00413 typedef typename result_type::temporary_type temporary_type;
00414
00415
00416 typedef typename result_type::vector_type vector_type;
00417
00418
00419 typedef typename vector_type::subvector_type imaginary_type;
00420
00421
00422 typedef typename result_type::order_type order_type;
00423
00424
00425 typedef GetCheckedSize<LeftT,RightT,size_tag> checked_size;
00426
00427
00428 public:
00429
00431 enum { array_size = 4 };
00432
00434 enum {
00435 W = order_type::W,
00436 X = order_type::X,
00437 Y = order_type::Y,
00438 Z = order_type::Z
00439 };
00440
00441
00442 public:
00443
00445 value_type real() const {
00446 return (*this)[W];
00447 }
00448
00450 imaginary_type imaginary() const {
00451 imaginary_type v;
00452 v[0] = (*this)[X]; v[1] = (*this)[Y]; v[2] = (*this)[Z];
00453 return v;
00454 }
00455
00457 value_type norm() const {
00458 return length_squared();
00459 }
00460
00462 value_type length_squared() const {
00463 return dot(
00464 QuaternionXpr<expr_type>(*this),
00465 QuaternionXpr<expr_type>(*this));
00466 }
00467
00469 value_type length() const {
00470 return std::sqrt(length_squared());
00471 }
00472
00474 temporary_type normalize() const {
00475 temporary_type q(QuaternionXpr<expr_type>(*this));
00476 return q.normalize();
00477 }
00478
00480 temporary_type log(
00481 value_type tolerance = epsilon<value_type>::placeholder()) const
00482 {
00483 value_type a = acos_safe(real());
00484 value_type s = std::sin(a);
00485
00486 if (s > tolerance) {
00487 return temporary_type(value_type(0), imaginary() * (a / s));
00488 } else {
00489 return temporary_type(value_type(0), imaginary());
00490 }
00491 }
00492
00497 temporary_type exp(
00498 value_type tolerance = epsilon<value_type>::placeholder()) const
00499 {
00500 imaginary_type v = imaginary();
00501 value_type a = cml::length(v);
00502
00503 if (a > tolerance) {
00504 return temporary_type(std::cos(a), v * (std::sin(a) / a));
00505 } else {
00506 return temporary_type(std::cos(a), v);
00507 }
00508 }
00509
00511 value_type operator[](size_t i) const {
00512
00513
00514
00515
00516 return OpT().apply(
00517 left_traits().get(m_left,i),
00518 right_traits().get(m_right,i));
00519 }
00520
00521
00522 public:
00523
00529 size_t size() const {
00530
00531
00532
00533 CheckedSize(m_left,m_right,size_tag());
00534
00535
00536 return 4;
00537 }
00538
00540 left_reference left_expression() const { return m_left; }
00541
00543 right_reference right_expression() const { return m_right; }
00544
00545
00546 public:
00547
00549 explicit BinaryQuaternionOp(left_reference left, right_reference right)
00550 : m_left(left), m_right(right) {}
00551
00553 BinaryQuaternionOp(const expr_type& e)
00554 : m_left(e.m_left), m_right(e.m_right) {}
00555
00556
00557 protected:
00558
00559 left_reference m_left;
00560 right_reference m_right;
00561
00562
00563 private:
00564
00565
00566 typename checked_size::check_type _dummy;
00567
00568
00569 private:
00570
00571
00572 expr_type& operator=(const expr_type&);
00573 };
00574
00576 template<class LeftT, class RightT, class OpT>
00577 struct ExprTraits< BinaryQuaternionOp<LeftT,RightT,OpT> >
00578 {
00579 typedef BinaryQuaternionOp<LeftT,RightT,OpT> expr_type;
00580 typedef LeftT left_type;
00581 typedef RightT right_type;
00582
00583 typedef typename expr_type::value_type value_type;
00584 typedef typename expr_type::expr_const_reference const_reference;
00585 typedef typename expr_type::result_tag result_tag;
00586 typedef typename expr_type::size_tag size_tag;
00587 typedef typename expr_type::result_type result_type;
00588 typedef typename expr_type::imaginary_type imaginary_type;
00589 typedef typename expr_type::assignable_tag not_assignable_tag;
00590 typedef expr_node_tag node_tag;
00591
00592 value_type get(const expr_type& v, size_t i) const { return v[i]; }
00593 size_t size(const expr_type& e) const { return e.size(); }
00594 };
00595
00596
00597
00598 template<class LeftTraits, class RightTraits>
00599 struct QuaternionExpressions
00600 {
00601
00602 typedef typename LeftTraits::result_tag left_result;
00603 typedef typename RightTraits::result_tag right_result;
00604 enum { is_true = (same_type<left_result,et::quaternion_result_tag>::is_true
00605 && same_type<right_result,et::quaternion_result_tag>::is_true) };
00606 };
00607
00608 }
00609 }
00610
00611 #endif
00612
00613
00614