]> Dogcows Code - chaz/yoink/blob - src/cml/quaternion/quaternion_comparison.h
now using cml for vectors and math stuff
[chaz/yoink] / src / cml / quaternion / quaternion_comparison.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_comparison_h
14 #define quaternion_comparison_h
15
16 #include <cml/core/cml_assert.h>
17 #include <cml/et/scalar_ops.h>
18
19 /* This is used below to create a more meaningful compile-time error when
20 * quaternion_comparison is not provided with quaternion or QuaternionExpr arguments:
21 */
22 struct quaternion_comparison_expects_quaternion_args_error;
23
24 #define CML_QUAT_QUAT_ORDER(_order_, _op_, _OpT_) \
25 template< \
26 typename E1, class AT1, typename E2, class AT2, class O, class C > \
27 inline bool \
28 _op_ ( \
29 const quaternion<E1,AT1,O,C>& left, \
30 const quaternion<E2,AT2,O,C>& right) \
31 { \
32 return detail::quaternion_##_order_ (left, right, _OpT_ <E1,E2>()); \
33 }
34
35 #define CML_QUAT_QUATXPR_ORDER(_order_, _op_, _OpT_) \
36 template<typename E, class AT, class O, class C, class XprT> \
37 inline bool \
38 _op_ ( \
39 const quaternion<E,AT,O,C>& left, \
40 QUATXPR_ARG_TYPE right) \
41 { \
42 return detail::quaternion_##_order_ (left, right, \
43 _OpT_ <E, typename XprT::value_type>()); \
44 }
45
46 #define CML_QUATXPR_QUAT_ORDER(_order_, _op_, _OpT_) \
47 template<class XprT, typename E, class AT, class O, class C > \
48 inline bool \
49 _op_ ( \
50 QUATXPR_ARG_TYPE left, \
51 const quaternion<E,AT,O,C>& right) \
52 { \
53 return detail::quaternion_##_order_ (left, right, \
54 _OpT_ <typename XprT::value_type, E>()); \
55 }
56
57 #define CML_QUATXPR_QUATXPR_ORDER(_order_, _op_, _OpT_) \
58 template<class XprT1, class XprT2> \
59 inline bool \
60 _op_ ( \
61 QUATXPR_ARG_TYPE_N(1) left, \
62 QUATXPR_ARG_TYPE_N(2) right) \
63 { \
64 return detail::quaternion_##_order_ (left, right, \
65 _OpT_ < \
66 typename XprT1::value_type, \
67 typename XprT2::value_type>()); \
68 }
69
70
71 namespace cml {
72 namespace detail {
73
74 /** Quaternion strict weak ordering relationship.
75 *
76 * OpT must implement a strict weak order on the quaternion element type.
77 * operator< and operator> on integer and floating-point types are
78 * examples.
79 */
80 template<typename LeftT, typename RightT, typename OpT>
81 inline bool
82 quaternion_weak_order(const LeftT& left, const RightT& right, OpT)
83 {
84 /* Shorthand: */
85 typedef et::ExprTraits<LeftT> left_traits;
86 typedef et::ExprTraits<RightT> right_traits;
87
88 /* quaternion_comparison() requires quaternion expressions: */
89 CML_STATIC_REQUIRE_M(
90 (et::QuaternionExpressions<LeftT,RightT>::is_true),
91 quaternion_comparison_expects_quaternion_args_error);
92 /* Note: parens are required here so that the preprocessor ignores the
93 * commas:
94 */
95
96 typedef typename et::QuaternionPromote<
97 typename left_traits::result_type,
98 typename right_traits::result_type
99 >::type result_type;
100
101 for(ssize_t i = 0; i < result_type::array_size; ++ i) {
102
103 if(OpT().apply(
104 left_traits().get(left,i),
105 right_traits().get(right,i)
106 ))
107 {
108 /* If weak order (a < b) is satisfied, return true: */
109 return true;
110 } else if(OpT().apply(
111 right_traits().get(right,i),
112 left_traits().get(left,i)
113 ))
114 {
115 /* If !(b < a), then return false: */
116 return false;
117 } else {
118
119 /* Have !(a < b) && !(b < a) <=> (a >= b && b >= a) <=> (a == b).
120 * so need to test next element:
121 */
122 continue;
123 }
124 }
125 /* XXX Can this be unrolled in any reasonable way? */
126
127 /* If we get here, then left == right: */
128 return false;
129 }
130
131 /** Quaternion total order relationship.
132 *
133 * OpT must implement a total order on the quaternion element type. operator<=
134 * and operator>= on integer and floating-point types are examples.
135 */
136 template<typename LeftT, typename RightT, typename OpT>
137 inline bool
138 quaternion_total_order(const LeftT& left, const RightT& right, OpT)
139 {
140 /* Shorthand: */
141 typedef et::ExprTraits<LeftT> left_traits;
142 typedef et::ExprTraits<RightT> right_traits;
143
144 /* quaternion_comparison() requires quaternion expressions: */
145 CML_STATIC_REQUIRE_M(
146 (et::QuaternionExpressions<LeftT,RightT>::is_true),
147 quaternion_comparison_expects_quaternion_args_error);
148 /* Note: parens are required here so that the preprocessor ignores the
149 * commas:
150 */
151
152 typedef typename et::QuaternionPromote<
153 typename left_traits::result_type,
154 typename right_traits::result_type
155 >::type result_type;
156
157 for(ssize_t i = 0; i < result_type::array_size; ++ i) {
158
159 /* Test total order: */
160 if(OpT().apply(
161 left_traits().get(left,i),
162 right_traits().get(right,i)
163 ))
164 {
165 /* Automatically true if weak order (a <= b) && !(b <= a) <=>
166 * (a <= b) && (b > a) <=> (a < b) is satisfied:
167 */
168 if(!OpT().apply(
169 right_traits().get(right,i),
170 left_traits().get(left,i)
171 ))
172 return true;
173
174 /* Otherwise, have equality (a <= b) && (b <= a), so continue
175 * to next element:
176 */
177 else
178 continue;
179
180 } else {
181
182 /* Total order isn't satisfied (a > b), so return false: */
183 return false;
184 }
185 }
186 /* XXX Can this be unrolled in any reasonable way? */
187
188 /* Total (==) or weak (<) order was satisfied, so return true: */
189 return true;
190 }
191
192 }
193
194 /* XXX There is a better way to handle these with operator traits... */
195
196 CML_QUAT_QUAT_ORDER( total_order, operator==, et::OpEqual)
197 CML_QUATXPR_QUAT_ORDER( total_order, operator==, et::OpEqual)
198 CML_QUAT_QUATXPR_ORDER( total_order, operator==, et::OpEqual)
199 CML_QUATXPR_QUATXPR_ORDER( total_order, operator==, et::OpEqual)
200
201 CML_QUAT_QUAT_ORDER( weak_order, operator!=, et::OpNotEqual)
202 CML_QUATXPR_QUAT_ORDER( weak_order, operator!=, et::OpNotEqual)
203 CML_QUAT_QUATXPR_ORDER( weak_order, operator!=, et::OpNotEqual)
204 CML_QUATXPR_QUATXPR_ORDER( weak_order, operator!=, et::OpNotEqual)
205
206 CML_QUAT_QUAT_ORDER( weak_order, operator<, et::OpLess)
207 CML_QUATXPR_QUAT_ORDER( weak_order, operator<, et::OpLess)
208 CML_QUAT_QUATXPR_ORDER( weak_order, operator<, et::OpLess)
209 CML_QUATXPR_QUATXPR_ORDER( weak_order, operator<, et::OpLess)
210
211 } // namespace cml
212
213 #endif
214
215 // -------------------------------------------------------------------------
216 // vim:ft=cpp
This page took 0.041053 seconds and 4 git commands to generate.