]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/math/test/quaternion_test.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / math / test / quaternion_test.cpp
CommitLineData
7c673cae
FG
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
b32b8144 14#define BOOST_TEST_MAIN
7c673cae
FG
15#include <boost/test/unit_test.hpp>
16#include <boost/test/unit_test_log.hpp>
b32b8144
FG
17#include <boost/multiprecision/cpp_bin_float.hpp>
18#include <boost/multiprecision/cpp_dec_float.hpp>
7c673cae
FG
19
20#include <boost/math/quaternion.hpp>
21
1e59de90 22#ifdef _MSC_VER
b32b8144
FG
23#pragma warning(disable:4127) // conditional expression is constant
24#endif
25
7c673cae
FG
26template<typename T>
27struct string_type_name;
28
29#define DEFINE_TYPE_NAME(Type) \
30template<> struct string_type_name<Type> \
31{ \
32 static char const * _() \
33 { \
34 return #Type; \
35 } \
36}
37
38DEFINE_TYPE_NAME(float);
39DEFINE_TYPE_NAME(double);
40DEFINE_TYPE_NAME(long double);
b32b8144
FG
41DEFINE_TYPE_NAME(boost::multiprecision::cpp_bin_float_quad);
42DEFINE_TYPE_NAME(boost::multiprecision::number<boost::multiprecision::cpp_dec_float<25> >);
7c673cae 43
b32b8144
FG
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
7c673cae 49#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
b32b8144 50# define LD_TEST , long double
7c673cae 51#else
b32b8144 52# define LD_TEST
7c673cae
FG
53#endif
54
b32b8144
FG
55
56typedef boost::mpl::list<float,double LD_TEST, boost::multiprecision::cpp_bin_float_quad CPP_DEC_FLOAT_TEST > test_types;
57
7c673cae
FG
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)
62typedef boost::mpl::list<float,double> near_eps_test_types;
63#else
64typedef 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:
71using ::std::sqrt;
72using ::std::atan;
73using ::std::log;
74using ::std::exp;
75using ::std::cos;
76using ::std::sin;
77using ::std::tan;
78using ::std::cosh;
79using ::std::sinh;
80using ::std::tanh;
81
82using ::std::numeric_limits;
83
84using ::boost::math::abs;
85#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
86
87#ifdef BOOST_NO_STDC_NAMESPACE
88using ::sqrt;
89using ::atan;
90using ::log;
91using ::exp;
92using ::cos;
93using ::sin;
94using ::tan;
95using ::cosh;
96using ::sinh;
97using ::tanh;
98#endif /* BOOST_NO_STDC_NAMESPACE */
99
100#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
101using ::boost::math::real;
102using ::boost::math::unreal;
103using ::boost::math::sup;
104using ::boost::math::l1;
105using ::boost::math::abs;
106using ::boost::math::norm;
107using ::boost::math::conj;
108using ::boost::math::exp;
109using ::boost::math::pow;
110using ::boost::math::cos;
111using ::boost::math::sin;
112using ::boost::math::tan;
113using ::boost::math::cosh;
114using ::boost::math::sinh;
115using ::boost::math::tanh;
116using ::boost::math::sinc_pi;
117using ::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))
125inline float abs(float v)
126{
127 return(fabs(v));
128}
129
130inline double abs(double v)
131{
132 return(fabs(v));
133}
134
135inline 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)
145template class ::boost::math::quaternion<int>;
146#else
147// gcc doesn't like the absolutely-qualified namespace
148template class boost::math::quaternion<int>;
149#endif /* !BOOST_WORKAROUND(__GNUC__) */
150
b32b8144
FG
151template <class T>
152struct other_type
153{
154 typedef double type;
155};
156template<>
157struct other_type<double>
158{
159 typedef float type;
160};
161template<>
162struct other_type<float>
163{
164 typedef short type;
165};
7c673cae
FG
166
167
b32b8144
FG
168template <class T, class U>
169void test_compare(const T& a, const U& b, bool eq)
7c673cae 170{
b32b8144
FG
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
187template <class T, class R1, class R2, class R3, class R4>
188void 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
198template <class T, class R1, class R2, class R3, class R4>
199void check_approx_quaternion_result(const boost::math::quaternion<T>& q, R1 a, R2 b, R3 c, R4 d, int eps = 10)
200{
f67539c2 201 T tol = std::numeric_limits<T>::epsilon() * eps * 100; // epsilon as a percentage.
b32b8144
FG
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
237template <class T>
238void 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
311template <class T>
312void check_complex_ops() {}
313
314template<>
315void check_complex_ops<float>() { check_complex_ops_imp<float>(); }
316template<>
317void check_complex_ops<double>() { check_complex_ops_imp<double>(); }
318template<>
319void check_complex_ops<long double>() { check_complex_ops_imp<long double>(); }
320
321BOOST_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
7c673cae 391 // using *= (const T &)
b32b8144
FG
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;
1e59de90
TL
400 if(std::numeric_limits<T>::radix == 2)
401 check_exact_quaternion_result(q4, -T(868) / 7, T(420) / 7, T(490) / 7, T(560) / 7);
402 else
403 // cpp_dec_float division is still inextact / not rounded:
404 check_approx_quaternion_result(q4, -T(868) / 7, T(420) / 7, T(490) / 7, T(560) / 7);
b32b8144
FG
405
406 q4 = q3;
407 q4 /= boost::math::quaternion<T>(9, 4, 6, 2);
408 check_approx_quaternion_result(q4, T(127) / 137, T(68) / 137, T(13) / 137, T(54) / 137);
409 q4 *= boost::math::quaternion<T>(9, 4, 6, 2);
410 check_approx_quaternion_result(q4, 5, 6, 7, 8);
411
412 q4 = boost::math::quaternion<T>(34, 56, 20, 2);
413 // using + (const T &, const quaternion<T> &)
414 q1 = f1 + q4;
415 check_exact_quaternion_result(q1, 41, 56, 20, 2);
416
417 // using + (const quaternion<T> &, const T &)
418 q1 = q4 + f1;
419 check_exact_quaternion_result(q1, 41, 56, 20, 2);
420
421 // using + (const T &, const quaternion<T> &)
422 q1 = f0 + q4;
423 check_exact_quaternion_result(q1, 41, 56, 20, 2);
424
425 // using + (const quaternion<T> &, const T &)
426 q1 = q4 + f0;
427 check_exact_quaternion_result(q1, 41, 56, 20, 2);
428
429 // using + (const quaternion<T> &,const quaternion<T> &)
430 q1 = q3 + q4;
431 check_exact_quaternion_result(q1, 39, 62, 27, 10);
432
433 // using - (const T &, const quaternion<T> &)
434 q1 = f1 - q4;
435 check_exact_quaternion_result(q1, 7-34, -56, -20, -2);
436
437 // using - (const quaternion<T> &, const T &)
438 q1 = q4 - f1;
439 check_exact_quaternion_result(q1, 34-7, 56, 20, 2);
440
441 // using - (const T &, const quaternion<T> &)
442 q1 = f0 - q4;
443 check_exact_quaternion_result(q1, 7-34, -56, -20, -2);
444
445 // using - (const quaternion<T> &, const T &)
446 q1 = q4 - f0;
447 check_exact_quaternion_result(q1, 34-7, 56, 20, 2);
448
449 // using - (const quaternion<T> &,const quaternion<T> &)
450 q1 = q3 - q4;
451 check_exact_quaternion_result(q1, -29, -50, -13, 6);
452
453 // using * (const T &, const quaternion<T> &)
454 q1 = f0 * q4;
455 check_exact_quaternion_result(q1, 238, 392, 140, 14);
456
457 // using * (const quaternion<T> &, const T &)
458 q1 = q4 * f0;
459 check_exact_quaternion_result(q1, 238, 392, 140, 14);
460
461 // using * (const quaternion<T> &,const quaternion<T> &)
462 q1 = q4 * q3;
463 check_exact_quaternion_result(q1, -322, 630, -98, 554);
464 q1 = q3 * q4;
465 check_exact_quaternion_result(q1, -322, 338, 774, 10);
466
467 // using / (const T &, const quaternion<T> &)
468 q1 = T(f0) / q4;
469 check_approx_quaternion_result(q1, T(119) / 2348, -T(49) / 587, -T(35) / 1174, -T(7) / 2348);
470 q1 *= q4;
471 BOOST_CHECK_CLOSE(q1.R_component_1(), T(7), tol);
472 BOOST_CHECK_SMALL(q1.R_component_2(), tol);
473 BOOST_CHECK_SMALL(q1.R_component_3(), tol);
474 BOOST_CHECK_SMALL(q1.R_component_3(), tol);
475
476 // using / (const quaternion<T> &, const T &)
477 q1 = q4 / T(f0);
478 check_approx_quaternion_result(q1, T(34) / 7, T(56) / 7, T(20) / 7, T(2) / 7);
479
480 // using / (const quaternion<T> &,const quaternion<T> &)
481 q1 = q4 / q3;
482 check_approx_quaternion_result(q1, T(331) / 87, -T(35) / 87, T(149) / 87, -T(89) / 29);
483 q1 *= q3;
484 check_approx_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 // using - (const quaternion<T> &)
491 q1 = -q4;
492 check_exact_quaternion_result(q1, -34, -56, -20, -2);
493
494 // comparisons:
495 q1 = f0;
496 test_compare(q1, f0, true);
497 q1 += 1;
498 test_compare(q1, f0, false);
499 q1 = q3;
500 test_compare(q1, q3, true);
501 q1 += 1;
502 test_compare(q1, q3, false);
503
1e59de90 504 #ifndef BOOST_MATH_STANDALONE
b32b8144
FG
505 BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(q4), "(34,56,20,2)");
506 q1 = boost::lexical_cast<boost::math::quaternion<T> >("(34,56,20,2)");
507 check_exact_quaternion_result(q1, 34, 56, 20, 2);
508
509 q1 = q4 + 1;
510 q1.swap(q4);
511 check_exact_quaternion_result(q1, 34, 56, 20, 2);
512 check_exact_quaternion_result(q4, 35, 56, 20, 2);
513 swap(q1, q4);
514 check_exact_quaternion_result(q1, 35, 56, 20, 2);
515 check_exact_quaternion_result(q4, 34, 56, 20, 2);
516
517 BOOST_CHECK_EQUAL(real(q4), 34);
518 check_exact_quaternion_result(unreal(q1), 0, 56, 20, 2);
519 BOOST_CHECK_EQUAL(sup(q4), 56);
520 BOOST_CHECK_EQUAL(sup(-q4), 56);
521 BOOST_CHECK_EQUAL(l1(q4), 34 + 56 + 20 + 2);
522 BOOST_CHECK_EQUAL(l1(-q4), 34 + 56 + 20 + 2);
523 BOOST_CHECK_CLOSE(abs(q4), boost::lexical_cast<T>("68.52736679604725626189080285032080446623"), tol);
524 BOOST_CHECK_EQUAL(norm(q4), 4696);
525 check_exact_quaternion_result(conj(q4), 34, -56, -20, -2);
526 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);
527 check_approx_quaternion_result(pow(q4, 3), -321776, -4032, -1440, -144);
528 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);
529 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);
530 if(std::numeric_limits<T>::max_exponent >= std::numeric_limits<double>::max_exponent)
531 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);
532
533 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);
534 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);
535 if(std::numeric_limits<T>::max_exponent >= std::numeric_limits<double>::max_exponent)
536 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);
537
538#ifndef BOOST_NO_TEMPLATE_TEMPLATES
539 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);
540 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);
7c673cae 541#endif
1e59de90 542 #endif // BOOST_MATH_STANDALONE
b32b8144
FG
543 //
544 // Construction variations:
545 //
546 T rho = boost::math::constants::root_two<T>() * 2;
547 T theta = boost::math::constants::pi<T>() / 4;
548 T phi1 = theta;
549 T phi2 = theta;
550 q1 = ::boost::math::spherical(rho, theta, phi1, phi2);
551 check_approx_quaternion_result(q1, 1, 1, boost::math::constants::root_two<T>(), 2, 10);
552 T alpha = theta;
553 q1 = ::boost::math::semipolar(rho, alpha, phi1, phi2);
554 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);
555 T rho1 = 1;
556 T rho2 = 2;
557 T theta1 = 0;
558 T theta2 = boost::math::constants::half_pi<T>();
559 q1 = ::boost::math::multipolar(rho1, theta1, rho2, theta2);
560 check_approx_quaternion_result(q1, 1, 0, 0, 2, 10);
561 T t = 5;
562 T radius = boost::math::constants::root_two<T>();
563 T longitude = boost::math::constants::pi<T>() / 4;
f67539c2
TL
564 T latitude = boost::math::constants::pi<T>() / 3;
565 q1 = ::boost::math::cylindrospherical(t, radius, longitude, latitude);
1e59de90
TL
566
567 #ifndef BOOST_MATH_STANDALONE
b32b8144 568 check_approx_quaternion_result(q1, 5, 0.5, 0.5, boost::lexical_cast<T>("1.224744871391589049098642037352945695983"), 10);
1e59de90
TL
569 #endif
570
b32b8144
FG
571 T r = boost::math::constants::root_two<T>();
572 T angle = boost::math::constants::pi<T>() / 4;
573 T h1 = 3;
574 T h2 = 4;
575 q1 = ::boost::math::cylindrical(r, angle, h1, h2);
576 check_approx_quaternion_result(q1, 1, 1, 3, 4, 10);
577
578 ::boost::math::quaternion<T> quaternion_1(1);
579 ::boost::math::quaternion<T> quaternion_i(0, 1);
580 ::boost::math::quaternion<T> quaternion_j(0, 0, 1);
581 ::boost::math::quaternion<T> quaternion_k(0, 0, 0, 1);
582 check_exact_quaternion_result(quaternion_1 * quaternion_1, 1, 0, 0, 0);
583 check_exact_quaternion_result(quaternion_1 * quaternion_i, 0, 1, 0, 0);
584 check_exact_quaternion_result(quaternion_1 * quaternion_j, 0, 0, 1, 0);
585 check_exact_quaternion_result(quaternion_1 * quaternion_k, 0, 0, 0, 1);
586
587 check_exact_quaternion_result(quaternion_i * quaternion_1, 0, 1, 0, 0);
588 check_exact_quaternion_result(quaternion_i * quaternion_i, -1, 0, 0, 0);
589 check_exact_quaternion_result(quaternion_i * quaternion_j, 0, 0, 0, 1);
590 check_exact_quaternion_result(quaternion_i * quaternion_k, 0, 0, -1, 0);
591
592 check_exact_quaternion_result(quaternion_j * quaternion_1, 0, 0, 1, 0);
593 check_exact_quaternion_result(quaternion_j * quaternion_i, 0, 0, 0, -1);
594 check_exact_quaternion_result(quaternion_j * quaternion_j, -1, 0, 0, 0);
595 check_exact_quaternion_result(quaternion_j * quaternion_k, 0, 1, 0, 0);
596
597 check_exact_quaternion_result(quaternion_k * quaternion_1, 0, 0, 0, 1);
598 check_exact_quaternion_result(quaternion_k * quaternion_i, 0, 0, 1, 0);
599 check_exact_quaternion_result(quaternion_k * quaternion_j, 0, -1, 0, 0);
600 check_exact_quaternion_result(quaternion_k * quaternion_k, -1, 0, 0, 0);
7c673cae
FG
601}
602
b32b8144 603BOOST_AUTO_TEST_CASE_TEMPLATE(multiplication_test, T, test_types)
7c673cae
FG
604{
605#if BOOST_WORKAROUND(__GNUC__, < 3)
606#else /* BOOST_WORKAROUND(__GNUC__, < 3) */
607 using ::std::numeric_limits;
608
609 using ::boost::math::abs;
610#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
611
612
613 BOOST_TEST_MESSAGE("Testing multiplication for "
614 << string_type_name<T>::_() << ".");
615
616 BOOST_REQUIRE_PREDICATE(::std::less_equal<T>(),
617 (abs(::boost::math::quaternion<T>(1,0,0,0)*
618 ::boost::math::quaternion<T>(1,0,0,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,1,0,0)*
623 ::boost::math::quaternion<T>(0,1,0,0)+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,0,1,0)*
628 ::boost::math::quaternion<T>(0,0,1,0)+static_cast<T>(1)))
629 (numeric_limits<T>::epsilon()));
630
631 BOOST_REQUIRE_PREDICATE(::std::less_equal<T>(),
632 (abs(::boost::math::quaternion<T>(0,0,0,1)*
633 ::boost::math::quaternion<T>(0,0,0,1)+static_cast<T>(1)))
634 (numeric_limits<T>::epsilon()));
635
636 BOOST_REQUIRE_PREDICATE(::std::less_equal<T>(),
637 (abs(::boost::math::quaternion<T>(0,1,0,0)*
638 ::boost::math::quaternion<T>(0,0,1,0)-
639 ::boost::math::quaternion<T>(0,0,0,1)))
640 (numeric_limits<T>::epsilon()));
641
642 BOOST_REQUIRE_PREDICATE(::std::less_equal<T>(),
643 (abs(::boost::math::quaternion<T>(0,0,1,0)*
644 ::boost::math::quaternion<T>(0,1,0,0)+
645 ::boost::math::quaternion<T>(0,0,0,1)))
646 (numeric_limits<T>::epsilon()));
647
648 BOOST_REQUIRE_PREDICATE(::std::less_equal<T>(),
649 (abs(::boost::math::quaternion<T>(0,0,1,0)*
650 ::boost::math::quaternion<T>(0,0,0,1)-
651 ::boost::math::quaternion<T>(0,1,0,0)))
652 (numeric_limits<T>::epsilon()));
653
654 BOOST_REQUIRE_PREDICATE(::std::less_equal<T>(),
655 (abs(::boost::math::quaternion<T>(0,0,0,1)*
656 ::boost::math::quaternion<T>(0,0,1,0)+
657 ::boost::math::quaternion<T>(0,1,0,0)))
658 (numeric_limits<T>::epsilon()));
659
660 BOOST_REQUIRE_PREDICATE(::std::less_equal<T>(),
661 (abs(::boost::math::quaternion<T>(0,0,0,1)*
662 ::boost::math::quaternion<T>(0,1,0,0)-
663 ::boost::math::quaternion<T>(0,0,1,0)))
664 (numeric_limits<T>::epsilon()));
665
666 BOOST_REQUIRE_PREDICATE(::std::less_equal<T>(),
667 (abs(::boost::math::quaternion<T>(0,1,0,0)*
668 ::boost::math::quaternion<T>(0,0,0,1)+
669 ::boost::math::quaternion<T>(0,0,1,0)))
670 (numeric_limits<T>::epsilon()));
671}
672
673
b32b8144 674BOOST_AUTO_TEST_CASE_TEMPLATE(exp_test, T, test_types)
7c673cae
FG
675{
676#if BOOST_WORKAROUND(__GNUC__, < 3)
677#else /* BOOST_WORKAROUND(__GNUC__, < 3) */
678 using ::std::numeric_limits;
679
680 using ::std::atan;
681
682 using ::boost::math::abs;
683#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
684
685
686 BOOST_TEST_MESSAGE("Testing exp for "
687 << string_type_name<T>::_() << ".");
688
689 BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
690 (abs(exp(::boost::math::quaternion<T>
691 (0,4*atan(static_cast<T>(1)),0,0))+static_cast<T>(1)))
692 (2*numeric_limits<T>::epsilon()));
693
694 BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
695 (abs(exp(::boost::math::quaternion<T>
696 (0,0,4*atan(static_cast<T>(1)),0))+static_cast<T>(1)))
697 (2*numeric_limits<T>::epsilon()));
698
699 BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
700 (abs(exp(::boost::math::quaternion<T>
701 (0,0,0,4*atan(static_cast<T>(1))))+static_cast<T>(1)))
702 (2*numeric_limits<T>::epsilon()));
703}
704
705
b32b8144 706BOOST_AUTO_TEST_CASE_TEMPLATE(cos_test, T, test_types)
7c673cae
FG
707{
708#if BOOST_WORKAROUND(__GNUC__, < 3)
709#else /* BOOST_WORKAROUND(__GNUC__, < 3) */
710 using ::std::numeric_limits;
711
712 using ::std::log;
713
714 using ::boost::math::abs;
715#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
716
717
718 BOOST_TEST_MESSAGE("Testing cos for "
719 << string_type_name<T>::_() << ".");
720
721 BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
722 (abs(static_cast<T>(4)*cos(::boost::math::quaternion<T>
723 (0,log(static_cast<T>(2)),0,0))-static_cast<T>(5)))
724 (4*numeric_limits<T>::epsilon()));
725
726 BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
727 (abs(static_cast<T>(4)*cos(::boost::math::quaternion<T>
728 (0,0,log(static_cast<T>(2)),0))-static_cast<T>(5)))
729 (4*numeric_limits<T>::epsilon()));
730
731 BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
732 (abs(static_cast<T>(4)*cos(::boost::math::quaternion<T>
733 (0,0,0,log(static_cast<T>(2))))-static_cast<T>(5)))
734 (4*numeric_limits<T>::epsilon()));
735}
736
737
b32b8144 738BOOST_AUTO_TEST_CASE_TEMPLATE(sin_test, T, test_types)
7c673cae
FG
739{
740#if BOOST_WORKAROUND(__GNUC__, < 3)
741#else /* BOOST_WORKAROUND(__GNUC__, < 3) */
742 using ::std::numeric_limits;
743
744 using ::std::log;
745
746 using ::boost::math::abs;
747#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
748
749
750 BOOST_TEST_MESSAGE("Testing sin for "
751 << string_type_name<T>::_() << ".");
752
753 BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
754 (abs(static_cast<T>(4)*sin(::boost::math::quaternion<T>
755 (0,log(static_cast<T>(2)),0,0))
756 -::boost::math::quaternion<T>(0,3,0,0)))
757 (4*numeric_limits<T>::epsilon()));
758
759 BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
760 (abs(static_cast<T>(4)*sin(::boost::math::quaternion<T>
761 (0,0,log(static_cast<T>(2)),0))
762 -::boost::math::quaternion<T>(0,0,3,0)))
763 (4*numeric_limits<T>::epsilon()));
764
765 BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
766 (abs(static_cast<T>(4)*sin(::boost::math::quaternion<T>
767 (0,0,0,log(static_cast<T>(2))))
768 -::boost::math::quaternion<T>(0,0,0,3)))
769 (4*numeric_limits<T>::epsilon()));
770}
771
772
b32b8144 773BOOST_AUTO_TEST_CASE_TEMPLATE(cosh_test, T, test_types)
7c673cae
FG
774{
775#if BOOST_WORKAROUND(__GNUC__, < 3)
776#else /* BOOST_WORKAROUND(__GNUC__, < 3) */
777 using ::std::numeric_limits;
778
779 using ::std::atan;
780
781 using ::boost::math::abs;
782#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
783
784
785 BOOST_TEST_MESSAGE("Testing cosh for "
786 << string_type_name<T>::_() << ".");
787
788 BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
789 (abs(cosh(::boost::math::quaternion<T>
790 (0,4*atan(static_cast<T>(1)),0,0))
791 +static_cast<T>(1)))
792 (4*numeric_limits<T>::epsilon()));
793
794 BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
795 (abs(cosh(::boost::math::quaternion<T>
796 (0,0,4*atan(static_cast<T>(1)),0))
797 +static_cast<T>(1)))
798 (4*numeric_limits<T>::epsilon()));
799
800 BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
801 (abs(cosh(::boost::math::quaternion<T>
802 (0,0,0,4*atan(static_cast<T>(1))))
803 +static_cast<T>(1)))
804 (4*numeric_limits<T>::epsilon()));
805}
806
807
b32b8144 808BOOST_AUTO_TEST_CASE_TEMPLATE(sinh_test, T, test_types)
7c673cae
FG
809{
810#if BOOST_WORKAROUND(__GNUC__, < 3)
811#else /* BOOST_WORKAROUND(__GNUC__, < 3) */
812 using ::std::numeric_limits;
813
814 using ::std::atan;
815
816 using ::boost::math::abs;
817#endif /* BOOST_WORKAROUND(__GNUC__, < 3) */
818
819
820 BOOST_TEST_MESSAGE("Testing sinh for "
821 << string_type_name<T>::_() << ".");
822
823 BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
824 (abs(sinh(::boost::math::quaternion<T>
825 (0,2*atan(static_cast<T>(1)),0,0))
826 -::boost::math::quaternion<T>(0,1,0,0)))
827 (4*numeric_limits<T>::epsilon()));
828
829 BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
830 (abs(sinh(::boost::math::quaternion<T>
831 (0,0,2*atan(static_cast<T>(1)),0))
832 -::boost::math::quaternion<T>(0,0,1,0)))
833 (4*numeric_limits<T>::epsilon()));
834
835 BOOST_CHECK_PREDICATE(::std::less_equal<T>(),
836 (abs(sinh(::boost::math::quaternion<T>
837 (0,0,0,2*atan(static_cast<T>(1))))
838 -::boost::math::quaternion<T>(0,0,0,1)))
839 (4*numeric_limits<T>::epsilon()));
840}
841