]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/numeric/interval/include/boost/numeric/interval/detail/division.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / numeric / interval / include / boost / numeric / interval / detail / division.hpp
1 /* Boost interval/detail/division.hpp file
2 *
3 * Copyright 2003 Guillaume Melquiond, Sylvain Pion
4 *
5 * Distributed under the Boost Software License, Version 1.0.
6 * (See accompanying file LICENSE_1_0.txt or
7 * copy at http://www.boost.org/LICENSE_1_0.txt)
8 */
9
10 #ifndef BOOST_NUMERIC_INTERVAL_DETAIL_DIVISION_HPP
11 #define BOOST_NUMERIC_INTERVAL_DETAIL_DIVISION_HPP
12
13 #include <boost/numeric/interval/detail/interval_prototype.hpp>
14 #include <boost/numeric/interval/detail/bugs.hpp>
15 #include <boost/numeric/interval/detail/test_input.hpp>
16 #include <boost/numeric/interval/rounded_arith.hpp>
17 #include <algorithm>
18
19 namespace boost {
20 namespace numeric {
21 namespace interval_lib {
22 namespace detail {
23
24 template<class T, class Policies> inline
25 interval<T, Policies> div_non_zero(const interval<T, Policies>& x,
26 const interval<T, Policies>& y)
27 {
28 // assert(!in_zero(y));
29 typename Policies::rounding rnd;
30 typedef interval<T, Policies> I;
31 const T& xl = x.lower();
32 const T& xu = x.upper();
33 const T& yl = y.lower();
34 const T& yu = y.upper();
35 if (::boost::numeric::interval_lib::user::is_neg(xu))
36 if (::boost::numeric::interval_lib::user::is_neg(yu))
37 return I(rnd.div_down(xu, yl), rnd.div_up(xl, yu), true);
38 else
39 return I(rnd.div_down(xl, yl), rnd.div_up(xu, yu), true);
40 else if (::boost::numeric::interval_lib::user::is_neg(xl))
41 if (::boost::numeric::interval_lib::user::is_neg(yu))
42 return I(rnd.div_down(xu, yu), rnd.div_up(xl, yu), true);
43 else
44 return I(rnd.div_down(xl, yl), rnd.div_up(xu, yl), true);
45 else
46 if (::boost::numeric::interval_lib::user::is_neg(yu))
47 return I(rnd.div_down(xu, yu), rnd.div_up(xl, yl), true);
48 else
49 return I(rnd.div_down(xl, yu), rnd.div_up(xu, yl), true);
50 }
51
52 template<class T, class Policies> inline
53 interval<T, Policies> div_non_zero(const T& x, const interval<T, Policies>& y)
54 {
55 // assert(!in_zero(y));
56 typename Policies::rounding rnd;
57 typedef interval<T, Policies> I;
58 const T& yl = y.lower();
59 const T& yu = y.upper();
60 if (::boost::numeric::interval_lib::user::is_neg(x))
61 return I(rnd.div_down(x, yl), rnd.div_up(x, yu), true);
62 else
63 return I(rnd.div_down(x, yu), rnd.div_up(x, yl), true);
64 }
65
66 template<class T, class Policies> inline
67 interval<T, Policies> div_positive(const interval<T, Policies>& x, const T& yu)
68 {
69 // assert(::boost::numeric::interval_lib::user::is_pos(yu));
70 if (::boost::numeric::interval_lib::user::is_zero(x.lower()) &&
71 ::boost::numeric::interval_lib::user::is_zero(x.upper()))
72 return x;
73 typename Policies::rounding rnd;
74 typedef interval<T, Policies> I;
75 const T& xl = x.lower();
76 const T& xu = x.upper();
77 typedef typename Policies::checking checking;
78 if (::boost::numeric::interval_lib::user::is_neg(xu))
79 return I(checking::neg_inf(), rnd.div_up(xu, yu), true);
80 else if (::boost::numeric::interval_lib::user::is_neg(xl))
81 return I(checking::neg_inf(), checking::pos_inf(), true);
82 else
83 return I(rnd.div_down(xl, yu), checking::pos_inf(), true);
84 }
85
86 template<class T, class Policies> inline
87 interval<T, Policies> div_positive(const T& x, const T& yu)
88 {
89 // assert(::boost::numeric::interval_lib::user::is_pos(yu));
90 typedef interval<T, Policies> I;
91 if (::boost::numeric::interval_lib::user::is_zero(x))
92 return I(static_cast<T>(0), static_cast<T>(0), true);
93 typename Policies::rounding rnd;
94 typedef typename Policies::checking checking;
95 if (::boost::numeric::interval_lib::user::is_neg(x))
96 return I(checking::neg_inf(), rnd.div_up(x, yu), true);
97 else
98 return I(rnd.div_down(x, yu), checking::pos_inf(), true);
99 }
100
101 template<class T, class Policies> inline
102 interval<T, Policies> div_negative(const interval<T, Policies>& x, const T& yl)
103 {
104 // assert(::boost::numeric::interval_lib::user::is_neg(yl));
105 if (::boost::numeric::interval_lib::user::is_zero(x.lower()) &&
106 ::boost::numeric::interval_lib::user::is_zero(x.upper()))
107 return x;
108 typename Policies::rounding rnd;
109 typedef interval<T, Policies> I;
110 const T& xl = x.lower();
111 const T& xu = x.upper();
112 typedef typename Policies::checking checking;
113 if (::boost::numeric::interval_lib::user::is_neg(xu))
114 return I(rnd.div_down(xu, yl), checking::pos_inf(), true);
115 else if (::boost::numeric::interval_lib::user::is_neg(xl))
116 return I(checking::neg_inf(), checking::pos_inf(), true);
117 else
118 return I(checking::neg_inf(), rnd.div_up(xl, yl), true);
119 }
120
121 template<class T, class Policies> inline
122 interval<T, Policies> div_negative(const T& x, const T& yl)
123 {
124 // assert(::boost::numeric::interval_lib::user::is_neg(yl));
125 typedef interval<T, Policies> I;
126 if (::boost::numeric::interval_lib::user::is_zero(x))
127 return I(static_cast<T>(0), static_cast<T>(0), true);
128 typename Policies::rounding rnd;
129 typedef typename Policies::checking checking;
130 if (::boost::numeric::interval_lib::user::is_neg(x))
131 return I(rnd.div_down(x, yl), checking::pos_inf(), true);
132 else
133 return I(checking::neg_inf(), rnd.div_up(x, yl), true);
134 }
135
136 template<class T, class Policies> inline
137 interval<T, Policies> div_zero(const interval<T, Policies>& x)
138 {
139 if (::boost::numeric::interval_lib::user::is_zero(x.lower()) &&
140 ::boost::numeric::interval_lib::user::is_zero(x.upper()))
141 return x;
142 else return interval<T, Policies>::whole();
143 }
144
145 template<class T, class Policies> inline
146 interval<T, Policies> div_zero(const T& x)
147 {
148 if (::boost::numeric::interval_lib::user::is_zero(x))
149 return interval<T, Policies>(static_cast<T>(0), static_cast<T>(0), true);
150 else return interval<T, Policies>::whole();
151 }
152
153 template<class T, class Policies> inline
154 interval<T, Policies> div_zero_part1(const interval<T, Policies>& x,
155 const interval<T, Policies>& y, bool& b)
156 {
157 // assert(::boost::numeric::interval_lib::user::is_neg(y.lower()) && ::boost::numeric::interval_lib::user::is_pos(y.upper()));
158 if (::boost::numeric::interval_lib::user::is_zero(x.lower()) && ::boost::numeric::interval_lib::user::is_zero(x.upper()))
159 { b = false; return x; }
160 typename Policies::rounding rnd;
161 typedef interval<T, Policies> I;
162 const T& xl = x.lower();
163 const T& xu = x.upper();
164 const T& yl = y.lower();
165 const T& yu = y.upper();
166 typedef typename Policies::checking checking;
167 if (::boost::numeric::interval_lib::user::is_neg(xu))
168 { b = true; return I(checking::neg_inf(), rnd.div_up(xu, yu), true); }
169 else if (::boost::numeric::interval_lib::user::is_neg(xl))
170 { b = false; return I(checking::neg_inf(), checking::pos_inf(), true); }
171 else
172 { b = true; return I(checking::neg_inf(), rnd.div_up(xl, yl), true); }
173 }
174
175 template<class T, class Policies> inline
176 interval<T, Policies> div_zero_part2(const interval<T, Policies>& x,
177 const interval<T, Policies>& y)
178 {
179 // assert(::boost::numeric::interval_lib::user::is_neg(y.lower()) && ::boost::numeric::interval_lib::user::is_pos(y.upper()) && (div_zero_part1(x, y, b), b));
180 typename Policies::rounding rnd;
181 typedef interval<T, Policies> I;
182 typedef typename Policies::checking checking;
183 if (::boost::numeric::interval_lib::user::is_neg(x.upper()))
184 return I(rnd.div_down(x.upper(), y.lower()), checking::pos_inf(), true);
185 else
186 return I(rnd.div_down(x.lower(), y.upper()), checking::pos_inf(), true);
187 }
188
189 } // namespace detail
190 } // namespace interval_lib
191 } // namespace numeric
192 } // namespace boost
193
194 #endif // BOOST_NUMERIC_INTERVAL_DETAIL_DIVISION_HPP