sl@0
|
1 |
/* Boost interval/transc.hpp template implementation file
|
sl@0
|
2 |
*
|
sl@0
|
3 |
* Copyright 2000 Jens Maurer
|
sl@0
|
4 |
* Copyright 2002 Hervé Brönnimann, Guillaume Melquiond, Sylvain Pion
|
sl@0
|
5 |
*
|
sl@0
|
6 |
* Distributed under the Boost Software License, Version 1.0.
|
sl@0
|
7 |
* (See accompanying file LICENSE_1_0.txt or
|
sl@0
|
8 |
* copy at http://www.boost.org/LICENSE_1_0.txt)
|
sl@0
|
9 |
*/
|
sl@0
|
10 |
|
sl@0
|
11 |
#ifndef BOOST_NUMERIC_INTERVAL_TRANSC_HPP
|
sl@0
|
12 |
#define BOOST_NUMERIC_INTERVAL_TRANSC_HPP
|
sl@0
|
13 |
|
sl@0
|
14 |
#include <boost/config.hpp>
|
sl@0
|
15 |
#include <boost/numeric/interval/detail/interval_prototype.hpp>
|
sl@0
|
16 |
#include <boost/numeric/interval/detail/bugs.hpp>
|
sl@0
|
17 |
#include <boost/numeric/interval/detail/test_input.hpp>
|
sl@0
|
18 |
#include <boost/numeric/interval/rounding.hpp>
|
sl@0
|
19 |
#include <boost/numeric/interval/constants.hpp>
|
sl@0
|
20 |
#include <boost/numeric/interval/arith.hpp>
|
sl@0
|
21 |
#include <boost/numeric/interval/arith2.hpp>
|
sl@0
|
22 |
#include <algorithm>
|
sl@0
|
23 |
|
sl@0
|
24 |
namespace boost {
|
sl@0
|
25 |
namespace numeric {
|
sl@0
|
26 |
|
sl@0
|
27 |
template<class T, class Policies> inline
|
sl@0
|
28 |
interval<T, Policies> exp(const interval<T, Policies>& x)
|
sl@0
|
29 |
{
|
sl@0
|
30 |
typedef interval<T, Policies> I;
|
sl@0
|
31 |
if (interval_lib::detail::test_input(x))
|
sl@0
|
32 |
return I::empty();
|
sl@0
|
33 |
typename Policies::rounding rnd;
|
sl@0
|
34 |
return I(rnd.exp_down(x.lower()), rnd.exp_up(x.upper()), true);
|
sl@0
|
35 |
}
|
sl@0
|
36 |
|
sl@0
|
37 |
template<class T, class Policies> inline
|
sl@0
|
38 |
interval<T, Policies> log(const interval<T, Policies>& x)
|
sl@0
|
39 |
{
|
sl@0
|
40 |
typedef interval<T, Policies> I;
|
sl@0
|
41 |
if (interval_lib::detail::test_input(x) ||
|
sl@0
|
42 |
!interval_lib::user::is_pos(x.upper()))
|
sl@0
|
43 |
return I::empty();
|
sl@0
|
44 |
typename Policies::rounding rnd;
|
sl@0
|
45 |
typedef typename Policies::checking checking;
|
sl@0
|
46 |
T l = !interval_lib::user::is_pos(x.lower())
|
sl@0
|
47 |
? checking::neg_inf() : rnd.log_down(x.lower());
|
sl@0
|
48 |
return I(l, rnd.log_up(x.upper()), true);
|
sl@0
|
49 |
}
|
sl@0
|
50 |
|
sl@0
|
51 |
template<class T, class Policies> inline
|
sl@0
|
52 |
interval<T, Policies> cos(const interval<T, Policies>& x)
|
sl@0
|
53 |
{
|
sl@0
|
54 |
if (interval_lib::detail::test_input(x))
|
sl@0
|
55 |
return interval<T, Policies>::empty();
|
sl@0
|
56 |
typename Policies::rounding rnd;
|
sl@0
|
57 |
typedef interval<T, Policies> I;
|
sl@0
|
58 |
typedef typename interval_lib::unprotect<I>::type R;
|
sl@0
|
59 |
|
sl@0
|
60 |
// get lower bound within [0, pi]
|
sl@0
|
61 |
const R pi2 = interval_lib::pi_twice<R>();
|
sl@0
|
62 |
R tmp = fmod((const R&)x, pi2);
|
sl@0
|
63 |
if (width(tmp) >= pi2.lower())
|
sl@0
|
64 |
return I(static_cast<T>(-1), static_cast<T>(1), true); // we are covering a full period
|
sl@0
|
65 |
if (tmp.lower() >= interval_lib::constants::pi_upper<T>())
|
sl@0
|
66 |
return -cos(tmp - interval_lib::pi<R>());
|
sl@0
|
67 |
T l = tmp.lower();
|
sl@0
|
68 |
T u = tmp.upper();
|
sl@0
|
69 |
|
sl@0
|
70 |
BOOST_USING_STD_MIN();
|
sl@0
|
71 |
// separate into monotone subintervals
|
sl@0
|
72 |
if (u <= interval_lib::constants::pi_lower<T>())
|
sl@0
|
73 |
return I(rnd.cos_down(u), rnd.cos_up(l), true);
|
sl@0
|
74 |
else if (u <= pi2.lower())
|
sl@0
|
75 |
return I(static_cast<T>(-1), rnd.cos_up(min BOOST_PREVENT_MACRO_SUBSTITUTION(rnd.sub_down(pi2.lower(), u), l)), true);
|
sl@0
|
76 |
else
|
sl@0
|
77 |
return I(static_cast<T>(-1), static_cast<T>(1), true);
|
sl@0
|
78 |
}
|
sl@0
|
79 |
|
sl@0
|
80 |
template<class T, class Policies> inline
|
sl@0
|
81 |
interval<T, Policies> sin(const interval<T, Policies>& x)
|
sl@0
|
82 |
{
|
sl@0
|
83 |
typedef interval<T, Policies> I;
|
sl@0
|
84 |
if (interval_lib::detail::test_input(x))
|
sl@0
|
85 |
return I::empty();
|
sl@0
|
86 |
typename Policies::rounding rnd;
|
sl@0
|
87 |
typedef typename interval_lib::unprotect<I>::type R;
|
sl@0
|
88 |
I r = cos((const R&)x - interval_lib::pi_half<R>());
|
sl@0
|
89 |
(void)&rnd;
|
sl@0
|
90 |
return r;
|
sl@0
|
91 |
}
|
sl@0
|
92 |
|
sl@0
|
93 |
template<class T, class Policies> inline
|
sl@0
|
94 |
interval<T, Policies> tan(const interval<T, Policies>& x)
|
sl@0
|
95 |
{
|
sl@0
|
96 |
typedef interval<T, Policies> I;
|
sl@0
|
97 |
if (interval_lib::detail::test_input(x))
|
sl@0
|
98 |
return I::empty();
|
sl@0
|
99 |
typename Policies::rounding rnd;
|
sl@0
|
100 |
typedef typename interval_lib::unprotect<I>::type R;
|
sl@0
|
101 |
|
sl@0
|
102 |
// get lower bound within [-pi/2, pi/2]
|
sl@0
|
103 |
const R pi = interval_lib::pi<R>();
|
sl@0
|
104 |
R tmp = fmod((const R&)x, pi);
|
sl@0
|
105 |
const T pi_half_d = interval_lib::constants::pi_half_lower<T>();
|
sl@0
|
106 |
if (tmp.lower() >= pi_half_d)
|
sl@0
|
107 |
tmp -= pi;
|
sl@0
|
108 |
if (tmp.lower() <= -pi_half_d || tmp.upper() >= pi_half_d)
|
sl@0
|
109 |
return I::whole();
|
sl@0
|
110 |
return I(rnd.tan_down(tmp.lower()), rnd.tan_up(tmp.upper()), true);
|
sl@0
|
111 |
}
|
sl@0
|
112 |
|
sl@0
|
113 |
template<class T, class Policies> inline
|
sl@0
|
114 |
interval<T, Policies> asin(const interval<T, Policies>& x)
|
sl@0
|
115 |
{
|
sl@0
|
116 |
typedef interval<T, Policies> I;
|
sl@0
|
117 |
if (interval_lib::detail::test_input(x)
|
sl@0
|
118 |
|| x.upper() < static_cast<T>(-1) || x.lower() > static_cast<T>(1))
|
sl@0
|
119 |
return I::empty();
|
sl@0
|
120 |
typename Policies::rounding rnd;
|
sl@0
|
121 |
T l = (x.lower() <= static_cast<T>(-1))
|
sl@0
|
122 |
? -interval_lib::constants::pi_half_upper<T>()
|
sl@0
|
123 |
: rnd.asin_down(x.lower());
|
sl@0
|
124 |
T u = (x.upper() >= static_cast<T>(1) )
|
sl@0
|
125 |
? interval_lib::constants::pi_half_upper<T>()
|
sl@0
|
126 |
: rnd.asin_up (x.upper());
|
sl@0
|
127 |
return I(l, u, true);
|
sl@0
|
128 |
}
|
sl@0
|
129 |
|
sl@0
|
130 |
template<class T, class Policies> inline
|
sl@0
|
131 |
interval<T, Policies> acos(const interval<T, Policies>& x)
|
sl@0
|
132 |
{
|
sl@0
|
133 |
typedef interval<T, Policies> I;
|
sl@0
|
134 |
if (interval_lib::detail::test_input(x)
|
sl@0
|
135 |
|| x.upper() < static_cast<T>(-1) || x.lower() > static_cast<T>(1))
|
sl@0
|
136 |
return I::empty();
|
sl@0
|
137 |
typename Policies::rounding rnd;
|
sl@0
|
138 |
T l = (x.upper() >= static_cast<T>(1) )
|
sl@0
|
139 |
? static_cast<T>(0)
|
sl@0
|
140 |
: rnd.acos_down(x.upper());
|
sl@0
|
141 |
T u = (x.lower() <= static_cast<T>(-1))
|
sl@0
|
142 |
? interval_lib::constants::pi_upper<T>()
|
sl@0
|
143 |
: rnd.acos_up (x.lower());
|
sl@0
|
144 |
return I(l, u, true);
|
sl@0
|
145 |
}
|
sl@0
|
146 |
|
sl@0
|
147 |
template<class T, class Policies> inline
|
sl@0
|
148 |
interval<T, Policies> atan(const interval<T, Policies>& x)
|
sl@0
|
149 |
{
|
sl@0
|
150 |
typedef interval<T, Policies> I;
|
sl@0
|
151 |
if (interval_lib::detail::test_input(x))
|
sl@0
|
152 |
return I::empty();
|
sl@0
|
153 |
typename Policies::rounding rnd;
|
sl@0
|
154 |
return I(rnd.atan_down(x.lower()), rnd.atan_up(x.upper()), true);
|
sl@0
|
155 |
}
|
sl@0
|
156 |
|
sl@0
|
157 |
template<class T, class Policies> inline
|
sl@0
|
158 |
interval<T, Policies> sinh(const interval<T, Policies>& x)
|
sl@0
|
159 |
{
|
sl@0
|
160 |
typedef interval<T, Policies> I;
|
sl@0
|
161 |
if (interval_lib::detail::test_input(x))
|
sl@0
|
162 |
return I::empty();
|
sl@0
|
163 |
typename Policies::rounding rnd;
|
sl@0
|
164 |
return I(rnd.sinh_down(x.lower()), rnd.sinh_up(x.upper()), true);
|
sl@0
|
165 |
}
|
sl@0
|
166 |
|
sl@0
|
167 |
template<class T, class Policies> inline
|
sl@0
|
168 |
interval<T, Policies> cosh(const interval<T, Policies>& x)
|
sl@0
|
169 |
{
|
sl@0
|
170 |
typedef interval<T, Policies> I;
|
sl@0
|
171 |
if (interval_lib::detail::test_input(x))
|
sl@0
|
172 |
return I::empty();
|
sl@0
|
173 |
typename Policies::rounding rnd;
|
sl@0
|
174 |
if (interval_lib::user::is_neg(x.upper()))
|
sl@0
|
175 |
return I(rnd.cosh_down(x.upper()), rnd.cosh_up(x.lower()), true);
|
sl@0
|
176 |
else if (!interval_lib::user::is_neg(x.lower()))
|
sl@0
|
177 |
return I(rnd.cosh_down(x.lower()), rnd.cosh_up(x.upper()), true);
|
sl@0
|
178 |
else
|
sl@0
|
179 |
return I(static_cast<T>(0), rnd.cosh_up(-x.lower() > x.upper() ? x.lower() : x.upper()), true);
|
sl@0
|
180 |
}
|
sl@0
|
181 |
|
sl@0
|
182 |
template<class T, class Policies> inline
|
sl@0
|
183 |
interval<T, Policies> tanh(const interval<T, Policies>& x)
|
sl@0
|
184 |
{
|
sl@0
|
185 |
typedef interval<T, Policies> I;
|
sl@0
|
186 |
if (interval_lib::detail::test_input(x))
|
sl@0
|
187 |
return I::empty();
|
sl@0
|
188 |
typename Policies::rounding rnd;
|
sl@0
|
189 |
return I(rnd.tanh_down(x.lower()), rnd.tanh_up(x.upper()), true);
|
sl@0
|
190 |
}
|
sl@0
|
191 |
|
sl@0
|
192 |
template<class T, class Policies> inline
|
sl@0
|
193 |
interval<T, Policies> asinh(const interval<T, Policies>& x)
|
sl@0
|
194 |
{
|
sl@0
|
195 |
typedef interval<T, Policies> I;
|
sl@0
|
196 |
if (interval_lib::detail::test_input(x))
|
sl@0
|
197 |
return I::empty();
|
sl@0
|
198 |
typename Policies::rounding rnd;
|
sl@0
|
199 |
return I(rnd.asinh_down(x.lower()), rnd.asinh_up(x.upper()), true);
|
sl@0
|
200 |
}
|
sl@0
|
201 |
|
sl@0
|
202 |
template<class T, class Policies> inline
|
sl@0
|
203 |
interval<T, Policies> acosh(const interval<T, Policies>& x)
|
sl@0
|
204 |
{
|
sl@0
|
205 |
typedef interval<T, Policies> I;
|
sl@0
|
206 |
if (interval_lib::detail::test_input(x) || x.upper() < static_cast<T>(1))
|
sl@0
|
207 |
return I::empty();
|
sl@0
|
208 |
typename Policies::rounding rnd;
|
sl@0
|
209 |
T l = x.lower() <= static_cast<T>(1) ? static_cast<T>(0) : rnd.acosh_down(x.lower());
|
sl@0
|
210 |
return I(l, rnd.acosh_up(x.upper()), true);
|
sl@0
|
211 |
}
|
sl@0
|
212 |
|
sl@0
|
213 |
template<class T, class Policies> inline
|
sl@0
|
214 |
interval<T, Policies> atanh(const interval<T, Policies>& x)
|
sl@0
|
215 |
{
|
sl@0
|
216 |
typedef interval<T, Policies> I;
|
sl@0
|
217 |
if (interval_lib::detail::test_input(x)
|
sl@0
|
218 |
|| x.upper() < static_cast<T>(-1) || x.lower() > static_cast<T>(1))
|
sl@0
|
219 |
return I::empty();
|
sl@0
|
220 |
typename Policies::rounding rnd;
|
sl@0
|
221 |
typedef typename Policies::checking checking;
|
sl@0
|
222 |
T l = (x.lower() <= static_cast<T>(-1))
|
sl@0
|
223 |
? checking::neg_inf() : rnd.atanh_down(x.lower());
|
sl@0
|
224 |
T u = (x.upper() >= static_cast<T>(1) )
|
sl@0
|
225 |
? checking::pos_inf() : rnd.atanh_up (x.upper());
|
sl@0
|
226 |
return I(l, u, true);
|
sl@0
|
227 |
}
|
sl@0
|
228 |
|
sl@0
|
229 |
} // namespace numeric
|
sl@0
|
230 |
} // namespace boost
|
sl@0
|
231 |
|
sl@0
|
232 |
#endif // BOOST_NUMERIC_INTERVAL_TRANSC_HPP
|