1 | /* Boost test/test_float.cpp |
---|
2 | * test arithmetic operations on a range of intervals |
---|
3 | * |
---|
4 | * Copyright 2003 Guillaume Melquiond |
---|
5 | * |
---|
6 | * Distributed under the Boost Software License, Version 1.0. |
---|
7 | * (See accompanying file LICENSE_1_0.txt or |
---|
8 | * copy at http://www.boost.org/LICENSE_1_0.txt) |
---|
9 | */ |
---|
10 | |
---|
11 | #include <boost/numeric/interval.hpp> |
---|
12 | #include <boost/test/test_tools.hpp> |
---|
13 | #include <boost/config.hpp> |
---|
14 | #include "bugs.hpp" |
---|
15 | |
---|
16 | /* All the following tests should be BOOST_CHECK; however, if a test fails, |
---|
17 | the probability is high that hundreds of other tests will fail, so it is |
---|
18 | replaced by BOOST_REQUIRE to avoid flooding the logs. */ |
---|
19 | |
---|
20 | template<class T, class F> |
---|
21 | void test_unary() { |
---|
22 | typedef typename F::I I; |
---|
23 | for(I a(-10., -9.91); a.lower() <= 10.; a += 0.3) { |
---|
24 | if (!F::validate(a)) continue; |
---|
25 | I rI = F::f_I(a); |
---|
26 | T rT1 = F::f_T(a.lower()), rT2 = F::f_T(a.upper()), |
---|
27 | rT3 = F::f_T(median(a)); |
---|
28 | BOOST_REQUIRE(in(rT1, rI)); |
---|
29 | BOOST_REQUIRE(in(rT2, rI)); |
---|
30 | BOOST_REQUIRE(in(rT3, rI)); |
---|
31 | } |
---|
32 | } |
---|
33 | |
---|
34 | template<class T, class F> |
---|
35 | void test_binary() { |
---|
36 | typedef typename F::I I; |
---|
37 | for(I a(-10., -9.91); a.lower() <= 10.; a += 0.3) { |
---|
38 | for(I b(-10., -9.91); b.lower() <= 10.; b += 0.3) { |
---|
39 | if (!F::validate(a, b)) continue; |
---|
40 | T al = a.lower(), au = a.upper(), bl = b.lower(), bu = b.upper(); |
---|
41 | I rII = F::f_II(a, b); |
---|
42 | I rIT1 = F::f_IT(a, bl), rIT2 = F::f_IT(a, bu); |
---|
43 | I rTI1 = F::f_TI(al, b), rTI2 = F::f_TI(au, b); |
---|
44 | I rTT1 = F::f_TT(al, bl), rTT2 = F::f_TT(al, bu); |
---|
45 | I rTT3 = F::f_TT(au, bl), rTT4 = F::f_TT(au, bu); |
---|
46 | BOOST_REQUIRE(subset(rTT1, rIT1)); |
---|
47 | BOOST_REQUIRE(subset(rTT3, rIT1)); |
---|
48 | BOOST_REQUIRE(subset(rTT2, rIT2)); |
---|
49 | BOOST_REQUIRE(subset(rTT4, rIT2)); |
---|
50 | BOOST_REQUIRE(subset(rTT1, rTI1)); |
---|
51 | BOOST_REQUIRE(subset(rTT2, rTI1)); |
---|
52 | BOOST_REQUIRE(subset(rTT3, rTI2)); |
---|
53 | BOOST_REQUIRE(subset(rTT4, rTI2)); |
---|
54 | BOOST_REQUIRE(subset(rIT1, rII)); |
---|
55 | BOOST_REQUIRE(subset(rIT2, rII)); |
---|
56 | BOOST_REQUIRE(subset(rTI1, rII)); |
---|
57 | BOOST_REQUIRE(subset(rTI2, rII)); |
---|
58 | } |
---|
59 | } |
---|
60 | } |
---|
61 | |
---|
62 | #define new_unary_bunch(name, op, val) \ |
---|
63 | template<class T> \ |
---|
64 | struct name { \ |
---|
65 | typedef boost::numeric::interval<T> I; \ |
---|
66 | static I f_I(const I& a) { return op(a); } \ |
---|
67 | static T f_T(const T& a) { return op(a); } \ |
---|
68 | static bool validate(const I& a) { return val; } \ |
---|
69 | } |
---|
70 | |
---|
71 | //#ifndef BOOST_NO_STDC_NAMESPACE |
---|
72 | using std::abs; |
---|
73 | using std::sqrt; |
---|
74 | //#endif |
---|
75 | |
---|
76 | new_unary_bunch(bunch_pos, +, true); |
---|
77 | new_unary_bunch(bunch_neg, -, true); |
---|
78 | new_unary_bunch(bunch_sqrt, sqrt, a.lower() >= 0.); |
---|
79 | new_unary_bunch(bunch_abs, abs, true); |
---|
80 | |
---|
81 | template<class T> |
---|
82 | void test_all_unaries() { |
---|
83 | BOOST_CHECKPOINT("pos"); test_unary<T, bunch_pos<T> >(); |
---|
84 | BOOST_CHECKPOINT("neg"); test_unary<T, bunch_neg<T> >(); |
---|
85 | BOOST_CHECKPOINT("sqrt"); test_unary<T, bunch_sqrt<T> >(); |
---|
86 | BOOST_CHECKPOINT("abs"); test_unary<T, bunch_abs<T> >(); |
---|
87 | } |
---|
88 | |
---|
89 | #define new_binary_bunch(name, op, val) \ |
---|
90 | template<class T> \ |
---|
91 | struct bunch_##name { \ |
---|
92 | typedef boost::numeric::interval<T> I; \ |
---|
93 | static I f_II(const I& a, const I& b) { return a op b; } \ |
---|
94 | static I f_IT(const I& a, const T& b) { return a op b; } \ |
---|
95 | static I f_TI(const T& a, const I& b) { return a op b; } \ |
---|
96 | static I f_TT(const T& a, const T& b) \ |
---|
97 | { return boost::numeric::interval_lib::name<I>(a,b); } \ |
---|
98 | static bool validate(const I& a, const I& b) { return val; } \ |
---|
99 | } |
---|
100 | |
---|
101 | new_binary_bunch(add, +, true); |
---|
102 | new_binary_bunch(sub, -, true); |
---|
103 | new_binary_bunch(mul, *, true); |
---|
104 | new_binary_bunch(div, /, !in_zero(b)); |
---|
105 | |
---|
106 | template<class T> |
---|
107 | void test_all_binaries() { |
---|
108 | BOOST_CHECKPOINT("add"); test_binary<T, bunch_add<T> >(); |
---|
109 | BOOST_CHECKPOINT("sub"); test_binary<T, bunch_sub<T> >(); |
---|
110 | BOOST_CHECKPOINT("mul"); test_binary<T, bunch_mul<T> >(); |
---|
111 | BOOST_CHECKPOINT("div"); test_binary<T, bunch_div<T> >(); |
---|
112 | } |
---|
113 | |
---|
114 | int test_main(int, char *[]) { |
---|
115 | BOOST_CHECKPOINT("float tests"); |
---|
116 | test_all_unaries<float> (); |
---|
117 | test_all_binaries<float> (); |
---|
118 | BOOST_CHECKPOINT("double tests"); |
---|
119 | test_all_unaries<double>(); |
---|
120 | test_all_binaries<double>(); |
---|
121 | //BOOST_CHECKPOINT("long double tests"); |
---|
122 | //test_all_unaries<long double>(); |
---|
123 | //test_all_binaries<long double>(); |
---|
124 | # ifdef __BORLANDC__ |
---|
125 | ::detail::ignore_warnings(); |
---|
126 | # endif |
---|
127 | return 0; |
---|
128 | } |
---|