]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/math/test/complex_test.cpp
1 // (C) Copyright John Maddock 2005.
2 // Use, modification and distribution are subject to the
3 // Boost Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 #define BOOST_TEST_MAIN
7 #include <boost/test/unit_test.hpp>
8 #include <boost/test/tools/floating_point_comparison.hpp>
9 #include <boost/type_traits/is_same.hpp>
10 #include <boost/type_traits/is_floating_point.hpp>
11 #include <boost/mpl/if.hpp>
12 #include <boost/static_assert.hpp>
13 #include <boost/math/complex.hpp>
20 #ifdef BOOST_NO_STDC_NAMESPACE
21 namespace std
{ using :: sqrt
; using :: tan
; using :: tanh
; }
25 #undef BOOST_TEST_MESSAGE
26 #define BOOST_TEST_MESSAGE(x)
31 // Verifies that expected value "a" and found value "b" have a relative error
32 // less than "max_error" epsilons. Note that relative error is calculated for
33 // the complex number as a whole; this means that the error in the real or
34 // imaginary parts alone can be much higher than max_error when the real and
35 // imaginary parts are of very different magnitudes. This is important, because
36 // the Hull et al analysis of the acos and asin algorithms requires that very small
37 // real/imaginary components can be safely ignored if they are negligible compared
38 // to the other component.
41 bool check_complex ( const std :: complex < T
>& a
, const std :: complex < T
>& b
, int max_error
)
44 // a is the expected value, b is what was actually found,
45 // compute | (a-b)/b | and compare with max_error which is the
46 // multiple of E to permit:
49 static const std :: complex < T
> zero ( 0 );
50 static const T eps
= std :: pow ( static_cast < T
>( std :: numeric_limits
< T
>:: radix
), static_cast < T
>( 1 - std :: numeric_limits
< T
>:: digits
));
55 if ( boost :: math :: fabs ( b
) > eps
)
58 BOOST_ERROR ( "Expected {0,0} but got: " << b
);
62 BOOST_TEST_MESSAGE ( "Expected {0,0} but got: " << b
);
69 if ( boost :: math :: fabs ( a
) > eps
)
71 BOOST_ERROR ( "Found {0,0} but expected: " << a
);
76 BOOST_TEST_MESSAGE ( "Found {0,0} but expected: " << a
);
80 if (( boost :: math :: isnan
)( a
. real ()))
82 BOOST_ERROR ( "Found non-finite value for real part: " << a
);
84 if (( boost :: math :: isnan
)( a
. imag ()))
86 BOOST_ERROR ( "Found non-finite value for inaginary part: " << a
);
89 T rel
= boost :: math :: fabs (( b
- a
)/ b
) / eps
;
93 BOOST_ERROR ( "Error in result exceeded permitted limit of " << max_error
<< " (actual relative error was " << rel
<< "e). Found " << b
<< " expected " << a
);
100 // This is nothing more than a sanity check, computes trig(atrig(z))
101 // and compare the result to z. Note that:
103 // atrig(trig(z)) != z
105 // for certain z because the inverse trig functions are multi-valued, this
106 // essentially rules this out as a testing method. On the other hand:
110 // can vary compare to z by an arbitrarily large amount. For one thing we
111 // have no control over the implementation of the trig functions, for another
112 // even if both functions were accurate to 1ulp (as accurate as transcendental
113 // number can get, thanks to the "table makers dilemma"), the errors can still
114 // be arbitrarily large - often the inverse trig functions will map a very large
115 // part of the complex domain into a small output domain, so you can never get
116 // back exactly where you started from. Consequently these tests are no more than
117 // sanity checks (just verifies that signs are correct and so on).
120 void test_inverse_trig ( T
)
124 static const T interval
= static_cast < T
>( 2.0L / 128.0L );
128 std :: cout
<< std :: setprecision ( std :: numeric_limits
< T
>:: digits10
+ 2 );
130 for ( x
= - 1 ; x
<= 1 ; x
+= interval
)
132 for ( y
= - 1 ; y
<= 1 ; y
+= interval
)
135 std :: complex < T
> val ( x
, y
), inter
, result
;
136 inter
= boost :: math :: acos ( val
);
138 if (! check_complex ( val
, result
, 50 ))
140 std :: cout
<< "Error in testing inverse complex cos for type " << typeid ( T
). name () << std :: endl
;
141 std :: cout
<< " val= " << val
<< std :: endl
;
142 std :: cout
<< " acos(val) = " << inter
<< std :: endl
;
143 std :: cout
<< " cos(acos(val)) = " << result
<< std :: endl
;
146 inter
= boost :: math :: asin ( val
);
148 if (! check_complex ( val
, result
, 5 ))
150 std :: cout
<< "Error in testing inverse complex sin for type " << typeid ( T
). name () << std :: endl
;
151 std :: cout
<< " val= " << val
<< std :: endl
;
152 std :: cout
<< " asin(val) = " << inter
<< std :: endl
;
153 std :: cout
<< " sin(asin(val)) = " << result
<< std :: endl
;
158 static const T interval2
= static_cast < T
>( 3.0L / 256.0L );
159 for ( x
= - 3 ; x
<= 3 ; x
+= interval2
)
161 for ( y
= - 3 ; y
<= 3 ; y
+= interval2
)
164 std :: complex < T
> val ( x
, y
), inter
, result
;
165 inter
= boost :: math :: asinh ( val
);
166 result
= sinh ( inter
);
167 if (! check_complex ( val
, result
, 5 ))
169 std :: cout
<< "Error in testing inverse complex sinh for type " << typeid ( T
). name () << std :: endl
;
170 std :: cout
<< " val= " << val
<< std :: endl
;
171 std :: cout
<< " asinh(val) = " << inter
<< std :: endl
;
172 std :: cout
<< " sinh(asinh(val)) = " << result
<< std :: endl
;
175 if (!(( y
== 0 ) && ( x
<= 1 ))) // can't test along the branch cut
177 inter
= boost :: math :: acosh ( val
);
178 result
= cosh ( inter
);
179 if (! check_complex ( val
, result
, 60 ))
181 std :: cout
<< "Error in testing inverse complex cosh for type " << typeid ( T
). name () << std :: endl
;
182 std :: cout
<< " val= " << val
<< std :: endl
;
183 std :: cout
<< " acosh(val) = " << inter
<< std :: endl
;
184 std :: cout
<< " cosh(acosh(val)) = " << result
<< std :: endl
;
188 // There is a problem in testing atan and atanh:
189 // The inverse functions map a large input range to a much
190 // smaller output range, so at the extremes too rather different
191 // inputs may map to the same output value once rounded to N places.
192 // Consequently tan(atan(z)) can suffer from arbitrarily large errors
193 // even if individually they each have a small error bound. On the other
194 // hand we can't test atan(tan(z)) either because atan is multi-valued, so
195 // round-tripping in this direction isn't always possible.
196 // The following heuristic is designed to make the best of a bad job,
197 // using atan(tan(z)) where possible and tan(atan(z)) when it's not.
199 static const int tanh_error
= 20 ;
200 if (( 0 != x
) && ( 0 != y
) && (( std :: fabs ( y
) < 1 ) || ( std :: fabs ( x
) < 1 )))
203 val
= boost :: math :: atanh ( val
);
205 result
= boost :: math :: atanh ( inter
);
206 if (! check_complex ( val
, result
, tanh_error
))
208 std :: cout
<< "Error in testing inverse complex tanh for type " << typeid ( T
). name () << std :: endl
;
209 std :: cout
<< " val= " << val
<< std :: endl
;
210 std :: cout
<< " tanh(val) = " << inter
<< std :: endl
;
211 std :: cout
<< " atanh(tanh(val)) = " << result
<< std :: endl
;
214 if (!(( x
== 0 ) && ( std :: fabs ( y
) == 1 ))) // we can't test infinities here
216 val
= std :: complex < T
>( x
, y
);
217 val
= boost :: math :: atan ( val
);
219 result
= boost :: math :: atan ( inter
);
220 if (! check_complex ( val
, result
, tanh_error
))
222 std :: cout
<< "Error in testing inverse complex tan for type " << typeid ( T
). name () << std :: endl
;
223 std :: cout
<< " val= " << val
<< std :: endl
;
224 std :: cout
<< " tan(val) = " << inter
<< std :: endl
;
225 std :: cout
<< " atan(tan(val)) = " << result
<< std :: endl
;
232 inter
= boost :: math :: atanh ( val
);
233 result
= tanh ( inter
);
234 if (! check_complex ( val
, result
, tanh_error
))
236 std :: cout
<< "Error in testing inverse complex atanh for type " << typeid ( T
). name () << std :: endl
;
237 std :: cout
<< " val= " << val
<< std :: endl
;
238 std :: cout
<< " atanh(val) = " << inter
<< std :: endl
;
239 std :: cout
<< " tanh(atanh(val)) = " << result
<< std :: endl
;
242 if (!(( x
== 0 ) && ( std :: fabs ( y
) == 1 ))) // we can't test infinities here
244 inter
= boost :: math :: atan ( val
);
246 if (! check_complex ( val
, result
, tanh_error
))
248 std :: cout
<< "Error in testing inverse complex atan for type " << typeid ( T
). name () << std :: endl
;
249 std :: cout
<< " val= " << val
<< std :: endl
;
250 std :: cout
<< " atan(val) = " << inter
<< std :: endl
;
251 std :: cout
<< " tan(atan(val)) = " << result
<< std :: endl
;
261 // Various spot values, mostly the C99 special cases (infinites and NAN's).
262 // TODO: add spot checks for the Wolfram spot values.
265 void check_spots ( const T
&)
267 typedef std :: complex < T
> ct
;
269 static const T two
= 2.0 ;
270 T eps
= std :: pow ( two
, T ( 1 - std :: numeric_limits
< T
>:: digits
)); // numeric_limits<>::epsilon way too small to be useful on Darwin.
271 static const T zero
= 0 ;
272 static const T mzero
= - zero
;
273 static const T one
= 1 ;
274 static const T pi
= boost :: math :: constants :: pi
< T
>();
275 static const T half_pi
= boost :: math :: constants :: half_pi
< T
>();
276 static const T quarter_pi
= half_pi
/ 2 ;
277 static const T three_quarter_pi
= boost :: math :: constants :: three_quarters_pi
< T
>();
278 T infinity
= std :: numeric_limits
< T
>:: infinity ();
279 bool test_infinity
= std :: numeric_limits
< T
>:: has_infinity
;
281 bool test_nan
= false ;
282 #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
283 // numeric_limits reports that a quiet NaN is present
284 // but an attempt to access it will terminate the program!!!!
285 if ( std :: numeric_limits
< T
>:: has_quiet_NaN
)
286 nan
= std :: numeric_limits
< T
>:: quiet_NaN ();
287 if (( boost :: math :: isnan
)( nan
))
290 #if defined(__DECCXX) && !defined(_IEEE_FP)
291 // Tru64 cxx traps infinities unless the -ieee option is used:
292 test_infinity
= false ;
296 // C99 spot tests for acos:
298 result
= boost :: math :: acos ( ct ( zero
));
299 check_complex ( ct ( half_pi
), result
, 2 );
301 result
= boost :: math :: acos ( ct ( mzero
));
302 check_complex ( ct ( half_pi
), result
, 2 );
304 result
= boost :: math :: acos ( ct ( zero
, mzero
));
305 check_complex ( ct ( half_pi
), result
, 2 );
307 result
= boost :: math :: acos ( ct ( mzero
, mzero
));
308 check_complex ( ct ( half_pi
), result
, 2 );
312 result
= boost :: math :: acos ( ct ( zero
, nan
));
313 BOOST_CHECK_CLOSE ( result
. real (), half_pi
, eps
* 200 );
314 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
316 result
= boost :: math :: acos ( ct ( mzero
, nan
));
317 BOOST_CHECK_CLOSE ( result
. real (), half_pi
, eps
* 200 );
318 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
322 result
= boost :: math :: acos ( ct ( zero
, infinity
));
323 BOOST_CHECK_CLOSE ( result
. real (), half_pi
, eps
* 200 );
324 BOOST_CHECK ( result
. imag () == - infinity
);
326 result
= boost :: math :: acos ( ct ( zero
, - infinity
));
327 BOOST_CHECK_CLOSE ( result
. real (), half_pi
, eps
* 200 );
328 BOOST_CHECK ( result
. imag () == infinity
);
333 result
= boost :: math :: acos ( ct ( one
, nan
));
334 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
335 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
339 result
= boost :: math :: acos ( ct (- infinity
, one
));
340 BOOST_CHECK_CLOSE ( result
. real (), pi
, eps
* 200 );
341 BOOST_CHECK ( result
. imag () == - infinity
);
343 result
= boost :: math :: acos ( ct ( infinity
, one
));
344 BOOST_CHECK ( result
. real () == 0 );
345 BOOST_CHECK ( result
. imag () == - infinity
);
347 result
= boost :: math :: acos ( ct (- infinity
, - one
));
348 BOOST_CHECK_CLOSE ( result
. real (), pi
, eps
* 200 );
349 BOOST_CHECK ( result
. imag () == infinity
);
351 result
= boost :: math :: acos ( ct ( infinity
, - one
));
352 BOOST_CHECK ( result
. real () == 0 );
353 BOOST_CHECK ( result
. imag () == infinity
);
355 result
= boost :: math :: acos ( ct (- infinity
, infinity
));
356 BOOST_CHECK_CLOSE ( result
. real (), three_quarter_pi
, eps
* 200 );
357 BOOST_CHECK ( result
. imag () == - infinity
);
359 result
= boost :: math :: acos ( ct ( infinity
, infinity
));
360 BOOST_CHECK_CLOSE ( result
. real (), quarter_pi
, eps
* 200 );
361 BOOST_CHECK ( result
. imag () == - infinity
);
363 result
= boost :: math :: acos ( ct (- infinity
, - infinity
));
364 BOOST_CHECK_CLOSE ( result
. real (), three_quarter_pi
, eps
* 200 );
365 BOOST_CHECK ( result
. imag () == infinity
);
367 result
= boost :: math :: acos ( ct ( infinity
, - infinity
));
368 BOOST_CHECK_CLOSE ( result
. real (), quarter_pi
, eps
* 200 );
369 BOOST_CHECK ( result
. imag () == infinity
);
373 result
= boost :: math :: acos ( ct ( infinity
, nan
));
374 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
375 BOOST_CHECK ( std :: fabs ( result
. imag ()) == infinity
);
377 result
= boost :: math :: acos ( ct (- infinity
, nan
));
378 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
379 BOOST_CHECK ( std :: fabs ( result
. imag ()) == infinity
);
381 result
= boost :: math :: acos ( ct ( nan
, zero
));
382 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
383 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
385 result
= boost :: math :: acos ( ct ( nan
, - zero
));
386 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
387 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
389 result
= boost :: math :: acos ( ct ( nan
, one
));
390 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
391 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
393 result
= boost :: math :: acos ( ct ( nan
, - one
));
394 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
395 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
397 result
= boost :: math :: acos ( ct ( nan
, nan
));
398 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
399 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
401 result
= boost :: math :: acos ( ct ( nan
, infinity
));
402 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
403 BOOST_CHECK ( result
. imag () == - infinity
);
405 result
= boost :: math :: acos ( ct ( nan
, - infinity
));
406 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
407 BOOST_CHECK ( result
. imag () == infinity
);
409 if ( boost :: math :: signbit ( mzero
))
411 result
= boost :: math :: acos ( ct (- 1.25 f
, zero
));
412 BOOST_CHECK ( result
. real () > 0 );
413 BOOST_CHECK ( result
. imag () < 0 );
414 result
= boost :: math :: asin ( ct (- 1.75 f
, mzero
));
415 BOOST_CHECK ( result
. real () < 0 );
416 BOOST_CHECK ( result
. imag () < 0 );
417 result
= boost :: math :: atan ( ct ( mzero
, - 1.75 f
));
418 BOOST_CHECK ( result
. real () < 0 );
419 BOOST_CHECK ( result
. imag () < 0 );
421 result
= boost :: math :: acos ( ct ( zero
, zero
));
422 BOOST_CHECK ( result
. real () > 0 );
423 BOOST_CHECK ( result
. imag () == 0 );
424 BOOST_CHECK (( boost :: math :: signbit
)( result
. imag ()));
425 result
= boost :: math :: acos ( ct ( zero
, mzero
));
426 BOOST_CHECK ( result
. real () > 0 );
427 BOOST_CHECK ( result
. imag () == 0 );
428 BOOST_CHECK ( 0 == ( boost :: math :: signbit
)( result
. imag ()));
429 result
= boost :: math :: acos ( ct ( mzero
, zero
));
430 BOOST_CHECK ( result
. real () > 0 );
431 BOOST_CHECK ( result
. imag () == 0 );
432 BOOST_CHECK (( boost :: math :: signbit
)( result
. imag ()));
433 result
= boost :: math :: acos ( ct ( mzero
, mzero
));
434 BOOST_CHECK ( result
. real () > 0 );
435 BOOST_CHECK ( result
. imag () == 0 );
436 BOOST_CHECK ( 0 == ( boost :: math :: signbit
)( result
. imag ()));
440 // C99 spot tests for acosh:
442 result
= boost :: math :: acosh ( ct ( zero
, zero
));
443 BOOST_CHECK ( result
. real () == 0 );
444 BOOST_CHECK_CLOSE ( result
. imag (), half_pi
, eps
* 200 );
446 result
= boost :: math :: acosh ( ct ( zero
, mzero
));
447 BOOST_CHECK ( result
. real () == 0 );
448 BOOST_CHECK_CLOSE ( result
. imag (), - half_pi
, eps
* 200 );
450 result
= boost :: math :: acosh ( ct ( mzero
, zero
));
451 BOOST_CHECK ( result
. real () == 0 );
452 BOOST_CHECK_CLOSE ( result
. imag (), half_pi
, eps
* 200 );
454 result
= boost :: math :: acosh ( ct ( mzero
, mzero
));
455 BOOST_CHECK ( result
. real () == 0 );
456 BOOST_CHECK_CLOSE ( result
. imag (), - half_pi
, eps
* 200 );
460 result
= boost :: math :: acosh ( ct ( one
, infinity
));
461 BOOST_CHECK ( result
. real () == infinity
);
462 BOOST_CHECK_CLOSE ( result
. imag (), half_pi
, eps
* 200 );
464 result
= boost :: math :: acosh ( ct ( one
, - infinity
));
465 BOOST_CHECK ( result
. real () == infinity
);
466 BOOST_CHECK_CLOSE ( result
. imag (), - half_pi
, eps
* 200 );
471 result
= boost :: math :: acosh ( ct ( one
, nan
));
472 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
473 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
477 result
= boost :: math :: acosh ( ct (- infinity
, one
));
478 BOOST_CHECK ( result
. real () == infinity
);
479 BOOST_CHECK_CLOSE ( result
. imag (), pi
, eps
* 200 );
481 result
= boost :: math :: acosh ( ct ( infinity
, one
));
482 BOOST_CHECK ( result
. real () == infinity
);
483 BOOST_CHECK ( result
. imag () == 0 );
485 result
= boost :: math :: acosh ( ct (- infinity
, - one
));
486 BOOST_CHECK ( result
. real () == infinity
);
487 BOOST_CHECK_CLOSE ( result
. imag (), - pi
, eps
* 200 );
489 result
= boost :: math :: acosh ( ct ( infinity
, - one
));
490 BOOST_CHECK ( result
. real () == infinity
);
491 BOOST_CHECK ( result
. imag () == 0 );
493 result
= boost :: math :: acosh ( ct (- infinity
, infinity
));
494 BOOST_CHECK ( result
. real () == infinity
);
495 BOOST_CHECK_CLOSE ( result
. imag (), three_quarter_pi
, eps
* 200 );
497 result
= boost :: math :: acosh ( ct ( infinity
, infinity
));
498 BOOST_CHECK ( result
. real () == infinity
);
499 BOOST_CHECK_CLOSE ( result
. imag (), quarter_pi
, eps
* 200 );
501 result
= boost :: math :: acosh ( ct (- infinity
, - infinity
));
502 BOOST_CHECK ( result
. real () == infinity
);
503 BOOST_CHECK_CLOSE ( result
. imag (), - three_quarter_pi
, eps
* 200 );
505 result
= boost :: math :: acosh ( ct ( infinity
, - infinity
));
506 BOOST_CHECK ( result
. real () == infinity
);
507 BOOST_CHECK_CLOSE ( result
. imag (), - quarter_pi
, eps
* 200 );
512 result
= boost :: math :: acosh ( ct ( infinity
, nan
));
513 BOOST_CHECK ( result
. real () == infinity
);
514 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
516 result
= boost :: math :: acosh ( ct (- infinity
, nan
));
517 BOOST_CHECK ( result
. real () == infinity
);
518 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
520 result
= boost :: math :: acosh ( ct ( nan
, one
));
521 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
522 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
524 result
= boost :: math :: acosh ( ct ( nan
, infinity
));
525 BOOST_CHECK ( result
. real () == infinity
);
526 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
528 result
= boost :: math :: acosh ( ct ( nan
, - one
));
529 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
530 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
532 result
= boost :: math :: acosh ( ct ( nan
, - infinity
));
533 BOOST_CHECK ( result
. real () == infinity
);
534 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
536 result
= boost :: math :: acosh ( ct ( nan
, nan
));
537 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
538 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
540 if ( boost :: math :: signbit ( mzero
))
542 result
= boost :: math :: acosh ( ct (- 2.5 f
, zero
));
543 BOOST_CHECK ( result
. real () > 0 );
544 BOOST_CHECK ( result
. imag () > 0 );
547 // C99 spot checks for asinh:
549 result
= boost :: math :: asinh ( ct ( zero
, zero
));
550 BOOST_CHECK ( result
. real () == 0 );
551 BOOST_CHECK ( result
. imag () == 0 );
553 result
= boost :: math :: asinh ( ct ( mzero
, zero
));
554 BOOST_CHECK ( result
. real () == 0 );
555 BOOST_CHECK ( result
. imag () == 0 );
557 result
= boost :: math :: asinh ( ct ( zero
, mzero
));
558 BOOST_CHECK ( result
. real () == 0 );
559 BOOST_CHECK ( result
. imag () == 0 );
561 result
= boost :: math :: asinh ( ct ( mzero
, mzero
));
562 BOOST_CHECK ( result
. real () == 0 );
563 BOOST_CHECK ( result
. imag () == 0 );
567 result
= boost :: math :: asinh ( ct ( one
, infinity
));
568 BOOST_CHECK ( result
. real () == infinity
);
569 BOOST_CHECK_CLOSE ( result
. imag (), half_pi
, eps
* 200 );
571 result
= boost :: math :: asinh ( ct ( one
, - infinity
));
572 BOOST_CHECK ( result
. real () == infinity
);
573 BOOST_CHECK_CLOSE ( result
. imag (), - half_pi
, eps
* 200 );
575 result
= boost :: math :: asinh ( ct (- one
, - infinity
));
576 BOOST_CHECK ( result
. real () == - infinity
);
577 BOOST_CHECK_CLOSE ( result
. imag (), - half_pi
, eps
* 200 );
579 result
= boost :: math :: asinh ( ct (- one
, infinity
));
580 BOOST_CHECK ( result
. real () == - infinity
);
581 BOOST_CHECK_CLOSE ( result
. imag (), half_pi
, eps
* 200 );
586 result
= boost :: math :: asinh ( ct ( one
, nan
));
587 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
588 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
590 result
= boost :: math :: asinh ( ct (- one
, nan
));
591 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
592 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
594 result
= boost :: math :: asinh ( ct ( zero
, nan
));
595 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
596 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
601 result
= boost :: math :: asinh ( ct ( infinity
, one
));
602 BOOST_CHECK ( result
. real () == infinity
);
603 BOOST_CHECK ( result
. imag () == 0 );
605 result
= boost :: math :: asinh ( ct ( infinity
, - one
));
606 BOOST_CHECK ( result
. real () == infinity
);
607 BOOST_CHECK ( result
. imag () == 0 );
609 result
= boost :: math :: asinh ( ct (- infinity
, - one
));
610 BOOST_CHECK ( result
. real () == - infinity
);
611 BOOST_CHECK ( result
. imag () == 0 );
613 result
= boost :: math :: asinh ( ct (- infinity
, one
));
614 BOOST_CHECK ( result
. real () == - infinity
);
615 BOOST_CHECK ( result
. imag () == 0 );
617 result
= boost :: math :: asinh ( ct ( infinity
, infinity
));
618 BOOST_CHECK ( result
. real () == infinity
);
619 BOOST_CHECK_CLOSE ( result
. imag (), quarter_pi
, eps
* 200 );
621 result
= boost :: math :: asinh ( ct ( infinity
, - infinity
));
622 BOOST_CHECK ( result
. real () == infinity
);
623 BOOST_CHECK_CLOSE ( result
. imag (), - quarter_pi
, eps
* 200 );
625 result
= boost :: math :: asinh ( ct (- infinity
, - infinity
));
626 BOOST_CHECK ( result
. real () == - infinity
);
627 BOOST_CHECK_CLOSE ( result
. imag (), - quarter_pi
, eps
* 200 );
629 result
= boost :: math :: asinh ( ct (- infinity
, infinity
));
630 BOOST_CHECK ( result
. real () == - infinity
);
631 BOOST_CHECK_CLOSE ( result
. imag (), quarter_pi
, eps
* 200 );
636 result
= boost :: math :: asinh ( ct ( infinity
, nan
));
637 BOOST_CHECK ( result
. real () == infinity
);
638 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
640 result
= boost :: math :: asinh ( ct (- infinity
, nan
));
641 BOOST_CHECK ( result
. real () == - infinity
);
642 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
644 result
= boost :: math :: asinh ( ct ( nan
, zero
));
645 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
646 BOOST_CHECK ( result
. imag () == 0 );
648 result
= boost :: math :: asinh ( ct ( nan
, mzero
));
649 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
650 BOOST_CHECK ( result
. imag () == 0 );
652 result
= boost :: math :: asinh ( ct ( nan
, one
));
653 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
654 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
656 result
= boost :: math :: asinh ( ct ( nan
, - one
));
657 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
658 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
660 result
= boost :: math :: asinh ( ct ( nan
, nan
));
661 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
662 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
664 result
= boost :: math :: asinh ( ct ( nan
, infinity
));
665 BOOST_CHECK ( std :: fabs ( result
. real ()) == infinity
);
666 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
668 result
= boost :: math :: asinh ( ct ( nan
, - infinity
));
669 BOOST_CHECK ( std :: fabs ( result
. real ()) == infinity
);
670 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
672 if ( boost :: math :: signbit ( mzero
))
674 result
= boost :: math :: asinh ( ct ( zero
, 1.5 f
));
675 BOOST_CHECK ( result
. real () > 0 );
676 BOOST_CHECK ( result
. imag () > 0 );
680 // C99 special cases for atanh:
682 result
= boost :: math :: atanh ( ct ( zero
, zero
));
683 BOOST_CHECK ( result
. real () == zero
);
684 BOOST_CHECK ( result
. imag () == zero
);
686 result
= boost :: math :: atanh ( ct ( mzero
, zero
));
687 BOOST_CHECK ( result
. real () == zero
);
688 BOOST_CHECK ( result
. imag () == zero
);
690 result
= boost :: math :: atanh ( ct ( zero
, mzero
));
691 BOOST_CHECK ( result
. real () == zero
);
692 BOOST_CHECK ( result
. imag () == zero
);
694 result
= boost :: math :: atanh ( ct ( mzero
, mzero
));
695 BOOST_CHECK ( result
. real () == zero
);
696 BOOST_CHECK ( result
. imag () == zero
);
700 result
= boost :: math :: atanh ( ct ( zero
, nan
));
701 BOOST_CHECK ( result
. real () == zero
);
702 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
704 result
= boost :: math :: atanh ( ct (- zero
, nan
));
705 BOOST_CHECK ( result
. real () == zero
);
706 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
711 result
= boost :: math :: atanh ( ct ( one
, zero
));
712 BOOST_CHECK_EQUAL ( result
. real (), infinity
);
713 BOOST_CHECK_EQUAL ( result
. imag (), zero
);
715 result
= boost :: math :: atanh ( ct (- one
, zero
));
716 BOOST_CHECK_EQUAL ( result
. real (), - infinity
);
717 BOOST_CHECK_EQUAL ( result
. imag (), zero
);
719 result
= boost :: math :: atanh ( ct (- one
, - zero
));
720 BOOST_CHECK_EQUAL ( result
. real (), - infinity
);
721 BOOST_CHECK_EQUAL ( result
. imag (), zero
);
723 result
= boost :: math :: atanh ( ct ( one
, - zero
));
724 BOOST_CHECK_EQUAL ( result
. real (), infinity
);
725 BOOST_CHECK_EQUAL ( result
. imag (), zero
);
727 result
= boost :: math :: atanh ( ct ( pi
, infinity
));
728 BOOST_CHECK_EQUAL ( result
. real (), zero
);
729 BOOST_CHECK_CLOSE ( result
. imag (), half_pi
, eps
* 200 );
731 result
= boost :: math :: atanh ( ct ( pi
, - infinity
));
732 BOOST_CHECK_EQUAL ( result
. real (), zero
);
733 BOOST_CHECK_CLOSE ( result
. imag (), - half_pi
, eps
* 200 );
735 result
= boost :: math :: atanh ( ct (- pi
, - infinity
));
736 BOOST_CHECK_EQUAL ( result
. real (), zero
);
737 BOOST_CHECK_CLOSE ( result
. imag (), - half_pi
, eps
* 200 );
739 result
= boost :: math :: atanh ( ct (- pi
, infinity
));
740 BOOST_CHECK_EQUAL ( result
. real (), zero
);
741 BOOST_CHECK_CLOSE ( result
. imag (), half_pi
, eps
* 200 );
745 result
= boost :: math :: atanh ( ct ( pi
, nan
));
746 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
747 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
749 result
= boost :: math :: atanh ( ct (- pi
, nan
));
750 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
751 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
756 result
= boost :: math :: atanh ( ct ( infinity
, pi
));
757 BOOST_CHECK ( result
. real () == zero
);
758 BOOST_CHECK_CLOSE ( result
. imag (), half_pi
, eps
* 200 );
760 result
= boost :: math :: atanh ( ct ( infinity
, - pi
));
761 BOOST_CHECK_EQUAL ( result
. real (), zero
);
762 BOOST_CHECK_CLOSE ( result
. imag (), - half_pi
, eps
* 200 );
764 result
= boost :: math :: atanh ( ct (- infinity
, - pi
));
765 BOOST_CHECK_EQUAL ( result
. real (), zero
);
766 BOOST_CHECK_CLOSE ( result
. imag (), - half_pi
, eps
* 200 );
768 result
= boost :: math :: atanh ( ct (- infinity
, pi
));
769 BOOST_CHECK_EQUAL ( result
. real (), zero
);
770 BOOST_CHECK_CLOSE ( result
. imag (), half_pi
, eps
* 200 );
772 result
= boost :: math :: atanh ( ct ( infinity
, infinity
));
773 BOOST_CHECK_EQUAL ( result
. real (), zero
);
774 BOOST_CHECK_CLOSE ( result
. imag (), half_pi
, eps
* 200 );
776 result
= boost :: math :: atanh ( ct ( infinity
, - infinity
));
777 BOOST_CHECK_EQUAL ( result
. real (), zero
);
778 BOOST_CHECK_CLOSE ( result
. imag (), - half_pi
, eps
* 200 );
780 result
= boost :: math :: atanh ( ct (- infinity
, - infinity
));
781 BOOST_CHECK_EQUAL ( result
. real (), zero
);
782 BOOST_CHECK_CLOSE ( result
. imag (), - half_pi
, eps
* 200 );
784 result
= boost :: math :: atanh ( ct (- infinity
, infinity
));
785 BOOST_CHECK_EQUAL ( result
. real (), zero
);
786 BOOST_CHECK_CLOSE ( result
. imag (), half_pi
, eps
* 200 );
791 result
= boost :: math :: atanh ( ct ( infinity
, nan
));
792 BOOST_CHECK ( result
. real () == 0 );
793 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
795 result
= boost :: math :: atanh ( ct (- infinity
, nan
));
796 BOOST_CHECK ( result
. real () == 0 );
797 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
799 result
= boost :: math :: atanh ( ct ( nan
, pi
));
800 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
801 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
803 result
= boost :: math :: atanh ( ct ( nan
, - pi
));
804 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
805 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
807 result
= boost :: math :: atanh ( ct ( nan
, infinity
));
808 BOOST_CHECK ( result
. real () == 0 );
809 BOOST_CHECK_CLOSE ( result
. imag (), half_pi
, eps
* 200 );
811 result
= boost :: math :: atanh ( ct ( nan
, - infinity
));
812 BOOST_CHECK ( result
. real () == 0 );
813 BOOST_CHECK_CLOSE ( result
. imag (), - half_pi
, eps
* 200 );
815 result
= boost :: math :: atanh ( ct ( nan
, nan
));
816 BOOST_CHECK (( boost :: math :: isnan
)( result
. real ()));
817 BOOST_CHECK (( boost :: math :: isnan
)( result
. imag ()));
820 if ( boost :: math :: signbit ( mzero
))
822 result
= boost :: math :: atanh ( ct (- 2.0 f
, mzero
));
823 BOOST_CHECK ( result
. real () < 0 );
824 BOOST_CHECK ( result
. imag () < 0 );
830 // This is an accuracy test, sets the real and imaginary components
831 // of the input argument to various "boundary conditions" that exist
832 // inside the implementation. Then computes the result at double precision
833 // and again at float precision. The double precision result will be
834 // computed using the "regular" code, where as the float precision versions
835 // will calculate the result using the "exceptional value" handlers, so
836 // we end up comparing the values calculated by two different methods.
838 const float boundaries
[] = {
842 ( std :: numeric_limits
< float >:: max
)(),
843 ( std :: numeric_limits
< float >:: min
)(),
844 std :: numeric_limits
< float >:: epsilon (),
845 std :: sqrt (( std :: numeric_limits
< float >:: max
)()) / 8 ,
846 static_cast < float >( 4 ) * std :: sqrt (( std :: numeric_limits
< float >:: min
)()),
849 std :: sqrt (( std :: numeric_limits
< float >:: max
)()) / 2 ,
850 std :: sqrt (( std :: numeric_limits
< float >:: min
)()),
854 void do_test_boundaries ( float x
, float y
)
856 std :: complex < float > r1
= boost :: math :: asin ( std :: complex < float >( x
, y
));
857 std :: complex < double > dr
= boost :: math :: asin ( std :: complex < double >( x
, y
));
858 std :: complex < float > r2 ( static_cast < float >( dr
. real ()), static_cast < float >( dr
. imag ()));
859 check_complex ( r2
, r1
, 5 );
860 r1
= boost :: math :: acos ( std :: complex < float >( x
, y
));
861 dr
= boost :: math :: acos ( std :: complex < double >( x
, y
));
862 r2
= std :: complex < float >( std :: complex < double >( dr
. real (), dr
. imag ()));
863 check_complex ( r2
, r1
, 5 );
864 r1
= boost :: math :: atanh ( std :: complex < float >( x
, y
));
865 dr
= boost :: math :: atanh ( std :: complex < double >( x
, y
));
866 r2
= std :: complex < float >( std :: complex < double >( dr
. real (), dr
. imag ()));
867 check_complex ( r2
, r1
, 5 );
870 void test_boundaries ( float x
, float y
)
872 do_test_boundaries ( x
, y
);
873 do_test_boundaries (- x
, y
);
874 do_test_boundaries (- x
, - y
);
875 do_test_boundaries ( x
, - y
);
878 void test_boundaries ( float x
)
880 for ( unsigned i
= 0 ; i
< sizeof ( boundaries
)/ sizeof ( float ); ++ i
)
882 test_boundaries ( x
, boundaries
[ i
]);
883 test_boundaries ( x
, boundaries
[ i
] + std :: numeric_limits
< float >:: epsilon ()* boundaries
[ i
]);
884 test_boundaries ( x
, boundaries
[ i
] - std :: numeric_limits
< float >:: epsilon ()* boundaries
[ i
]);
888 void test_boundaries ()
890 for ( unsigned i
= 0 ; i
< sizeof ( boundaries
)/ sizeof ( float ); ++ i
)
892 test_boundaries ( boundaries
[ i
]);
893 test_boundaries ( boundaries
[ i
] + std :: numeric_limits
< float >:: epsilon ()* boundaries
[ i
]);
894 test_boundaries ( boundaries
[ i
] - std :: numeric_limits
< float >:: epsilon ()* boundaries
[ i
]); //here
899 BOOST_AUTO_TEST_CASE ( test_main
)
901 std :: cout
<< "Running complex trig sanity checks for type float." << std :: endl
;
902 test_inverse_trig ( float ( 0 ));
903 std :: cout
<< "Running complex trig sanity checks for type double." << std :: endl
;
904 test_inverse_trig ( double ( 0 ));
905 //test_inverse_trig((long double)(0));
907 std :: cout
<< "Running complex trig spot checks for type float." << std :: endl
;
908 check_spots ( float ( 0 ));
909 std :: cout
<< "Running complex trig spot checks for type double." << std :: endl
;
910 check_spots ( double ( 0 ));
911 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
912 std :: cout
<< "Running complex trig spot checks for type long double." << std :: endl
;
913 check_spots (( long double )( 0 ));
916 std :: cout
<< "Running complex trig boundary and accuracy tests." << std :: endl
;