Chris@49
|
1 // Copyright (C) 2008-2010 NICTA (www.nicta.com.au)
|
Chris@49
|
2 // Copyright (C) 2008-2010 Conrad Sanderson
|
Chris@49
|
3 //
|
Chris@49
|
4 // This Source Code Form is subject to the terms of the Mozilla Public
|
Chris@49
|
5 // License, v. 2.0. If a copy of the MPL was not distributed with this
|
Chris@49
|
6 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
Chris@49
|
7
|
Chris@49
|
8
|
Chris@49
|
9
|
Chris@49
|
10 //! \addtogroup cmath_wrap
|
Chris@49
|
11 //! @{
|
Chris@49
|
12
|
Chris@49
|
13
|
Chris@49
|
14
|
Chris@49
|
15 //
|
Chris@49
|
16 // wrappers for isfinite
|
Chris@49
|
17 //
|
Chris@49
|
18
|
Chris@49
|
19
|
Chris@49
|
20
|
Chris@49
|
21 template<typename eT>
|
Chris@49
|
22 arma_inline
|
Chris@49
|
23 bool
|
Chris@49
|
24 arma_isfinite(eT val)
|
Chris@49
|
25 {
|
Chris@49
|
26 arma_ignore(val);
|
Chris@49
|
27
|
Chris@49
|
28 return true;
|
Chris@49
|
29 }
|
Chris@49
|
30
|
Chris@49
|
31
|
Chris@49
|
32
|
Chris@49
|
33 template<>
|
Chris@49
|
34 arma_inline
|
Chris@49
|
35 bool
|
Chris@49
|
36 arma_isfinite(float x)
|
Chris@49
|
37 {
|
Chris@49
|
38 #if defined(ARMA_HAVE_STD_ISFINITE)
|
Chris@49
|
39 {
|
Chris@49
|
40 return (std::isfinite(x) != 0);
|
Chris@49
|
41 }
|
Chris@49
|
42 #else
|
Chris@49
|
43 {
|
Chris@49
|
44 const bool x_is_inf = ( (x == x) && ((x - x) != float(0)) );
|
Chris@49
|
45 const bool x_is_nan = (x != x);
|
Chris@49
|
46
|
Chris@49
|
47 return ( (x_is_inf == false) && (x_is_nan == false) );
|
Chris@49
|
48 }
|
Chris@49
|
49 #endif
|
Chris@49
|
50 }
|
Chris@49
|
51
|
Chris@49
|
52
|
Chris@49
|
53
|
Chris@49
|
54 template<>
|
Chris@49
|
55 arma_inline
|
Chris@49
|
56 bool
|
Chris@49
|
57 arma_isfinite(double x)
|
Chris@49
|
58 {
|
Chris@49
|
59 #if defined(ARMA_HAVE_STD_ISFINITE)
|
Chris@49
|
60 {
|
Chris@49
|
61 return (std::isfinite(x) != 0);
|
Chris@49
|
62 }
|
Chris@49
|
63 #else
|
Chris@49
|
64 {
|
Chris@49
|
65 const bool x_is_inf = ( (x == x) && ((x - x) != double(0)) );
|
Chris@49
|
66 const bool x_is_nan = (x != x);
|
Chris@49
|
67
|
Chris@49
|
68 return ( (x_is_inf == false) && (x_is_nan == false) );
|
Chris@49
|
69 }
|
Chris@49
|
70 #endif
|
Chris@49
|
71 }
|
Chris@49
|
72
|
Chris@49
|
73
|
Chris@49
|
74
|
Chris@49
|
75 template<typename T>
|
Chris@49
|
76 arma_inline
|
Chris@49
|
77 bool
|
Chris@49
|
78 arma_isfinite(const std::complex<T>& x)
|
Chris@49
|
79 {
|
Chris@49
|
80 if( (arma_isfinite(x.real()) == false) || (arma_isfinite(x.imag()) == false) )
|
Chris@49
|
81 {
|
Chris@49
|
82 return false;
|
Chris@49
|
83 }
|
Chris@49
|
84 else
|
Chris@49
|
85 {
|
Chris@49
|
86 return true;
|
Chris@49
|
87 }
|
Chris@49
|
88 }
|
Chris@49
|
89
|
Chris@49
|
90
|
Chris@49
|
91
|
Chris@49
|
92 //
|
Chris@49
|
93 // wrappers for trigonometric functions
|
Chris@49
|
94 //
|
Chris@49
|
95
|
Chris@49
|
96
|
Chris@49
|
97
|
Chris@49
|
98 // Wherever possible, try to use TR1 versions of the functions below,
|
Chris@49
|
99 // otherwise fall back to Boost Math.
|
Chris@49
|
100 //
|
Chris@49
|
101 // complex acos
|
Chris@49
|
102 // complex asin
|
Chris@49
|
103 // complex atan
|
Chris@49
|
104 //
|
Chris@49
|
105 // real acosh
|
Chris@49
|
106 // real asinh
|
Chris@49
|
107 // real atanh
|
Chris@49
|
108 //
|
Chris@49
|
109 // complex acosh
|
Chris@49
|
110 // complex asinh
|
Chris@49
|
111 // complex atanh
|
Chris@49
|
112 //
|
Chris@49
|
113 //
|
Chris@49
|
114 // If TR1 not present and Boost math not present,
|
Chris@49
|
115 // we have our own rudimentary versions of:
|
Chris@49
|
116 //
|
Chris@49
|
117 // real acosh
|
Chris@49
|
118 // real asinh
|
Chris@49
|
119 // real atanh
|
Chris@49
|
120
|
Chris@49
|
121
|
Chris@49
|
122
|
Chris@49
|
123 #if defined(ARMA_USE_BOOST)
|
Chris@49
|
124 #define arma_boost_wrap(trig_fn, val) ( (boost::math::trig_fn)(val) )
|
Chris@49
|
125 #else
|
Chris@49
|
126 #define arma_boost_wrap(trig_fn, val) ( arma_stop( #trig_fn "(): need Boost libraries" ), val )
|
Chris@49
|
127 #endif
|
Chris@49
|
128
|
Chris@49
|
129
|
Chris@49
|
130 template<typename T>
|
Chris@49
|
131 arma_inline
|
Chris@49
|
132 std::complex<T>
|
Chris@49
|
133 arma_acos(const std::complex<T>& x)
|
Chris@49
|
134 {
|
Chris@49
|
135 #if defined(ARMA_HAVE_STD_TR1)
|
Chris@49
|
136 {
|
Chris@49
|
137 return std::tr1::acos(x);
|
Chris@49
|
138 }
|
Chris@49
|
139 #else
|
Chris@49
|
140 {
|
Chris@49
|
141 return arma_boost_wrap(acos, x);
|
Chris@49
|
142 }
|
Chris@49
|
143 #endif
|
Chris@49
|
144 }
|
Chris@49
|
145
|
Chris@49
|
146
|
Chris@49
|
147
|
Chris@49
|
148 template<typename T>
|
Chris@49
|
149 arma_inline
|
Chris@49
|
150 std::complex<T>
|
Chris@49
|
151 arma_asin(const std::complex<T>& x)
|
Chris@49
|
152 {
|
Chris@49
|
153 #if defined(ARMA_HAVE_STD_TR1)
|
Chris@49
|
154 {
|
Chris@49
|
155 return std::tr1::asin(x);
|
Chris@49
|
156 }
|
Chris@49
|
157 #else
|
Chris@49
|
158 {
|
Chris@49
|
159 return arma_boost_wrap(asin, x);
|
Chris@49
|
160 }
|
Chris@49
|
161 #endif
|
Chris@49
|
162 }
|
Chris@49
|
163
|
Chris@49
|
164
|
Chris@49
|
165
|
Chris@49
|
166 template<typename T>
|
Chris@49
|
167 arma_inline
|
Chris@49
|
168 std::complex<T>
|
Chris@49
|
169 arma_atan(const std::complex<T>& x)
|
Chris@49
|
170 {
|
Chris@49
|
171 #if defined(ARMA_HAVE_STD_TR1)
|
Chris@49
|
172 {
|
Chris@49
|
173 return std::tr1::atan(x);
|
Chris@49
|
174 }
|
Chris@49
|
175 #else
|
Chris@49
|
176 {
|
Chris@49
|
177 return arma_boost_wrap(atan, x);
|
Chris@49
|
178 }
|
Chris@49
|
179 #endif
|
Chris@49
|
180 }
|
Chris@49
|
181
|
Chris@49
|
182
|
Chris@49
|
183
|
Chris@49
|
184 template<typename eT>
|
Chris@49
|
185 arma_inline
|
Chris@49
|
186 eT
|
Chris@49
|
187 arma_acosh(const eT x)
|
Chris@49
|
188 {
|
Chris@49
|
189 #if defined(ARMA_HAVE_STD_TR1)
|
Chris@49
|
190 {
|
Chris@49
|
191 return std::tr1::acosh(x);
|
Chris@49
|
192 }
|
Chris@49
|
193 #elif defined(ARMA_USE_BOOST)
|
Chris@49
|
194 {
|
Chris@49
|
195 return boost::math::acosh(x);
|
Chris@49
|
196 }
|
Chris@49
|
197 #else
|
Chris@49
|
198 {
|
Chris@49
|
199 if(x >= eT(1))
|
Chris@49
|
200 {
|
Chris@49
|
201 // http://functions.wolfram.com/ElementaryFunctions/ArcCosh/02/
|
Chris@49
|
202 return std::log( x + std::sqrt(x*x - eT(1)) );
|
Chris@49
|
203 }
|
Chris@49
|
204 else
|
Chris@49
|
205 {
|
Chris@49
|
206 if(std::numeric_limits<eT>::has_quiet_NaN == true)
|
Chris@49
|
207 {
|
Chris@49
|
208 return -(std::numeric_limits<eT>::quiet_NaN());
|
Chris@49
|
209 }
|
Chris@49
|
210 else
|
Chris@49
|
211 {
|
Chris@49
|
212 return eT(0);
|
Chris@49
|
213 }
|
Chris@49
|
214 }
|
Chris@49
|
215 }
|
Chris@49
|
216 #endif
|
Chris@49
|
217 }
|
Chris@49
|
218
|
Chris@49
|
219
|
Chris@49
|
220
|
Chris@49
|
221 template<typename eT>
|
Chris@49
|
222 arma_inline
|
Chris@49
|
223 eT
|
Chris@49
|
224 arma_asinh(const eT x)
|
Chris@49
|
225 {
|
Chris@49
|
226 #if defined(ARMA_HAVE_STD_TR1)
|
Chris@49
|
227 {
|
Chris@49
|
228 return std::tr1::asinh(x);
|
Chris@49
|
229 }
|
Chris@49
|
230 #elif defined(ARMA_USE_BOOST)
|
Chris@49
|
231 {
|
Chris@49
|
232 return boost::math::asinh(x);
|
Chris@49
|
233 }
|
Chris@49
|
234 #else
|
Chris@49
|
235 {
|
Chris@49
|
236 // http://functions.wolfram.com/ElementaryFunctions/ArcSinh/02/
|
Chris@49
|
237 return std::log( x + std::sqrt(x*x + eT(1)) );
|
Chris@49
|
238 }
|
Chris@49
|
239 #endif
|
Chris@49
|
240 }
|
Chris@49
|
241
|
Chris@49
|
242
|
Chris@49
|
243
|
Chris@49
|
244 template<typename eT>
|
Chris@49
|
245 arma_inline
|
Chris@49
|
246 eT
|
Chris@49
|
247 arma_atanh(const eT x)
|
Chris@49
|
248 {
|
Chris@49
|
249 #if defined(ARMA_HAVE_STD_TR1)
|
Chris@49
|
250 {
|
Chris@49
|
251 return std::tr1::atanh(x);
|
Chris@49
|
252 }
|
Chris@49
|
253 #elif defined(ARMA_USE_BOOST)
|
Chris@49
|
254 {
|
Chris@49
|
255 return boost::math::atanh(x);
|
Chris@49
|
256 }
|
Chris@49
|
257 #else
|
Chris@49
|
258 {
|
Chris@49
|
259 if( (x >= eT(-1)) && (x <= eT(+1)) )
|
Chris@49
|
260 {
|
Chris@49
|
261 // http://functions.wolfram.com/ElementaryFunctions/ArcTanh/02/
|
Chris@49
|
262 return std::log( ( eT(1)+x ) / ( eT(1)-x ) ) / eT(2);
|
Chris@49
|
263 }
|
Chris@49
|
264 else
|
Chris@49
|
265 {
|
Chris@49
|
266 if(std::numeric_limits<eT>::has_quiet_NaN == true)
|
Chris@49
|
267 {
|
Chris@49
|
268 return -(std::numeric_limits<eT>::quiet_NaN());
|
Chris@49
|
269 }
|
Chris@49
|
270 else
|
Chris@49
|
271 {
|
Chris@49
|
272 return eT(0);
|
Chris@49
|
273 }
|
Chris@49
|
274 }
|
Chris@49
|
275 }
|
Chris@49
|
276 #endif
|
Chris@49
|
277 }
|
Chris@49
|
278
|
Chris@49
|
279
|
Chris@49
|
280
|
Chris@49
|
281 template<typename T>
|
Chris@49
|
282 arma_inline
|
Chris@49
|
283 std::complex<T>
|
Chris@49
|
284 arma_acosh(const std::complex<T>& x)
|
Chris@49
|
285 {
|
Chris@49
|
286 #if defined(ARMA_HAVE_STD_TR1)
|
Chris@49
|
287 {
|
Chris@49
|
288 return std::tr1::acosh(x);
|
Chris@49
|
289 }
|
Chris@49
|
290 #else
|
Chris@49
|
291 {
|
Chris@49
|
292 return arma_boost_wrap(acosh, x);
|
Chris@49
|
293 }
|
Chris@49
|
294 #endif
|
Chris@49
|
295 }
|
Chris@49
|
296
|
Chris@49
|
297
|
Chris@49
|
298
|
Chris@49
|
299 template<typename T>
|
Chris@49
|
300 arma_inline
|
Chris@49
|
301 std::complex<T>
|
Chris@49
|
302 arma_asinh(const std::complex<T>& x)
|
Chris@49
|
303 {
|
Chris@49
|
304 #if defined(ARMA_HAVE_STD_TR1)
|
Chris@49
|
305 {
|
Chris@49
|
306 return std::tr1::asinh(x);
|
Chris@49
|
307 }
|
Chris@49
|
308 #else
|
Chris@49
|
309 {
|
Chris@49
|
310 return arma_boost_wrap(asinh, x);
|
Chris@49
|
311 }
|
Chris@49
|
312 #endif
|
Chris@49
|
313 }
|
Chris@49
|
314
|
Chris@49
|
315
|
Chris@49
|
316
|
Chris@49
|
317 template<typename T>
|
Chris@49
|
318 arma_inline
|
Chris@49
|
319 std::complex<T>
|
Chris@49
|
320 arma_atanh(const std::complex<T>& x)
|
Chris@49
|
321 {
|
Chris@49
|
322 #if defined(ARMA_HAVE_STD_TR1)
|
Chris@49
|
323 {
|
Chris@49
|
324 return std::tr1::atanh(x);
|
Chris@49
|
325 }
|
Chris@49
|
326 #else
|
Chris@49
|
327 {
|
Chris@49
|
328 return arma_boost_wrap(atanh, x);
|
Chris@49
|
329 }
|
Chris@49
|
330 #endif
|
Chris@49
|
331 }
|
Chris@49
|
332
|
Chris@49
|
333
|
Chris@49
|
334
|
Chris@49
|
335 #undef arma_boost_wrap
|
Chris@49
|
336
|
Chris@49
|
337
|
Chris@49
|
338
|
Chris@49
|
339 //! @}
|