//This file is part of Bertini 2. // //fundamentals_test.cpp is free software: you can redistribute it and/or modify //it under the terms of the GNU General Public License as published by //the Free Software Foundation, either version 3 of the License, or //(at your option) any later version. // //fundamentals_test.cpp is distributed in the hope that it will be useful, //but WITHOUT ANY WARRANTY; without even the implied warranty of //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //GNU General Public License for more details. // //You should have received a copy of the GNU General Public License //along with fundamentals_test.cpp. If not, see . // // Copyright(C) 2015 - 2021 by Bertini2 Development Team // // See for a copy of the license, // as well as COPYING. Bertini2 is provided with permitted // additional terms in the b2/licenses/ directory. // individual authors of this file include: // silviana amethyst, university of wisconsin eau claire #include #include #include #include "bertini2/double_extensions.hpp" #include "bertini2/num_traits.hpp" BOOST_AUTO_TEST_SUITE(super_fundamentals) using mpfr_float = bertini::mpfr_float; using mpq_rational = bertini::mpq_rational; using dbl = bertini::dbl; using bertini::DefaultPrecision; #include BOOST_AUTO_TEST_CASE(complex_pow) { auto x = bertini::rand_complex(); using bertini::pow; BOOST_CHECK_EQUAL(pow(x, 2), x*x); } BOOST_AUTO_TEST_CASE(complex_pow_on_real_stays_real) { using bertini::pow; for (int ii=0; ii<100; ++ii) { auto x = dbl(bertini::RandReal()); auto result = pow(x, 2); BOOST_CHECK_EQUAL(result, x*x); BOOST_CHECK_EQUAL(imag(result), 0); } } BOOST_AUTO_TEST_CASE(complex_double_nans) { dbl x(0., std::numeric_limits::quiet_NaN()); using bertini::isnan; BOOST_CHECK(isnan(x)); } BOOST_AUTO_TEST_CASE(complex_double_nans2) { dbl x(std::numeric_limits::quiet_NaN(), 0.); using bertini::isnan; BOOST_CHECK(isnan(x)); } BOOST_AUTO_TEST_CASE(complex_double_nans3) { dbl x(std::numeric_limits::quiet_NaN(), std::numeric_limits::quiet_NaN()); using bertini::isnan; BOOST_CHECK(isnan(x)); } BOOST_AUTO_TEST_CASE(complex_double_nans4) { dbl x(0., 0.); using bertini::isnan; BOOST_CHECK(!isnan(x)); } BOOST_AUTO_TEST_CASE(complex_double_random_subsequent_not_equal) { using T = dbl; auto x = bertini::RandomUnit(); auto y = bertini::RandomUnit(); BOOST_CHECK(x!=y); } BOOST_AUTO_TEST_CASE(mpfr_float_can_be_nan) { DefaultPrecision(50); mpfr_float a(std::numeric_limits::quiet_NaN()); BOOST_CHECK(isnan(a)); } BOOST_AUTO_TEST_CASE(constructing_mpfr_from_double) { DefaultPrecision(50); mpfr_float from_double(0.1); mpfr_float from_string("0.1"); BOOST_CHECK(abs(from_string - from_double) < std::numeric_limits::epsilon()); } BOOST_AUTO_TEST_CASE(construct_rational_from_integers) { mpq_rational p(1,2); mpq_rational q(-1,2); BOOST_CHECK_EQUAL(p+q, mpq_rational(0)); } // commented out code below checks construction of mpq_rationals from other types. they're broken. :( // BOOST_AUTO_TEST_CASE(construct_rational_from_mpfr) // { // DefaultPrecision(50); // mpfr_float p("1.1"); // mpq_rational q(p); // BOOST_CHECK_EQUAL(mpq_rational(11,10), q); // } // BOOST_AUTO_TEST_CASE(construct_rational_from_string) // { // mpq_rational q("1.1"); // BOOST_CHECK_EQUAL(mpq_rational(11,10), q); // } // this commented out test will fail... because of mixed precision arithmetic // BOOST_AUTO_TEST_CASE(multiple_mpfr_by_double) // { // DefaultPrecision(50); // mpfr_float a("0.1"); // double factor = 0.1; // mpfr_float result = a*factor; // mpfr_float expected("0.01"); // BOOST_CHECK_CLOSE(expected, result, 1e-50); // } BOOST_AUTO_TEST_CASE(making_mpfr_from_pow_int_base) { DefaultPrecision(50); mpfr_float result = pow(mpfr_float(10), -5); mpfr_float expected("1e-5"); BOOST_CHECK_CLOSE(expected, result, 1e-50); } BOOST_AUTO_TEST_CASE(making_mpfr_from_pow_str_base) { DefaultPrecision(50); mpfr_float result = pow(mpfr_float("10"), -5); mpfr_float expected("1e-5"); BOOST_CHECK_CLOSE(expected, result, 1e-50); } BOOST_AUTO_TEST_CASE(making_mpfr_from_pow_doub_exp) { DefaultPrecision(50); using boost::multiprecision::pow; mpfr_float result = pow(mpfr_float(10), -5); mpfr_float expected("1e-5"); BOOST_CHECK_CLOSE(expected, result, 1e-50); } BOOST_AUTO_TEST_CASE(making_mpfr_from_pow_int_base_mpfr_exp) { DefaultPrecision(50); mpfr_float result = pow(10, mpfr_float(-5)); mpfr_float expected("1e-5"); BOOST_CHECK_CLOSE(expected, result, 1e-50); } BOOST_AUTO_TEST_CASE(make_rational_from_double) { mpq_rational result(0.1); mpq_rational expected(1,10); BOOST_CHECK_CLOSE(result, expected, 1e-16); } BOOST_AUTO_TEST_CASE(make_random_mpfr_float_50) { using mpfr_50 = boost::multiprecision::number, boost::multiprecision::et_off>; using namespace boost::multiprecision; using namespace boost::random; DefaultPrecision(50); uniform_real_distribution ur(0,1); independent_bits_engine gen; auto c = ur(gen); mpfr_50 r(c); mpfr_50 s(ur(gen)); } BOOST_AUTO_TEST_CASE(make_random_mpfr_float_100) { using mpfr_100 = boost::multiprecision::number, boost::multiprecision::et_off>; using namespace boost::multiprecision; using namespace boost::random; DefaultPrecision(100); uniform_real_distribution ur(0,1); independent_bits_engine gen; auto c = ur(gen); mpfr_100 r(c); mpfr_100 s(ur(gen)); } BOOST_AUTO_TEST_CASE(RandomMP_default_precision_50) { using namespace bertini; DefaultPrecision(50); auto a = RandomMp(mpfr_float(-1),mpfr_float(1)); BOOST_CHECK_EQUAL(a.precision(), DefaultPrecision()); BOOST_CHECK_EQUAL(50, DefaultPrecision()); } BOOST_AUTO_TEST_CASE(RandomMP_default_precision_100) { using namespace bertini; DefaultPrecision(100); auto a = RandomMp(mpfr_float(-1),mpfr_float(1)); BOOST_CHECK_EQUAL(a.precision(), DefaultPrecision()); BOOST_CHECK_EQUAL(100, DefaultPrecision()); } BOOST_AUTO_TEST_CASE(RandomMP_nondefault_precision_100) { using namespace bertini; DefaultPrecision(100); mpfr_float a; RandomMpAssign(a,500); BOOST_CHECK_EQUAL(a.precision(), 500); BOOST_CHECK_EQUAL(100, DefaultPrecision()); } BOOST_AUTO_TEST_CASE(max_et_on) { mpfr_float a(1), b(2), c(4); // auto d = max(a,b*b+c); } struct scoped_mpfr_precision_options_all_threads { boost::multiprecision::variable_precision_options saved_options; scoped_mpfr_precision_options_all_threads(boost::multiprecision::variable_precision_options opts) : saved_options(mpfr_float::default_variable_precision_options()) { mpfr_float::default_variable_precision_options(opts); } ~scoped_mpfr_precision_options_all_threads() { mpfr_float::default_variable_precision_options(saved_options); } void reset(boost::multiprecision::variable_precision_options opts) { mpfr_float::default_variable_precision_options(opts); } }; struct scoped_mpfr_precision_options_this_thread { boost::multiprecision::variable_precision_options saved_options; scoped_mpfr_precision_options_this_thread(boost::multiprecision::variable_precision_options opts) : saved_options(mpfr_float::thread_default_variable_precision_options()) { mpfr_float::thread_default_variable_precision_options(opts); } ~scoped_mpfr_precision_options_this_thread() { mpfr_float::thread_default_variable_precision_options(saved_options); } void reset(boost::multiprecision::variable_precision_options opts) { mpfr_float::thread_default_variable_precision_options(opts); } }; BOOST_AUTO_TEST_CASE(precision_through_arithemetic) { DefaultPrecision(50); scoped_mpfr_precision_options_this_thread scoped_opts1(boost::multiprecision::variable_precision_options::preserve_related_precision); mpfr_float x("0.01234567890123456789012345678901234567890123456789"); BOOST_CHECK_EQUAL(x.precision(), 50); // https://github.com/boostorg/multiprecision/issues/60 // // "Copying or move-assignment copies the precision of the source. // Assignment keeps the precision of the target." DefaultPrecision(30); mpfr_float y = pow(x,2); BOOST_CHECK_EQUAL(y.precision(), 50); mpfr_float z = x; mpfr_float q(x); BOOST_CHECK_EQUAL(z.precision(), 50); BOOST_CHECK_EQUAL(q.precision(), 50); BOOST_CHECK(fabs(z - x) < 1e-50); DefaultPrecision(70); z = x; BOOST_CHECK_EQUAL(z.precision(),50); BOOST_CHECK(fabs(z - x) < 1e-50); y.precision(70); z.precision(30); BOOST_CHECK_EQUAL(y.precision(),70); BOOST_CHECK_EQUAL(z.precision(),30); BOOST_CHECK_EQUAL(x.precision(),50); scoped_mpfr_precision_options_this_thread scoped_opts2(boost::multiprecision::variable_precision_options::preserve_target_precision); y = z*x; BOOST_CHECK_EQUAL(z.precision(),30); BOOST_CHECK_EQUAL(x.precision(),50); BOOST_CHECK_EQUAL(y.precision(), 70); } BOOST_AUTO_TEST_CASE(precision_in_construction) { DefaultPrecision(50); mpfr_float x("0.01234567890123456789012345678901234567890123456789"); BOOST_CHECK_EQUAL(x.precision(), 50); DefaultPrecision(30); mpfr_float a = x; mpfr_float b(x); BOOST_CHECK_EQUAL(a.precision(), 50); BOOST_CHECK_EQUAL(b.precision(), 50); BOOST_CHECK_EQUAL(a,x); BOOST_CHECK_EQUAL(b,x); DefaultPrecision(70); mpfr_float c = x; mpfr_float d(x); BOOST_CHECK_EQUAL(c.precision(), 50); BOOST_CHECK_EQUAL(d.precision(), 50); BOOST_CHECK_EQUAL(c,x); BOOST_CHECK_EQUAL(d,x); } BOOST_AUTO_TEST_CASE(precision_through_arithemetic2) { DefaultPrecision(50); mpfr_float a(1); DefaultPrecision(400); mpfr_float b(2); DefaultPrecision(600); mpfr_float c(3); a = b; BOOST_CHECK_EQUAL(a.precision(),400); // the precision of source a = b+c; BOOST_CHECK_EQUAL(a.precision(),600); // the bigger of 400,600 is 600 } BOOST_AUTO_TEST_CASE(precision_mpfr_constructed_from_string) { DefaultPrecision(30); mpfr_float x("0.01234567890123456789012345678901234567890123456789"); BOOST_CHECK_EQUAL(x.precision(),30); } BOOST_AUTO_TEST_CASE(precision_of_double_is_16) { double a(1.23124); BOOST_CHECK_EQUAL(bertini::Precision(a), 16); } BOOST_AUTO_TEST_CASE(precision_of_complex_double_is_16) { std::complex a(1.23124, -0.12345679); BOOST_CHECK_EQUAL(bertini::Precision(a), 16); } BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE(numtraits) using bertini::DefaultPrecision; template using NumTraits = bertini::NumTraits; BOOST_AUTO_TEST_CASE(num_digits_double) { using T = double; DefaultPrecision(16); BOOST_CHECK_EQUAL(NumTraits::NumDigits(), 16); DefaultPrecision(30); BOOST_CHECK_EQUAL(NumTraits::NumDigits(), 16); DefaultPrecision(100); BOOST_CHECK_EQUAL(NumTraits::NumDigits(), 16); } BOOST_AUTO_TEST_CASE(num_digits_complex_double) { using T = std::complex; DefaultPrecision(16); BOOST_CHECK_EQUAL(NumTraits::NumDigits(), 16); DefaultPrecision(30); BOOST_CHECK_EQUAL(NumTraits::NumDigits(), 16); DefaultPrecision(100); BOOST_CHECK_EQUAL(NumTraits::NumDigits(), 16); } BOOST_AUTO_TEST_CASE(num_digits_mpfr_float) { using T = bertini::mpfr_float; DefaultPrecision(16); BOOST_CHECK_EQUAL(NumTraits::NumDigits(), 16); DefaultPrecision(30); BOOST_CHECK_EQUAL(NumTraits::NumDigits(), 30); DefaultPrecision(100); BOOST_CHECK_EQUAL(NumTraits::NumDigits(), 100); } BOOST_AUTO_TEST_CASE(num_digits_mpfr_complex) { using T = bertini::mpfr_complex; DefaultPrecision(16); BOOST_CHECK_EQUAL(NumTraits::NumDigits(), 16); DefaultPrecision(30); BOOST_CHECK_EQUAL(NumTraits::NumDigits(), 30); DefaultPrecision(100); BOOST_CHECK_EQUAL(NumTraits::NumDigits(), 100); } BOOST_AUTO_TEST_SUITE_END() // numtraits tests