1 // test file for quaternion.hpp
3 // (C) Copyright Hubert Holin 2001.
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
12 #include <boost/mpl/list.hpp>
14 #define BOOST_TEST_MAIN
15 #include <boost/test/unit_test.hpp>
16 #include <boost/test/unit_test_log.hpp>
17 #include <boost/multiprecision/cpp_bin_float.hpp>
18 #include <boost/multiprecision/cpp_dec_float.hpp>
20 #include <boost/math/quaternion.hpp>
23 #pragma warning(disable:4127) // conditional expression is constant
27 struct string_type_name
;
29 #define DEFINE_TYPE_NAME(Type) \
30 template<> struct string_type_name<Type> \
32 static char const * _() \
38 DEFINE_TYPE_NAME(float);
39 DEFINE_TYPE_NAME(double);
40 DEFINE_TYPE_NAME(long double);
41 DEFINE_TYPE_NAME(boost::multiprecision::cpp_bin_float_quad
);
42 DEFINE_TYPE_NAME(boost::multiprecision::number
<boost::multiprecision::cpp_dec_float
<25> >);
44 #if BOOST_WORKAROUND(BOOST_MSVC, < 1900)
45 # define CPP_DEC_FLOAT_TEST
47 # define CPP_DEC_FLOAT_TEST , boost::multiprecision::number<boost::multiprecision::cpp_dec_float<25> >
49 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
50 # define LD_TEST , long double
56 typedef boost::mpl::list
<float,double LD_TEST
, boost::multiprecision::cpp_bin_float_quad CPP_DEC_FLOAT_TEST
> test_types
;
58 // Apple GCC 4.0 uses the "double double" format for its long double,
59 // which means that epsilon is VERY small but useless for
60 // comparisons. So, don't do those comparisons.
61 #if (defined(__APPLE_CC__) && defined(__GNUC__) && __GNUC__ == 4) || defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
62 typedef boost::mpl::list
<float,double> near_eps_test_types
;
64 typedef boost::mpl::list
<float,double,long double> near_eps_test_types
;
68 #if BOOST_WORKAROUND(__GNUC__, < 3)
69 // gcc 2.x ignores function scope using declarations,
70 // put them in the scope of the enclosing namespace instead:
82 using ::std::numeric_limits
;
84 using ::boost::math::abs
;
85 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
87 #ifdef BOOST_NO_STDC_NAMESPACE
98 #endif /* BOOST_NO_STDC_NAMESPACE */
100 #ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
101 using ::boost::math::real
;
102 using ::boost::math::unreal
;
103 using ::boost::math::sup
;
104 using ::boost::math::l1
;
105 using ::boost::math::abs
;
106 using ::boost::math::norm
;
107 using ::boost::math::conj
;
108 using ::boost::math::exp
;
109 using ::boost::math::pow
;
110 using ::boost::math::cos
;
111 using ::boost::math::sin
;
112 using ::boost::math::tan
;
113 using ::boost::math::cosh
;
114 using ::boost::math::sinh
;
115 using ::boost::math::tanh
;
116 using ::boost::math::sinc_pi
;
117 using ::boost::math::sinhc_pi
;
118 #endif /* BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP */
120 // Provide standard floating point abs() overloads if older Microsoft
121 // library is used with _MSC_EXTENSIONS defined. This code also works
122 // for the Intel compiler using the Microsoft library.
123 #if defined(_MSC_EXTENSIONS) && BOOST_WORKAROUND(_MSC_VER, < 1310)
124 #if !((__INTEL__ && _WIN32) && BOOST_WORKAROUND(__MWERKS__, >= 0x3201))
125 inline float abs(float v
)
130 inline double abs(double v
)
135 inline long double abs(long double v
)
139 #endif /* !((__INTEL__ && _WIN32) && BOOST_WORKAROUND(__MWERKS__, >= 0x3201)) */
140 #endif /* defined(_MSC_EXTENSIONS) && BOOST_WORKAROUND(_MSC_VER, < 1310) */
143 // explicit (if ludicrous) instanciation
144 #if !BOOST_WORKAROUND(__GNUC__, < 3)
145 template class ::boost::math::quaternion
<int>;
147 // gcc doesn't like the absolutely-qualified namespace
148 template class boost::math::quaternion
<int>;
149 #endif /* !BOOST_WORKAROUND(__GNUC__) */
157 struct other_type
<double>
162 struct other_type
<float>
168 template <class T
, class U
>
169 void test_compare(const T
& a
, const U
& b
, bool eq
)
173 BOOST_CHECK_EQUAL(a
, b
);
174 BOOST_CHECK((a
!= b
) == false);
175 BOOST_CHECK_EQUAL(b
, a
);
176 BOOST_CHECK((b
!= a
) == false);
180 BOOST_CHECK_NE(a
, b
);
181 BOOST_CHECK((a
== b
) == false);
182 BOOST_CHECK_NE(b
, a
);
183 BOOST_CHECK((b
== a
) == false);
187 template <class T
, class R1
, class R2
, class R3
, class R4
>
188 void check_exact_quaternion_result(const boost::math::quaternion
<T
>& q
, R1 a
, R2 b
, R3 c
, R4 d
)
190 BOOST_CHECK_EQUAL(q
.R_component_1(), a
);
191 BOOST_CHECK_EQUAL(q
.R_component_2(), b
);
192 BOOST_CHECK_EQUAL(q
.R_component_3(), c
);
193 BOOST_CHECK_EQUAL(q
.R_component_4(), d
);
194 BOOST_CHECK_EQUAL(q
.C_component_1(), std::complex<T
>(T(a
), T(b
)));
195 BOOST_CHECK_EQUAL(q
.C_component_2(), std::complex<T
>(T(c
), T(d
)));
198 template <class T
, class R1
, class R2
, class R3
, class R4
>
199 void check_approx_quaternion_result(const boost::math::quaternion
<T
>& q
, R1 a
, R2 b
, R3 c
, R4 d
, int eps
= 10)
201 T tol
= std::numeric_limits
<T
>::epsilon() * eps
* 100; // epsilon as a persentage.
203 if (abs(a
) > tol
/ 100)
205 BOOST_CHECK_CLOSE(q
.R_component_1(), static_cast<T
>(a
), tol
);
209 BOOST_CHECK_SMALL(q
.R_component_1(), tol
);
213 BOOST_CHECK_CLOSE(q
.R_component_2(), static_cast<T
>(b
), tol
);
217 BOOST_CHECK_SMALL(q
.R_component_2(), tol
);
221 BOOST_CHECK_CLOSE(q
.R_component_3(), static_cast<T
>(c
), tol
);
225 BOOST_CHECK_SMALL(q
.R_component_3(), tol
);
229 BOOST_CHECK_CLOSE(q
.R_component_4(), static_cast<T
>(d
), tol
);
233 BOOST_CHECK_SMALL(q
.R_component_4(), tol
);
238 void check_complex_ops_imp()
240 T tol
= std::numeric_limits
<T
>::epsilon() * 200;
242 ::std::complex<T
> c0(5, 6);
244 // using constructor "H seen as C^2"
245 ::boost::math::quaternion
<T
> q2(c0
), q1
;
246 check_exact_quaternion_result(q2
, 5, 6, 0, 0);
248 // using converting assignment operator
251 check_exact_quaternion_result(q2
, 5, 6, 0, 0);
253 // using += (const ::std::complex<T> &)
254 q2
= ::boost::math::quaternion
<T
>(5, 6, 7, 8);
256 check_exact_quaternion_result(q2
, 10, 12, 7, 8);
258 // using -= (const ::std::complex<T> &)
260 check_exact_quaternion_result(q2
, 5, 6, 7, 8);
262 // using *= (const ::std::complex<T> &)
264 check_exact_quaternion_result(q2
, -11, 60, 83, -2);
267 check_approx_quaternion_result(q2
, 5, 6, 7, 8);
269 q2
= ::boost::math::quaternion
<T
>(4, 5, 7, 8);
272 check_exact_quaternion_result(q1
, 9, 11, 7, 8);
274 check_exact_quaternion_result(q1
, 9, 11, 7, 8);
278 check_exact_quaternion_result(q1
, 1, 1, -7, -8);
280 check_exact_quaternion_result(q1
, -1, -1, 7, 8);
282 // using * (const ::std::complex<T> &, const quaternion<T> &)
284 check_exact_quaternion_result(q1
, -10, 49, -13, 82);
286 // using * (const quaternion<T> &, const ::std::complex<T> &)
288 check_exact_quaternion_result(q1
, -10, 49, 83, -2);
290 // using / (const ::std::complex<T> &, const quaternion<T> &)
292 check_approx_quaternion_result(q1
, T(25) / 77, -T(1) / 154, T(13) / 154, -T(41) / 77);
294 BOOST_CHECK_CLOSE(q1
.R_component_1(), T(5), tol
);
295 BOOST_CHECK_CLOSE(q1
.R_component_2(), T(6), tol
);
296 BOOST_CHECK_SMALL(q1
.R_component_3(), tol
);
297 BOOST_CHECK_SMALL(q1
.R_component_4(), tol
);
299 // using / (const quaternion<T> &, const ::std::complex<T> &)
301 check_approx_quaternion_result(q1
, T(50) / 61, T(1)/ 61, -T(13) / 61, T(82) / 61);
303 check_approx_quaternion_result(q1
, 4, 5, 7, 8);
306 test_compare(q1
, c0
, true);
308 test_compare(q1
, c0
, false);
312 void check_complex_ops() {}
315 void check_complex_ops
<float>() { check_complex_ops_imp
<float>(); }
317 void check_complex_ops
<double>() { check_complex_ops_imp
<double>(); }
319 void check_complex_ops
<long double>() { check_complex_ops_imp
<long double>(); }
321 BOOST_AUTO_TEST_CASE_TEMPLATE(arithmetic_test
, T
, test_types
)
323 typedef typename other_type
<T
>::type other_type
;
324 check_complex_ops
<T
>();
326 T tol
= std::numeric_limits
<T
>::epsilon() * 200;
328 // using default constructor
329 ::boost::math::quaternion
<T
> q0
, q2
;
330 check_exact_quaternion_result(q0
, 0, 0, 0, 0);
331 BOOST_CHECK_EQUAL(q0
, 0);
333 ::boost::math::quaternion
<T
> qa
[2];
334 check_exact_quaternion_result(qa
[0], 0, 0, 0, 0);
335 check_exact_quaternion_result(qa
[1], 0, 0, 0, 0);
336 BOOST_CHECK_EQUAL(qa
[0], 0);
337 BOOST_CHECK_EQUAL(qa
[1], 0.f
);
339 // using constructor "H seen as R^4"
340 ::boost::math::quaternion
<T
> q1(1, 2, 3, 4);
341 check_exact_quaternion_result(q1
, 1, 2, 3, 4);
343 // using untemplated copy constructor
344 ::boost::math::quaternion
<T
> q3(q1
);
345 check_exact_quaternion_result(q3
, 1, 2, 3, 4);
347 // using templated copy constructor
348 ::boost::math::quaternion
<other_type
> qo(5, 6, 7, 8);
349 boost::math::quaternion
<T
> q4(qo
);
350 check_exact_quaternion_result(q4
, 5, 6, 7, 8);
352 // using untemplated assignment operator
354 check_exact_quaternion_result(q0
, 0, 0, 0, 0);
355 //BOOST_CHECK_EQUAL(q3, 0.f);
356 BOOST_CHECK_EQUAL(q3
, q0
);
358 check_exact_quaternion_result(q3
, 5, 6, 7, 8);
360 check_exact_quaternion_result(qa
[0], 5, 6, 7, 8);
362 // using templated assignment operator
364 check_exact_quaternion_result(q4
, 5, 6, 7, 8);
369 // using converting assignment operator
371 check_exact_quaternion_result(q2
, 7, 0, 0, 0);
373 check_exact_quaternion_result(q2
, 33, 0, 0, 0);
375 // using += (const T &)
377 check_exact_quaternion_result(q4
, 12, 6, 7, 8);
379 // using += (const quaternion<X> &)
381 check_exact_quaternion_result(q4
, 17, 12, 14, 16);
383 // using -= (const T &)
385 check_exact_quaternion_result(q4
, 10, 12, 14, 16);
387 // using -= (const quaternion<X> &)
389 check_exact_quaternion_result(q4
, 5, 6, 7, 8);
391 // using *= (const T &)
393 check_exact_quaternion_result(q4
, 35, 42, 49, 56);
394 // using *= (const quaternion<X> &)
396 check_exact_quaternion_result(q4
, -868, 420, 490, 560);
398 // using /= (const T &)
400 check_exact_quaternion_result(q4
, -T(868) / 7, T(420) / 7, T(490) / 7, T(560) / 7);
403 q4
/= boost::math::quaternion
<T
>(9, 4, 6, 2);
404 check_approx_quaternion_result(q4
, T(127) / 137, T(68) / 137, T(13) / 137, T(54) / 137);
405 q4
*= boost::math::quaternion
<T
>(9, 4, 6, 2);
406 check_approx_quaternion_result(q4
, 5, 6, 7, 8);
408 q4
= boost::math::quaternion
<T
>(34, 56, 20, 2);
409 // using + (const T &, const quaternion<T> &)
411 check_exact_quaternion_result(q1
, 41, 56, 20, 2);
413 // using + (const quaternion<T> &, const T &)
415 check_exact_quaternion_result(q1
, 41, 56, 20, 2);
417 // using + (const T &, const quaternion<T> &)
419 check_exact_quaternion_result(q1
, 41, 56, 20, 2);
421 // using + (const quaternion<T> &, const T &)
423 check_exact_quaternion_result(q1
, 41, 56, 20, 2);
425 // using + (const quaternion<T> &,const quaternion<T> &)
427 check_exact_quaternion_result(q1
, 39, 62, 27, 10);
429 // using - (const T &, const quaternion<T> &)
431 check_exact_quaternion_result(q1
, 7-34, -56, -20, -2);
433 // using - (const quaternion<T> &, const T &)
435 check_exact_quaternion_result(q1
, 34-7, 56, 20, 2);
437 // using - (const T &, const quaternion<T> &)
439 check_exact_quaternion_result(q1
, 7-34, -56, -20, -2);
441 // using - (const quaternion<T> &, const T &)
443 check_exact_quaternion_result(q1
, 34-7, 56, 20, 2);
445 // using - (const quaternion<T> &,const quaternion<T> &)
447 check_exact_quaternion_result(q1
, -29, -50, -13, 6);
449 // using * (const T &, const quaternion<T> &)
451 check_exact_quaternion_result(q1
, 238, 392, 140, 14);
453 // using * (const quaternion<T> &, const T &)
455 check_exact_quaternion_result(q1
, 238, 392, 140, 14);
457 // using * (const quaternion<T> &,const quaternion<T> &)
459 check_exact_quaternion_result(q1
, -322, 630, -98, 554);
461 check_exact_quaternion_result(q1
, -322, 338, 774, 10);
463 // using / (const T &, const quaternion<T> &)
465 check_approx_quaternion_result(q1
, T(119) / 2348, -T(49) / 587, -T(35) / 1174, -T(7) / 2348);
467 BOOST_CHECK_CLOSE(q1
.R_component_1(), T(7), tol
);
468 BOOST_CHECK_SMALL(q1
.R_component_2(), tol
);
469 BOOST_CHECK_SMALL(q1
.R_component_3(), tol
);
470 BOOST_CHECK_SMALL(q1
.R_component_3(), tol
);
472 // using / (const quaternion<T> &, const T &)
474 check_approx_quaternion_result(q1
, T(34) / 7, T(56) / 7, T(20) / 7, T(2) / 7);
476 // using / (const quaternion<T> &,const quaternion<T> &)
478 check_approx_quaternion_result(q1
, T(331) / 87, -T(35) / 87, T(149) / 87, -T(89) / 29);
480 check_approx_quaternion_result(q1
, 34, 56, 20, 2);
482 // using + (const quaternion<T> &)
484 check_exact_quaternion_result(q1
, 34, 56, 20, 2);
486 // using - (const quaternion<T> &)
488 check_exact_quaternion_result(q1
, -34, -56, -20, -2);
492 test_compare(q1
, f0
, true);
494 test_compare(q1
, f0
, false);
496 test_compare(q1
, q3
, true);
498 test_compare(q1
, q3
, false);
500 BOOST_CHECK_EQUAL(boost::lexical_cast
<std::string
>(q4
), "(34,56,20,2)");
501 q1
= boost::lexical_cast
<boost::math::quaternion
<T
> >("(34,56,20,2)");
502 check_exact_quaternion_result(q1
, 34, 56, 20, 2);
506 check_exact_quaternion_result(q1
, 34, 56, 20, 2);
507 check_exact_quaternion_result(q4
, 35, 56, 20, 2);
509 check_exact_quaternion_result(q1
, 35, 56, 20, 2);
510 check_exact_quaternion_result(q4
, 34, 56, 20, 2);
512 BOOST_CHECK_EQUAL(real(q4
), 34);
513 check_exact_quaternion_result(unreal(q1
), 0, 56, 20, 2);
514 BOOST_CHECK_EQUAL(sup(q4
), 56);
515 BOOST_CHECK_EQUAL(sup(-q4
), 56);
516 BOOST_CHECK_EQUAL(l1(q4
), 34 + 56 + 20 + 2);
517 BOOST_CHECK_EQUAL(l1(-q4
), 34 + 56 + 20 + 2);
518 BOOST_CHECK_CLOSE(abs(q4
), boost::lexical_cast
<T
>("68.52736679604725626189080285032080446623"), tol
);
519 BOOST_CHECK_EQUAL(norm(q4
), 4696);
520 check_exact_quaternion_result(conj(q4
), 34, -56, -20, -2);
521 check_approx_quaternion_result(exp(q4
), boost::lexical_cast
<T
>("-572700109350177.2871954597833265926769952"), boost::lexical_cast
<T
>("104986825963321.656891930274999993423955"), boost::lexical_cast
<T
>("37495294986900.59174711795535714050855537"), boost::lexical_cast
<T
>("3749529498690.059174711795535714050855537"), 300);
522 check_approx_quaternion_result(pow(q4
, 3), -321776, -4032, -1440, -144);
523 check_approx_quaternion_result(sin(q4
), boost::lexical_cast
<T
>("18285331065398556228976865.03309127394107"), boost::lexical_cast
<T
>("-27602822237164214909853379.68314411086089"), boost::lexical_cast
<T
>("-9858150798987219610661921.315408611021748"), boost::lexical_cast
<T
>("-985815079898721961066192.1315408611021748"), 40);
524 check_approx_quaternion_result(cos(q4
), boost::lexical_cast
<T
>("-29326963088663226843378365.81173441507358"), boost::lexical_cast
<T
>("-17210331032912252411431342.73890926302336"), boost::lexical_cast
<T
>("-6146546797468661575511193.835324736794056"), boost::lexical_cast
<T
>("-614654679746866157551119.3835324736794056"), 40);
525 if(std::numeric_limits
<T
>::max_exponent
>= std::numeric_limits
<double>::max_exponent
)
526 check_approx_quaternion_result(tan(q4
), boost::lexical_cast
<T
>("-3.758831069989140832054627039712718213887e-52"), boost::lexical_cast
<T
>("0.941209703633940052004990419391011076385"), boost::lexical_cast
<T
>("0.3361463227264071614303537212110753844232"), boost::lexical_cast
<T
>("0.03361463227264071614303537212110753844232"), 40);
528 check_approx_quaternion_result(sinh(q4
), boost::lexical_cast
<T
>("-286350054675088.6435977298916624551903343"), boost::lexical_cast
<T
>("52493412981660.82844596513750015091043914"), boost::lexical_cast
<T
>("18747647493450.29587355897767862532515683"), boost::lexical_cast
<T
>("1874764749345.029587355897767862532515683"), 200);
529 check_approx_quaternion_result(cosh(q4
), boost::lexical_cast
<T
>("-286350054675088.6435977298916641374866609"), boost::lexical_cast
<T
>("52493412981660.82844596513749984251351591"), boost::lexical_cast
<T
>("18747647493450.29587355897767851518339854"), boost::lexical_cast
<T
>("1874764749345.029587355897767851518339854"), 200);
530 if(std::numeric_limits
<T
>::max_exponent
>= std::numeric_limits
<double>::max_exponent
)
531 check_approx_quaternion_result(tanh(q4
), boost::lexical_cast
<T
>("0.9999999999999999999999999999945544805016"), boost::lexical_cast
<T
>("-2.075260044344318549117301019071435084233e-30"), boost::lexical_cast
<T
>("-7.411643015515423389704646496683696729404e-31"), boost::lexical_cast
<T
>("-7.411643015515423389704646496683696729404e-32"), 200);
533 #ifndef BOOST_NO_TEMPLATE_TEMPLATES
534 check_approx_quaternion_result(sinc_pi(q4
), boost::lexical_cast
<T
>("-239180458943182912968898.352151239530846"), boost::lexical_cast
<T
>("-417903427539587405399855.0577257263862799"), boost::lexical_cast
<T
>("-149251224121281216214233.9491877594236714"), boost::lexical_cast
<T
>("-14925122412128121621423.39491877594236714"), 200);
535 check_approx_quaternion_result(sinhc_pi(q4
), boost::lexical_cast
<T
>("-1366603120232.604666248483234115586439226"), boost::lexical_cast
<T
>("3794799638667.255581055299959135992677524"), boost::lexical_cast
<T
>("1355285585238.305564662607128262854527687"), boost::lexical_cast
<T
>("135528558523.8305564662607128262854527687"), 200);
538 // Construction variations:
540 T rho
= boost::math::constants::root_two
<T
>() * 2;
541 T theta
= boost::math::constants::pi
<T
>() / 4;
544 q1
= ::boost::math::spherical(rho
, theta
, phi1
, phi2
);
545 check_approx_quaternion_result(q1
, 1, 1, boost::math::constants::root_two
<T
>(), 2, 10);
547 q1
= ::boost::math::semipolar(rho
, alpha
, phi1
, phi2
);
548 check_approx_quaternion_result(q1
, boost::math::constants::root_two
<T
>(), boost::math::constants::root_two
<T
>(), boost::math::constants::root_two
<T
>(), boost::math::constants::root_two
<T
>(), 10);
552 T theta2
= boost::math::constants::half_pi
<T
>();
553 q1
= ::boost::math::multipolar(rho1
, theta1
, rho2
, theta2
);
554 check_approx_quaternion_result(q1
, 1, 0, 0, 2, 10);
556 T radius
= boost::math::constants::root_two
<T
>();
557 T longitude
= boost::math::constants::pi
<T
>() / 4;
558 T lattitude
= boost::math::constants::pi
<T
>() / 3;
559 q1
= ::boost::math::cylindrospherical(t
, radius
, longitude
, lattitude
);
560 check_approx_quaternion_result(q1
, 5, 0.5, 0.5, boost::lexical_cast
<T
>("1.224744871391589049098642037352945695983"), 10);
561 T r
= boost::math::constants::root_two
<T
>();
562 T angle
= boost::math::constants::pi
<T
>() / 4;
565 q1
= ::boost::math::cylindrical(r
, angle
, h1
, h2
);
566 check_approx_quaternion_result(q1
, 1, 1, 3, 4, 10);
568 ::boost::math::quaternion
<T
> quaternion_1(1);
569 ::boost::math::quaternion
<T
> quaternion_i(0, 1);
570 ::boost::math::quaternion
<T
> quaternion_j(0, 0, 1);
571 ::boost::math::quaternion
<T
> quaternion_k(0, 0, 0, 1);
572 check_exact_quaternion_result(quaternion_1
* quaternion_1
, 1, 0, 0, 0);
573 check_exact_quaternion_result(quaternion_1
* quaternion_i
, 0, 1, 0, 0);
574 check_exact_quaternion_result(quaternion_1
* quaternion_j
, 0, 0, 1, 0);
575 check_exact_quaternion_result(quaternion_1
* quaternion_k
, 0, 0, 0, 1);
577 check_exact_quaternion_result(quaternion_i
* quaternion_1
, 0, 1, 0, 0);
578 check_exact_quaternion_result(quaternion_i
* quaternion_i
, -1, 0, 0, 0);
579 check_exact_quaternion_result(quaternion_i
* quaternion_j
, 0, 0, 0, 1);
580 check_exact_quaternion_result(quaternion_i
* quaternion_k
, 0, 0, -1, 0);
582 check_exact_quaternion_result(quaternion_j
* quaternion_1
, 0, 0, 1, 0);
583 check_exact_quaternion_result(quaternion_j
* quaternion_i
, 0, 0, 0, -1);
584 check_exact_quaternion_result(quaternion_j
* quaternion_j
, -1, 0, 0, 0);
585 check_exact_quaternion_result(quaternion_j
* quaternion_k
, 0, 1, 0, 0);
587 check_exact_quaternion_result(quaternion_k
* quaternion_1
, 0, 0, 0, 1);
588 check_exact_quaternion_result(quaternion_k
* quaternion_i
, 0, 0, 1, 0);
589 check_exact_quaternion_result(quaternion_k
* quaternion_j
, 0, -1, 0, 0);
590 check_exact_quaternion_result(quaternion_k
* quaternion_k
, -1, 0, 0, 0);
593 BOOST_AUTO_TEST_CASE_TEMPLATE(multiplication_test
, T
, test_types
)
595 #if BOOST_WORKAROUND(__GNUC__, < 3)
596 #else /* BOOST_WORKAROUND(__GNUC__, < 3) */
597 using ::std::numeric_limits
;
599 using ::boost::math::abs
;
600 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
603 BOOST_TEST_MESSAGE("Testing multiplication for "
604 << string_type_name
<T
>::_() << ".");
606 BOOST_REQUIRE_PREDICATE(::std::less_equal
<T
>(),
607 (abs(::boost::math::quaternion
<T
>(1,0,0,0)*
608 ::boost::math::quaternion
<T
>(1,0,0,0)-static_cast<T
>(1)))
609 (numeric_limits
<T
>::epsilon()));
611 BOOST_REQUIRE_PREDICATE(::std::less_equal
<T
>(),
612 (abs(::boost::math::quaternion
<T
>(0,1,0,0)*
613 ::boost::math::quaternion
<T
>(0,1,0,0)+static_cast<T
>(1)))
614 (numeric_limits
<T
>::epsilon()));
616 BOOST_REQUIRE_PREDICATE(::std::less_equal
<T
>(),
617 (abs(::boost::math::quaternion
<T
>(0,0,1,0)*
618 ::boost::math::quaternion
<T
>(0,0,1,0)+static_cast<T
>(1)))
619 (numeric_limits
<T
>::epsilon()));
621 BOOST_REQUIRE_PREDICATE(::std::less_equal
<T
>(),
622 (abs(::boost::math::quaternion
<T
>(0,0,0,1)*
623 ::boost::math::quaternion
<T
>(0,0,0,1)+static_cast<T
>(1)))
624 (numeric_limits
<T
>::epsilon()));
626 BOOST_REQUIRE_PREDICATE(::std::less_equal
<T
>(),
627 (abs(::boost::math::quaternion
<T
>(0,1,0,0)*
628 ::boost::math::quaternion
<T
>(0,0,1,0)-
629 ::boost::math::quaternion
<T
>(0,0,0,1)))
630 (numeric_limits
<T
>::epsilon()));
632 BOOST_REQUIRE_PREDICATE(::std::less_equal
<T
>(),
633 (abs(::boost::math::quaternion
<T
>(0,0,1,0)*
634 ::boost::math::quaternion
<T
>(0,1,0,0)+
635 ::boost::math::quaternion
<T
>(0,0,0,1)))
636 (numeric_limits
<T
>::epsilon()));
638 BOOST_REQUIRE_PREDICATE(::std::less_equal
<T
>(),
639 (abs(::boost::math::quaternion
<T
>(0,0,1,0)*
640 ::boost::math::quaternion
<T
>(0,0,0,1)-
641 ::boost::math::quaternion
<T
>(0,1,0,0)))
642 (numeric_limits
<T
>::epsilon()));
644 BOOST_REQUIRE_PREDICATE(::std::less_equal
<T
>(),
645 (abs(::boost::math::quaternion
<T
>(0,0,0,1)*
646 ::boost::math::quaternion
<T
>(0,0,1,0)+
647 ::boost::math::quaternion
<T
>(0,1,0,0)))
648 (numeric_limits
<T
>::epsilon()));
650 BOOST_REQUIRE_PREDICATE(::std::less_equal
<T
>(),
651 (abs(::boost::math::quaternion
<T
>(0,0,0,1)*
652 ::boost::math::quaternion
<T
>(0,1,0,0)-
653 ::boost::math::quaternion
<T
>(0,0,1,0)))
654 (numeric_limits
<T
>::epsilon()));
656 BOOST_REQUIRE_PREDICATE(::std::less_equal
<T
>(),
657 (abs(::boost::math::quaternion
<T
>(0,1,0,0)*
658 ::boost::math::quaternion
<T
>(0,0,0,1)+
659 ::boost::math::quaternion
<T
>(0,0,1,0)))
660 (numeric_limits
<T
>::epsilon()));
664 BOOST_AUTO_TEST_CASE_TEMPLATE(exp_test
, T
, test_types
)
666 #if BOOST_WORKAROUND(__GNUC__, < 3)
667 #else /* BOOST_WORKAROUND(__GNUC__, < 3) */
668 using ::std::numeric_limits
;
672 using ::boost::math::abs
;
673 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
676 BOOST_TEST_MESSAGE("Testing exp for "
677 << string_type_name
<T
>::_() << ".");
679 BOOST_CHECK_PREDICATE(::std::less_equal
<T
>(),
680 (abs(exp(::boost::math::quaternion
<T
>
681 (0,4*atan(static_cast<T
>(1)),0,0))+static_cast<T
>(1)))
682 (2*numeric_limits
<T
>::epsilon()));
684 BOOST_CHECK_PREDICATE(::std::less_equal
<T
>(),
685 (abs(exp(::boost::math::quaternion
<T
>
686 (0,0,4*atan(static_cast<T
>(1)),0))+static_cast<T
>(1)))
687 (2*numeric_limits
<T
>::epsilon()));
689 BOOST_CHECK_PREDICATE(::std::less_equal
<T
>(),
690 (abs(exp(::boost::math::quaternion
<T
>
691 (0,0,0,4*atan(static_cast<T
>(1))))+static_cast<T
>(1)))
692 (2*numeric_limits
<T
>::epsilon()));
696 BOOST_AUTO_TEST_CASE_TEMPLATE(cos_test
, T
, test_types
)
698 #if BOOST_WORKAROUND(__GNUC__, < 3)
699 #else /* BOOST_WORKAROUND(__GNUC__, < 3) */
700 using ::std::numeric_limits
;
704 using ::boost::math::abs
;
705 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
708 BOOST_TEST_MESSAGE("Testing cos for "
709 << string_type_name
<T
>::_() << ".");
711 BOOST_CHECK_PREDICATE(::std::less_equal
<T
>(),
712 (abs(static_cast<T
>(4)*cos(::boost::math::quaternion
<T
>
713 (0,log(static_cast<T
>(2)),0,0))-static_cast<T
>(5)))
714 (4*numeric_limits
<T
>::epsilon()));
716 BOOST_CHECK_PREDICATE(::std::less_equal
<T
>(),
717 (abs(static_cast<T
>(4)*cos(::boost::math::quaternion
<T
>
718 (0,0,log(static_cast<T
>(2)),0))-static_cast<T
>(5)))
719 (4*numeric_limits
<T
>::epsilon()));
721 BOOST_CHECK_PREDICATE(::std::less_equal
<T
>(),
722 (abs(static_cast<T
>(4)*cos(::boost::math::quaternion
<T
>
723 (0,0,0,log(static_cast<T
>(2))))-static_cast<T
>(5)))
724 (4*numeric_limits
<T
>::epsilon()));
728 BOOST_AUTO_TEST_CASE_TEMPLATE(sin_test
, T
, test_types
)
730 #if BOOST_WORKAROUND(__GNUC__, < 3)
731 #else /* BOOST_WORKAROUND(__GNUC__, < 3) */
732 using ::std::numeric_limits
;
736 using ::boost::math::abs
;
737 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
740 BOOST_TEST_MESSAGE("Testing sin for "
741 << string_type_name
<T
>::_() << ".");
743 BOOST_CHECK_PREDICATE(::std::less_equal
<T
>(),
744 (abs(static_cast<T
>(4)*sin(::boost::math::quaternion
<T
>
745 (0,log(static_cast<T
>(2)),0,0))
746 -::boost::math::quaternion
<T
>(0,3,0,0)))
747 (4*numeric_limits
<T
>::epsilon()));
749 BOOST_CHECK_PREDICATE(::std::less_equal
<T
>(),
750 (abs(static_cast<T
>(4)*sin(::boost::math::quaternion
<T
>
751 (0,0,log(static_cast<T
>(2)),0))
752 -::boost::math::quaternion
<T
>(0,0,3,0)))
753 (4*numeric_limits
<T
>::epsilon()));
755 BOOST_CHECK_PREDICATE(::std::less_equal
<T
>(),
756 (abs(static_cast<T
>(4)*sin(::boost::math::quaternion
<T
>
757 (0,0,0,log(static_cast<T
>(2))))
758 -::boost::math::quaternion
<T
>(0,0,0,3)))
759 (4*numeric_limits
<T
>::epsilon()));
763 BOOST_AUTO_TEST_CASE_TEMPLATE(cosh_test
, T
, test_types
)
765 #if BOOST_WORKAROUND(__GNUC__, < 3)
766 #else /* BOOST_WORKAROUND(__GNUC__, < 3) */
767 using ::std::numeric_limits
;
771 using ::boost::math::abs
;
772 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
775 BOOST_TEST_MESSAGE("Testing cosh for "
776 << string_type_name
<T
>::_() << ".");
778 BOOST_CHECK_PREDICATE(::std::less_equal
<T
>(),
779 (abs(cosh(::boost::math::quaternion
<T
>
780 (0,4*atan(static_cast<T
>(1)),0,0))
782 (4*numeric_limits
<T
>::epsilon()));
784 BOOST_CHECK_PREDICATE(::std::less_equal
<T
>(),
785 (abs(cosh(::boost::math::quaternion
<T
>
786 (0,0,4*atan(static_cast<T
>(1)),0))
788 (4*numeric_limits
<T
>::epsilon()));
790 BOOST_CHECK_PREDICATE(::std::less_equal
<T
>(),
791 (abs(cosh(::boost::math::quaternion
<T
>
792 (0,0,0,4*atan(static_cast<T
>(1))))
794 (4*numeric_limits
<T
>::epsilon()));
798 BOOST_AUTO_TEST_CASE_TEMPLATE(sinh_test
, T
, test_types
)
800 #if BOOST_WORKAROUND(__GNUC__, < 3)
801 #else /* BOOST_WORKAROUND(__GNUC__, < 3) */
802 using ::std::numeric_limits
;
806 using ::boost::math::abs
;
807 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
810 BOOST_TEST_MESSAGE("Testing sinh for "
811 << string_type_name
<T
>::_() << ".");
813 BOOST_CHECK_PREDICATE(::std::less_equal
<T
>(),
814 (abs(sinh(::boost::math::quaternion
<T
>
815 (0,2*atan(static_cast<T
>(1)),0,0))
816 -::boost::math::quaternion
<T
>(0,1,0,0)))
817 (4*numeric_limits
<T
>::epsilon()));
819 BOOST_CHECK_PREDICATE(::std::less_equal
<T
>(),
820 (abs(sinh(::boost::math::quaternion
<T
>
821 (0,0,2*atan(static_cast<T
>(1)),0))
822 -::boost::math::quaternion
<T
>(0,0,1,0)))
823 (4*numeric_limits
<T
>::epsilon()));
825 BOOST_CHECK_PREDICATE(::std::less_equal
<T
>(),
826 (abs(sinh(::boost::math::quaternion
<T
>
827 (0,0,0,2*atan(static_cast<T
>(1))))
828 -::boost::math::quaternion
<T
>(0,0,0,1)))
829 (4*numeric_limits
<T
>::epsilon()));