2 * test with symbolic operations if the addition algorithm is correct
4 * Copyright 2002-2003 Guillaume Melquiond
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)
11 #include <boost/numeric/interval/interval.hpp>
12 #include <boost/numeric/interval/arith.hpp>
13 #include <boost/numeric/interval/rounding.hpp>
14 #include <boost/numeric/interval/rounded_arith.hpp>
15 #include <boost/numeric/interval/utility.hpp>
16 #include <boost/numeric/interval/policies.hpp>
17 #include <boost/test/minimal.hpp>
20 typedef enum { EXPR_VAR
, EXPR_NEG
, EXPR_UP
, EXPR_DOWN
, EXPR_ADD
, EXPR_SUB
} e_type
;
25 expr
* operator->() { return ptr
; }
26 pexpr(expr
*p
= NULL
): ptr(p
) { }
43 pexpr
operator+(pexpr
, pexpr
);
44 pexpr
operator-(pexpr
, pexpr
);
45 pexpr
operator-(pexpr
);
47 pexpr
operator+(pexpr a
, pexpr b
) {
48 if (a
->type
== EXPR_NEG
) return b
- a
->e
;
49 if (b
->type
== EXPR_NEG
) return a
- b
->e
;
50 if (a
->type
== EXPR_VAR
&& b
->type
== EXPR_VAR
&& a
->var
> b
->var
) return b
+ a
;
58 pexpr
operator-(pexpr a
, pexpr b
) {
59 if (b
->type
== EXPR_NEG
) return a
+ b
->e
;
81 pexpr
operator-(pexpr a
) {
82 if (a
->type
== EXPR_NEG
) return a
->e
;
83 if (a
->type
== EXPR_UP
) return down(-a
->e
);
84 if (a
->type
== EXPR_DOWN
) return up(-a
->e
);
85 if (a
->type
== EXPR_SUB
) return a
->e2
- a
->e1
;
86 if (a
->type
== EXPR_ADD
) return -a
->e1
- a
->e2
;
93 bool operator==(pexpr a
, pexpr b
) {
94 if (a
->type
!= b
->type
) return false;
95 if (a
->type
== EXPR_VAR
) return a
->var
== b
->var
;
96 if (a
->type
== EXPR_DOWN
|| a
->type
== EXPR_UP
|| a
->type
== EXPR_NEG
)
98 return a
->e1
== b
->e1
&& a
->e2
== b
->e2
;
101 bool operator<=(pexpr
, pexpr
) { return true; }
105 namespace interval_lib
{
108 struct rounding_control
<pexpr
> {
109 typedef enum { RND_U
, RND_M
, RND_D
} rounding_mode
;
110 static rounding_mode mode
;
111 rounding_control() { mode
= RND_M
; }
112 void get_rounding_mode(rounding_mode
& m
) { m
= mode
; }
113 void set_rounding_mode(rounding_mode m
) { mode
= m
; }
114 void upward() { mode
= RND_U
; }
115 void downward() { mode
= RND_D
; }
116 pexpr
force_rounding(pexpr a
) {
118 case RND_U
: return up(a
);
119 case RND_D
: return down(a
);
120 default: throw "Unset rounding mode";
125 rounding_control
<pexpr
>::rounding_mode rounding_control
<pexpr
>::mode
= RND_M
;
127 } // namespace interval_lib
128 } // namespace numeric
134 return equal(-a
, I(-var(1), -var(0)));
139 I
a(var(0), var(1)), b(var(2), var(3));
140 return equal(a
+ b
, I(down(var(0) + var(2)), up(var(1) + var(3))));
146 return equal(a
+ var(2), I(down(var(0) + var(2)), up(var(1) + var(2))));
152 return equal(var(2) + a
, I(down(var(0) + var(2)), up(var(1) + var(2))));
157 I
a(var(0), var(1)), b(var(2), var(3));
158 return equal(a
- b
, I(down(var(0) - var(3)), up(var(1) - var(2))));
164 return equal(a
- var(2), I(down(var(0) - var(2)), up(var(1) - var(2))));
170 return equal(var(2) - a
, I(down(var(2) - var(1)), up(var(2) - var(0))));
175 I
a(var(0), var(1)), b(var(2), var(3));
176 return equal(a
+= b
, I(down(var(0) + var(2)), up(var(1) + var(3))));
182 return equal(a
+= var(2), I(down(var(0) + var(2)), up(var(1) + var(2))));
187 I
a(var(0), var(1)), b(var(2), var(3));
188 return equal(a
-= b
, I(down(var(0) - var(3)), up(var(1) - var(2))));
194 return equal(a
-= var(2), I(down(var(0) - var(2)), up(var(1) - var(2))));
199 static pexpr
pos_inf() { throw; }
200 static pexpr
neg_inf() { throw; }
201 static pexpr
nan() { throw; }
202 static bool is_nan(const pexpr
&) { return false; }
203 static pexpr
empty_lower() { throw; }
204 static pexpr
empty_upper() { throw; }
205 static bool is_empty(const pexpr
&, const pexpr
&) { return false; }
208 template<class Rounding
>
211 typedef boost::numeric::interval_lib::save_state
<Rounding
> my_rounding
;
212 typedef boost::numeric::interval_lib::policies
<my_rounding
, my_checking
> my_policies
;
214 typedef boost::numeric::interval
<pexpr
, my_policies
> type
;
217 int test_main(int, char *[]) {
218 typedef my_interval
<boost::numeric::interval_lib::rounded_arith_std
<pexpr
> >::type I1
;
219 typedef my_interval
<boost::numeric::interval_lib::rounded_arith_opp
<pexpr
> >::type I2
;
220 BOOST_CHECK((test_neg
<I1
>()));
221 BOOST_CHECK((test_neg
<I2
>()));
222 BOOST_CHECK((test_add
<I1
>()));
223 BOOST_CHECK((test_add
<I2
>()));
224 BOOST_CHECK((test_add1
<I1
>()));
225 BOOST_CHECK((test_add1
<I2
>()));
226 BOOST_CHECK((test_add2
<I1
>()));
227 BOOST_CHECK((test_add2
<I2
>()));
228 BOOST_CHECK((test_sub
<I1
>()));
229 BOOST_CHECK((test_sub
<I2
>()));
230 BOOST_CHECK((test_sub1
<I1
>()));
231 BOOST_CHECK((test_sub1
<I2
>()));
232 BOOST_CHECK((test_sub2
<I1
>()));
233 BOOST_CHECK((test_sub2
<I2
>()));
234 BOOST_CHECK((test_addeq
<I1
>()));
235 BOOST_CHECK((test_addeq
<I2
>()));
236 BOOST_CHECK((test_addeq1
<I1
>()));
237 BOOST_CHECK((test_addeq1
<I2
>()));
238 BOOST_CHECK((test_subeq
<I1
>()));
239 BOOST_CHECK((test_subeq
<I2
>()));
240 BOOST_CHECK((test_subeq1
<I1
>()));
241 BOOST_CHECK((test_subeq1
<I2
>()));