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