diff --git a/test/octonion_test_simple.cpp b/test/octonion_test_simple.cpp index 8cc78ad801..53a9fc3d9e 100644 --- a/test/octonion_test_simple.cpp +++ b/test/octonion_test_simple.cpp @@ -4,47 +4,95 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include - #include #include #include +#include +#include + // test file for octonion.hpp -namespace +namespace local { - template - ::boost::math::octonion index_i_element(int idx) + std::mt19937 eng(static_cast(UINT8_C(42))); + std::uniform_int_distribution dst_one(1, 1); + + template + auto is_close_fraction(const NumericType& a, + const NumericType& b, + const NumericType& tol) noexcept -> bool + { + using std::fabs; + + auto result_is_ok = bool { }; + + if(b == static_cast(0)) { - return( - ::boost::math::octonion( - (idx == 0) ? - static_cast(1) : - static_cast(0), - (idx == 1) ? - static_cast(1) : - static_cast(0), - (idx == 2) ? - static_cast(1) : - static_cast(0), - (idx == 3) ? - static_cast(1) : - static_cast(0), - (idx == 4) ? - static_cast(1) : - static_cast(0), - (idx == 5) ? - static_cast(1) : - static_cast(0), - (idx == 6) ? - static_cast(1) : - static_cast(0), - (idx == 7) ? - static_cast(1) : - static_cast(0) - )); + result_is_ok = (fabs(a - b) < tol); } + else + { + const auto delta = fabs(1 - (a / b)); + + result_is_ok = (delta < tol); + } + + return result_is_ok; + } + + template + auto is_close_fraction(const ::boost::math::octonion& a, + const ::boost::math::octonion& b, + const T& tol) noexcept -> bool + { + using std::fabs; + + bool result_is_ok { true }; + + result_is_ok = (is_close_fraction(a.R_component_1(), b.R_component_1(), tol) && result_is_ok); + result_is_ok = (is_close_fraction(a.R_component_2(), b.R_component_2(), tol) && result_is_ok); + result_is_ok = (is_close_fraction(a.R_component_3(), b.R_component_3(), tol) && result_is_ok); + result_is_ok = (is_close_fraction(a.R_component_4(), b.R_component_4(), tol) && result_is_ok); + result_is_ok = (is_close_fraction(a.R_component_5(), b.R_component_5(), tol) && result_is_ok); + result_is_ok = (is_close_fraction(a.R_component_6(), b.R_component_6(), tol) && result_is_ok); + result_is_ok = (is_close_fraction(a.R_component_7(), b.R_component_7(), tol) && result_is_ok); + result_is_ok = (is_close_fraction(a.R_component_8(), b.R_component_8(), tol) && result_is_ok); + + return result_is_ok; + } + + template + ::boost::math::octonion index_i_element(int idx) + { + return( + ::boost::math::octonion( + (idx == 0) ? + static_cast(1) : + static_cast(0), + (idx == 1) ? + static_cast(1) : + static_cast(0), + (idx == 2) ? + static_cast(1) : + static_cast(0), + (idx == 3) ? + static_cast(1) : + static_cast(0), + (idx == 4) ? + static_cast(1) : + static_cast(0), + (idx == 5) ? + static_cast(1) : + static_cast(0), + (idx == 6) ? + static_cast(1) : + static_cast(0), + (idx == 7) ? + static_cast(1) : + static_cast(0) + )); + } } template @@ -66,7 +114,7 @@ void multiplication_test() for (int idx = 1; idx < 8; ++idx) { - ::boost::math::octonion toto = index_i_element(idx); + ::boost::math::octonion toto = local::index_i_element(idx); const T tabs { abs(toto*toto+static_cast(1)) }; @@ -86,9 +134,13 @@ void multiplication_test() BOOST_TEST(prod == ctrl); } + for(auto i = static_cast(UINT8_C(0)); i < static_cast(UINT8_C(16)); ++i) { const boost::math::octonion lhs(T(1),T(2),T(3),T(4),T(5),T(6),T(7),T(8)); - const boost::math::octonion rhs(T(1),T(1),T(1),T(1),T(1),T(1),T(1),T(1)); + + const boost::math::octonion rhs = + boost::math::octonion { T(1),T(1),T(1),T(1),T(1),T(1),T(1),T(1) } + * static_cast(local::dst_one(local::eng)); const boost::math::octonion quot = lhs / rhs; @@ -374,7 +426,7 @@ void elem_func_test() for(int idx = 1; idx < 8; ++idx) { ::boost::math::octonion toto = - static_cast(4)*atan(static_cast(1))*index_i_element(idx); + static_cast(4)*atan(static_cast(1)) * local::index_i_element(idx); const T tabs { abs(exp(toto)+static_cast(1)) }; @@ -401,6 +453,41 @@ void elem_func_test() using std::exp; BOOST_TEST(r0 < exp(one_sixteenth_one_over_32.real())); + + { + auto octo_small_exp_inv = ::boost::math::octonion(1); + octo_small_exp_inv /= octo_small_exp; + + const auto value_cosh = cosh(octo_small); + const auto value_cosh_ctrl = (octo_small_exp + octo_small_exp_inv) / T(2); + + const auto result_cosh_is_ok = local::is_close_fraction(value_cosh, value_cosh_ctrl, std::numeric_limits::epsilon() * 64); + + BOOST_TEST(result_cosh_is_ok); + } + + { + auto octo_small_exp_inv = ::boost::math::octonion(1); + octo_small_exp_inv /= octo_small_exp; + + const auto value_sinh = sinh(octo_small); + const auto value_sinh_ctrl = (octo_small_exp - octo_small_exp_inv) / T(2); + + const auto result_sinh_is_ok = local::is_close_fraction(value_sinh, value_sinh_ctrl, std::numeric_limits::epsilon() * 64); + + BOOST_TEST(result_sinh_is_ok); + } + + { + const auto value_sinh = sinh(octo_small); + const auto value_cosh = cosh(octo_small); + const auto value_tanh = tanh(octo_small); + const auto value_tanh_ctrl = value_sinh / value_cosh; + + const auto result_tanh_is_ok = local::is_close_fraction(value_tanh, value_tanh_ctrl, std::numeric_limits::epsilon() * 64); + + BOOST_TEST(result_tanh_is_ok); + } } { @@ -422,6 +509,93 @@ void elem_func_test() BOOST_TEST(r0 > sin(one_sixteenth_one_over_32.real())); } + + { + const std::complex one_sixteenth_one_over_32 { T { 1 } / 16, T { 1 } / 32 }; + const ::boost::math::octonion + octo_small + { + one_sixteenth_one_over_32, + T { 2 } * one_sixteenth_one_over_32, + T { 3 } * one_sixteenth_one_over_32, + T { 4 } * one_sixteenth_one_over_32 + }; + + const auto octo_small_cos = cos(octo_small); + + const auto r0 = octo_small_cos.real(); + + using std::cos; + + BOOST_TEST(r0 > cos(one_sixteenth_one_over_32.real())); + } + + { + const std::complex one_sixteenth_one_over_32 { T { 1 } / 16, T { 1 } / 32 }; + const ::boost::math::octonion + octo_small + { + one_sixteenth_one_over_32, + T { 2 } * one_sixteenth_one_over_32, + T { 3 } * one_sixteenth_one_over_32, + T { 4 } * one_sixteenth_one_over_32 + }; + + const auto octo_small_sin = sin(octo_small); + const auto octo_small_cos = cos(octo_small); + const auto octo_small_tan = tan(octo_small); + + const auto octo_small_tan_ctrl = octo_small_sin / octo_small_cos; + + const auto result_tan_is_ok = local::is_close_fraction(octo_small_tan, octo_small_tan_ctrl, std::numeric_limits::epsilon() * 64); + + BOOST_TEST(result_tan_is_ok); + } + + for(auto i = static_cast(UINT8_C(0)); i < static_cast(UINT8_C(8)); ++i) + { + static_cast(i); + + ::boost::math::octonion b { T {1}, T {2}, T {3}, T {4}, T {5}, T {6}, T {7}, T {8} }; + + b *= static_cast(local::dst_one(local::eng)); + + { + ::boost::math::octonion bp0 = pow(b, 0); + ::boost::math::octonion bp0_ctrl { T { 1 } }; + + const auto result_b0_is_ok = local::is_close_fraction(bp0, bp0_ctrl, std::numeric_limits::epsilon() * 64); + } + + { + ::boost::math::octonion bp1 = pow(b, 1); + ::boost::math::octonion bp1_ctrl = b; + + const auto result_b1_is_ok = local::is_close_fraction(bp1, bp1_ctrl, std::numeric_limits::epsilon() * 64); + } + + { + ::boost::math::octonion bp2 = pow(b, 2); + ::boost::math::octonion bp2_ctrl = b * b; + + const auto result_b2_is_ok = local::is_close_fraction(bp2, bp2_ctrl, std::numeric_limits::epsilon() * 64); + } + + { + ::boost::math::octonion bp3 = pow(b, 3); + ::boost::math::octonion bp3_ctrl = (b * b) * b; + + const auto result_b3_is_ok = local::is_close_fraction(bp3, bp3_ctrl, std::numeric_limits::epsilon() * 64); + } + + { + ::boost::math::octonion bp4 = pow(b, 4); + ::boost::math::octonion bp2_ctrl = b * b; + ::boost::math::octonion bp4_ctrl = bp2_ctrl * bp2_ctrl; + + const auto result_b3_is_ok = local::is_close_fraction(bp4, bp4_ctrl, std::numeric_limits::epsilon() * 64); + } + } } auto main() -> int