]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/math/test/quaternion_test.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / math / test / quaternion_test.cpp
1 // test file for quaternion.hpp
2
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)
7
8
9 #include <iomanip>
10
11
12 #include <boost/mpl/list.hpp>
13
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>
19
20 #include <boost/math/quaternion.hpp>
21
22 #ifdef BOOST_MSVC
23 #pragma warning(disable:4127) // conditional expression is constant
24 #endif
25
26 template<typename T>
27 struct string_type_name;
28
29 #define DEFINE_TYPE_NAME(Type) \
30 template<> struct string_type_name<Type> \
31 { \
32 static char const * _() \
33 { \
34 return #Type; \
35 } \
36 }
37
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> >);
43
44 #if BOOST_WORKAROUND(BOOST_MSVC, < 1900)
45 # define CPP_DEC_FLOAT_TEST
46 #else
47 # define CPP_DEC_FLOAT_TEST , boost::multiprecision::number<boost::multiprecision::cpp_dec_float<25> >
48 #endif
49 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
50 # define LD_TEST , long double
51 #else
52 # define LD_TEST
53 #endif
54
55
56 typedef boost::mpl::list<float,double LD_TEST, boost::multiprecision::cpp_bin_float_quad CPP_DEC_FLOAT_TEST > test_types;
57
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;
63 #else
64 typedef boost::mpl::list<float,double,long double> near_eps_test_types;
65 #endif
66
67
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:
71 using ::std::sqrt;
72 using ::std::atan;
73 using ::std::log;
74 using ::std::exp;
75 using ::std::cos;
76 using ::std::sin;
77 using ::std::tan;
78 using ::std::cosh;
79 using ::std::sinh;
80 using ::std::tanh;
81
82 using ::std::numeric_limits;
83
84 using ::boost::math::abs;
85 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
86
87 #ifdef BOOST_NO_STDC_NAMESPACE
88 using ::sqrt;
89 using ::atan;
90 using ::log;
91 using ::exp;
92 using ::cos;
93 using ::sin;
94 using ::tan;
95 using ::cosh;
96 using ::sinh;
97 using ::tanh;
98 #endif /* BOOST_NO_STDC_NAMESPACE */
99
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 */
119
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)
126 {
127 return(fabs(v));
128 }
129
130 inline double abs(double v)
131 {
132 return(fabs(v));
133 }
134
135 inline long double abs(long double v)
136 {
137 return(fabs(v));
138 }
139 #endif /* !((__INTEL__ && _WIN32) && BOOST_WORKAROUND(__MWERKS__, >= 0x3201)) */
140 #endif /* defined(_MSC_EXTENSIONS) && BOOST_WORKAROUND(_MSC_VER, < 1310) */
141
142
143 // explicit (if ludicrous) instanciation
144 #if !BOOST_WORKAROUND(__GNUC__, < 3)
145 template class ::boost::math::quaternion<int>;
146 #else
147 // gcc doesn't like the absolutely-qualified namespace
148 template class boost::math::quaternion<int>;
149 #endif /* !BOOST_WORKAROUND(__GNUC__) */
150
151 template <class T>
152 struct other_type
153 {
154 typedef double type;
155 };
156 template<>
157 struct other_type<double>
158 {
159 typedef float type;
160 };
161 template<>
162 struct other_type<float>
163 {
164 typedef short type;
165 };
166
167
168 template <class T, class U>
169 void test_compare(const T& a, const U& b, bool eq)
170 {
171 if (eq)
172 {
173 BOOST_CHECK_EQUAL(a, b);
174 BOOST_CHECK((a != b) == false);
175 BOOST_CHECK_EQUAL(b, a);
176 BOOST_CHECK((b != a) == false);
177 }
178 else
179 {
180 BOOST_CHECK_NE(a, b);
181 BOOST_CHECK((a == b) == false);
182 BOOST_CHECK_NE(b, a);
183 BOOST_CHECK((b == a) == false);
184 }
185 }
186
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)
189 {
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)));
196 }
197
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)
200 {
201 T tol = std::numeric_limits<T>::epsilon() * eps * 100; // epsilon as a persentage.
202 using std::abs;
203 if (abs(a) > tol / 100)
204 {
205 BOOST_CHECK_CLOSE(q.R_component_1(), static_cast<T>(a), tol);
206 }
207 else
208 {
209 BOOST_CHECK_SMALL(q.R_component_1(), tol);
210 }
211 if (abs(b) > tol)
212 {
213 BOOST_CHECK_CLOSE(q.R_component_2(), static_cast<T>(b), tol);
214 }
215 else
216 {
217 BOOST_CHECK_SMALL(q.R_component_2(), tol);
218 }
219 if (abs(c) > tol)
220 {
221 BOOST_CHECK_CLOSE(q.R_component_3(), static_cast<T>(c), tol);
222 }
223 else
224 {
225 BOOST_CHECK_SMALL(q.R_component_3(), tol);
226 }
227 if (abs(d) > tol)
228 {
229 BOOST_CHECK_CLOSE(q.R_component_4(), static_cast<T>(d), tol);
230 }
231 else
232 {
233 BOOST_CHECK_SMALL(q.R_component_4(), tol);
234 }
235 }
236
237 template <class T>
238 void check_complex_ops_imp()
239 {
240 T tol = std::numeric_limits<T>::epsilon() * 200;
241
242 ::std::complex<T> c0(5, 6);
243
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);
247
248 // using converting assignment operator
249 q2 = 0;
250 q2 = c0;
251 check_exact_quaternion_result(q2, 5, 6, 0, 0);
252
253 // using += (const ::std::complex<T> &)
254 q2 = ::boost::math::quaternion<T>(5, 6, 7, 8);
255 q2 += c0;
256 check_exact_quaternion_result(q2, 10, 12, 7, 8);
257
258 // using -= (const ::std::complex<T> &)
259 q2 -= c0;
260 check_exact_quaternion_result(q2, 5, 6, 7, 8);
261
262 // using *= (const ::std::complex<T> &)
263 q2 *= c0;
264 check_exact_quaternion_result(q2, -11, 60, 83, -2);
265
266 q2 /= c0;
267 check_approx_quaternion_result(q2, 5, 6, 7, 8);
268
269 q2 = ::boost::math::quaternion<T>(4, 5, 7, 8);
270 // operator +
271 q1 = c0 + q2;
272 check_exact_quaternion_result(q1, 9, 11, 7, 8);
273 q1 = q2 + c0;
274 check_exact_quaternion_result(q1, 9, 11, 7, 8);
275
276 // operator -
277 q1 = c0 - q2;
278 check_exact_quaternion_result(q1, 1, 1, -7, -8);
279 q1 = q2 - c0;
280 check_exact_quaternion_result(q1, -1, -1, 7, 8);
281
282 // using * (const ::std::complex<T> &, const quaternion<T> &)
283 q1 = c0 * q2;
284 check_exact_quaternion_result(q1, -10, 49, -13, 82);
285
286 // using * (const quaternion<T> &, const ::std::complex<T> &)
287 q1 = q2 * c0;
288 check_exact_quaternion_result(q1, -10, 49, 83, -2);
289
290 // using / (const ::std::complex<T> &, const quaternion<T> &)
291 q1 = c0 / q2;
292 check_approx_quaternion_result(q1, T(25) / 77, -T(1) / 154, T(13) / 154, -T(41) / 77);
293 q1 *= q2;
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);
298
299 // using / (const quaternion<T> &, const ::std::complex<T> &)
300 q1 = q2 / c0;
301 check_approx_quaternion_result(q1, T(50) / 61, T(1)/ 61, -T(13) / 61, T(82) / 61);
302 q1 *= c0;
303 check_approx_quaternion_result(q1, 4, 5, 7, 8);
304
305 q1 = c0;
306 test_compare(q1, c0, true);
307 q1 += 1;
308 test_compare(q1, c0, false);
309 }
310
311 template <class T>
312 void check_complex_ops() {}
313
314 template<>
315 void check_complex_ops<float>() { check_complex_ops_imp<float>(); }
316 template<>
317 void check_complex_ops<double>() { check_complex_ops_imp<double>(); }
318 template<>
319 void check_complex_ops<long double>() { check_complex_ops_imp<long double>(); }
320
321 BOOST_AUTO_TEST_CASE_TEMPLATE(arithmetic_test, T, test_types)
322 {
323 typedef typename other_type<T>::type other_type;
324 check_complex_ops<T>();
325
326 T tol = std::numeric_limits<T>::epsilon() * 200;
327
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);
332
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);
338
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);
342
343 // using untemplated copy constructor
344 ::boost::math::quaternion<T> q3(q1);
345 check_exact_quaternion_result(q3, 1, 2, 3, 4);
346
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);
351
352 // using untemplated assignment operator
353 q3 = q0;
354 check_exact_quaternion_result(q0, 0, 0, 0, 0);
355 //BOOST_CHECK_EQUAL(q3, 0.f);
356 BOOST_CHECK_EQUAL(q3, q0);
357 q3 = q4;
358 check_exact_quaternion_result(q3, 5, 6, 7, 8);
359 qa[0] = q4;
360 check_exact_quaternion_result(qa[0], 5, 6, 7, 8);
361
362 // using templated assignment operator
363 q4 = qo;
364 check_exact_quaternion_result(q4, 5, 6, 7, 8);
365
366 other_type f0(7);
367 T f1(7);
368
369 // using converting assignment operator
370 q2 = f0;
371 check_exact_quaternion_result(q2, 7, 0, 0, 0);
372 q2 = 33.;
373 check_exact_quaternion_result(q2, 33, 0, 0, 0);
374
375 // using += (const T &)
376 q4 += f0;
377 check_exact_quaternion_result(q4, 12, 6, 7, 8);
378
379 // using += (const quaternion<X> &)
380 q4 += q3;
381 check_exact_quaternion_result(q4, 17, 12, 14, 16);
382
383 // using -= (const T &)
384 q4 -= f0;
385 check_exact_quaternion_result(q4, 10, 12, 14, 16);
386
387 // using -= (const quaternion<X> &)
388 q4 -= q3;
389 check_exact_quaternion_result(q4, 5, 6, 7, 8);
390
391 // using *= (const T &)
392 q4 *= f0;
393 check_exact_quaternion_result(q4, 35, 42, 49, 56);
394 // using *= (const quaternion<X> &)
395 q4 *= q3;
396 check_exact_quaternion_result(q4, -868, 420, 490, 560);
397
398 // using /= (const T &)
399 q4 /= f0;
400 check_exact_quaternion_result(q4, -T(868) / 7, T(420) / 7, T(490) / 7, T(560) / 7);
401
402 q4 = q3;
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);
407
408 q4 = boost::math::quaternion<T>(34, 56, 20, 2);
409 // using + (const T &, const quaternion<T> &)
410 q1 = f1 + q4;
411 check_exact_quaternion_result(q1, 41, 56, 20, 2);
412
413 // using + (const quaternion<T> &, const T &)
414 q1 = q4 + f1;
415 check_exact_quaternion_result(q1, 41, 56, 20, 2);
416
417 // using + (const T &, const quaternion<T> &)
418 q1 = f0 + q4;
419 check_exact_quaternion_result(q1, 41, 56, 20, 2);
420
421 // using + (const quaternion<T> &, const T &)
422 q1 = q4 + f0;
423 check_exact_quaternion_result(q1, 41, 56, 20, 2);
424
425 // using + (const quaternion<T> &,const quaternion<T> &)
426 q1 = q3 + q4;
427 check_exact_quaternion_result(q1, 39, 62, 27, 10);
428
429 // using - (const T &, const quaternion<T> &)
430 q1 = f1 - q4;
431 check_exact_quaternion_result(q1, 7-34, -56, -20, -2);
432
433 // using - (const quaternion<T> &, const T &)
434 q1 = q4 - f1;
435 check_exact_quaternion_result(q1, 34-7, 56, 20, 2);
436
437 // using - (const T &, const quaternion<T> &)
438 q1 = f0 - q4;
439 check_exact_quaternion_result(q1, 7-34, -56, -20, -2);
440
441 // using - (const quaternion<T> &, const T &)
442 q1 = q4 - f0;
443 check_exact_quaternion_result(q1, 34-7, 56, 20, 2);
444
445 // using - (const quaternion<T> &,const quaternion<T> &)
446 q1 = q3 - q4;
447 check_exact_quaternion_result(q1, -29, -50, -13, 6);
448
449 // using * (const T &, const quaternion<T> &)
450 q1 = f0 * q4;
451 check_exact_quaternion_result(q1, 238, 392, 140, 14);
452
453 // using * (const quaternion<T> &, const T &)
454 q1 = q4 * f0;
455 check_exact_quaternion_result(q1, 238, 392, 140, 14);
456
457 // using * (const quaternion<T> &,const quaternion<T> &)
458 q1 = q4 * q3;
459 check_exact_quaternion_result(q1, -322, 630, -98, 554);
460 q1 = q3 * q4;
461 check_exact_quaternion_result(q1, -322, 338, 774, 10);
462
463 // using / (const T &, const quaternion<T> &)
464 q1 = T(f0) / q4;
465 check_approx_quaternion_result(q1, T(119) / 2348, -T(49) / 587, -T(35) / 1174, -T(7) / 2348);
466 q1 *= q4;
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);
471
472 // using / (const quaternion<T> &, const T &)
473 q1 = q4 / T(f0);
474 check_approx_quaternion_result(q1, T(34) / 7, T(56) / 7, T(20) / 7, T(2) / 7);
475
476 // using / (const quaternion<T> &,const quaternion<T> &)
477 q1 = q4 / q3;
478 check_approx_quaternion_result(q1, T(331) / 87, -T(35) / 87, T(149) / 87, -T(89) / 29);
479 q1 *= q3;
480 check_approx_quaternion_result(q1, 34, 56, 20, 2);
481
482 // using + (const quaternion<T> &)
483 q1 = +q4;
484 check_exact_quaternion_result(q1, 34, 56, 20, 2);
485
486 // using - (const quaternion<T> &)
487 q1 = -q4;
488 check_exact_quaternion_result(q1, -34, -56, -20, -2);
489
490 // comparisons:
491 q1 = f0;
492 test_compare(q1, f0, true);
493 q1 += 1;
494 test_compare(q1, f0, false);
495 q1 = q3;
496 test_compare(q1, q3, true);
497 q1 += 1;
498 test_compare(q1, q3, false);
499
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);
503
504 q1 = q4 + 1;
505 q1.swap(q4);
506 check_exact_quaternion_result(q1, 34, 56, 20, 2);
507 check_exact_quaternion_result(q4, 35, 56, 20, 2);
508 swap(q1, q4);
509 check_exact_quaternion_result(q1, 35, 56, 20, 2);
510 check_exact_quaternion_result(q4, 34, 56, 20, 2);
511
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);
527
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);
532
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);
536 #endif
537 //
538 // Construction variations:
539 //
540 T rho = boost::math::constants::root_two<T>() * 2;
541 T theta = boost::math::constants::pi<T>() / 4;
542 T phi1 = theta;
543 T phi2 = theta;
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);
546 T alpha = theta;
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);
549 T rho1 = 1;
550 T rho2 = 2;
551 T theta1 = 0;
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);
555 T t = 5;
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;
563 T h1 = 3;
564 T h2 = 4;
565 q1 = ::boost::math::cylindrical(r, angle, h1, h2);
566 check_approx_quaternion_result(q1, 1, 1, 3, 4, 10);
567
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);
576
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);
581
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);
586
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);
591 }
592
593 BOOST_AUTO_TEST_CASE_TEMPLATE(multiplication_test, T, test_types)
594 {
595 #if BOOST_WORKAROUND(__GNUC__, < 3)
596 #else /* BOOST_WORKAROUND(__GNUC__, < 3) */
597 using ::std::numeric_limits;
598
599 using ::boost::math::abs;
600 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
601
602
603 BOOST_TEST_MESSAGE("Testing multiplication for "
604 << string_type_name<T>::_() << ".");
605
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()));
610
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()));
615
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()));
620
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()));
625
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()));
631
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()));
637
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()));
643
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()));
649
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()));
655
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()));
661 }
662
663
664 BOOST_AUTO_TEST_CASE_TEMPLATE(exp_test, T, test_types)
665 {
666 #if BOOST_WORKAROUND(__GNUC__, < 3)
667 #else /* BOOST_WORKAROUND(__GNUC__, < 3) */
668 using ::std::numeric_limits;
669
670 using ::std::atan;
671
672 using ::boost::math::abs;
673 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
674
675
676 BOOST_TEST_MESSAGE("Testing exp for "
677 << string_type_name<T>::_() << ".");
678
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()));
683
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()));
688
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()));
693 }
694
695
696 BOOST_AUTO_TEST_CASE_TEMPLATE(cos_test, T, test_types)
697 {
698 #if BOOST_WORKAROUND(__GNUC__, < 3)
699 #else /* BOOST_WORKAROUND(__GNUC__, < 3) */
700 using ::std::numeric_limits;
701
702 using ::std::log;
703
704 using ::boost::math::abs;
705 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
706
707
708 BOOST_TEST_MESSAGE("Testing cos for "
709 << string_type_name<T>::_() << ".");
710
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()));
715
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()));
720
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()));
725 }
726
727
728 BOOST_AUTO_TEST_CASE_TEMPLATE(sin_test, T, test_types)
729 {
730 #if BOOST_WORKAROUND(__GNUC__, < 3)
731 #else /* BOOST_WORKAROUND(__GNUC__, < 3) */
732 using ::std::numeric_limits;
733
734 using ::std::log;
735
736 using ::boost::math::abs;
737 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
738
739
740 BOOST_TEST_MESSAGE("Testing sin for "
741 << string_type_name<T>::_() << ".");
742
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()));
748
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()));
754
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()));
760 }
761
762
763 BOOST_AUTO_TEST_CASE_TEMPLATE(cosh_test, T, test_types)
764 {
765 #if BOOST_WORKAROUND(__GNUC__, < 3)
766 #else /* BOOST_WORKAROUND(__GNUC__, < 3) */
767 using ::std::numeric_limits;
768
769 using ::std::atan;
770
771 using ::boost::math::abs;
772 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
773
774
775 BOOST_TEST_MESSAGE("Testing cosh for "
776 << string_type_name<T>::_() << ".");
777
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))
781 +static_cast<T>(1)))
782 (4*numeric_limits<T>::epsilon()));
783
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))
787 +static_cast<T>(1)))
788 (4*numeric_limits<T>::epsilon()));
789
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))))
793 +static_cast<T>(1)))
794 (4*numeric_limits<T>::epsilon()));
795 }
796
797
798 BOOST_AUTO_TEST_CASE_TEMPLATE(sinh_test, T, test_types)
799 {
800 #if BOOST_WORKAROUND(__GNUC__, < 3)
801 #else /* BOOST_WORKAROUND(__GNUC__, < 3) */
802 using ::std::numeric_limits;
803
804 using ::std::atan;
805
806 using ::boost::math::abs;
807 #endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
808
809
810 BOOST_TEST_MESSAGE("Testing sinh for "
811 << string_type_name<T>::_() << ".");
812
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()));
818
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()));
824
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()));
830 }
831