quaternion_comparison.h

Go to the documentation of this file.
00001 /* -*- C++ -*- ------------------------------------------------------------
00002  
00003 Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
00004 
00005 The Configurable Math Library (CML) is distributed under the terms of the
00006 Boost Software License, v1.0 (see cml/LICENSE for details).
00007 
00008  *-----------------------------------------------------------------------*/
00013 #ifndef quaternion_comparison_h
00014 #define quaternion_comparison_h
00015 
00016 #include <cml/core/cml_assert.h>
00017 #include <cml/et/scalar_ops.h>
00018 
00019 /* This is used below to create a more meaningful compile-time error when
00020  * quaternion_comparison is not provided with quaternion or QuaternionExpr arguments:
00021  */
00022 struct quaternion_comparison_expects_quaternion_args_error;
00023 
00024 #define CML_QUAT_QUAT_ORDER(_order_, _op_, _OpT_)                       \
00025 template<                                                               \
00026     typename E1, class AT1, typename E2, class AT2, class O, class C >  \
00027 inline bool                                                             \
00028 _op_ (                                                                  \
00029         const quaternion<E1,AT1,O,C>& left,                             \
00030         const quaternion<E2,AT2,O,C>& right)                            \
00031 {                                                                       \
00032     return detail::quaternion_##_order_ (left, right, _OpT_ <E1,E2>()); \
00033 }
00034 
00035 #define CML_QUAT_QUATXPR_ORDER(_order_, _op_, _OpT_)                    \
00036 template<typename E, class AT, class O, class C, class XprT>            \
00037 inline bool                                                             \
00038 _op_ (                                                                  \
00039         const quaternion<E,AT,O,C>& left,                               \
00040         QUATXPR_ARG_TYPE right)                                         \
00041 {                                                                       \
00042     return detail::quaternion_##_order_ (left, right,                   \
00043             _OpT_ <E, typename XprT::value_type>());                    \
00044 }
00045 
00046 #define CML_QUATXPR_QUAT_ORDER(_order_, _op_, _OpT_)                    \
00047 template<class XprT, typename E, class AT, class O, class C >           \
00048 inline bool                                                             \
00049 _op_ (                                                                  \
00050         QUATXPR_ARG_TYPE left,                                          \
00051         const quaternion<E,AT,O,C>& right)                              \
00052 {                                                                       \
00053     return detail::quaternion_##_order_ (left, right,                   \
00054             _OpT_ <typename XprT::value_type, E>());                    \
00055 }
00056 
00057 #define CML_QUATXPR_QUATXPR_ORDER(_order_, _op_, _OpT_)                 \
00058 template<class XprT1, class XprT2>                                      \
00059 inline bool                                                             \
00060 _op_ (                                                                  \
00061         QUATXPR_ARG_TYPE_N(1) left,                                     \
00062         QUATXPR_ARG_TYPE_N(2) right)                                    \
00063 {                                                                       \
00064     return detail::quaternion_##_order_ (left, right,                   \
00065             _OpT_ <                                                     \
00066                 typename XprT1::value_type,                             \
00067                 typename XprT2::value_type>());                         \
00068 }
00069 
00070 
00071 namespace cml {
00072 namespace detail {
00073 
00080 template<typename LeftT, typename RightT, typename OpT>
00081 inline bool
00082 quaternion_weak_order(const LeftT& left, const RightT& right, OpT)
00083 {
00084     /* Shorthand: */
00085     typedef et::ExprTraits<LeftT> left_traits;
00086     typedef et::ExprTraits<RightT> right_traits;
00087 
00088     /* quaternion_comparison() requires quaternion expressions: */
00089     CML_STATIC_REQUIRE_M(
00090             (et::QuaternionExpressions<LeftT,RightT>::is_true),
00091             quaternion_comparison_expects_quaternion_args_error);
00092     /* Note: parens are required here so that the preprocessor ignores the
00093      * commas:
00094      */
00095 
00096     typedef typename et::QuaternionPromote<
00097         typename left_traits::result_type,
00098         typename right_traits::result_type
00099     >::type result_type;
00100 
00101     for(ssize_t i = 0; i < result_type::array_size; ++ i) {
00102 
00103         if(OpT().apply(
00104                     left_traits().get(left,i),
00105                     right_traits().get(right,i)
00106                     ))
00107         {
00108             /* If weak order (a < b) is satisfied, return true: */
00109             return true;
00110         } else if(OpT().apply(
00111                     right_traits().get(right,i),
00112                     left_traits().get(left,i)
00113                     ))
00114         {
00115             /* If !(b < a), then return false: */
00116             return false;
00117         } else {
00118 
00119             /* Have !(a < b) && !(b < a) <=> (a >= b && b >= a) <=> (a == b).
00120              * so need to test next element:
00121              */
00122             continue;
00123         }
00124     }
00125     /* XXX Can this be unrolled in any reasonable way? */
00126 
00127     /* If we get here, then left == right: */
00128     return false;
00129 }
00130 
00136 template<typename LeftT, typename RightT, typename OpT>
00137 inline bool
00138 quaternion_total_order(const LeftT& left, const RightT& right, OpT)
00139 {
00140     /* Shorthand: */
00141     typedef et::ExprTraits<LeftT> left_traits;
00142     typedef et::ExprTraits<RightT> right_traits;
00143 
00144     /* quaternion_comparison() requires quaternion expressions: */
00145     CML_STATIC_REQUIRE_M(
00146             (et::QuaternionExpressions<LeftT,RightT>::is_true),
00147             quaternion_comparison_expects_quaternion_args_error);
00148     /* Note: parens are required here so that the preprocessor ignores the
00149      * commas:
00150      */
00151 
00152     typedef typename et::QuaternionPromote<
00153         typename left_traits::result_type,
00154         typename right_traits::result_type
00155     >::type result_type;
00156 
00157     for(ssize_t i = 0; i < result_type::array_size; ++ i) {
00158 
00159         /* Test total order: */
00160         if(OpT().apply(
00161                     left_traits().get(left,i),
00162                     right_traits().get(right,i)
00163             ))
00164         {
00165             /* Automatically true if weak order (a <= b) && !(b <= a) <=>
00166              * (a <= b) && (b > a) <=> (a < b) is satisfied:
00167              */
00168             if(!OpT().apply(
00169                         right_traits().get(right,i),
00170                         left_traits().get(left,i)
00171                         ))
00172                 return true;
00173 
00174             /* Otherwise, have equality (a <= b) && (b <= a), so continue
00175              * to next element:
00176              */
00177             else
00178                 continue;
00179 
00180         } else {
00181             
00182             /* Total order isn't satisfied (a > b), so return false: */
00183             return false;
00184         }
00185     }
00186     /* XXX Can this be unrolled in any reasonable way? */
00187 
00188     /* Total (==) or weak (<) order was satisfied, so return true: */
00189     return true;
00190 }
00191 
00192 }
00193 
00194 /* XXX There is a better way to handle these with operator traits... */
00195 
00196 CML_QUAT_QUAT_ORDER(       total_order, operator==, et::OpEqual)
00197 CML_QUATXPR_QUAT_ORDER(    total_order, operator==, et::OpEqual)
00198 CML_QUAT_QUATXPR_ORDER(    total_order, operator==, et::OpEqual)
00199 CML_QUATXPR_QUATXPR_ORDER( total_order, operator==, et::OpEqual)
00200 
00201 CML_QUAT_QUAT_ORDER(       weak_order, operator!=, et::OpNotEqual)
00202 CML_QUATXPR_QUAT_ORDER(    weak_order, operator!=, et::OpNotEqual)
00203 CML_QUAT_QUATXPR_ORDER(    weak_order, operator!=, et::OpNotEqual)
00204 CML_QUATXPR_QUATXPR_ORDER( weak_order, operator!=, et::OpNotEqual)
00205 
00206 CML_QUAT_QUAT_ORDER(       weak_order, operator<, et::OpLess)
00207 CML_QUATXPR_QUAT_ORDER(    weak_order, operator<, et::OpLess)
00208 CML_QUAT_QUATXPR_ORDER(    weak_order, operator<, et::OpLess)
00209 CML_QUATXPR_QUATXPR_ORDER( weak_order, operator<, et::OpLess)
00210 
00211 } // namespace cml
00212 
00213 #endif
00214 
00215 // -------------------------------------------------------------------------
00216 // vim:ft=cpp

Generated on Sat Jul 18 19:35:28 2009 for CML 1.0 by  doxygen 1.5.9