]> Dogcows Code - chaz/yoink/blob - src/moof/cml/vector/vector_comparison.h
fixes for newer versions of g++
[chaz/yoink] / src / moof / cml / vector / vector_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 vector_comparison_h
14 #define vector_comparison_h
15
16 #include <cml/core/cml_assert.h>
17 #include <cml/et/size_checking.h>
18 #include <cml/et/scalar_ops.h>
19
20 /* This is used below to create a more meaningful compile-time error when
21 * vector_comparison is not provided with vector or VectorExpr arguments:
22 */
23 struct vector_comparison_expects_vector_args_error;
24
25 #define CML_VEC_VEC_ORDER(_order_, _op_, _OpT_) \
26 template<typename E1, class AT1, typename E2, class AT2> \
27 inline bool \
28 _op_ ( \
29 const vector<E1,AT1>& left, \
30 const vector<E2,AT2>& right) \
31 { \
32 return detail::vector_##_order_ (left, right, _OpT_ <E1,E2>()); \
33 }
34
35 #define CML_VEC_VECXPR_ORDER(_order_, _op_, _OpT_) \
36 template<typename E, class AT, class XprT> \
37 inline bool \
38 _op_ ( \
39 const vector<E,AT>& left, \
40 VECXPR_ARG_TYPE right) \
41 { \
42 return detail::vector_##_order_ (left, right, \
43 _OpT_ <E, typename XprT::value_type>()); \
44 }
45
46 #define CML_VECXPR_VEC_ORDER(_order_, _op_, _OpT_) \
47 template<class XprT, typename E, class AT> \
48 inline bool \
49 _op_ ( \
50 VECXPR_ARG_TYPE left, \
51 const vector<E,AT>& right) \
52 { \
53 return detail::vector_##_order_ (left, right, \
54 _OpT_ <typename XprT::value_type, E>()); \
55 }
56
57 #define CML_VECXPR_VECXPR_ORDER(_order_, _op_, _OpT_) \
58 template<class XprT1, class XprT2> \
59 inline bool \
60 _op_ ( \
61 VECXPR_ARG_TYPE_N(1) left, \
62 VECXPR_ARG_TYPE_N(2) right) \
63 { \
64 return detail::vector_##_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 /** Vector strict weak ordering relationship.
75 *
76 * OpT must implement a strict weak order on the vector 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 vector_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 /* vector_comparison() requires vector expressions: */
89 CML_STATIC_REQUIRE_M(
90 (et::VectorExpressions<LeftT,RightT>::is_true),
91 vector_comparison_expects_vector_args_error);
92 /* Note: parens are required here so that the preprocessor ignores the
93 * commas:
94 */
95
96 typedef typename et::VectorPromote<
97 typename left_traits::result_type,
98 typename right_traits::result_type
99 >::type result_type;
100 typedef typename result_type::size_tag size_tag;
101
102 /* Verify expression size: */
103 ssize_t N = (ssize_t) et::CheckedSize(left,right,size_tag());
104 for(ssize_t i = 0; i < N; ++ i) {
105 if(OpT().apply(
106 left_traits().get(left,i),
107 right_traits().get(right,i)
108 ))
109 {
110 /* If weak order (a < b) is satisfied, return true: */
111 return true;
112 } else if(OpT().apply(
113 right_traits().get(right,i),
114 left_traits().get(left,i)
115 ))
116 {
117 /* If !(b < a), then return false: */
118 return false;
119 } else {
120
121 /* Have !(a < b) && !(b < a) <=> (a >= b && b >= a) <=> (a == b).
122 * so need to test next element:
123 */
124 continue;
125 }
126 }
127 /* XXX Can this be unrolled in any reasonable way? */
128
129 /* If we get here, then left == right: */
130 return false;
131 }
132
133 /** Vector total order relationship.
134 *
135 * OpT must implement a total order on the vector element type. operator<=
136 * and operator>= on integer and floating-point types are examples.
137 */
138 template<typename LeftT, typename RightT, typename OpT>
139 inline bool
140 vector_total_order(const LeftT& left, const RightT& right, OpT)
141 {
142 /* Shorthand: */
143 typedef et::ExprTraits<LeftT> left_traits;
144 typedef et::ExprTraits<RightT> right_traits;
145
146 /* vector_comparison() requires vector expressions: */
147 CML_STATIC_REQUIRE_M(
148 (et::VectorExpressions<LeftT,RightT>::is_true),
149 vector_comparison_expects_vector_args_error);
150 /* Note: parens are required here so that the preprocessor ignores the
151 * commas:
152 */
153
154 typedef typename et::VectorPromote<
155 typename left_traits::result_type,
156 typename right_traits::result_type
157 >::type result_type;
158 typedef typename result_type::size_tag size_tag;
159
160 /* Verify expression size: */
161 ssize_t N = (ssize_t) et::CheckedSize(left,right,size_tag());
162 for(ssize_t i = 0; i < N; ++ i) {
163
164 /* Test total order: */
165 if(OpT().apply(
166 left_traits().get(left,i),
167 right_traits().get(right,i)
168 ))
169 {
170 /* Automatically true if weak order (a <= b) && !(b <= a) <=>
171 * (a <= b) && (b > a) <=> (a < b) is satisfied:
172 */
173 if(!OpT().apply(
174 right_traits().get(right,i),
175 left_traits().get(left,i)
176 ))
177 return true;
178
179 /* Otherwise, have equality (a <= b) && (b <= a), so continue
180 * to next element:
181 */
182 else
183 continue;
184
185 } else {
186
187 /* Total order isn't satisfied (a > b), so return false: */
188 return false;
189 }
190 }
191 /* XXX Can this be unrolled in any reasonable way? */
192
193 /* Total (==) or weak (<) order was satisfied, so return true: */
194 return true;
195 }
196
197 }
198
199 /* XXX There is a better way to handle these with operator traits... */
200
201 CML_VEC_VEC_ORDER( total_order, operator==, et::OpEqual)
202 CML_VECXPR_VEC_ORDER( total_order, operator==, et::OpEqual)
203 CML_VEC_VECXPR_ORDER( total_order, operator==, et::OpEqual)
204 CML_VECXPR_VECXPR_ORDER( total_order, operator==, et::OpEqual)
205
206 CML_VEC_VEC_ORDER( weak_order, operator!=, et::OpNotEqual)
207 CML_VECXPR_VEC_ORDER( weak_order, operator!=, et::OpNotEqual)
208 CML_VEC_VECXPR_ORDER( weak_order, operator!=, et::OpNotEqual)
209 CML_VECXPR_VECXPR_ORDER( weak_order, operator!=, et::OpNotEqual)
210
211 CML_VEC_VEC_ORDER( weak_order, operator<, et::OpLess)
212 CML_VECXPR_VEC_ORDER( weak_order, operator<, et::OpLess)
213 CML_VEC_VECXPR_ORDER( weak_order, operator<, et::OpLess)
214 CML_VECXPR_VECXPR_ORDER( weak_order, operator<, et::OpLess)
215
216 CML_VEC_VEC_ORDER( weak_order, operator>, et::OpGreater)
217 CML_VECXPR_VEC_ORDER( weak_order, operator>, et::OpGreater)
218 CML_VEC_VECXPR_ORDER( weak_order, operator>, et::OpGreater)
219 CML_VECXPR_VECXPR_ORDER( weak_order, operator>, et::OpGreater)
220
221 CML_VEC_VEC_ORDER( total_order, operator<=, et::OpLessEqual)
222 CML_VECXPR_VEC_ORDER( total_order, operator<=, et::OpLessEqual)
223 CML_VEC_VECXPR_ORDER( total_order, operator<=, et::OpLessEqual)
224 CML_VECXPR_VECXPR_ORDER( total_order, operator<=, et::OpLessEqual)
225
226 CML_VEC_VEC_ORDER( total_order, operator>=, et::OpGreaterEqual)
227 CML_VECXPR_VEC_ORDER( total_order, operator>=, et::OpGreaterEqual)
228 CML_VEC_VECXPR_ORDER( total_order, operator>=, et::OpGreaterEqual)
229 CML_VECXPR_VECXPR_ORDER( total_order, operator>=, et::OpGreaterEqual)
230
231 } // namespace cml
232
233 #endif
234
235 // -------------------------------------------------------------------------
236 // vim:ft=cpp
This page took 0.039519 seconds and 4 git commands to generate.