comparison DEPENDENCIES/generic/include/boost/multiprecision/detail/number_compare.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
comparison
equal deleted inserted replaced
15:663ca0da4350 16:2665513ce2d3
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright 2012 John Maddock. Distributed under the Boost
3 // Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6 #ifndef BOOST_MP_COMPARE_HPP
7 #define BOOST_MP_COMPARE_HPP
8
9 //
10 // Comparison operators for number.
11 //
12
13 namespace boost{ namespace multiprecision{
14
15 namespace default_ops{
16
17 template <class B>
18 inline bool eval_eq(const B& a, const B& b)
19 {
20 return a.compare(b) == 0;
21 }
22 //
23 // For the default version which compares to some arbitrary type convertible to
24 // our number type, we don't know what value the ExpressionTemplates parameter to
25 // class number should be. We generally prefer ExpressionTemplates to be enabled
26 // in case type A is itself an expression template, but we need to test both options
27 // with is_convertible in case A has an implicit conversion operator to number<B,something>.
28 // This is the case with many uBlas types for example.
29 //
30 template <class B, class A>
31 inline bool eval_eq(const B& a, const A& b)
32 {
33 typedef typename mpl::if_c<
34 is_convertible<A, number<B, et_on> >::value,
35 number<B, et_on>,
36 number<B, et_off> >::type mp_type;
37 mp_type t(b);
38 return eval_eq(a, t.backend());
39 }
40
41 template <class B>
42 inline bool eval_lt(const B& a, const B& b)
43 {
44 return a.compare(b) < 0;
45 }
46 template <class B, class A>
47 inline bool eval_lt(const B& a, const A& b)
48 {
49 typedef typename mpl::if_c<
50 is_convertible<A, number<B, et_on> >::value,
51 number<B, et_on>,
52 number<B, et_off> >::type mp_type;
53 mp_type t(b);
54 return eval_lt(a, t.backend());
55 }
56
57 template <class B>
58 inline bool eval_gt(const B& a, const B& b)
59 {
60 return a.compare(b) > 0;
61 }
62 template <class B, class A>
63 inline bool eval_gt(const B& a, const A& b)
64 {
65 typedef typename mpl::if_c<
66 is_convertible<A, number<B, et_on> >::value,
67 number<B, et_on>,
68 number<B, et_off> >::type mp_type;
69 mp_type t(b);
70 return eval_gt(a, t.backend());
71 }
72
73 } // namespace default_ops
74
75 namespace detail{
76
77 template <class Num, class Val>
78 struct is_valid_mixed_compare : public mpl::false_ {};
79
80 template <class B, expression_template_option ET, class Val>
81 struct is_valid_mixed_compare<number<B, ET>, Val> : public is_convertible<Val, number<B, ET> > {};
82
83 template <class B, expression_template_option ET>
84 struct is_valid_mixed_compare<number<B, ET>, number<B, ET> > : public mpl::false_ {};
85
86 template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
87 struct is_valid_mixed_compare<number<B, ET>, expression<tag, Arg1, Arg2, Arg3, Arg4> >
88 : public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value> {};
89
90 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
91 struct is_valid_mixed_compare<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
92 : public mpl::bool_<is_convertible<expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::value> {};
93
94 }
95
96 template <class Backend, expression_template_option ExpressionTemplates>
97 inline bool operator == (const number<Backend, ExpressionTemplates>& a, const number<Backend, ExpressionTemplates>& b)
98 {
99 using default_ops::eval_eq;
100 return eval_eq(a.backend(), b.backend());
101 }
102 template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
103 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
104 operator == (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
105 {
106 using default_ops::eval_eq;
107 return eval_eq(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
108 }
109 template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
110 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
111 operator == (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
112 {
113 using default_ops::eval_eq;
114 return eval_eq(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
115 }
116 template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
117 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
118 operator == (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
119 {
120 typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
121 using default_ops::eval_eq;
122 result_type t(b);
123 return eval_eq(t.backend(), result_type::canonical_value(a));
124 }
125 template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
126 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
127 operator == (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
128 {
129 typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
130 using default_ops::eval_eq;
131 result_type t(a);
132 return eval_eq(t.backend(), result_type::canonical_value(b));
133 }
134 template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
135 inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
136 operator == (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
137 {
138 using default_ops::eval_eq;
139 typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
140 typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
141 return eval_eq(t.backend(), t2.backend());
142 }
143
144 template <class Backend, expression_template_option ExpressionTemplates>
145 inline bool operator != (const number<Backend, ExpressionTemplates>& a, const number<Backend, ExpressionTemplates>& b)
146 {
147 using default_ops::eval_eq;
148 return !eval_eq(a.backend(), b.backend());
149 }
150 template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
151 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
152 operator != (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
153 {
154 using default_ops::eval_eq;
155 return !eval_eq(a.backend(), number<Backend, et_on>::canonical_value(b));
156 }
157 template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
158 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
159 operator != (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
160 {
161 using default_ops::eval_eq;
162 return !eval_eq(b.backend(), number<Backend, et_on>::canonical_value(a));
163 }
164 template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
165 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
166 operator != (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
167 {
168 typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
169 using default_ops::eval_eq;
170 result_type t(b);
171 return !eval_eq(t.backend(), result_type::canonical_value(a));
172 }
173 template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
174 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
175 operator != (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
176 {
177 typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
178 using default_ops::eval_eq;
179 result_type t(a);
180 return !eval_eq(t.backend(), result_type::canonical_value(b));
181 }
182 template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
183 inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
184 operator != (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
185 {
186 using default_ops::eval_eq;
187 typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
188 typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
189 return !eval_eq(t.backend(), t2.backend());
190 }
191
192 template <class Backend, expression_template_option ExpressionTemplates>
193 inline bool operator < (const number<Backend, ExpressionTemplates>& a, const number<Backend, ExpressionTemplates>& b)
194 {
195 using default_ops::eval_lt;
196 return eval_lt(a.backend(), b.backend());
197 }
198 template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
199 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
200 operator < (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
201 {
202 using default_ops::eval_lt;
203 return eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
204 }
205 template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
206 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
207 operator < (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
208 {
209 using default_ops::eval_gt;
210 return eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
211 }
212 template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
213 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
214 operator < (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
215 {
216 typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
217 using default_ops::eval_gt;
218 result_type t(b);
219 return eval_gt(t.backend(), result_type::canonical_value(a));
220 }
221 template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
222 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
223 operator < (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
224 {
225 typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
226 using default_ops::eval_lt;
227 result_type t(a);
228 return eval_lt(t.backend(), result_type::canonical_value(b));
229 }
230 template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
231 inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
232 operator < (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
233 {
234 using default_ops::eval_lt;
235 typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
236 typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
237 return eval_lt(t.backend(), t2.backend());
238 }
239
240 template <class Backend, expression_template_option ExpressionTemplates>
241 inline bool operator > (const number<Backend, ExpressionTemplates>& a, const number<Backend, ExpressionTemplates>& b)
242 {
243 using default_ops::eval_gt;
244 return eval_gt(a.backend(), b.backend());
245 }
246 template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
247 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
248 operator > (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
249 {
250 using default_ops::eval_gt;
251 return eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
252 }
253 template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
254 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
255 operator > (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
256 {
257 using default_ops::eval_lt;
258 return eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
259 }
260 template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
261 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
262 operator > (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
263 {
264 typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
265 using default_ops::eval_lt;
266 result_type t(b);
267 return eval_lt(t.backend(), result_type::canonical_value(a));
268 }
269 template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
270 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
271 operator > (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
272 {
273 typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
274 using default_ops::eval_gt;
275 result_type t(a);
276 return eval_gt(t.backend(), result_type::canonical_value(b));
277 }
278 template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
279 inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
280 operator > (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
281 {
282 using default_ops::eval_gt;
283 typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
284 typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
285 return eval_gt(t.backend(), t2.backend());
286 }
287
288 template <class Backend, expression_template_option ExpressionTemplates>
289 inline bool operator <= (const number<Backend, ExpressionTemplates>& a, const number<Backend, ExpressionTemplates>& b)
290 {
291 using default_ops::eval_gt;
292 return !eval_gt(a.backend(), b.backend());
293 }
294 template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
295 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
296 operator <= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
297 {
298 using default_ops::eval_gt;
299 return !eval_gt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
300 }
301 template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
302 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
303 operator <= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
304 {
305 using default_ops::eval_lt;
306 return !eval_lt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
307 }
308 template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
309 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
310 operator <= (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
311 {
312 typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
313 using default_ops::eval_lt;
314 result_type t(b);
315 return !eval_lt(t.backend(), result_type::canonical_value(a));
316 }
317 template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
318 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
319 operator <= (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
320 {
321 typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
322 using default_ops::eval_gt;
323 result_type t(a);
324 return !eval_gt(t.backend(), result_type::canonical_value(b));
325 }
326 template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
327 inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
328 operator <= (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
329 {
330 using default_ops::eval_gt;
331 typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
332 typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
333 return !eval_gt(t.backend(), t2.backend());
334 }
335
336 template <class Backend, expression_template_option ExpressionTemplates>
337 inline bool operator >= (const number<Backend, ExpressionTemplates>& a, const number<Backend, ExpressionTemplates>& b)
338 {
339 using default_ops::eval_lt;
340 return !eval_lt(a.backend(), b.backend());
341 }
342 template <class Backend, expression_template_option ExpressionTemplates, class Arithmetic>
343 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
344 operator >= (const number<Backend, ExpressionTemplates>& a, const Arithmetic& b)
345 {
346 using default_ops::eval_lt;
347 return !eval_lt(a.backend(), number<Backend, ExpressionTemplates>::canonical_value(b));
348 }
349 template <class Arithmetic, class Backend, expression_template_option ExpressionTemplates>
350 inline typename enable_if_c<detail::is_valid_mixed_compare<number<Backend, ExpressionTemplates>, Arithmetic>::value, bool>::type
351 operator >= (const Arithmetic& a, const number<Backend, ExpressionTemplates>& b)
352 {
353 using default_ops::eval_gt;
354 return !eval_gt(b.backend(), number<Backend, ExpressionTemplates>::canonical_value(a));
355 }
356 template <class Arithmetic, class Tag, class A1, class A2, class A3, class A4>
357 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
358 operator >= (const Arithmetic& a, const detail::expression<Tag, A1, A2, A3, A4>& b)
359 {
360 typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
361 using default_ops::eval_gt;
362 result_type t(b);
363 return !eval_gt(t.backend(), result_type::canonical_value(a));
364 }
365 template <class Tag, class A1, class A2, class A3, class A4, class Arithmetic>
366 inline typename enable_if_c<detail::is_valid_mixed_compare<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, Arithmetic>::value, bool>::type
367 operator >= (const detail::expression<Tag, A1, A2, A3, A4>& a, const Arithmetic& b)
368 {
369 typedef typename detail::expression<Tag, A1, A2, A3, A4>::result_type result_type;
370 using default_ops::eval_lt;
371 result_type t(a);
372 return !eval_lt(t.backend(), result_type::canonical_value(b));
373 }
374 template <class Tag, class A1, class A2, class A3, class A4, class Tagb, class A1b, class A2b, class A3b, class A4b>
375 inline typename enable_if<is_same<typename detail::expression<Tag, A1, A2, A3, A4>::result_type, typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type>, bool>::type
376 operator >= (const detail::expression<Tag, A1, A2, A3, A4>& a, const detail::expression<Tagb, A1b, A2b, A3b, A4b>& b)
377 {
378 using default_ops::eval_lt;
379 typename detail::expression<Tag, A1, A2, A3, A4>::result_type t(a);
380 typename detail::expression<Tagb, A1b, A2b, A3b, A4b>::result_type t2(b);
381 return !eval_lt(t.backend(), t2.backend());
382 }
383
384
385 }} // namespaces
386
387 #endif // BOOST_MP_COMPARE_HPP
388