From 6f57c68e902e295d67cd7b7f7ed9dabc0aa9cb92 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Mon, 23 Apr 2018 17:13:13 +0200 Subject: [PATCH 01/61] bugfix in vectorized gdual comparisons (and tests added) --- doc/doxygen/Doxyfile | 2 +- doc/sphinx/conf.py | 4 +- include/audi/gdual.hpp | 2 +- include/audi/vectorized_double.hpp | 19 +++++++-- pyaudi/expose_gdual.hpp | 2 +- tests/CMakeLists.txt | 1 + tests/gdual_v.cpp | 7 ++++ tests/vectorized_double.cpp | 65 ++++++++++++++++++++++++++++++ 8 files changed, 93 insertions(+), 9 deletions(-) create mode 100644 tests/vectorized_double.cpp diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index 8dfd5437..779cdfff 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "audi" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.3 +PROJECT_NUMBER = 1.2.4 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/doc/sphinx/conf.py b/doc/sphinx/conf.py index 4332ce9d..95f77fb9 100644 --- a/doc/sphinx/conf.py +++ b/doc/sphinx/conf.py @@ -63,9 +63,9 @@ # built documents. # # The short X.Y version. -version = '1.3' +version = '1.2.4' # The full version, including alpha/beta/rc tags. -release = '1.3' +release = '1.2.4' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/include/audi/gdual.hpp b/include/audi/gdual.hpp index e33b31cd..b7904583 100644 --- a/include/audi/gdual.hpp +++ b/include/audi/gdual.hpp @@ -422,7 +422,7 @@ class gdual gdual trim(double epsilon) const { auto new_p - = m_p.filter([epsilon](const std::pair &coeff) { return std::abs(coeff.first) > epsilon; }); + = m_p.filter([epsilon](const std::pair &coeff) { return abs(coeff.first) > epsilon; }); return gdual(std::move(new_p), m_order); } diff --git a/include/audi/vectorized_double.hpp b/include/audi/vectorized_double.hpp index 819204ab..21ccba8e 100644 --- a/include/audi/vectorized_double.hpp +++ b/include/audi/vectorized_double.hpp @@ -33,20 +33,20 @@ class vectorized_double explicit vectorized_double(const std::vector &c) : m_c(c) { if (m_c.size() == 0) { - throw std::invalid_argument("Cannot build an empty coefficient_v"); + throw std::invalid_argument("Cannot build an empty coefficient_v (lvalue)"); } }; // Constructor from an std::vector r value explicit vectorized_double(std::vector &&c) : m_c(c) { if (m_c.size() == 0) { - throw std::invalid_argument("Cannot build an empty coefficient_v"); + throw std::invalid_argument("Cannot build an empty coefficient_v (rvalue)"); } }; explicit vectorized_double(std::initializer_list c) : m_c(c) { if (m_c.size() == 0) { - throw std::invalid_argument("Cannot build an empty coefficient_v"); + throw std::invalid_argument("Cannot build an empty coefficient_v (initializer)"); } }; // ------------------- Binary arithmetic operators implemented using +=,-=, etc. @@ -179,12 +179,23 @@ class vectorized_double if (d1.size() == d2.size()) { return d1.m_c > d2.m_c; } else if (d1.size() == 1u) { - return std::all_of(d2.begin(), d2.end(), [d1](double x) { return x > d1[0]; }); + return std::all_of(d2.begin(), d2.end(), [d1](double x) { return d1[0] > x; }); } else if (d2.size() == 1u) { return std::all_of(d1.begin(), d1.end(), [d2](double x) { return x > d2[0]; }); } return false; } + friend bool operator<(const vectorized_double &d1, const vectorized_double &d2) + { + if (d1.size() == d2.size()) { + return d1.m_c < d2.m_c; + } else if (d1.size() == 1u) { + return std::all_of(d2.begin(), d2.end(), [d1](double x) { return d1[0] < x; }); + } else if (d2.size() == 1u) { + return std::all_of(d1.begin(), d1.end(), [d2](double x) { return x < d2[0]; }); + } + return false; + } friend vectorized_double abs(vectorized_double in) { std::transform(in.m_c.begin(), in.m_c.end(), in.m_c.begin(), [](double x) { return std::abs(x); }); diff --git a/pyaudi/expose_gdual.hpp b/pyaudi/expose_gdual.hpp index dff6f4c7..670e6a25 100644 --- a/pyaudi/expose_gdual.hpp +++ b/pyaudi/expose_gdual.hpp @@ -51,7 +51,7 @@ struct gdual_pickle_suite : bp::pickle_suite { } auto ptr = PyBytes_AsString(bp::object(state[0]).ptr()); if (!ptr) { - pyaudi_throw(PyExc_TypeError, "a bytes object is needed to deserialize a population"); + pyaudi_throw(PyExc_TypeError, "a bytes object is needed to deserialize"); } const auto size = len(state[0]); std::string s(ptr, ptr + size); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5801d371..20026fd9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -29,6 +29,7 @@ ENDMACRO(ADD_AUDI_PERFORMANCE_TESTCASE) ADD_AUDI_TESTCASE(gdual_d) ADD_AUDI_TESTCASE(gdual_v) +ADD_AUDI_TESTCASE(vectorized_double) ADD_AUDI_TESTCASE(functions) ADD_AUDI_TESTCASE(functions_from_d) ADD_AUDI_TESTCASE(functions_floating_precision) diff --git a/tests/gdual_v.cpp b/tests/gdual_v.cpp index 733a36c1..45e7a70d 100644 --- a/tests/gdual_v.cpp +++ b/tests/gdual_v.cpp @@ -257,3 +257,10 @@ BOOST_AUTO_TEST_CASE(is_zero) BOOST_CHECK(!f.is_zero(1e-12)); } } + +BOOST_AUTO_TEST_CASE(trim) +{ + vectorized_double x{1, -2, -3, 4, 0.123, -21.211}; + // gdual_v x(std::vector{{1, -2, -3, 4, 0.123, -21.211}}, "x", 4); + print(30 > x); +} diff --git a/tests/vectorized_double.cpp b/tests/vectorized_double.cpp new file mode 100644 index 00000000..040f6977 --- /dev/null +++ b/tests/vectorized_double.cpp @@ -0,0 +1,65 @@ +#define BOOST_TEST_MODULE audi_gdual_test +#include +#include +#include + +#include +#include +#include + +#include "helpers.hpp" +#include + +using namespace audi; + +BOOST_AUTO_TEST_CASE(construction) +{ + // Default Constructor + { + vectorized_double x; + BOOST_CHECK(x.size() == 1); + BOOST_CHECK(*x.begin() == 0); + } + // Constructor from int. + { + vectorized_double x{123}; + BOOST_CHECK(x.size() == 1); + BOOST_CHECK(*x.begin() == 123); + } + // Constructor from double. + { + vectorized_double x{123.}; + BOOST_CHECK(x.size() == 1); + BOOST_CHECK(*x.begin() == 123.); + } + // Constructor from an std::vector + { + std::vector in{1, 2, 3, 4, 2.2}; + vectorized_double x(in); + BOOST_CHECK(x.size() == 5); + BOOST_CHECK(std::equal(in.begin(), in.end(), x.begin())); + std::vector empty; + // rvalue + BOOST_CHECK_THROW(vectorized_double(std::vector{}), std::invalid_argument); + // lvalue + BOOST_CHECK_THROW(vectorized_double{empty}, std::invalid_argument); + // initializer list + BOOST_CHECK_THROW(vectorized_double({}), std::invalid_argument); + } +} +BOOST_AUTO_TEST_CASE(math) +{ + vectorized_double x1{-1., 1., 2., -3., 4.}; + vectorized_double x2{1., 1., 2., 3., 4.}; + vectorized_double x3{-100., -100., -100., -100., -100.}; + vectorized_double x4{100., 100., 100., 100., 100.}; + BOOST_CHECK(abs(x1)==x2); + BOOST_CHECK(x3 < x1); + BOOST_CHECK(x1 > x3); + BOOST_CHECK(x2 < x4); + BOOST_CHECK(x4 > x2); + BOOST_CHECK(x1 < 100.); + BOOST_CHECK(-100 < x1); + BOOST_CHECK(100. > x1); + BOOST_CHECK(x1 > -100); +} \ No newline at end of file From f2ee98861a98df7c6574befdb74381a16af30f70 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Tue, 24 Apr 2018 09:04:55 +0200 Subject: [PATCH 02/61] more tests on vectorized double --- tests/vectorized_double.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/vectorized_double.cpp b/tests/vectorized_double.cpp index 040f6977..5306d324 100644 --- a/tests/vectorized_double.cpp +++ b/tests/vectorized_double.cpp @@ -62,4 +62,10 @@ BOOST_AUTO_TEST_CASE(math) BOOST_CHECK(-100 < x1); BOOST_CHECK(100. > x1); BOOST_CHECK(x1 > -100); + BOOST_CHECK(x1 != x2); + BOOST_CHECK(x1 == x1); + BOOST_CHECK(x3 == -100); + BOOST_CHECK(x4 == 100); + BOOST_CHECK(x3 != 32); + BOOST_CHECK(x4 != 32); } \ No newline at end of file From 2a4aebc8cad2132e055e837bfd752ec13b7faba1 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Tue, 24 Apr 2018 11:49:07 +0200 Subject: [PATCH 03/61] adding trim and extract_terms --- include/audi/gdual.hpp | 24 ++++++++++++++++++-- include/audi/vectorized_double.hpp | 2 +- pyaudi/_version.py | 2 +- pyaudi/expose_gdual.hpp | 2 ++ tests/gdual_d.cpp | 10 +++++++++ tests/gdual_v.cpp | 35 ++++++++++++++++++++++++++---- tests/vectorized_double.cpp | 4 +++- 7 files changed, 70 insertions(+), 9 deletions(-) diff --git a/include/audi/gdual.hpp b/include/audi/gdual.hpp index b7904583..4fe4c1e1 100644 --- a/include/audi/gdual.hpp +++ b/include/audi/gdual.hpp @@ -251,6 +251,11 @@ class gdual { } + template + explicit gdual(const std::initializer_list &value) : m_p(value), m_order(0u) + { + } + template = 0> explicit gdual(const T &value, const std::string &symbol, unsigned order) : m_p(), m_order(order) { @@ -264,6 +269,19 @@ class gdual m_p += Cf(value); } + template + explicit gdual(const std::initializer_list &value, const std::string &symbol, unsigned order) : m_p(), m_order(order) + { + check_order(); + check_var_name(symbol); + if (order == 0) { + extend_symbol_set(std::vector{std::string("d") + symbol}); + } else { + m_p = p_type(std::string("d") + symbol); + } + m_p += Cf(value); + } + /// Defaulted assignment operator gdual &operator=(const gdual &) = default; /// Defaulted assignment operator @@ -421,8 +439,10 @@ class gdual */ gdual trim(double epsilon) const { - auto new_p - = m_p.filter([epsilon](const std::pair &coeff) { return abs(coeff.first) > epsilon; }); + if (epsilon < 0) { + throw std::invalid_argument("When trimming a gdual the trim tolerance must be positive, you seem to have used a negative value: " + std::to_string(epsilon) ); + } + auto new_p = m_p.filter([epsilon](const std::pair &coeff) { return !(abs(coeff.first) < epsilon); }); return gdual(std::move(new_p), m_order); } diff --git a/include/audi/vectorized_double.hpp b/include/audi/vectorized_double.hpp index 21ccba8e..40e44802 100644 --- a/include/audi/vectorized_double.hpp +++ b/include/audi/vectorized_double.hpp @@ -198,7 +198,7 @@ class vectorized_double } friend vectorized_double abs(vectorized_double in) { - std::transform(in.m_c.begin(), in.m_c.end(), in.m_c.begin(), [](double x) { return std::abs(x); }); + std::transform(in.m_c.begin(), in.m_c.end(), in.m_c.begin(), [](const double &x) { return std::abs(x); }); return in; } friend std::ostream &operator<<(std::ostream &os, const vectorized_double &d) diff --git a/pyaudi/_version.py b/pyaudi/_version.py index f9014086..b3f9ac7f 100644 --- a/pyaudi/_version.py +++ b/pyaudi/_version.py @@ -1 +1 @@ -__version__ = "1.1" +__version__ = "1.2.4" diff --git a/pyaudi/expose_gdual.hpp b/pyaudi/expose_gdual.hpp index 670e6a25..1870cfb2 100644 --- a/pyaudi/expose_gdual.hpp +++ b/pyaudi/expose_gdual.hpp @@ -134,6 +134,8 @@ bp::class_> expose_gdual(std::string type) .def("integrate", &gdual::template integrate<>, "Integrate with respect to argument") .def("partial", &gdual::template partial<>, "Partial derivative with respect to argument") .def("is_zero", &gdual::is_zero, "checks if all coefficients of the gdual are zero within a tolerance") + .def("trim", &gdual::trim, "returns a new gdual removing all coefficients that are smaller than a tolerance") + .def("extract_terms", &gdual::extract_terms, "returns a new gdual containing only terms of a given order") .def(bp::self + bp::self) .def(bp::self - bp::self) .def(bp::self * bp::self) diff --git a/tests/gdual_d.cpp b/tests/gdual_d.cpp index 53ff6500..1c59b69f 100644 --- a/tests/gdual_d.cpp +++ b/tests/gdual_d.cpp @@ -334,3 +334,13 @@ BOOST_AUTO_TEST_CASE(serialization_test) BOOST_CHECK(newf == f); BOOST_CHECK(newf.get_order() == f.get_order()); } + +BOOST_AUTO_TEST_CASE(trim) +{ + gdual_d x(1e-5, "x", 4); + gdual_d y(1e-3, "x", 4); + BOOST_CHECK(x.trim(1e-6) == x); + BOOST_CHECK(y.trim(1e-2) == gdual_d(0., "x", 1)); + BOOST_CHECK(y.trim(100) == gdual_d(0., "x", 0)); + BOOST_CHECK_THROW(x.trim(-1e-3), std::invalid_argument); +} \ No newline at end of file diff --git a/tests/gdual_v.cpp b/tests/gdual_v.cpp index 45e7a70d..6686166d 100644 --- a/tests/gdual_v.cpp +++ b/tests/gdual_v.cpp @@ -258,9 +258,36 @@ BOOST_AUTO_TEST_CASE(is_zero) } } -BOOST_AUTO_TEST_CASE(trim) +BOOST_AUTO_TEST_CASE(extract_order) { - vectorized_double x{1, -2, -3, 4, 0.123, -21.211}; - // gdual_v x(std::vector{{1, -2, -3, 4, 0.123, -21.211}}, "x", 4); - print(30 > x); + unsigned int order = 8u; + gdual_v x({0.123, 0.222}, "x", order); + gdual_v y({0.456, -0.12}, "y", order); + auto f = audi::sin(x * y); + // We test that the extracted gduals have the requested order + for (auto i = 0u; i <= order; ++i) { + auto fi = f.extract_terms(i); + BOOST_CHECK_EQUAL(fi.degree(), fi.get_order()); + BOOST_CHECK_EQUAL(fi.get_order(), i); + } + // We test that f = f0+f1+f2+...+fn + std::vector terms; + for (auto i = 0u; i <= order; ++i) { + auto f2 = f.extract_terms(i); + terms.push_back(f2); + } + auto sum = std::accumulate(terms.begin(), terms.end(), gdual_v({0.,0.})); + BOOST_CHECK((sum - f).is_zero(0.)); + // And we test the throw + BOOST_CHECK_THROW(f.extract_terms(order + 1), std::invalid_argument); + BOOST_CHECK_NO_THROW(f.extract_terms(order)); } + +BOOST_AUTO_TEST_CASE(trim) +{ + gdual_v x({10., -1e-4, 10., -10.}, "x", 4); + gdual_v y({1e-3, -1e-4, 1e-9, 1e-5}, "x", 4); + BOOST_CHECK(x.trim(1e-1) == x); + BOOST_CHECK(y.trim(1e-2) == gdual_v({0.,0.,0.,0.}, "x", 4)); + BOOST_CHECK_THROW(x.trim(-1e-3), std::invalid_argument); +} \ No newline at end of file diff --git a/tests/vectorized_double.cpp b/tests/vectorized_double.cpp index 5306d324..86bbcbec 100644 --- a/tests/vectorized_double.cpp +++ b/tests/vectorized_double.cpp @@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE(construction) } BOOST_AUTO_TEST_CASE(math) { - vectorized_double x1{-1., 1., 2., -3., 4.}; + vectorized_double x1{1., 1., 2., -3., 4.}; vectorized_double x2{1., 1., 2., 3., 4.}; vectorized_double x3{-100., -100., -100., -100., -100.}; vectorized_double x4{100., 100., 100., 100., 100.}; @@ -68,4 +68,6 @@ BOOST_AUTO_TEST_CASE(math) BOOST_CHECK(x4 == 100); BOOST_CHECK(x3 != 32); BOOST_CHECK(x4 != 32); + BOOST_CHECK(abs(x1) == x2); + BOOST_CHECK(abs(x2) != x1); } \ No newline at end of file From aeee6ad32f170f47b9b90b806a18a78061634c44 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Tue, 24 Apr 2018 11:57:56 +0200 Subject: [PATCH 04/61] more tests in python --- pyaudi/test.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/pyaudi/test.py b/pyaudi/test.py index bf6d2421..3dcb3c30 100644 --- a/pyaudi/test.py +++ b/pyaudi/test.py @@ -202,6 +202,20 @@ def test_subs(self): self.assertEqual(res3.get_derivative({"dx": 1}), -0.75) self.assertEqual(res3.get_derivative({"dy": 1}), 0.) + def test_trim(self): + from pyaudi import gdual_double as gdual + x = gdual(1e-4, "x", 1) + self.assertEqual(x, x.trim(1e-5)) + self.assertEqual(x.trim(1e-3), gdual(0,"x",1)) + + def test_extract_terms(self): + from pyaudi import gdual_double as gdual + from pyaudi import sin + x = gdual(1e-4, "x", 3) + sinx = sin(x) + self.assertEqual(sinx, sinx.extract_terms(0) + sinx.extract_terms(1)+ sinx.extract_terms(2)+ sinx.extract_terms(3)) + self.assertEqual(x.trim(1e-3), gdual(0,"x",1)) + def test_serialization(self): from pyaudi import gdual_double as gdual import pickle as pk @@ -486,6 +500,20 @@ def test_consistency_functions(self): self.assertAlmostEqual(f3.get_derivative( [dx, dy, dz]), fv.get_derivative([dx, dy, dz])[2], delta=1e-12) + def test_trim(self): + from pyaudi import gdual_vdouble as gdual + x = gdual([1e-4, -1e-4], "x", 1) + self.assertTrue(x == x.trim(1e-5)) + self.assertTrue(x.trim(1e-3) == gdual([0, 0],"x",1)) + + def test_extract_terms(self): + from pyaudi import gdual_vdouble as gdual + from pyaudi import sin + x = gdual([1e-4, -1e-4], "x", 3) + sinx = sin(x) + self.assertTrue(sinx == sinx.extract_terms(0) + sinx.extract_terms(1)+ sinx.extract_terms(2)+ sinx.extract_terms(3)) + self.assertTrue(x.trim(1e-3) == gdual([0, 0],"x",1)) + class test_utilities(_ut.TestCase): def test_map_inversion(self): From 007d9fa079d53b0fe26df450aa44e9daf6ef59a8 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Tue, 24 Apr 2018 13:40:49 +0200 Subject: [PATCH 05/61] version bump 1.3 --- CMakeLists.txt | 2 +- doc/doxygen/Doxyfile | 2 +- doc/sphinx/conf.py | 4 ++-- pyaudi/_version.py | 1 - 4 files changed, 4 insertions(+), 5 deletions(-) delete mode 100644 pyaudi/_version.py diff --git a/CMakeLists.txt b/CMakeLists.txt index aa7b3a36..af3e0909 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ if((NOT AUDI_BUILD_AUDI) AND (NOT AUDI_BUILD_PYAUDI)) endif() # Main audi/pyaudi project version. -set(AUDI_PROJECT_VERSION 1.2.4) +set(AUDI_PROJECT_VERSION 1.3) if(AUDI_BUILD_AUDI) # Initial setup of a audi build. diff --git a/doc/doxygen/Doxyfile b/doc/doxygen/Doxyfile index 779cdfff..8dfd5437 100644 --- a/doc/doxygen/Doxyfile +++ b/doc/doxygen/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "audi" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.2.4 +PROJECT_NUMBER = 1.3 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/doc/sphinx/conf.py b/doc/sphinx/conf.py index 95f77fb9..4332ce9d 100644 --- a/doc/sphinx/conf.py +++ b/doc/sphinx/conf.py @@ -63,9 +63,9 @@ # built documents. # # The short X.Y version. -version = '1.2.4' +version = '1.3' # The full version, including alpha/beta/rc tags. -release = '1.2.4' +release = '1.3' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/pyaudi/_version.py b/pyaudi/_version.py deleted file mode 100644 index b3f9ac7f..00000000 --- a/pyaudi/_version.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "1.2.4" From 59584a5223b235968b41c8d9cd6ef34115882ee8 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Wed, 25 Apr 2018 15:21:38 +0200 Subject: [PATCH 06/61] splitting test in two files (mingw failed on CI) --- tests/CMakeLists.txt | 1 + tests/gdual_v.cpp | 70 -------------------------------------------- 2 files changed, 1 insertion(+), 70 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 20026fd9..a71b8be6 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -29,6 +29,7 @@ ENDMACRO(ADD_AUDI_PERFORMANCE_TESTCASE) ADD_AUDI_TESTCASE(gdual_d) ADD_AUDI_TESTCASE(gdual_v) +ADD_AUDI_TESTCASE(gdual_v2) ADD_AUDI_TESTCASE(vectorized_double) ADD_AUDI_TESTCASE(functions) ADD_AUDI_TESTCASE(functions_from_d) diff --git a/tests/gdual_v.cpp b/tests/gdual_v.cpp index 6686166d..5a91344b 100644 --- a/tests/gdual_v.cpp +++ b/tests/gdual_v.cpp @@ -221,73 +221,3 @@ BOOST_AUTO_TEST_CASE(arithmetic_div) } } } -BOOST_AUTO_TEST_CASE(substitution) -{ - gdual_v x(std::vector{1., 1.}, "x", 1); - gdual_v y(std::vector{-1., -1}, "y", 1); - auto res = x * y * x / (x - y); // [-0.75, -0.75]*dx+[-0.5, -0.5]+[0.25, 0.25]*dy - auto res2 = res.subs("dx", std::vector{1.}); - auto res3 = res.subs("dy", std::vector{1.}); - BOOST_CHECK_EQUAL(res2.constant_cf()[0], -1.25); - BOOST_CHECK_EQUAL(res2.constant_cf()[1], -1.25); - BOOST_CHECK_EQUAL(res2.get_derivative({0, 1})[0], 0.25); - BOOST_CHECK_EQUAL(res2.get_derivative({0, 1})[1], 0.25); - BOOST_CHECK_EQUAL(res2.get_derivative({1, 0})[0], 0.); - BOOST_CHECK_EQUAL(res2.get_derivative({1, 0}).size(), 1); - BOOST_CHECK_EQUAL(res3.constant_cf()[0], -0.25); - BOOST_CHECK_EQUAL(res3.constant_cf()[1], -0.25); - BOOST_CHECK_EQUAL(res3.get_derivative({1, 0})[0], -0.75); - BOOST_CHECK_EQUAL(res3.get_derivative({1, 0})[1], -0.75); - BOOST_CHECK_EQUAL(res3.get_derivative({0, 1})[0], 0.); - BOOST_CHECK_EQUAL(res3.get_derivative({0, 1}).size(), 1); -} - -BOOST_AUTO_TEST_CASE(is_zero) -{ - // We test some trivial cases where truncation order does not influence the results - { - gdual_v x(std::vector{{1, 2, 3, 4, 0.123, -21.211}}, "x", 4); - gdual_v y(std::vector{{0.123, 1.2, 4.3, 2.4, 0.23, -1.211}}, "y", 4); - gdual_v z(std::vector{{-0.2, -2.01, 0.123, -0.132, 1.123, -0.211}}, "z", 4); - gdual_v f = x * x * x + x * y * z + z * x * y; - - BOOST_CHECK((f - f).is_zero(1e-12)); - BOOST_CHECK((f - 1 / (1 / f)).is_zero(1e-12)); - BOOST_CHECK(((f * f) / (f)-f).is_zero(1e-12)); - BOOST_CHECK(!f.is_zero(1e-12)); - } -} - -BOOST_AUTO_TEST_CASE(extract_order) -{ - unsigned int order = 8u; - gdual_v x({0.123, 0.222}, "x", order); - gdual_v y({0.456, -0.12}, "y", order); - auto f = audi::sin(x * y); - // We test that the extracted gduals have the requested order - for (auto i = 0u; i <= order; ++i) { - auto fi = f.extract_terms(i); - BOOST_CHECK_EQUAL(fi.degree(), fi.get_order()); - BOOST_CHECK_EQUAL(fi.get_order(), i); - } - // We test that f = f0+f1+f2+...+fn - std::vector terms; - for (auto i = 0u; i <= order; ++i) { - auto f2 = f.extract_terms(i); - terms.push_back(f2); - } - auto sum = std::accumulate(terms.begin(), terms.end(), gdual_v({0.,0.})); - BOOST_CHECK((sum - f).is_zero(0.)); - // And we test the throw - BOOST_CHECK_THROW(f.extract_terms(order + 1), std::invalid_argument); - BOOST_CHECK_NO_THROW(f.extract_terms(order)); -} - -BOOST_AUTO_TEST_CASE(trim) -{ - gdual_v x({10., -1e-4, 10., -10.}, "x", 4); - gdual_v y({1e-3, -1e-4, 1e-9, 1e-5}, "x", 4); - BOOST_CHECK(x.trim(1e-1) == x); - BOOST_CHECK(y.trim(1e-2) == gdual_v({0.,0.,0.,0.}, "x", 4)); - BOOST_CHECK_THROW(x.trim(-1e-3), std::invalid_argument); -} \ No newline at end of file From b797f9ac6613d5c522d1e3e63284ed0cce43d203 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Wed, 25 Apr 2018 17:02:18 +0200 Subject: [PATCH 07/61] forgotten file --- tests/gdual_v2.cpp | 83 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 tests/gdual_v2.cpp diff --git a/tests/gdual_v2.cpp b/tests/gdual_v2.cpp new file mode 100644 index 00000000..81c70742 --- /dev/null +++ b/tests/gdual_v2.cpp @@ -0,0 +1,83 @@ +#define BOOST_TEST_MODULE audi_gdual_test +#include +#include +#include + +#include +#include + +#include "helpers.hpp" +#include + +using namespace audi; + +BOOST_AUTO_TEST_CASE(substitution) +{ + gdual_v x(std::vector{1., 1.}, "x", 1); + gdual_v y(std::vector{-1., -1}, "y", 1); + auto res = x * y * x / (x - y); // [-0.75, -0.75]*dx+[-0.5, -0.5]+[0.25, 0.25]*dy + auto res2 = res.subs("dx", std::vector{1.}); + auto res3 = res.subs("dy", std::vector{1.}); + BOOST_CHECK_EQUAL(res2.constant_cf()[0], -1.25); + BOOST_CHECK_EQUAL(res2.constant_cf()[1], -1.25); + BOOST_CHECK_EQUAL(res2.get_derivative({0, 1})[0], 0.25); + BOOST_CHECK_EQUAL(res2.get_derivative({0, 1})[1], 0.25); + BOOST_CHECK_EQUAL(res2.get_derivative({1, 0})[0], 0.); + BOOST_CHECK_EQUAL(res2.get_derivative({1, 0}).size(), 1); + BOOST_CHECK_EQUAL(res3.constant_cf()[0], -0.25); + BOOST_CHECK_EQUAL(res3.constant_cf()[1], -0.25); + BOOST_CHECK_EQUAL(res3.get_derivative({1, 0})[0], -0.75); + BOOST_CHECK_EQUAL(res3.get_derivative({1, 0})[1], -0.75); + BOOST_CHECK_EQUAL(res3.get_derivative({0, 1})[0], 0.); + BOOST_CHECK_EQUAL(res3.get_derivative({0, 1}).size(), 1); +} + +BOOST_AUTO_TEST_CASE(is_zero) +{ + // We test some trivial cases where truncation order does not influence the results + { + gdual_v x(std::vector{{1, 2, 3, 4, 0.123, -21.211}}, "x", 4); + gdual_v y(std::vector{{0.123, 1.2, 4.3, 2.4, 0.23, -1.211}}, "y", 4); + gdual_v z(std::vector{{-0.2, -2.01, 0.123, -0.132, 1.123, -0.211}}, "z", 4); + gdual_v f = x * x * x + x * y * z + z * x * y; + + BOOST_CHECK((f - f).is_zero(1e-12)); + BOOST_CHECK((f - 1 / (1 / f)).is_zero(1e-12)); + BOOST_CHECK(((f * f) / (f)-f).is_zero(1e-12)); + BOOST_CHECK(!f.is_zero(1e-12)); + } +} + +BOOST_AUTO_TEST_CASE(extract_order) +{ + unsigned int order = 8u; + gdual_v x({0.123, 0.222}, "x", order); + gdual_v y({0.456, -0.12}, "y", order); + auto f = audi::sin(x * y); + // We test that the extracted gduals have the requested order + for (auto i = 0u; i <= order; ++i) { + auto fi = f.extract_terms(i); + BOOST_CHECK_EQUAL(fi.degree(), fi.get_order()); + BOOST_CHECK_EQUAL(fi.get_order(), i); + } + // We test that f = f0+f1+f2+...+fn + std::vector terms; + for (auto i = 0u; i <= order; ++i) { + auto f2 = f.extract_terms(i); + terms.push_back(f2); + } + auto sum = std::accumulate(terms.begin(), terms.end(), gdual_v({0.,0.})); + BOOST_CHECK((sum - f).is_zero(0.)); + // And we test the throw + BOOST_CHECK_THROW(f.extract_terms(order + 1), std::invalid_argument); + BOOST_CHECK_NO_THROW(f.extract_terms(order)); +} + +BOOST_AUTO_TEST_CASE(trim) +{ + gdual_v x({10., -1e-4, 10., -10.}, "x", 4); + gdual_v y({1e-3, -1e-4, 1e-9, 1e-5}, "x", 4); + BOOST_CHECK(x.trim(1e-1) == x); + BOOST_CHECK(y.trim(1e-2) == gdual_v({0.,0.,0.,0.}, "x", 4)); + BOOST_CHECK_THROW(x.trim(-1e-3), std::invalid_argument); +} \ No newline at end of file From bffa580d4ea9df5e140a472ca433248027575c83 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Thu, 26 Apr 2018 15:29:02 +0200 Subject: [PATCH 08/61] introducing explicit in the vectorized double constructor --- include/audi/detail/overloads.hpp | 4 +- include/audi/gdual.hpp | 5 +- include/audi/vectorized_double.hpp | 93 ++++++++++++++++++------------ tests/gdual_d.cpp | 2 +- tests/gdual_v.cpp | 2 +- tests/gdual_v2.cpp | 2 +- tests/vectorized_double.cpp | 35 ++++++++++- 7 files changed, 98 insertions(+), 45 deletions(-) diff --git a/include/audi/detail/overloads.hpp b/include/audi/detail/overloads.hpp index 57de0030..5c242bf7 100644 --- a/include/audi/detail/overloads.hpp +++ b/include/audi/detail/overloads.hpp @@ -1,8 +1,8 @@ #ifndef AUDI_OVERLOADS_HPP #define AUDI_OVERLOADS_HPP -#include "../back_compatibility.hpp" -#include "../vectorized_double.hpp" +#include +#include #include // This is repeated here instead of including type_traits as to avoid a circular dependency diff --git a/include/audi/gdual.hpp b/include/audi/gdual.hpp index 4fe4c1e1..c891ea02 100644 --- a/include/audi/gdual.hpp +++ b/include/audi/gdual.hpp @@ -125,8 +125,9 @@ class gdual // A private constructor to move-initialise a gdual from a polynomial. Used // in the implementation of the operators. explicit gdual(p_type &&p, unsigned int order) : m_p(std::move(p)), m_order(order) {} - // A private constructor used in the implementation of the operators (is it necessary?) - explicit gdual(Cf value, unsigned int order) : m_p(value), m_order(order) {} + // A private constructor used in the implementation of the operators. + template + explicit gdual(T value, unsigned int order) : m_p(Cf(value)), m_order(order) {} // Basic overloads for the addition static gdual add(const gdual &d1, const gdual &d2) diff --git a/include/audi/vectorized_double.hpp b/include/audi/vectorized_double.hpp index 40e44802..29ccd3aa 100644 --- a/include/audi/vectorized_double.hpp +++ b/include/audi/vectorized_double.hpp @@ -10,6 +10,8 @@ #include #include +#include + // The streaming operator will only output the first MAX_STREAMED_COMPONENTS elements of the vector #define MAX_STREAMED_COMPONENTS 5u @@ -23,12 +25,16 @@ namespace audi class vectorized_double { public: + template + using operator_enabler + = enable_if_t<(std::is_same::value || std::is_arithmetic::value), int>; // Default constructor. Constructs [0.] vectorized_double() : m_c({0.}){}; // Constructor from int. Its mandatory for piranha::polynomial coefficient explicit vectorized_double(int a) : m_c({static_cast(a)}){}; - // Constructor from double value a. Construct [a] TODO: should we make this explicit? - vectorized_double(double a) : m_c({a}){}; + + // Constructor from double value a. Construct [a] + explicit vectorized_double(double a) : m_c({a}){}; // Constructor from an std::vector explicit vectorized_double(const std::vector &c) : m_c(c) { @@ -49,37 +55,39 @@ class vectorized_double throw std::invalid_argument("Cannot build an empty coefficient_v (initializer)"); } }; - // ------------------- Binary arithmetic operators implemented using +=,-=, etc. - friend vectorized_double operator+(const vectorized_double &d1, const vectorized_double &d2) - { - vectorized_double retval(d1); - retval += d2; - return retval; - }; - friend vectorized_double operator-(const vectorized_double &d1, const vectorized_double &d2) - { - vectorized_double retval(d1); - retval -= d2; - return retval; - }; - friend vectorized_double operator*(const vectorized_double &d1, const vectorized_double &d2) + // ------------------- Binary arithmetic operators implemented using the available +=,-=, etc. + template = 0, operator_enabler = 0> + friend vectorized_double operator+(const T1 &d1v, const T2 &d2v) + { + vectorized_double d1(d1v); + vectorized_double d2(d2v); + d1 += d2; + return d1; + } + template = 0, operator_enabler = 0> + friend vectorized_double operator-(const T1 &d1v, const T2 &d2v) { - vectorized_double retval(d1); - retval *= d2; - return retval; - }; - friend vectorized_double operator*(int d1, const vectorized_double &d2) + vectorized_double d1(d1v); + vectorized_double d2(d2v); + d1 -= d2; + return d1; + } + template = 0, operator_enabler = 0> + friend vectorized_double operator*(const T1 &d1v, const T2 &d2v) { - vectorized_double retval(d1); - retval *= d2; - return retval; - }; - friend vectorized_double operator/(const vectorized_double &d1, const vectorized_double &d2) + vectorized_double d1(d1v); + vectorized_double d2(d2v); + d1 *= d2; + return d1; + } + template = 0, operator_enabler = 0> + friend vectorized_double operator/(const T1 &d1v, const T2 &d2v) { - vectorized_double retval(d1); - retval /= d2; - return retval; - }; + vectorized_double d1(d1v); + vectorized_double d2(d2v); + d1 /= d2; + return d1; + } // ----------------- Juice implementation of the operators. It also deals with the case [b1] op [a1,a2,..an] to // take care of scalar multiplication/division etc. @@ -159,8 +167,11 @@ class vectorized_double transform(retval.m_c.begin(), retval.m_c.end(), retval.m_c.begin(), std::negate()); return retval; } - friend bool operator==(const vectorized_double &d1, const vectorized_double &d2) + template = 0, operator_enabler = 0> + friend bool operator==(const T1 &d1v, const T2 &d2v) { + vectorized_double d1(d1v); + vectorized_double d2(d2v); if (d1.size() == d2.size()) { return d1.m_c == d2.m_c; } else if (d1.size() == 1u) { @@ -170,12 +181,16 @@ class vectorized_double } return false; } - friend bool operator!=(const vectorized_double &d1, const vectorized_double &d2) + template = 0, operator_enabler = 0> + friend bool operator!=(const T1 &d1, const T2 &d2) { return !(d1 == d2); } - friend bool operator>(const vectorized_double &d1, const vectorized_double &d2) + template = 0, operator_enabler = 0> + friend bool operator>(const T1 &d1v, const T2 &d2v) { + vectorized_double d1(d1v); + vectorized_double d2(d2v); if (d1.size() == d2.size()) { return d1.m_c > d2.m_c; } else if (d1.size() == 1u) { @@ -185,8 +200,12 @@ class vectorized_double } return false; } - friend bool operator<(const vectorized_double &d1, const vectorized_double &d2) + + template = 0, operator_enabler = 0> + friend bool operator<(const T1 &d1v, const T2 &d2v) { + vectorized_double d1(d1v); + vectorized_double d2(d2v); if (d1.size() == d2.size()) { return d1.m_c < d2.m_c; } else if (d1.size() == 1u) { @@ -272,7 +291,7 @@ class vectorized_double std::vector m_c; }; -} // end of audi namespace +} // namespace audi namespace piranha { @@ -352,7 +371,7 @@ struct pow_impl struct boost_save_impl : boost_save_via_boost_api { @@ -366,7 +385,7 @@ template <> struct zero_is_absorbing : std::false_type { }; -} // end of piranha namespace +} // namespace piranha #undef MAX_STREAMED_COMPONENTS #endif diff --git a/tests/gdual_d.cpp b/tests/gdual_d.cpp index 1c59b69f..821ff413 100644 --- a/tests/gdual_d.cpp +++ b/tests/gdual_d.cpp @@ -1,4 +1,4 @@ -#define BOOST_TEST_MODULE audi_gdual_test +#define BOOST_TEST_MODULE audi_gduald_test #include #include #include diff --git a/tests/gdual_v.cpp b/tests/gdual_v.cpp index 5a91344b..9fc3c2dc 100644 --- a/tests/gdual_v.cpp +++ b/tests/gdual_v.cpp @@ -1,4 +1,4 @@ -#define BOOST_TEST_MODULE audi_gdual_test +#define BOOST_TEST_MODULE audi_gdualv_test #include #include #include diff --git a/tests/gdual_v2.cpp b/tests/gdual_v2.cpp index 81c70742..633f95c1 100644 --- a/tests/gdual_v2.cpp +++ b/tests/gdual_v2.cpp @@ -1,4 +1,4 @@ -#define BOOST_TEST_MODULE audi_gdual_test +#define BOOST_TEST_MODULE audi_gdualv2_test #include #include #include diff --git a/tests/vectorized_double.cpp b/tests/vectorized_double.cpp index 86bbcbec..c9298ead 100644 --- a/tests/vectorized_double.cpp +++ b/tests/vectorized_double.cpp @@ -53,7 +53,7 @@ BOOST_AUTO_TEST_CASE(math) vectorized_double x2{1., 1., 2., 3., 4.}; vectorized_double x3{-100., -100., -100., -100., -100.}; vectorized_double x4{100., 100., 100., 100., 100.}; - BOOST_CHECK(abs(x1)==x2); + BOOST_CHECK(abs(x1) == x2); BOOST_CHECK(x3 < x1); BOOST_CHECK(x1 > x3); BOOST_CHECK(x2 < x4); @@ -70,4 +70,37 @@ BOOST_AUTO_TEST_CASE(math) BOOST_CHECK(x4 != 32); BOOST_CHECK(abs(x1) == x2); BOOST_CHECK(abs(x2) != x1); + BOOST_CHECK(x1 - 1. == (vectorized_double{0., 0., 1., -4., 3.})); +} + +BOOST_AUTO_TEST_CASE(more_math) +{ + vectorized_double x1{1., 2.}; + vectorized_double x2{3., 3.}; + // Interoperability against arith types + BOOST_CHECK(x1 * 2. == (vectorized_double{2., 4.})); + BOOST_CHECK(x1 / 2. == (vectorized_double{0.5, 1.})); + BOOST_CHECK(x1 + 2. == (vectorized_double{3., 4.})); + BOOST_CHECK(x1 - 2. == (vectorized_double{-1., 0.})); + BOOST_CHECK(x1 * 2 == (vectorized_double{2., 4.})); + BOOST_CHECK(x1 / 2 == (vectorized_double{0.5, 1.})); + BOOST_CHECK(x1 + 2 == (vectorized_double{3., 4.})); + BOOST_CHECK(x1 - 2 == (vectorized_double{-1., 0.})); + BOOST_CHECK(2 * x1 == (vectorized_double{2., 4.})); + BOOST_CHECK(2 / x1 == (vectorized_double{2., 1.})); + BOOST_CHECK(2 + x1 == (vectorized_double{3., 4.})); + BOOST_CHECK(2 - x1 == (vectorized_double{1., 0.})); + BOOST_CHECK(2 * x1 == (vectorized_double{2., 4.})); + BOOST_CHECK(2 / x1 == (vectorized_double{2., 1.})); + BOOST_CHECK(2 + x1 == (vectorized_double{3., 4.})); + BOOST_CHECK(2 - x1 == (vectorized_double{1., 0.})); + BOOST_CHECK(x1 != 1.); + BOOST_CHECK(x2 == 2.); + BOOST_CHECK(x1 > -1.); + BOOST_CHECK(x1 < 3.); + // operators with vectorized-vectorized + BOOST_CHECK(x1 + x2 == (vectorized_double{4., 5.})); + BOOST_CHECK(x1 - x2 == (vectorized_double{4., 5.})); + BOOST_CHECK(x1 / x2 == (vectorized_double{4., 5.})); + BOOST_CHECK(x1 * x2 == (vectorized_double{4., 5.})); } \ No newline at end of file From 8729e5fdf537ec92260bba495f12d18298517e95 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Thu, 26 Apr 2018 16:59:27 +0200 Subject: [PATCH 09/61] adding unsigned short /= --- include/audi/vectorized_double.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/audi/vectorized_double.hpp b/include/audi/vectorized_double.hpp index 29ccd3aa..5081db48 100644 --- a/include/audi/vectorized_double.hpp +++ b/include/audi/vectorized_double.hpp @@ -161,6 +161,14 @@ class vectorized_double } throw std::invalid_argument("Coefficients of different sizes in /"); } + template + vectorized_double &operator/=(const T &d1) + { + std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), + [&d1](double x) { return x / d1; }); + return *this; + + } vectorized_double operator-() const { vectorized_double retval(m_c); From a247d9dabc9e98c10a399ca659b62eba7d302419 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Mon, 30 Apr 2018 15:11:39 +0200 Subject: [PATCH 10/61] several fixes towards a generic code (working on real128 too) --- include/audi/audi.hpp | 4 +++ include/audi/detail/overloads.hpp | 55 ++++++++++++++++++++++++------- include/audi/functions.hpp | 24 +++++++------- include/audi/gdual.hpp | 7 ++-- include/audi/real128.hpp | 31 +++++++++++++++++ tests/CMakeLists.txt | 1 + tests/gdual_mp.cpp | 45 +++++++++++++++++++++++++ tests/vectorized_double.cpp | 8 ++--- 8 files changed, 144 insertions(+), 31 deletions(-) create mode 100644 include/audi/real128.hpp create mode 100644 tests/gdual_mp.cpp diff --git a/include/audi/audi.hpp b/include/audi/audi.hpp index 845a35ce..53225a59 100644 --- a/include/audi/audi.hpp +++ b/include/audi/audi.hpp @@ -3,17 +3,21 @@ #include +#include + #include #include #include #include #include +#include namespace audi { using gdual_d = audi::gdual; using gdual_v = audi::gdual; using gdual_c = audi::gdual>; +using gdual_mp = audi::gdual; } #endif diff --git a/include/audi/detail/overloads.hpp b/include/audi/detail/overloads.hpp index 5c242bf7..c70a1e43 100644 --- a/include/audi/detail/overloads.hpp +++ b/include/audi/detail/overloads.hpp @@ -3,6 +3,7 @@ #include #include +#include #include // This is repeated here instead of including type_traits as to avoid a circular dependency @@ -30,55 +31,95 @@ struct is_arithmetic_or_complex return std::fun_name(in); \ } +// This macro writes the overload for std::fun_name af a mppp::real128. It simply calls mppp::fun_name +// It is used to allow calls such as audi::cos(T) [T = double] in templated functions. +#define REAL128_OVERLOAD(fun_name) \ + inline mppp::real128 fun_name(mppp::real128 in) \ + { \ + return mppp::fun_name(in); \ + } + namespace audi { - VECTORIZED_OVERLOAD(exp) ARITH_OR_COMPLEX_OVERLOAD(exp) +REAL128_OVERLOAD(exp) VECTORIZED_OVERLOAD(erf) ARITH_OR_COMPLEX_OVERLOAD(erf) +REAL128_OVERLOAD(erf) VECTORIZED_OVERLOAD(log) ARITH_OR_COMPLEX_OVERLOAD(log) +REAL128_OVERLOAD(log) VECTORIZED_OVERLOAD(sin) ARITH_OR_COMPLEX_OVERLOAD(sin) +REAL128_OVERLOAD(sin) VECTORIZED_OVERLOAD(cos) ARITH_OR_COMPLEX_OVERLOAD(cos) +REAL128_OVERLOAD(cos) VECTORIZED_OVERLOAD(tan) ARITH_OR_COMPLEX_OVERLOAD(tan) +REAL128_OVERLOAD(tan) VECTORIZED_OVERLOAD(sinh) ARITH_OR_COMPLEX_OVERLOAD(sinh) +REAL128_OVERLOAD(sinh) VECTORIZED_OVERLOAD(cosh) ARITH_OR_COMPLEX_OVERLOAD(cosh) +REAL128_OVERLOAD(cosh) VECTORIZED_OVERLOAD(tanh) ARITH_OR_COMPLEX_OVERLOAD(tanh) +REAL128_OVERLOAD(tanh) VECTORIZED_OVERLOAD(asin) ARITH_OR_COMPLEX_OVERLOAD(asin) +REAL128_OVERLOAD(asin) VECTORIZED_OVERLOAD(acos) ARITH_OR_COMPLEX_OVERLOAD(acos) +REAL128_OVERLOAD(acos) VECTORIZED_OVERLOAD(atan) ARITH_OR_COMPLEX_OVERLOAD(atan) +REAL128_OVERLOAD(atan) VECTORIZED_OVERLOAD(asinh) ARITH_OR_COMPLEX_OVERLOAD(asinh) +REAL128_OVERLOAD(asinh) VECTORIZED_OVERLOAD(acosh) ARITH_OR_COMPLEX_OVERLOAD(acosh) +REAL128_OVERLOAD(acosh) VECTORIZED_OVERLOAD(atanh) ARITH_OR_COMPLEX_OVERLOAD(atanh) +REAL128_OVERLOAD(atanh) VECTORIZED_OVERLOAD(cbrt) +REAL128_OVERLOAD(cbrt) + +template ::value, int> = 0> +inline T cbrt(T in) +{ + return std::cbrt(in); +} +template ::value, int> = 0> +inline T cbrt(T in) +{ + return std::pow(in, 1. / 3.); // needs a separate template as cbrt does not exist for complex types +} + +template ::value, int> = 0> +inline U pow(const U &base, const T &d) +{ + return mppp::pow(base, d); +} template ::value && std::is_arithmetic::value, int> = 0> inline double pow(const U &base, const T &d) @@ -114,17 +155,7 @@ inline vectorized_double pow(vectorized_double in, double exponent) return in; } -template ::value, int> = 0> -inline T cbrt(T in) -{ - return std::cbrt(in); -} -template ::value, int> = 0> -inline T cbrt(T in) -{ - return std::pow(in, 1. / 3.); // needs a separate template as cbrt does not exist for complex types -} - ARITH_OR_COMPLEX_OVERLOAD(abs) + } #endif diff --git a/include/audi/functions.hpp b/include/audi/functions.hpp index 16c73724..31b5091b 100644 --- a/include/audi/functions.hpp +++ b/include/audi/functions.hpp @@ -34,7 +34,7 @@ template ::value, int> = 0> inline T exp(const T &d) { T retval(1.); - double fact = 1; + T fact(1.); auto p0 = d.constant_cf(); auto phat = d - p0; T tmp(phat); @@ -69,7 +69,7 @@ template ::value, int> = 0> inline T log(const T &d) { T retval(0.); - double fatt = 1; + T fatt(1.); auto p0 = d.constant_cf(); auto log_p0 = audi::log(p0); @@ -79,7 +79,7 @@ inline T log(const T &d) retval = log_p0 + phat; for (auto i = 2u; i <= d.get_order(); ++i) { - fatt *= -1; + fatt *= -1.; phat *= tmp; retval = retval + fatt * phat / i; } @@ -135,8 +135,8 @@ inline T pow(const T &d, double alpha) // This is also a workaround to the issue (https://github.com/darioizzo/audi/issues/6) // TODO: is there a better way to do this? Calling the pow (gdual, int) overload is not possible as it // cannot be moved upfront. - double n; - if (std::modf(alpha, &n) == 0.0 && n > 0) { + int n = (alpha*10.); + if (n % 10 == 0 && alpha > 0) { T retval(d); for (auto i = 1; i < (int)n; ++i) { retval *= d; @@ -292,7 +292,7 @@ inline T sin(const T &d) coeff *= -1.; // -1, 1, -1, 1, ... tmp *= phat2; // phat^2, phat^4, phat^6 ... factorial *= i * (i - 1.); // 2!, 4!, 6!, ... - cos_taylor += (coeff / factorial) * tmp; + cos_taylor += (coeff * tmp) / factorial; } factorial = 1.; @@ -303,7 +303,7 @@ inline T sin(const T &d) coeff *= -1.; // -1, 1, -1, 1, ... tmp *= phat2; // phat^3, phat^5, phat^7 ... factorial *= i * (i - 1.); // 3!, 5!, 7!, ... - sin_taylor += (coeff / factorial) * tmp; + sin_taylor += (coeff * tmp) / factorial; } return (sin_p0 * cos_taylor + cos_p0 * sin_taylor); } @@ -342,7 +342,7 @@ inline T cos(const T &d) coeff *= -1.; // -1, 1, -1, 1, ... tmp *= phat2; // phat^2, phat^4, phat^6 ... factorial *= i * (i - 1.); // 2!, 4!, 6!, ... - cos_taylor += (coeff / factorial) * tmp; + cos_taylor += (coeff * tmp) / factorial; // factorial is double, so the operation order matters not to loose precision in case of real128 } factorial = 1.; @@ -353,7 +353,7 @@ inline T cos(const T &d) coeff *= -1.; // -1, 1, -1, 1, ... tmp *= phat2; // phat^3, phat^5, phat^7 ... factorial *= i * (i - 1.); // 3!, 5!, 7!, ... - sin_taylor += (coeff / factorial) * tmp; + sin_taylor += (coeff * tmp) / factorial; // factorial is double, so the operation order matters not to loose precision in case of real128 } return (cos_p0 * cos_taylor - sin_p0 * sin_taylor); } @@ -387,7 +387,7 @@ std::array sin_and_cos(const T &d) coeff *= -1.; // -1, 1, -1, 1, ... tmp *= phat2; // phat^2, phat^4, phat^6 ... factorial *= i * (i - 1.); // 2!, 4!, 6!, ... - cos_taylor += (coeff / factorial) * tmp; + cos_taylor += (coeff / factorial) * tmp; // factorial is double, so the operation order matters not to loose precision in case of real128 } factorial = 1.; @@ -398,7 +398,7 @@ std::array sin_and_cos(const T &d) coeff *= -1.; // -1, 1, -1, 1, ... tmp *= phat2; // phat^3, phat^5, phat^7 ... factorial *= i * (i - 1.); // 3!, 5!, 7!, ... - sin_taylor += (coeff / factorial) * tmp; + sin_taylor += (coeff / factorial) * tmp; // factorial is double, so the operation order matters not to loose precision in case of real128 } auto sine = sin_p0 * cos_taylor + cos_p0 * sin_taylor; auto cosine = cos_p0 * cos_taylor - sin_p0 * sin_taylor; @@ -654,7 +654,7 @@ inline T atanh(const T &d) double coeff = 1.; for (auto k = 1u; k <= d.get_order(); ++k) { - auto add = (1. / audi::pow(1. - p0, k) + coeff / audi::pow(1. + p0, k)) / k; + auto add = (1. / audi::pow(1. - p0, k) + coeff / audi::pow(1. + p0, k)) / static_cast(k); retval += add * powphat; coeff *= -1; powphat *= phat; diff --git a/include/audi/gdual.hpp b/include/audi/gdual.hpp index c891ea02..27cf1d03 100644 --- a/include/audi/gdual.hpp +++ b/include/audi/gdual.hpp @@ -188,7 +188,7 @@ class gdual static gdual div(const gdual &d1, const gdual &d2) { gdual retval(1); - double fatt = -1.; + Cf fatt(-1); auto p0 = d2.constant_cf(); auto phat = (d2 - p0); phat = phat / p0; @@ -208,7 +208,7 @@ class gdual static gdual div(const T &d1, const gdual &d2) { gdual retval(1.); - double fatt = -1.; + Cf fatt(-1.); auto p0 = d2.constant_cf(); auto phat = (d2 - p0); @@ -227,7 +227,8 @@ class gdual template static gdual div(const gdual &d1, const T &d2) { - return d1 * (1. / d2); + // Note: we create the reciprocal of d2 constructing a Cf otherwise we could loose precision, e.g. when T is double and Cf is real128 + return d1 * (1. / Cf(d2)); } p_type m_p; diff --git a/include/audi/real128.hpp b/include/audi/real128.hpp new file mode 100644 index 00000000..aa59f02a --- /dev/null +++ b/include/audi/real128.hpp @@ -0,0 +1,31 @@ +#ifndef AUDI_REAL128_HPP +#define AUDI_REAL128_HPP + +#include +#include +#include +#include + +#include + +// This header adds to the mppp::real128 class the necessary methods that allow it to be +// considered as a type in gdual (piranha::is_Cf, piranha::is_differentiable) + +namespace piranha +{ +namespace math +{ +template <> +struct partial_impl { + /// Call operator. + /** + * @return an instance of piranha::real128 constructed from zero. + */ + mppp::real128 operator()(const mppp::real128 &, const std::string &) const + { + return mppp::real128{}; + } +}; +}} // end of piranha namespace + +#endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a71b8be6..9a7e7b38 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -30,6 +30,7 @@ ENDMACRO(ADD_AUDI_PERFORMANCE_TESTCASE) ADD_AUDI_TESTCASE(gdual_d) ADD_AUDI_TESTCASE(gdual_v) ADD_AUDI_TESTCASE(gdual_v2) +ADD_AUDI_TESTCASE(gdual_mp) ADD_AUDI_TESTCASE(vectorized_double) ADD_AUDI_TESTCASE(functions) ADD_AUDI_TESTCASE(functions_from_d) diff --git a/tests/gdual_mp.cpp b/tests/gdual_mp.cpp new file mode 100644 index 00000000..bb206579 --- /dev/null +++ b/tests/gdual_mp.cpp @@ -0,0 +1,45 @@ +#define BOOST_TEST_MODULE audi_gdualld_test +#include +#include +#include + +#include +#include + +#include "helpers.hpp" +#include + +using namespace audi; + +BOOST_AUTO_TEST_CASE(construction) +{ + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 10}; + BOOST_CHECK(abs(onethird - x.constant_cf()) == 0.); + +} + +BOOST_AUTO_TEST_CASE(exp_and_log) +{ + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 4}; + auto res = exp(x); + BOOST_CHECK(abs(res.find_cf({0}) - audi::exp(onethird)) < 1e-33); + BOOST_CHECK(abs(res.find_cf({1}) - audi::exp(onethird)) < 1e-33); + BOOST_CHECK(abs(res.find_cf({2}) - audi::exp(onethird) / 2.) < 1e-33); + BOOST_CHECK(abs(res.find_cf({3}) - audi::exp(onethird) / 6.) < 1e-33); + BOOST_CHECK((exp(log(x)) - x).trim(1e-34) == gdual_mp(0.)); + BOOST_CHECK((log(exp(x)) - x).trim(1e-34) == gdual_mp(0.)); +} + +BOOST_AUTO_TEST_CASE(trigonometric) +{ + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 4}; + auto res = sin(x); + BOOST_CHECK(abs(res.find_cf({0}) - audi::sin(onethird)) < 1e-33); + BOOST_CHECK(abs(res.find_cf({1}) - audi::cos(onethird)) < 1e-33); + BOOST_CHECK(abs(res.find_cf({2}) + audi::sin(onethird) / 2.) < 1e-33); + BOOST_CHECK(abs(res.find_cf({3}) + audi::cos(onethird) / 6.) < 1e-33); + BOOST_CHECK((sin(asin(x)) - x).trim(1e-34) == gdual_mp(0.)); +} \ No newline at end of file diff --git a/tests/vectorized_double.cpp b/tests/vectorized_double.cpp index c9298ead..9bccd2f0 100644 --- a/tests/vectorized_double.cpp +++ b/tests/vectorized_double.cpp @@ -95,12 +95,12 @@ BOOST_AUTO_TEST_CASE(more_math) BOOST_CHECK(2 + x1 == (vectorized_double{3., 4.})); BOOST_CHECK(2 - x1 == (vectorized_double{1., 0.})); BOOST_CHECK(x1 != 1.); - BOOST_CHECK(x2 == 2.); + BOOST_CHECK(x2 == 3.); BOOST_CHECK(x1 > -1.); BOOST_CHECK(x1 < 3.); // operators with vectorized-vectorized BOOST_CHECK(x1 + x2 == (vectorized_double{4., 5.})); - BOOST_CHECK(x1 - x2 == (vectorized_double{4., 5.})); - BOOST_CHECK(x1 / x2 == (vectorized_double{4., 5.})); - BOOST_CHECK(x1 * x2 == (vectorized_double{4., 5.})); + BOOST_CHECK(x1 - x2 == (vectorized_double{-2., -1.})); + BOOST_CHECK(x1 / x2 == (vectorized_double{1./3., 2./3.})); + BOOST_CHECK(x1 * x2 == (vectorized_double{3., 6.})); } \ No newline at end of file From ef094e5948d9056e4922c4dc3866e317b2eec49b Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Mon, 30 Apr 2018 16:35:07 +0200 Subject: [PATCH 11/61] towards making real128 compute actually in high precision --- include/audi/detail/overloads.hpp | 8 +++++--- include/audi/functions.hpp | 10 +++++----- include/audi/gdual.hpp | 4 ++-- include/audi/vectorized_double.hpp | 2 ++ tests/gdual_mp.cpp | 19 ++++++++++++++++++- 5 files changed, 32 insertions(+), 11 deletions(-) diff --git a/include/audi/detail/overloads.hpp b/include/audi/detail/overloads.hpp index c70a1e43..324a4bfd 100644 --- a/include/audi/detail/overloads.hpp +++ b/include/audi/detail/overloads.hpp @@ -101,6 +101,8 @@ VECTORIZED_OVERLOAD(atanh) ARITH_OR_COMPLEX_OVERLOAD(atanh) REAL128_OVERLOAD(atanh) +ARITH_OR_COMPLEX_OVERLOAD(abs) + VECTORIZED_OVERLOAD(cbrt) REAL128_OVERLOAD(cbrt) @@ -115,8 +117,9 @@ inline T cbrt(T in) return std::pow(in, 1. / 3.); // needs a separate template as cbrt does not exist for complex types } -template ::value, int> = 0> -inline U pow(const U &base, const T &d) +// NON UNARY FUNCTIONS -------------------------------------------------------------------------------// +template ::value || std::is_same::value, int> = 0> +inline mppp::real128 pow(const T &base, const U &d) { return mppp::pow(base, d); } @@ -155,7 +158,6 @@ inline vectorized_double pow(vectorized_double in, double exponent) return in; } -ARITH_OR_COMPLEX_OVERLOAD(abs) } #endif diff --git a/include/audi/functions.hpp b/include/audi/functions.hpp index 31b5091b..a7756dff 100644 --- a/include/audi/functions.hpp +++ b/include/audi/functions.hpp @@ -97,16 +97,16 @@ inline T log(const T &d) * @param d audi::gdual argument * */ -template ::value, int> = 0> -inline T pow(double base, const T &d) +template ::value || std::is_same::value || std::is_same::value, int> = 0> +inline gdual pow(U base, const gdual &d) { // checks wether the exponent is a constant in which // case it calls for a different overload if (d.degree() == 0) { auto p0 = d.constant_cf(); - return T(audi::pow(base, p0)); + return gdual(audi::pow(base, p0)); } - return exp(std::log(base) * d); + return exp(audi::log(T(base)) * d); } /// Overload for the exponentiation @@ -138,7 +138,7 @@ inline T pow(const T &d, double alpha) int n = (alpha*10.); if (n % 10 == 0 && alpha > 0) { T retval(d); - for (auto i = 1; i < (int)n; ++i) { + for (auto i = 1; i < (int)alpha; ++i) { retval *= d; } return retval; diff --git a/include/audi/gdual.hpp b/include/audi/gdual.hpp index 27cf1d03..3ef544a0 100644 --- a/include/audi/gdual.hpp +++ b/include/audi/gdual.hpp @@ -196,7 +196,7 @@ class gdual retval = retval - phat; for (auto i = 2u; i <= d2.m_order; ++i) { - fatt *= -1.; + fatt = -1. * fatt; phat *= tmp; retval = retval + fatt * phat; } @@ -217,7 +217,7 @@ class gdual retval = retval - phat; for (auto i = 2u; i <= d2.m_order; ++i) { - fatt *= -1.; + fatt = -1. * fatt; phat *= tmp; retval = retval + fatt * phat; } diff --git a/include/audi/vectorized_double.hpp b/include/audi/vectorized_double.hpp index 5081db48..d7da8461 100644 --- a/include/audi/vectorized_double.hpp +++ b/include/audi/vectorized_double.hpp @@ -32,6 +32,8 @@ class vectorized_double vectorized_double() : m_c({0.}){}; // Constructor from int. Its mandatory for piranha::polynomial coefficient explicit vectorized_double(int a) : m_c({static_cast(a)}){}; + explicit vectorized_double(unsigned a) : m_c({static_cast(a)}){}; + // Constructor from double value a. Construct [a] explicit vectorized_double(double a) : m_c({a}){}; diff --git a/tests/gdual_mp.cpp b/tests/gdual_mp.cpp index bb206579..5639a3f4 100644 --- a/tests/gdual_mp.cpp +++ b/tests/gdual_mp.cpp @@ -32,6 +32,23 @@ BOOST_AUTO_TEST_CASE(exp_and_log) BOOST_CHECK((log(exp(x)) - x).trim(1e-34) == gdual_mp(0.)); } +BOOST_AUTO_TEST_CASE(exponentiation) +{ + // overload double^gdual + { + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 4}; + auto res = pow(mppp::real128(2.), x); + //BOOST_CHECK(abs(res.find_cf({0}) - audi::pow(2., onethird)) < 1e-33); + //BOOST_CHECK(abs(res.find_cf({1}) - audi::pow(2., onethird) * audi::log(onethird)) < 1e-33); + //BOOST_CHECK(abs(res.find_cf({2}) - audi::pow(2., onethird)) < 1e-33); + //BOOST_CHECK(abs(res.find_cf({3}) - audi::pow(2., onethird)) < 1e-33); + std::cout << res << std::endl; + std::cout << "\n" << audi::pow(2., onethird) << std::endl; + + } +} + BOOST_AUTO_TEST_CASE(trigonometric) { mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; @@ -41,5 +58,5 @@ BOOST_AUTO_TEST_CASE(trigonometric) BOOST_CHECK(abs(res.find_cf({1}) - audi::cos(onethird)) < 1e-33); BOOST_CHECK(abs(res.find_cf({2}) + audi::sin(onethird) / 2.) < 1e-33); BOOST_CHECK(abs(res.find_cf({3}) + audi::cos(onethird) / 6.) < 1e-33); - BOOST_CHECK((sin(asin(x)) - x).trim(1e-34) == gdual_mp(0.)); + //BOOST_CHECK((sin(asin(x)) - x).trim(1e-34) == gdual_mp(0.)); } \ No newline at end of file From 1100c66170f9fc0401cfd0318a78f03f39cd0225 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Tue, 1 May 2018 16:01:34 +0200 Subject: [PATCH 12/61] WIP pow --- include/audi/detail/overloads.hpp | 8 ++- include/audi/functions.hpp | 107 +++++++++++++++++------------- include/audi/type_traits.hpp | 30 ++++++++- tests/gdual_mp.cpp | 53 ++++++++++----- 4 files changed, 133 insertions(+), 65 deletions(-) diff --git a/include/audi/detail/overloads.hpp b/include/audi/detail/overloads.hpp index 324a4bfd..cd1b587b 100644 --- a/include/audi/detail/overloads.hpp +++ b/include/audi/detail/overloads.hpp @@ -1,6 +1,8 @@ #ifndef AUDI_OVERLOADS_HPP #define AUDI_OVERLOADS_HPP +#include + #include #include #include @@ -26,7 +28,7 @@ struct is_arithmetic_or_complex // It is used to allow calls such as audi::cos(T) [T = double] in templated functions. #define ARITH_OR_COMPLEX_OVERLOAD(fun_name) \ template ::value, int> = 0> \ - inline T fun_name(T in) \ + inline auto fun_name(T in) -> decltype(std::fun_name(T(0.))) \ { \ return std::fun_name(in); \ } @@ -49,6 +51,10 @@ VECTORIZED_OVERLOAD(erf) ARITH_OR_COMPLEX_OVERLOAD(erf) REAL128_OVERLOAD(erf) +VECTORIZED_OVERLOAD(lgamma) +ARITH_OR_COMPLEX_OVERLOAD(lgamma) +REAL128_OVERLOAD(lgamma) + VECTORIZED_OVERLOAD(log) ARITH_OR_COMPLEX_OVERLOAD(log) REAL128_OVERLOAD(log) diff --git a/include/audi/functions.hpp b/include/audi/functions.hpp index a7756dff..c49e15b2 100644 --- a/include/audi/functions.hpp +++ b/include/audi/functions.hpp @@ -30,14 +30,14 @@ namespace audi * * @return an audi:gdual containing the Taylor expansion of the exponential of \p d */ -template ::value, int> = 0> -inline T exp(const T &d) +template +inline gdual exp(const gdual &d) { - T retval(1.); - T fact(1.); + gdual retval(1.); + gdual fact(1.); auto p0 = d.constant_cf(); auto phat = d - p0; - T tmp(phat); + gdual tmp(phat); retval += phat; for (auto i = 2u; i <= d.get_order(); ++i) { @@ -65,17 +65,17 @@ inline T exp(const T &d) * @return an audi:gdual containing the Taylor expansion of the logarithm of \p d * */ -template ::value, int> = 0> -inline T log(const T &d) +template +inline gdual log(const gdual &d) { - T retval(0.); - T fatt(1.); + gdual retval(0.); + gdual fatt(1.); auto p0 = d.constant_cf(); auto log_p0 = audi::log(p0); auto phat = (d - p0); phat = phat / p0; - T tmp(phat); + gdual tmp(phat); retval = log_p0 + phat; for (auto i = 2u; i <= d.get_order(); ++i) { @@ -97,7 +97,7 @@ inline T log(const T &d) * @param d audi::gdual argument * */ -template ::value || std::is_same::value || std::is_same::value, int> = 0> +template ::value, int> = 0> inline gdual pow(U base, const gdual &d) { // checks wether the exponent is a constant in which @@ -109,6 +109,13 @@ inline gdual pow(U base, const gdual &d) return exp(audi::log(T(base)) * d); } +template +T binomial(T x, unsigned y) +{ + T retval(audi::lgamma(x + 1) - audi::lgamma(y + 1) - audi::lgamma(x - y + 1)); + return audi::exp(retval); +} + /// Overload for the exponentiation /** * Implements the exponentiation of a audi::gdual. @@ -127,34 +134,34 @@ inline gdual pow(U base, const gdual &d) * @return an audi:gdual containing the Taylor expansion of \p d elevated to the power \p alpha * */ -template ::value, int> = 0> -inline T pow(const T &d, double alpha) +template ::value, int> = 0> +inline gdual pow(const gdual &d, U alpha) { // We check if the exponent is representable as a positive integer, // in which case we just do d*d*d*d*... etc. - // This is also a workaround to the issue (https://github.com/darioizzo/audi/issues/6) - // TODO: is there a better way to do this? Calling the pow (gdual, int) overload is not possible as it - // cannot be moved upfront. - int n = (alpha*10.); - if (n % 10 == 0 && alpha > 0) { - T retval(d); - for (auto i = 1; i < (int)alpha; ++i) { + int n = static_cast(alpha); + if (n == alpha && alpha > 0.) { +std::cout << "NOT HERE!" << std::endl; + gdual retval(d); + for (auto i = 1; i < n; ++i) { retval *= d; } return retval; + } else { +std::cout << "I AM HERE!" << std::endl; + auto p0 = d.constant_cf(); + auto phat = d - p0; + gdual retval(audi::pow(p0, alpha)); + phat = phat; + gdual tmp(phat); + + retval += alpha * phat * audi::pow(p0, alpha - 1); + for (auto i = 2u; i <= d.get_order(); ++i) { + phat *= tmp; + retval += binomial(alpha, i) * phat * audi::pow(p0, alpha - i); + } + return retval; } - auto p0 = d.constant_cf(); - auto phat = d - p0; - T retval(audi::pow(p0, alpha)); - phat = phat; - T tmp(phat); - - retval += alpha * phat * audi::pow(p0, alpha - 1); - for (auto i = 2u; i <= d.get_order(); ++i) { - phat *= tmp; - retval += piranha::math::binomial(alpha, i) * phat * audi::pow(p0, alpha - i); - } - return retval; } // Its important this comes after the pow(gdual, double) overload @@ -166,13 +173,13 @@ inline T pow(const T &d, double alpha) * @param d audi::gdual argument * @param n integer exponent */ -template ::value, int> = 0> -inline T pow(const T &d, int n) +template +inline gdual pow(const gdual &d, int n) { if (n <= 0) { return audi::pow(d, (double)n); } - T retval(d); + gdual retval(d); for (auto i = 1; i < n; ++i) { retval *= d; } @@ -191,8 +198,8 @@ inline T pow(const T &d, int n) * * @throw std::domain_error if std::log(\f$f_0\f$) is not finite (uses std::isfinite) */ -template ::value, int> = 0> -inline T pow(const T &d1, const T &d2) +template +inline gdual pow(const gdual &d1, const gdual &d2) { return exp(d2 * log(d1)); } @@ -339,10 +346,11 @@ inline T cos(const T &d) T cos_taylor(1.); T tmp(cos_taylor); for (auto i = 2u; i <= d.get_order(); i += 2) { - coeff *= -1.; // -1, 1, -1, 1, ... - tmp *= phat2; // phat^2, phat^4, phat^6 ... - factorial *= i * (i - 1.); // 2!, 4!, 6!, ... - cos_taylor += (coeff * tmp) / factorial; // factorial is double, so the operation order matters not to loose precision in case of real128 + coeff *= -1.; // -1, 1, -1, 1, ... + tmp *= phat2; // phat^2, phat^4, phat^6 ... + factorial *= i * (i - 1.); // 2!, 4!, 6!, ... + cos_taylor += (coeff * tmp) / factorial; // factorial is double, so the operation order matters not to loose + // precision in case of real128 } factorial = 1.; @@ -350,10 +358,11 @@ inline T cos(const T &d) T sin_taylor(phat); tmp = sin_taylor; for (auto i = 3u; i <= d.get_order(); i += 2) { - coeff *= -1.; // -1, 1, -1, 1, ... - tmp *= phat2; // phat^3, phat^5, phat^7 ... - factorial *= i * (i - 1.); // 3!, 5!, 7!, ... - sin_taylor += (coeff * tmp) / factorial; // factorial is double, so the operation order matters not to loose precision in case of real128 + coeff *= -1.; // -1, 1, -1, 1, ... + tmp *= phat2; // phat^3, phat^5, phat^7 ... + factorial *= i * (i - 1.); // 3!, 5!, 7!, ... + sin_taylor += (coeff * tmp) / factorial; // factorial is double, so the operation order matters not to loose + // precision in case of real128 } return (cos_p0 * cos_taylor - sin_p0 * sin_taylor); } @@ -387,7 +396,9 @@ std::array sin_and_cos(const T &d) coeff *= -1.; // -1, 1, -1, 1, ... tmp *= phat2; // phat^2, phat^4, phat^6 ... factorial *= i * (i - 1.); // 2!, 4!, 6!, ... - cos_taylor += (coeff / factorial) * tmp; // factorial is double, so the operation order matters not to loose precision in case of real128 + cos_taylor + += (coeff / factorial) + * tmp; // factorial is double, so the operation order matters not to loose precision in case of real128 } factorial = 1.; @@ -398,7 +409,9 @@ std::array sin_and_cos(const T &d) coeff *= -1.; // -1, 1, -1, 1, ... tmp *= phat2; // phat^3, phat^5, phat^7 ... factorial *= i * (i - 1.); // 3!, 5!, 7!, ... - sin_taylor += (coeff / factorial) * tmp; // factorial is double, so the operation order matters not to loose precision in case of real128 + sin_taylor + += (coeff / factorial) + * tmp; // factorial is double, so the operation order matters not to loose precision in case of real128 } auto sine = sin_p0 * cos_taylor + cos_p0 * sin_taylor; auto cosine = cos_p0 * cos_taylor - sin_p0 * sin_taylor; diff --git a/include/audi/type_traits.hpp b/include/audi/type_traits.hpp index c67068ab..4f67128b 100644 --- a/include/audi/type_traits.hpp +++ b/include/audi/type_traits.hpp @@ -1,8 +1,12 @@ #ifndef AUDI_TYPE_TRAITS_HPP #define AUDI_TYPE_TRAITS_HPP -#include #include +#include + +#include +#include + namespace audi { @@ -21,6 +25,17 @@ template struct is_gdual> : std::true_type { }; +/// Type is arithmetic (includes multiple precision floats) +/** + * Checks whether T is an arithmetic type (that is, an integral type or a floating-point type that includes multiple precision floats if available) + * + * \tparam T a type to check + */ +template +struct is_arithmetic + : std::integral_constant::value || std::is_same::value > { +}; + /// Type is arithmetic or complex /** * Checks whether T is an arithmetic type (that is, an integral type or a floating-point type) or a complex @@ -30,7 +45,18 @@ struct is_gdual> : std::true_type { */ template struct is_arithmetic_or_complex - : std::integral_constant::value || boost::is_complex::value> { + : std::integral_constant::value || boost::is_complex::value> { +}; + +/// Type is allowed to be a coefficient for gduals +/** + * Checks whether T is a type from which gdual construction is allowed + * + * \tparam T a type to check + */ +template +struct is_gdual_cf + : std::integral_constant::value || std::is_same::value > { }; } diff --git a/tests/gdual_mp.cpp b/tests/gdual_mp.cpp index 5639a3f4..3afd8de3 100644 --- a/tests/gdual_mp.cpp +++ b/tests/gdual_mp.cpp @@ -10,7 +10,7 @@ #include using namespace audi; - +/* BOOST_AUTO_TEST_CASE(construction) { mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; @@ -22,7 +22,7 @@ BOOST_AUTO_TEST_CASE(construction) BOOST_AUTO_TEST_CASE(exp_and_log) { mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; - gdual_mp x{onethird, "x", 4}; + gdual_mp x{onethird, "x", 3}; auto res = exp(x); BOOST_CHECK(abs(res.find_cf({0}) - audi::exp(onethird)) < 1e-33); BOOST_CHECK(abs(res.find_cf({1}) - audi::exp(onethird)) < 1e-33); @@ -31,32 +31,55 @@ BOOST_AUTO_TEST_CASE(exp_and_log) BOOST_CHECK((exp(log(x)) - x).trim(1e-34) == gdual_mp(0.)); BOOST_CHECK((log(exp(x)) - x).trim(1e-34) == gdual_mp(0.)); } - +*/ BOOST_AUTO_TEST_CASE(exponentiation) { - // overload double^gdual +// // overload arith^gdual +// { +// mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; +// gdual_mp x{onethird, "x", 3}; +// auto res = pow(mppp::real128(2.), x); +// auto log_2 = audi::log(mppp::real128(2.)); +// BOOST_CHECK(abs(res.find_cf({0}) - audi::pow(2., onethird)) < 1e-33); +// BOOST_CHECK(abs(res.find_cf({1}) - audi::pow(2., onethird) * log_2) < 1e-33); +// BOOST_CHECK(abs(res.find_cf({2}) - audi::pow(2., onethird) * log_2 * log_2 / 2.) < 1e-33); +// BOOST_CHECK(abs(res.find_cf({3}) - audi::pow(2., onethird) * log_2 * log_2 * log_2 / 6.) < 1e-33); +// +// x = gdual_mp(4); // exponent is an integer constant +// res = pow(mppp::real128(2.), x); +// BOOST_CHECK(abs(res.constant_cf() - 2*2*2*2) < 1e-33); +// } +// // overload gdual^arith { mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; - gdual_mp x{onethird, "x", 4}; - auto res = pow(mppp::real128(2.), x); - //BOOST_CHECK(abs(res.find_cf({0}) - audi::pow(2., onethird)) < 1e-33); - //BOOST_CHECK(abs(res.find_cf({1}) - audi::pow(2., onethird) * audi::log(onethird)) < 1e-33); - //BOOST_CHECK(abs(res.find_cf({2}) - audi::pow(2., onethird)) < 1e-33); - //BOOST_CHECK(abs(res.find_cf({3}) - audi::pow(2., onethird)) < 1e-33); - std::cout << res << std::endl; - std::cout << "\n" << audi::pow(2., onethird) << std::endl; + gdual_mp x{onethird, "x", 3}; + auto res = pow(x, onethird); + //BOOST_CHECK(abs(res.find_cf({0}) - audi::pow(onethird, onethird)) < 1e-33); + //BOOST_CHECK(abs(res.find_cf({1}) - onethird * audi::pow(onethird, onethird - 1.)) < 1e-33); + //BOOST_CHECK(abs(res.find_cf({2}) - onethird * (onethird - 1.) * audi::pow(onethird, onethird - 2.) / 2.) < 1e-33); + //BOOST_CHECK(abs(res.find_cf({3}) - onethird * (onethird - 1.) * (onethird - 2.) * audi::pow(onethird, onethird - 3.) / 6.) < 1e-33); + +print(res, "\n"); + // exponent is an integer + //res = pow(x, 3); + //BOOST_CHECK(abs(res.find_cf({0}) - audi::pow(onethird, 3)) < 1e-33); + //BOOST_CHECK(abs(res.find_cf({1}) - 3 * audi::pow(3, 3 - 1)) < 1e-33); + //BOOST_CHECK(abs(res.find_cf({2}) - 3 * (3 - 1.) * audi::pow(3, 3 - 2)) < 1e-33); + //BOOST_CHECK(abs(res.find_cf({3}) - 3 * (3 - 1.) * (3 - 2.) * audi::pow(3, 3 - 3)) < 1e-33); } -} +} +/* BOOST_AUTO_TEST_CASE(trigonometric) { mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; - gdual_mp x{onethird, "x", 4}; + gdual_mp x{onethird, "x", 3}; auto res = sin(x); BOOST_CHECK(abs(res.find_cf({0}) - audi::sin(onethird)) < 1e-33); BOOST_CHECK(abs(res.find_cf({1}) - audi::cos(onethird)) < 1e-33); BOOST_CHECK(abs(res.find_cf({2}) + audi::sin(onethird) / 2.) < 1e-33); BOOST_CHECK(abs(res.find_cf({3}) + audi::cos(onethird) / 6.) < 1e-33); //BOOST_CHECK((sin(asin(x)) - x).trim(1e-34) == gdual_mp(0.)); -} \ No newline at end of file +} +*/ \ No newline at end of file From 4e4f4cc4913d592470d020c761f2246d37dfa5ae Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Wed, 2 May 2018 16:21:06 +0200 Subject: [PATCH 13/61] more functions and tests --- include/audi/detail/overloads.hpp | 4 + include/audi/functions.hpp | 69 ++++++++++++------ tests/gdual_mp.cpp | 117 ++++++++++++++++++++++-------- 3 files changed, 135 insertions(+), 55 deletions(-) diff --git a/include/audi/detail/overloads.hpp b/include/audi/detail/overloads.hpp index cd1b587b..00df8e09 100644 --- a/include/audi/detail/overloads.hpp +++ b/include/audi/detail/overloads.hpp @@ -112,6 +112,10 @@ ARITH_OR_COMPLEX_OVERLOAD(abs) VECTORIZED_OVERLOAD(cbrt) REAL128_OVERLOAD(cbrt) +VECTORIZED_OVERLOAD(sqrt) +REAL128_OVERLOAD(sqrt) + + template ::value, int> = 0> inline T cbrt(T in) { diff --git a/include/audi/functions.hpp b/include/audi/functions.hpp index c49e15b2..e6161053 100644 --- a/include/audi/functions.hpp +++ b/include/audi/functions.hpp @@ -112,8 +112,11 @@ inline gdual pow(U base, const gdual &d) template T binomial(T x, unsigned y) { - T retval(audi::lgamma(x + 1) - audi::lgamma(y + 1) - audi::lgamma(x - y + 1)); - return audi::exp(retval); + T retval(x); + for (auto i = 1u; i < y; ++i) { + retval = retval * (x - i) / (i + 1); + } + return retval; } /// Overload for the exponentiation @@ -141,30 +144,26 @@ inline gdual pow(const gdual &d, U alpha) // in which case we just do d*d*d*d*... etc. int n = static_cast(alpha); if (n == alpha && alpha > 0.) { -std::cout << "NOT HERE!" << std::endl; gdual retval(d); for (auto i = 1; i < n; ++i) { retval *= d; } return retval; } else { -std::cout << "I AM HERE!" << std::endl; auto p0 = d.constant_cf(); auto phat = d - p0; gdual retval(audi::pow(p0, alpha)); - phat = phat; gdual tmp(phat); - retval += alpha * phat * audi::pow(p0, alpha - 1); for (auto i = 2u; i <= d.get_order(); ++i) { phat *= tmp; - retval += binomial(alpha, i) * phat * audi::pow(p0, alpha - i); + auto achoosei = binomial(alpha, i); + retval += achoosei * phat * audi::pow(p0, alpha - i); } return retval; } } -// Its important this comes after the pow(gdual, double) overload /// Overload for the integer exponentiation /** * Implements the integer exponentiation of a audi::gdual. Essentially, @@ -176,14 +175,21 @@ std::cout << "I AM HERE!" << std::endl; template inline gdual pow(const gdual &d, int n) { - if (n <= 0) { - return audi::pow(d, (double)n); - } - gdual retval(d); - for (auto i = 1; i < n; ++i) { - retval *= d; + if (n < 0) { + gdual retval(T(1.) / d); + for (auto i = 1; i < -n; ++i) { + retval /= d; + } + return retval; + } else if (n > 0) { + gdual retval(d); + for (auto i = 1; i < n; ++i) { + retval *= d; + } + return retval; + } else { //==0 case + return d - d + 1; // TODO: can this be made more efficient? (preserving symbol set and order) } - return retval; } /// Overload for the exponentiation of a gdual to a gdual power @@ -221,10 +227,25 @@ inline gdual pow(const gdual &d1, const gdual &d2) * @return an audi:gdual containing the Taylor expansion of the square root of \p d * */ -template ::value, int> = 0> -inline T sqrt(const T &d) +template +inline gdual sqrt(const gdual &d) { - return pow(d, 0.5); // TODO: subsitute this by similar code to cbrt? + T alpha(0.5); + gdual retval(1.); + auto p0 = d.constant_cf(); + auto sqrt_p0 = audi::sqrt(p0); + + auto phat = d - p0; + phat = phat / p0; + gdual tmp(phat); + + retval += alpha * phat; + for (auto i = 2u; i <= d.get_order(); ++i) { + phat *= tmp; + retval += binomial(alpha, i) * phat; + } + retval *= sqrt_p0; + return retval; } /// Overload for the cubic root @@ -244,22 +265,22 @@ inline T sqrt(const T &d) * @return an audi:gdual containing the Taylor expansion of the square root of \p d * */ -template ::value, int> = 0> -inline T cbrt(const T &d) +template +inline gdual cbrt(const gdual &d) { - double alpha = 1 / 3.; - T retval(1.); + T alpha(T(1.)/T(3.)); + gdual retval(1.); auto p0 = d.constant_cf(); auto cbrt_p0 = audi::cbrt(p0); auto phat = d - p0; phat = phat / p0; - T tmp(phat); + gdual tmp(phat); retval += alpha * phat; for (auto i = 2u; i <= d.get_order(); ++i) { phat *= tmp; - retval += piranha::math::binomial(alpha, i) * phat; + retval += binomial(alpha, i) * phat; } retval *= cbrt_p0; return retval; diff --git a/tests/gdual_mp.cpp b/tests/gdual_mp.cpp index 3afd8de3..f5e5b896 100644 --- a/tests/gdual_mp.cpp +++ b/tests/gdual_mp.cpp @@ -10,13 +10,12 @@ #include using namespace audi; -/* + BOOST_AUTO_TEST_CASE(construction) { mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; gdual_mp x{onethird, "x", 10}; BOOST_CHECK(abs(onethird - x.constant_cf()) == 0.); - } BOOST_AUTO_TEST_CASE(exp_and_log) @@ -31,44 +30,100 @@ BOOST_AUTO_TEST_CASE(exp_and_log) BOOST_CHECK((exp(log(x)) - x).trim(1e-34) == gdual_mp(0.)); BOOST_CHECK((log(exp(x)) - x).trim(1e-34) == gdual_mp(0.)); } -*/ + BOOST_AUTO_TEST_CASE(exponentiation) { -// // overload arith^gdual -// { -// mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; -// gdual_mp x{onethird, "x", 3}; -// auto res = pow(mppp::real128(2.), x); -// auto log_2 = audi::log(mppp::real128(2.)); -// BOOST_CHECK(abs(res.find_cf({0}) - audi::pow(2., onethird)) < 1e-33); -// BOOST_CHECK(abs(res.find_cf({1}) - audi::pow(2., onethird) * log_2) < 1e-33); -// BOOST_CHECK(abs(res.find_cf({2}) - audi::pow(2., onethird) * log_2 * log_2 / 2.) < 1e-33); -// BOOST_CHECK(abs(res.find_cf({3}) - audi::pow(2., onethird) * log_2 * log_2 * log_2 / 6.) < 1e-33); -// -// x = gdual_mp(4); // exponent is an integer constant -// res = pow(mppp::real128(2.), x); -// BOOST_CHECK(abs(res.constant_cf() - 2*2*2*2) < 1e-33); -// } -// // overload gdual^arith + // overload arith^gdual { mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; gdual_mp x{onethird, "x", 3}; - auto res = pow(x, onethird); - //BOOST_CHECK(abs(res.find_cf({0}) - audi::pow(onethird, onethird)) < 1e-33); - //BOOST_CHECK(abs(res.find_cf({1}) - onethird * audi::pow(onethird, onethird - 1.)) < 1e-33); - //BOOST_CHECK(abs(res.find_cf({2}) - onethird * (onethird - 1.) * audi::pow(onethird, onethird - 2.) / 2.) < 1e-33); - //BOOST_CHECK(abs(res.find_cf({3}) - onethird * (onethird - 1.) * (onethird - 2.) * audi::pow(onethird, onethird - 3.) / 6.) < 1e-33); + auto res = pow(mppp::real128(2.), x); + auto log_2 = audi::log(mppp::real128(2.)); + BOOST_CHECK(abs(res.find_cf({0}) - audi::pow(2., onethird)) < 1e-33); + BOOST_CHECK(abs(res.find_cf({1}) - audi::pow(2., onethird) * log_2) < 1e-33); + BOOST_CHECK(abs(res.find_cf({2}) - audi::pow(2., onethird) * log_2 * log_2 / 2.) < 1e-33); + BOOST_CHECK(abs(res.find_cf({3}) - audi::pow(2., onethird) * log_2 * log_2 * log_2 / 6.) < 1e-33); -print(res, "\n"); + x = gdual_mp(4); // exponent is an integer constant + res = pow(mppp::real128(2.), x); + BOOST_CHECK(abs(res.constant_cf() - 2 * 2 * 2 * 2) < 1e-33); + } + // overload gdual^arith + { + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 3}; + auto res = pow(x, onethird); + BOOST_CHECK(abs(res.find_cf({0}) - audi::pow(onethird, onethird)) < 1e-33); + BOOST_CHECK(abs(res.find_cf({1}) - onethird * audi::pow(onethird, onethird - 1.)) < 1e-33); + BOOST_CHECK(abs(res.find_cf({2}) - onethird * (onethird - 1.) * audi::pow(onethird, onethird - 2.) / 2.) + < 1e-33); + BOOST_CHECK(abs(res.find_cf({3}) + - onethird * (onethird - 1.) * (onethird - 2.) * audi::pow(onethird, onethird - 3.) / 6.) + < 1e-33); - // exponent is an integer - //res = pow(x, 3); - //BOOST_CHECK(abs(res.find_cf({0}) - audi::pow(onethird, 3)) < 1e-33); - //BOOST_CHECK(abs(res.find_cf({1}) - 3 * audi::pow(3, 3 - 1)) < 1e-33); - //BOOST_CHECK(abs(res.find_cf({2}) - 3 * (3 - 1.) * audi::pow(3, 3 - 2)) < 1e-33); - //BOOST_CHECK(abs(res.find_cf({3}) - 3 * (3 - 1.) * (3 - 2.) * audi::pow(3, 3 - 3)) < 1e-33); + // exponent is a double representable as integer + x = gdual_mp(3, "x", 3); + res = pow(x, 3.); // note that the constant 3 is double + BOOST_CHECK(abs(res.find_cf({0}) - audi::pow(3, 3)) < 1e-33); + BOOST_CHECK(abs(res.find_cf({1}) - 3 * audi::pow(3, 3 - 1)) < 1e-33); + BOOST_CHECK(abs(res.find_cf({2}) - 3 * (3 - 1.) * audi::pow(3, 3 - 2) / 2.) < 1e-33); + BOOST_CHECK(abs(res.find_cf({3}) - 3 * (3 - 1.) * (3 - 2.) * audi::pow(3, 3 - 3) / 6.) < 1e-33); } + // overload gdual^int + { + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 3}; + auto res = pow(x, 3); + BOOST_CHECK(abs(res.find_cf({0}) - audi::pow(onethird, 3)) < 1e-33); + BOOST_CHECK(abs(res.find_cf({1}) - 3 * audi::pow(onethird, 3 - 1)) < 1e-33); + BOOST_CHECK(abs(res.find_cf({2}) - 3 * (3 - 1.) * audi::pow(onethird, 3 - 2) / 2.) < 1e-33); + BOOST_CHECK(abs(res.find_cf({3}) - 3 * (3 - 1.) * (3 - 2.) * audi::pow(onethird, 3 - 3) / 6.) < 1e-33); + res = pow(x, -3); + BOOST_CHECK(abs(res.find_cf({0}) - audi::pow(onethird, -3)) < 1e-32); // we check for absolute error, hence the precision loss + BOOST_CHECK(abs(res.find_cf({1}) + 3 * audi::pow(onethird, -3 - 1)) < 1e-31); // we check for absolute error, hence the precision loss + BOOST_CHECK(abs(res.find_cf({2}) + 3 * (-3 - 1) * audi::pow(onethird, -3 - 2) / 2) < 1e-30); // we check for absolute error, hence the precision loss + BOOST_CHECK(abs(res.find_cf({3}) + 3 * (-3 - 1) * (-3 - 2) * audi::pow(onethird, -3 - 3) / 6) < 1e-29); // we check for absolute error, hence the precision loss + res = pow(x, 0); + BOOST_CHECK(abs(res.find_cf({0}) - 1 == 0)); + BOOST_CHECK(abs(res.find_cf({1}) == 0)); + BOOST_CHECK(abs(res.find_cf({2}) == 0)); + BOOST_CHECK(abs(res.find_cf({3}) == 0)); + } + // overload gdual^gdual + { + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 3}; + auto res = pow(x, x); + BOOST_CHECK(abs(res.find_cf({0}) - mppp::real128("0.693361274350634704843352274785961795445935113457754036565863693400")) < 1e-33); + BOOST_CHECK(abs(res.find_cf({1}) - mppp::real128("-0.0683739421375531895286241688670376535021100832441426057588451227360656")) < 1e-33); + BOOST_CHECK(abs(res.find_cf({2}) - mppp::real128("1.043413166985674569326084555526740070128227383299088804220207359748035")) < 1e-33); + BOOST_CHECK(abs(res.find_cf({3}) - mppp::real128("-1.142713640471137873959384027190746725008973893684368645673060217249986")) < 1e-33); + } +} +BOOST_AUTO_TEST_CASE(sqrt_fun) +{ + { + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 3}; + auto res = sqrt(x); + BOOST_CHECK(abs(res.find_cf({0}) - mppp::real128("0.577350269189625764509148780501957455647601751270126876018602326484")) < 1e-33); + BOOST_CHECK(abs(res.find_cf({1}) - mppp::real128("0.8660254037844386467637231707529361834714026269051903140279034897263995")) < 1e-33); + BOOST_CHECK(abs(res.find_cf({2}) - mppp::real128("-0.6495190528383289850727923780647021376035519701788927355209276172954492")) < 1e-33); + BOOST_CHECK(abs(res.find_cf({3}) - mppp::real128("0.974278579257493477609188567097053206405327955268339103281391425944148")) < 1e-33); + } +} +BOOST_AUTO_TEST_CASE(cbrt_fun) +{ + { + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 3}; + auto res = cbrt(x); + BOOST_CHECK(abs(res.find_cf({0}) - mppp::real128("0.693361274350634704843352274785961795445935113457754036565863693400")) < 1e-33); + BOOST_CHECK(abs(res.find_cf({1}) - mppp::real128("0.6933612743506347048433522747859617954459351134577540365658636934004977")) < 1e-33); + BOOST_CHECK(abs(res.find_cf({2}) - mppp::real128("-0.693361274350634704843352274785961795445935113457754036565863693401191")) < 1e-33); + BOOST_CHECK(abs(res.find_cf({3}) - mppp::real128("1.155602123917724508072253791309936325743225189096256727609772822336474")) < 1e-33); + } } /* BOOST_AUTO_TEST_CASE(trigonometric) From ee56f8212dd286a25472fc1b698f47b6f92c5d86 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Thu, 3 May 2018 14:27:03 +0200 Subject: [PATCH 14/61] more tests and fixes to get a generic code --- include/audi/detail/overloads.hpp | 10 +- include/audi/functions.hpp | 223 ++++++++++++++--------------- include/audi/functions_from_d.hpp | 2 +- include/audi/gdual.hpp | 3 +- include/audi/real128.hpp | 20 +++ include/audi/vectorized_double.hpp | 10 +- tests/gdual_d.cpp | 2 + tests/gdual_mp.cpp | 197 ++++++++++++++++++------- 8 files changed, 288 insertions(+), 179 deletions(-) diff --git a/include/audi/detail/overloads.hpp b/include/audi/detail/overloads.hpp index 00df8e09..fe42d6d3 100644 --- a/include/audi/detail/overloads.hpp +++ b/include/audi/detail/overloads.hpp @@ -107,15 +107,17 @@ VECTORIZED_OVERLOAD(atanh) ARITH_OR_COMPLEX_OVERLOAD(atanh) REAL128_OVERLOAD(atanh) +VECTORIZED_OVERLOAD(sqrt) +ARITH_OR_COMPLEX_OVERLOAD(sqrt) +REAL128_OVERLOAD(sqrt) + +VECTORIZED_OVERLOAD(abs) ARITH_OR_COMPLEX_OVERLOAD(abs) +REAL128_OVERLOAD(abs) VECTORIZED_OVERLOAD(cbrt) REAL128_OVERLOAD(cbrt) -VECTORIZED_OVERLOAD(sqrt) -REAL128_OVERLOAD(sqrt) - - template ::value, int> = 0> inline T cbrt(T in) { diff --git a/include/audi/functions.hpp b/include/audi/functions.hpp index e6161053..f9243a52 100644 --- a/include/audi/functions.hpp +++ b/include/audi/functions.hpp @@ -302,8 +302,8 @@ inline gdual cbrt(const gdual &d) * * @return an audi:gdual containing the Taylor expansion of the sine of \p d */ -template ::value, int> = 0> -inline T sin(const T &d) +template +inline gdual sin(const gdual &d) { auto p0 = d.constant_cf(); auto phat = (d - p0); @@ -312,25 +312,25 @@ inline T sin(const T &d) auto sin_p0 = audi::sin(p0); auto cos_p0 = audi::cos(p0); - double factorial = 1.; - double coeff = 1.; - T cos_taylor(1.); - T tmp(cos_taylor); + double factorial(1.); + int coeff(1.); + gdual cos_taylor(1.); + gdual tmp(cos_taylor); for (auto i = 2u; i <= d.get_order(); i += 2) { - coeff *= -1.; // -1, 1, -1, 1, ... + coeff = -coeff; // -1, 1, -1, 1, ... tmp *= phat2; // phat^2, phat^4, phat^6 ... - factorial *= i * (i - 1.); // 2!, 4!, 6!, ... + factorial *= i * (i - 1); // 2!, 4!, 6!, ... cos_taylor += (coeff * tmp) / factorial; } factorial = 1.; - coeff = 1.; - T sin_taylor(phat); + coeff = 1; + gdual sin_taylor(phat); tmp = sin_taylor; for (auto i = 3u; i <= d.get_order(); i += 2) { - coeff *= -1.; // -1, 1, -1, 1, ... + coeff = -coeff; // -1, 1, -1, 1, ... tmp *= phat2; // phat^3, phat^5, phat^7 ... - factorial *= i * (i - 1.); // 3!, 5!, 7!, ... + factorial *= i * (i - 1); // 3!, 5!, 7!, ... sin_taylor += (coeff * tmp) / factorial; } return (sin_p0 * cos_taylor + cos_p0 * sin_taylor); @@ -352,8 +352,8 @@ inline T sin(const T &d) * * @return an audi:gdual containing the Taylor expansion of the cosine of \p d */ -template ::value, int> = 0> -inline T cos(const T &d) +template +inline gdual cos(const gdual &d) { auto p0 = d.constant_cf(); auto phat = (d - p0); @@ -362,28 +362,26 @@ inline T cos(const T &d) auto sin_p0 = audi::sin(p0); auto cos_p0 = audi::cos(p0); - double factorial = 1.; - double coeff = 1.; - T cos_taylor(1.); - T tmp(cos_taylor); + double factorial(1.); + int coeff(1.); + gdual cos_taylor(1.); + gdual tmp(cos_taylor); for (auto i = 2u; i <= d.get_order(); i += 2) { - coeff *= -1.; // -1, 1, -1, 1, ... - tmp *= phat2; // phat^2, phat^4, phat^6 ... - factorial *= i * (i - 1.); // 2!, 4!, 6!, ... - cos_taylor += (coeff * tmp) / factorial; // factorial is double, so the operation order matters not to loose - // precision in case of real128 + coeff = -coeff; // -1, 1, -1, 1, ... + tmp *= phat2; // phat^2, phat^4, phat^6 ... + factorial *= i * (i - 1); // 2!, 4!, 6!, ... + cos_taylor += (coeff * tmp) / factorial; } factorial = 1.; - coeff = 1.; - T sin_taylor(phat); + coeff = 1; + gdual sin_taylor(phat); tmp = sin_taylor; for (auto i = 3u; i <= d.get_order(); i += 2) { - coeff *= -1.; // -1, 1, -1, 1, ... - tmp *= phat2; // phat^3, phat^5, phat^7 ... - factorial *= i * (i - 1.); // 3!, 5!, 7!, ... - sin_taylor += (coeff * tmp) / factorial; // factorial is double, so the operation order matters not to loose - // precision in case of real128 + coeff = -coeff; // -1, 1, -1, 1, ... + tmp *= phat2; // phat^3, phat^5, phat^7 ... + factorial *= i * (i - 1); // 3!, 5!, 7!, ... + sin_taylor += (coeff * tmp) / factorial; } return (cos_p0 * cos_taylor - sin_p0 * sin_taylor); } @@ -399,8 +397,8 @@ inline T cos(const T &d) * @return an std::array containing the Taylor expansions of sine and the cosine (first element, second element) * */ -template ::value, int> = 0> -std::array sin_and_cos(const T &d) +template +std::array, 2> sin_and_cos(const gdual &d) { auto p0 = d.constant_cf(); auto phat = (d - p0); @@ -409,34 +407,30 @@ std::array sin_and_cos(const T &d) auto sin_p0 = audi::sin(p0); auto cos_p0 = audi::cos(p0); - double factorial = 1.; - double coeff = 1.; - T cos_taylor(1.); - T tmp(cos_taylor); + double factorial(1.); + int coeff(1.); + gdual cos_taylor(1.); + gdual tmp(cos_taylor); for (auto i = 2u; i <= d.get_order(); i += 2) { - coeff *= -1.; // -1, 1, -1, 1, ... + coeff = -coeff; // -1, 1, -1, 1, ... tmp *= phat2; // phat^2, phat^4, phat^6 ... - factorial *= i * (i - 1.); // 2!, 4!, 6!, ... - cos_taylor - += (coeff / factorial) - * tmp; // factorial is double, so the operation order matters not to loose precision in case of real128 + factorial *= i * (i - 1); // 2!, 4!, 6!, ... + cos_taylor += (coeff * tmp) / factorial; } factorial = 1.; - coeff = 1.; - T sin_taylor(phat); + coeff = 1; + gdual sin_taylor(phat); tmp = sin_taylor; for (auto i = 3u; i <= d.get_order(); i += 2) { - coeff *= -1.; // -1, 1, -1, 1, ... + coeff = -coeff; // -1, 1, -1, 1, ... tmp *= phat2; // phat^3, phat^5, phat^7 ... - factorial *= i * (i - 1.); // 3!, 5!, 7!, ... - sin_taylor - += (coeff / factorial) - * tmp; // factorial is double, so the operation order matters not to loose precision in case of real128 + factorial *= i * (i - 1); // 3!, 5!, 7!, ... + sin_taylor += (coeff * tmp) / factorial; } auto sine = sin_p0 * cos_taylor + cos_p0 * sin_taylor; auto cosine = cos_p0 * cos_taylor - sin_p0 * sin_taylor; - return std::array{{std::move(sine), std::move(cosine)}}; + return std::array, 2>{{std::move(sine), std::move(cosine)}}; } /// Overload for the tangent @@ -456,8 +450,8 @@ std::array sin_and_cos(const T &d) * @return an audi:gdual containing the Taylor expansion of the tangent of \p d * */ -template ::value, int> = 0> -inline T tan(const T &d) +template +inline gdual tan(const gdual &d) { auto p0 = d.constant_cf(); auto phat = (d - p0); @@ -465,17 +459,17 @@ inline T tan(const T &d) auto tan_p0 = audi::tan(p0); // Pre-compute Bernoulli numbers. - std::vector bn; - boost::math::bernoulli_b2n(0, (d.get_order() + 1) / 2 + 1, + std::vector bn; + boost::math::bernoulli_b2n(0, (d.get_order() + 1) / 2 + 1, std::back_inserter(bn)); // Fill vector with even Bernoulli numbers. - T tan_taylor = phat; + gdual tan_taylor = phat; // Factors - double factorial = 24.; - double four_k = 16.; + T factorial(24); + T four_k(16); for (auto k = 2u; 2 * k - 1 <= d.get_order(); ++k) { phat *= phat2; - tan_taylor += bn[k] * four_k * (1 - std::abs(four_k)) / factorial * phat; + tan_taylor += bn[k] * four_k * (1 - audi::abs(four_k)) / factorial * phat; four_k *= -4.; factorial *= (2. * k + 1.) * (2. * k + 2.); } @@ -498,8 +492,8 @@ inline T tan(const T &d) * * @return an audi:gdual containing the Taylor expansion of the hyperbolic sine of \p d */ -template ::value, int> = 0> -inline T sinh(const T &d) +template +inline gdual sinh(const gdual &d) { auto p0 = d.constant_cf(); auto phat = (d - p0); @@ -508,17 +502,17 @@ inline T sinh(const T &d) auto sinh_p0 = audi::sinh(p0); auto cosh_p0 = audi::cosh(p0); - double factorial = 1.; - T cosh_taylor(1.); - T tmp(cosh_taylor); + T factorial(1.); + gdual cosh_taylor(1.); + gdual tmp(cosh_taylor); for (auto i = 2u; i <= d.get_order(); i += 2) { tmp *= phat2; // phat^2, phat^4, phat^6 ... factorial *= i * (i - 1.); // 2!, 4!, 6!, ... cosh_taylor += tmp / factorial; } - factorial = 1.; - T sinh_taylor(phat); + factorial = T(1.); + gdual sinh_taylor(phat); tmp = sinh_taylor; for (auto i = 3u; i <= d.get_order(); i += 2) { tmp *= phat2; // phat^3, phat^5, phat^7 ... @@ -544,8 +538,8 @@ inline T sinh(const T &d) * * @return an audi:gdual containing the Taylor expansion of the hyperbolic cosine of \p d */ -template ::value, int> = 0> -inline T cosh(const T &d) +template +inline gdual cosh(const gdual &d) { auto p0 = d.constant_cf(); auto phat = (d - p0); @@ -554,17 +548,17 @@ inline T cosh(const T &d) auto sinh_p0 = audi::sinh(p0); auto cosh_p0 = audi::cosh(p0); - double factorial = 1.; - T cosh_taylor(1.); - T tmp(cosh_taylor); + T factorial(1.); + gdual cosh_taylor(1.); + gdual tmp(cosh_taylor); for (auto i = 2u; i <= d.get_order(); i += 2) { tmp *= phat2; // phat^2, phat^4, phat^6 ... factorial *= i * (i - 1.); // 2!, 4!, 6!, ... cosh_taylor += tmp / factorial; } - factorial = 1.; - T sinh_taylor(phat); + factorial = T(1.); + gdual sinh_taylor(phat); tmp = sinh_taylor; for (auto i = 3u; i <= d.get_order(); i += 2) { tmp *= phat2; // phat^3, phat^5, phat^7 ... @@ -585,8 +579,8 @@ inline T cosh(const T &d) * @return an std::array containing the Taylor expansions of hyperbolic sine and cosine (first element, second element) * */ -template ::value, int> = 0> -std::array sinh_and_cosh(const T &d) +template +std::array, 2> sinh_and_cosh(const gdual &d) { auto p0 = d.constant_cf(); auto phat = (d - p0); @@ -595,17 +589,17 @@ std::array sinh_and_cosh(const T &d) auto sinh_p0 = audi::sinh(p0); auto cosh_p0 = audi::cosh(p0); - double factorial = 1.; - T cosh_taylor(1.); - T tmp(cosh_taylor); + T factorial(1.); + gdual cosh_taylor(1.); + gdual tmp(cosh_taylor); for (auto i = 2u; i <= d.get_order(); i += 2) { tmp *= phat2; // phat^2, phat^4, phat^6 ... factorial *= i * (i - 1.); // 2!, 4!, 6!, ... cosh_taylor += tmp / factorial; } - factorial = 1.; - T sinh_taylor(phat); + factorial = T(1.); + gdual sinh_taylor(phat); tmp = sinh_taylor; for (auto i = 3u; i <= d.get_order(); i += 2) { tmp *= phat2; // phat^3, phat^5, phat^7 ... @@ -614,7 +608,7 @@ std::array sinh_and_cosh(const T &d) } auto sineh = sinh_p0 * cosh_taylor + cosh_p0 * sinh_taylor; auto cosineh = cosh_p0 * cosh_taylor + sinh_p0 * sinh_taylor; - return std::array{{std::move(sineh), std::move(cosineh)}}; + return std::array, 2>{{std::move(sineh), std::move(cosineh)}}; } /// Overload for the hyperbolic tangent @@ -634,8 +628,8 @@ std::array sinh_and_cosh(const T &d) * @return an audi::gdual containing the Taylor expansion of the hyperbolic tangent of \p d * */ -template ::value, int> = 0> -inline T tanh(const T &d) +template +inline gdual tanh(const gdual &d) { auto p0 = d.constant_cf(); auto phat = (d - p0); @@ -643,14 +637,14 @@ inline T tanh(const T &d) auto tanh_p0 = audi::tanh(p0); // Pre-compute Bernoulli numbers. - std::vector bn; - boost::math::bernoulli_b2n(0, (d.get_order() + 1) / 2 + 1, + std::vector bn; + boost::math::bernoulli_b2n(0, (d.get_order() + 1) / 2 + 1, std::back_inserter(bn)); // Fill vector with even Bernoulli numbers. - T tanh_taylor = phat; + gdual tanh_taylor = phat; // Factors - double factorial = 24.; - double four_k = 16.; + T factorial(24.); + T four_k(16.); for (auto k = 2u; 2 * k - 1 <= d.get_order(); ++k) { phat *= phat2; tanh_taylor += bn[k] * four_k * (four_k - 1.) / factorial * phat; @@ -676,19 +670,19 @@ inline T tanh(const T &d) * @return an audi::gdual containing the Taylor expansion of the inverse hyperbolic tangent of \p d * */ -template ::value, int> = 0> -inline T atanh(const T &d) +template +inline gdual atanh(const gdual &d) { auto p0 = d.constant_cf(); auto phat = (d - p0); auto powphat(phat); auto atanh_p0 = audi::atanh(p0); - T retval(0.); + gdual retval(0.); double coeff = 1.; for (auto k = 1u; k <= d.get_order(); ++k) { - auto add = (1. / audi::pow(1. - p0, k) + coeff / audi::pow(1. + p0, k)) / static_cast(k); + auto add = (1. / audi::pow(1. - p0, k) + coeff / audi::pow(1. + p0, k)) / static_cast(k); retval += add * powphat; coeff *= -1; powphat *= phat; @@ -716,25 +710,24 @@ inline T atanh(const T &d) * @return an audi::gdual containing the Taylor expansion of the inverse tangent of \p d * */ -template ::value, int> = 0> -inline T atan(const T &d) +template +inline gdual atan(const gdual &d) { auto p0 = d.constant_cf(); auto phat = (d - p0) / (1. + p0 * p0); auto powphat(phat); - auto retval = T(audi::atan(p0)); - double coeff1 = 1.; - double coeff2 = -1.; + auto retval = gdual(audi::atan(p0)); + T coeff1(1.); + T coeff2(-1.); for (auto k = 1u; k <= d.get_order(); ++k) { if (k % 2u) { // This is for odd powers 1..3..5 T binom(1.); auto f0 = p0 * p0; - double cf_i = -1.; + T cf_i(-1.); for (auto j = 1u; 2 * j <= k; ++j) { - binom - += T(piranha::math::binomial(k, 2u * j) * cf_i) * f0; // A bug in some old compiler requires the T() + binom += (binomial(k, 2u * j) * cf_i) * f0; f0 *= p0 * p0; cf_i *= -1.; } @@ -743,10 +736,9 @@ inline T atan(const T &d) } else { // This is for even powers 2..4..6 T binom(0.); auto f0 = p0; - double cf_i = 1.; + T cf_i(1.); for (auto j = 1u; 2 * j - 1 <= k; ++j) { - binom += T(piranha::math::binomial(k, 2u * j - 1u) * cf_i) - * f0; // A bug in some old compiler requires the T() + binom += T(binomial(k, 2u * j - 1u) * cf_i) * f0; f0 *= p0 * p0; cf_i *= -1; } @@ -774,8 +766,8 @@ inline T atan(const T &d) * @return an audi::gdual containing the Taylor expansion of the inverse hyperbolic sine of \p d * */ -template ::value, int> = 0> -inline T asinh(const T &d) +template +inline gdual asinh(const gdual &d) { return log(d + sqrt(1. + d * d)); } @@ -796,8 +788,8 @@ inline T asinh(const T &d) * @return an audi::gdual containing the Taylor expansion of the inverse hyperbolic cosine of \p d * */ -template ::value, int> = 0> -inline T acosh(const T &d) +template +inline gdual acosh(const gdual &d) { return log(d + sqrt(d * d - 1.)); } @@ -818,8 +810,8 @@ inline T acosh(const T &d) * @return an audi::gdual containing the Taylor expansion of the inverse sine of \p d * */ -template ::value, int> = 0> -inline T asin(const T &d) +template +inline gdual asin(const gdual &d) { return atan(d / sqrt(1. - d * d)); } @@ -840,10 +832,11 @@ inline T asin(const T &d) * @return an audi::gdual containing the Taylor expansion of the inverse cosine of \p d * */ -template ::value, int> = 0> -inline T acos(const T &d) +template +inline gdual acos(const gdual &d) { - return 0.5 * boost::math::constants::pi() - atan(d / sqrt(1. - d * d)); + return 0.5 * boost::math::constants::pi() - asin(d); + } /// Overload for the absolute value @@ -866,8 +859,8 @@ inline T acos(const T &d) * @return an audi:gdual containing the Taylor expansion of the absoute value of \p d * */ -template ::value && std::is_arithmetic::value, int> = 0> -inline T abs(const T &d) +template +inline gdual abs(const gdual &d) { auto p0 = d.constant_cf(); if (p0 >= 0) { @@ -876,11 +869,9 @@ inline T abs(const T &d) return -d; } // Vectorized abs -template ::value && std::is_same::value, int> = 0> -inline T abs(const T &d) +inline gdual abs(const gdual &d) { - T retval(d); + gdual retval(d); auto p0 = retval.constant_cf(); for (auto it = retval._container().begin(); it != retval._container().end(); ++it) { // if the coefficient has one only element copy it over to the whole length of p0 diff --git a/include/audi/functions_from_d.hpp b/include/audi/functions_from_d.hpp index 3ec2eb98..698b0902 100644 --- a/include/audi/functions_from_d.hpp +++ b/include/audi/functions_from_d.hpp @@ -132,7 +132,7 @@ inline T asinh_d(const T &f) /// Possible overload for the inverse cosine /** - * Implements the inverse cosine of an audi::gdual. The audi:acos + * Implements the inverse cosine of an audi::gdual. The audi::acos * overload may be slower, but this is currently only provided as to benchmark the * performances of audi::_compose_from_derivative * diff --git a/include/audi/gdual.hpp b/include/audi/gdual.hpp index 3ef544a0..cd55b0b3 100644 --- a/include/audi/gdual.hpp +++ b/include/audi/gdual.hpp @@ -26,6 +26,7 @@ #include #include //for audi::abs + /// Root namespace for AuDi symbols namespace audi @@ -444,7 +445,7 @@ class gdual if (epsilon < 0) { throw std::invalid_argument("When trimming a gdual the trim tolerance must be positive, you seem to have used a negative value: " + std::to_string(epsilon) ); } - auto new_p = m_p.filter([epsilon](const std::pair &coeff) { return !(abs(coeff.first) < epsilon); }); + auto new_p = m_p.filter([epsilon](const std::pair &coeff) { return !(audi::abs(coeff.first) < epsilon); }); return gdual(std::move(new_p), m_order); } diff --git a/include/audi/real128.hpp b/include/audi/real128.hpp index aa59f02a..a9b3fef8 100644 --- a/include/audi/real128.hpp +++ b/include/audi/real128.hpp @@ -28,4 +28,24 @@ struct partial_impl { }; }} // end of piranha namespace +// Specialization for numeric limits. Implementing the becessary ones for bernoulli numbers to work in boost +namespace std { +template<> +class numeric_limits { +public: +constexpr static int radix = 2u; +constexpr static int digits = 113u; +constexpr static int max_exponent = 16384u; +constexpr static bool is_specialized = true; +constexpr static bool has_infinity = true; +constexpr static bool has_quiet_NaN = true; +constexpr static bool has_signaling_NaN = false; +static mppp::real128 min() noexcept { return mppp::real128("3.36210314311209350626267781732175260e-4932"); } +static mppp::real128 max() noexcept { return mppp::real128("1.18973149535723176508575932662800702e4932"); } +static mppp::real128 lowest() {return mppp::real128_min();}; +static mppp::real128 quiet_NaN() {return mppp::real128(0.)/mppp::real128(0.);}; //todo: use nanq +static mppp::real128 infinity() {return mppp::real128(1.)/mppp::real128(0.);}; //todo: can this be made better? +}; +} + #endif diff --git a/include/audi/vectorized_double.hpp b/include/audi/vectorized_double.hpp index d7da8461..7492a1fa 100644 --- a/include/audi/vectorized_double.hpp +++ b/include/audi/vectorized_double.hpp @@ -225,11 +225,11 @@ class vectorized_double } return false; } - friend vectorized_double abs(vectorized_double in) - { - std::transform(in.m_c.begin(), in.m_c.end(), in.m_c.begin(), [](const double &x) { return std::abs(x); }); - return in; - } + //friend vectorized_double abs(vectorized_double in) + //{ + // std::transform(in.m_c.begin(), in.m_c.end(), in.m_c.begin(), [](const double &x) { return std::abs(x); }); + // return in; + //} friend std::ostream &operator<<(std::ostream &os, const vectorized_double &d) { os << "["; diff --git a/tests/gdual_d.cpp b/tests/gdual_d.cpp index 821ff413..8872c956 100644 --- a/tests/gdual_d.cpp +++ b/tests/gdual_d.cpp @@ -273,6 +273,8 @@ BOOST_AUTO_TEST_CASE(subs) gdual_d x(0, "x", 100); auto sx = sin(x); auto sx1 = sx.subs("dx", 1.); + std::cout << sx << std::endl; + std::cout << sx1 << std::endl; BOOST_CHECK_CLOSE(sx1.constant_cf(), std::sin(1.), 1e-12); } } diff --git a/tests/gdual_mp.cpp b/tests/gdual_mp.cpp index f5e5b896..059fddc1 100644 --- a/tests/gdual_mp.cpp +++ b/tests/gdual_mp.cpp @@ -15,7 +15,7 @@ BOOST_AUTO_TEST_CASE(construction) { mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; gdual_mp x{onethird, "x", 10}; - BOOST_CHECK(abs(onethird - x.constant_cf()) == 0.); + BOOST_CHECK(audi::abs(onethird - x.constant_cf()) == 0.); } BOOST_AUTO_TEST_CASE(exp_and_log) @@ -23,10 +23,10 @@ BOOST_AUTO_TEST_CASE(exp_and_log) mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; gdual_mp x{onethird, "x", 3}; auto res = exp(x); - BOOST_CHECK(abs(res.find_cf({0}) - audi::exp(onethird)) < 1e-33); - BOOST_CHECK(abs(res.find_cf({1}) - audi::exp(onethird)) < 1e-33); - BOOST_CHECK(abs(res.find_cf({2}) - audi::exp(onethird) / 2.) < 1e-33); - BOOST_CHECK(abs(res.find_cf({3}) - audi::exp(onethird) / 6.) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({0}) - audi::exp(onethird)) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - audi::exp(onethird)) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - audi::exp(onethird) / 2.) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) - audi::exp(onethird) / 6.) < 1e-33); BOOST_CHECK((exp(log(x)) - x).trim(1e-34) == gdual_mp(0.)); BOOST_CHECK((log(exp(x)) - x).trim(1e-34) == gdual_mp(0.)); } @@ -39,66 +39,66 @@ BOOST_AUTO_TEST_CASE(exponentiation) gdual_mp x{onethird, "x", 3}; auto res = pow(mppp::real128(2.), x); auto log_2 = audi::log(mppp::real128(2.)); - BOOST_CHECK(abs(res.find_cf({0}) - audi::pow(2., onethird)) < 1e-33); - BOOST_CHECK(abs(res.find_cf({1}) - audi::pow(2., onethird) * log_2) < 1e-33); - BOOST_CHECK(abs(res.find_cf({2}) - audi::pow(2., onethird) * log_2 * log_2 / 2.) < 1e-33); - BOOST_CHECK(abs(res.find_cf({3}) - audi::pow(2., onethird) * log_2 * log_2 * log_2 / 6.) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({0}) - audi::pow(2., onethird)) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - audi::pow(2., onethird) * log_2) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - audi::pow(2., onethird) * log_2 * log_2 / 2.) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) - audi::pow(2., onethird) * log_2 * log_2 * log_2 / 6.) < 1e-33); x = gdual_mp(4); // exponent is an integer constant res = pow(mppp::real128(2.), x); - BOOST_CHECK(abs(res.constant_cf() - 2 * 2 * 2 * 2) < 1e-33); + BOOST_CHECK(audi::abs(res.constant_cf() - 2 * 2 * 2 * 2) < 1e-33); } // overload gdual^arith { mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; gdual_mp x{onethird, "x", 3}; auto res = pow(x, onethird); - BOOST_CHECK(abs(res.find_cf({0}) - audi::pow(onethird, onethird)) < 1e-33); - BOOST_CHECK(abs(res.find_cf({1}) - onethird * audi::pow(onethird, onethird - 1.)) < 1e-33); - BOOST_CHECK(abs(res.find_cf({2}) - onethird * (onethird - 1.) * audi::pow(onethird, onethird - 2.) / 2.) + BOOST_CHECK(audi::abs(res.find_cf({0}) - audi::pow(onethird, onethird)) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - onethird * audi::pow(onethird, onethird - 1.)) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - onethird * (onethird - 1.) * audi::pow(onethird, onethird - 2.) / 2.) < 1e-33); - BOOST_CHECK(abs(res.find_cf({3}) + BOOST_CHECK(audi::abs(res.find_cf({3}) - onethird * (onethird - 1.) * (onethird - 2.) * audi::pow(onethird, onethird - 3.) / 6.) < 1e-33); // exponent is a double representable as integer x = gdual_mp(3, "x", 3); res = pow(x, 3.); // note that the constant 3 is double - BOOST_CHECK(abs(res.find_cf({0}) - audi::pow(3, 3)) < 1e-33); - BOOST_CHECK(abs(res.find_cf({1}) - 3 * audi::pow(3, 3 - 1)) < 1e-33); - BOOST_CHECK(abs(res.find_cf({2}) - 3 * (3 - 1.) * audi::pow(3, 3 - 2) / 2.) < 1e-33); - BOOST_CHECK(abs(res.find_cf({3}) - 3 * (3 - 1.) * (3 - 2.) * audi::pow(3, 3 - 3) / 6.) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({0}) - audi::pow(3, 3)) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - 3 * audi::pow(3, 3 - 1)) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - 3 * (3 - 1.) * audi::pow(3, 3 - 2) / 2.) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) - 3 * (3 - 1.) * (3 - 2.) * audi::pow(3, 3 - 3) / 6.) < 1e-33); } // overload gdual^int { mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; gdual_mp x{onethird, "x", 3}; auto res = pow(x, 3); - BOOST_CHECK(abs(res.find_cf({0}) - audi::pow(onethird, 3)) < 1e-33); - BOOST_CHECK(abs(res.find_cf({1}) - 3 * audi::pow(onethird, 3 - 1)) < 1e-33); - BOOST_CHECK(abs(res.find_cf({2}) - 3 * (3 - 1.) * audi::pow(onethird, 3 - 2) / 2.) < 1e-33); - BOOST_CHECK(abs(res.find_cf({3}) - 3 * (3 - 1.) * (3 - 2.) * audi::pow(onethird, 3 - 3) / 6.) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({0}) - audi::pow(onethird, 3)) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - 3 * audi::pow(onethird, 3 - 1)) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - 3 * (3 - 1.) * audi::pow(onethird, 3 - 2) / 2.) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) - 3 * (3 - 1.) * (3 - 2.) * audi::pow(onethird, 3 - 3) / 6.) < 1e-33); res = pow(x, -3); - BOOST_CHECK(abs(res.find_cf({0}) - audi::pow(onethird, -3)) < 1e-32); // we check for absolute error, hence the precision loss - BOOST_CHECK(abs(res.find_cf({1}) + 3 * audi::pow(onethird, -3 - 1)) < 1e-31); // we check for absolute error, hence the precision loss - BOOST_CHECK(abs(res.find_cf({2}) + 3 * (-3 - 1) * audi::pow(onethird, -3 - 2) / 2) < 1e-30); // we check for absolute error, hence the precision loss - BOOST_CHECK(abs(res.find_cf({3}) + 3 * (-3 - 1) * (-3 - 2) * audi::pow(onethird, -3 - 3) / 6) < 1e-29); // we check for absolute error, hence the precision loss + BOOST_CHECK(audi::abs(res.find_cf({0}) - audi::pow(onethird, -3)) < 1e-32); // we check for absolute error, hence the precision loss + BOOST_CHECK(audi::abs(res.find_cf({1}) + 3 * audi::pow(onethird, -3 - 1)) < 1e-31); // we check for absolute error, hence the precision loss + BOOST_CHECK(audi::abs(res.find_cf({2}) + 3 * (-3 - 1) * audi::pow(onethird, -3 - 2) / 2) < 1e-30); // we check for absolute error, hence the precision loss + BOOST_CHECK(audi::abs(res.find_cf({3}) + 3 * (-3 - 1) * (-3 - 2) * audi::pow(onethird, -3 - 3) / 6) < 1e-29); // we check for absolute error, hence the precision loss res = pow(x, 0); - BOOST_CHECK(abs(res.find_cf({0}) - 1 == 0)); - BOOST_CHECK(abs(res.find_cf({1}) == 0)); - BOOST_CHECK(abs(res.find_cf({2}) == 0)); - BOOST_CHECK(abs(res.find_cf({3}) == 0)); + BOOST_CHECK(audi::abs(res.find_cf({0}) - 1 == 0)); + BOOST_CHECK(audi::abs(res.find_cf({1}) == 0)); + BOOST_CHECK(audi::abs(res.find_cf({2}) == 0)); + BOOST_CHECK(audi::abs(res.find_cf({3}) == 0)); } // overload gdual^gdual { mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; gdual_mp x{onethird, "x", 3}; auto res = pow(x, x); - BOOST_CHECK(abs(res.find_cf({0}) - mppp::real128("0.693361274350634704843352274785961795445935113457754036565863693400")) < 1e-33); - BOOST_CHECK(abs(res.find_cf({1}) - mppp::real128("-0.0683739421375531895286241688670376535021100832441426057588451227360656")) < 1e-33); - BOOST_CHECK(abs(res.find_cf({2}) - mppp::real128("1.043413166985674569326084555526740070128227383299088804220207359748035")) < 1e-33); - BOOST_CHECK(abs(res.find_cf({3}) - mppp::real128("-1.142713640471137873959384027190746725008973893684368645673060217249986")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.693361274350634704843352274785961795445935113457754036565863693400")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("-0.0683739421375531895286241688670376535021100832441426057588451227360656")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("1.043413166985674569326084555526740070128227383299088804220207359748035")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("-1.142713640471137873959384027190746725008973893684368645673060217249986")) < 1e-33); } } BOOST_AUTO_TEST_CASE(sqrt_fun) @@ -107,10 +107,10 @@ BOOST_AUTO_TEST_CASE(sqrt_fun) mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; gdual_mp x{onethird, "x", 3}; auto res = sqrt(x); - BOOST_CHECK(abs(res.find_cf({0}) - mppp::real128("0.577350269189625764509148780501957455647601751270126876018602326484")) < 1e-33); - BOOST_CHECK(abs(res.find_cf({1}) - mppp::real128("0.8660254037844386467637231707529361834714026269051903140279034897263995")) < 1e-33); - BOOST_CHECK(abs(res.find_cf({2}) - mppp::real128("-0.6495190528383289850727923780647021376035519701788927355209276172954492")) < 1e-33); - BOOST_CHECK(abs(res.find_cf({3}) - mppp::real128("0.974278579257493477609188567097053206405327955268339103281391425944148")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.577350269189625764509148780501957455647601751270126876018602326484")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("0.8660254037844386467637231707529361834714026269051903140279034897263995")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("-0.6495190528383289850727923780647021376035519701788927355209276172954492")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("0.974278579257493477609188567097053206405327955268339103281391425944148")) < 1e-33); } } BOOST_AUTO_TEST_CASE(cbrt_fun) @@ -119,22 +119,115 @@ BOOST_AUTO_TEST_CASE(cbrt_fun) mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; gdual_mp x{onethird, "x", 3}; auto res = cbrt(x); - BOOST_CHECK(abs(res.find_cf({0}) - mppp::real128("0.693361274350634704843352274785961795445935113457754036565863693400")) < 1e-33); - BOOST_CHECK(abs(res.find_cf({1}) - mppp::real128("0.6933612743506347048433522747859617954459351134577540365658636934004977")) < 1e-33); - BOOST_CHECK(abs(res.find_cf({2}) - mppp::real128("-0.693361274350634704843352274785961795445935113457754036565863693401191")) < 1e-33); - BOOST_CHECK(abs(res.find_cf({3}) - mppp::real128("1.155602123917724508072253791309936325743225189096256727609772822336474")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.693361274350634704843352274785961795445935113457754036565863693400")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("0.6933612743506347048433522747859617954459351134577540365658636934004977")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("-0.693361274350634704843352274785961795445935113457754036565863693401191")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("1.155602123917724508072253791309936325743225189096256727609772822336474")) < 1e-33); } } -/* BOOST_AUTO_TEST_CASE(trigonometric) { - mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; - gdual_mp x{onethird, "x", 3}; - auto res = sin(x); - BOOST_CHECK(abs(res.find_cf({0}) - audi::sin(onethird)) < 1e-33); - BOOST_CHECK(abs(res.find_cf({1}) - audi::cos(onethird)) < 1e-33); - BOOST_CHECK(abs(res.find_cf({2}) + audi::sin(onethird) / 2.) < 1e-33); - BOOST_CHECK(abs(res.find_cf({3}) + audi::cos(onethird) / 6.) < 1e-33); - //BOOST_CHECK((sin(asin(x)) - x).trim(1e-34) == gdual_mp(0.)); + //sine + { + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 3}; + auto res = sin(x); + BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.3271946967961522441733440852676206060643014")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("0.94495694631473766438828400767588060784585271047")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("-0.16359734839807612208667204263381030303215068770")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("-0.157492824385789610731380667945980101307642118412")) < 1e-33); + } + //cosine + { + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 3}; + auto res = cos(x); + BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.9449569463147376643882840076758806078458527")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("-0.32719469679615224417334408526762060606430137540")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("-0.472478473157368832194142003837940303922926355236")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("0.054532449466025374028890680877936767677383562566")) < 1e-33); + } + //sincos + { + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 3}; + auto res = sin_and_cos(x); + BOOST_CHECK(res[0] == sin(x)); + BOOST_CHECK(res[1] == cos(x)); + } + //tan + { + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 3}; + auto res = tan(x); + BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.3462535495105754910385435656097407745957039")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("1.11989152054867255286971414281622406522119684361")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("0.38776641405677346168406834694334831426784259534")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("0.50756267076436951015232120845633638256350224970")) < 1e-33); + } + // inverse functions + { + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 3}; + BOOST_CHECK((sin(asin(x)) - x).trim(1e-34) == gdual_mp(0.)); + BOOST_CHECK((asin(sin(x)) - x).trim(1e-34) == gdual_mp(0.)); + BOOST_CHECK((cos(acos(x)) - x).trim(1e-32) == gdual_mp(0.)); // in this computation we have an accumulating precision loss at high orders + BOOST_CHECK((acos(cos(x)) - x).trim(1e-32) == gdual_mp(0.)); // in this computation we have an accumulating precision loss at high orders + BOOST_CHECK((tan(atan(x)) - x).trim(1e-34) == gdual_mp(0.)); + BOOST_CHECK((atan(tan(x)) - x).trim(1e-34) == gdual_mp(0.)); + + + } +} +BOOST_AUTO_TEST_CASE(hyperbolic) +{ + // hyperbolic sine + { + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 3}; + auto res = sinh(x); + BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.339540557256150139101260611338603585072")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("1.0560718678299393895268647082639832525253961")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("0.1697702786280750695506303056693017925360226")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("0.17601197797165656492114411804399720875423268")) < 1e-33); + } + // hyperbolic cosine + { + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 3}; + auto res = cosh(x); + BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("1.056071867829939389526864708263983252525")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("0.3395405572561501391012606113386035850720452")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("0.52803593391496969476343235413199162626269805")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("0.05659009287602502318354343522310059751200753")) < 1e-33); + } + // hyperbolic sine and cosine + { + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 3}; + auto res = sinh_and_cosh(x); + BOOST_CHECK(res[0] == sinh(x)); + BOOST_CHECK(res[1] == cosh(x)); + } + //hyperbolic tan + { + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 3}; + auto res = tanh(x); + BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.3215127375316343447194062224252064660052920025020835116798050")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("0.89662955960491440420948934034124973587445145348001949661874818114")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("-0.28827782426035973712472569203365039113005161345723090151632152611")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("-0.20619152742069314951779955121670628474663040144796586567125202883")) < 1e-33); + } + // hyperbolic inverse functions + { + mppp::real128 onethird{"1.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 3}; + BOOST_CHECK((sinh(asinh(x)) - x).trim(1e-33) == gdual_mp(0.)); + BOOST_CHECK((asinh(sinh(x)) - x).trim(1e-33) == gdual_mp(0.)); + BOOST_CHECK((cosh(acosh(x)) - x).trim(1e-33) == gdual_mp(0.)); + BOOST_CHECK((acosh(cosh(x)) - x).trim(1e-33) == gdual_mp(0.)); + BOOST_CHECK((tanh(atanh(x-1)) - (x-1)).trim(1e-33) == gdual_mp(0.)); + BOOST_CHECK((atanh(tanh(x)) - x).trim(1e-33) == gdual_mp(0.)); + } } -*/ \ No newline at end of file From e4a643158eeffb453cabaa833c353e13e2c51fe3 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Thu, 3 May 2018 16:15:56 +0200 Subject: [PATCH 15/61] a stable code. still some tests missing and docs --- include/audi/functions.hpp | 94 +++++++++++++++++++++++--------------- include/audi/real128.hpp | 23 ++-------- tests/gdual_mp.cpp | 2 +- 3 files changed, 62 insertions(+), 57 deletions(-) diff --git a/include/audi/functions.hpp b/include/audi/functions.hpp index f9243a52..627e8e4e 100644 --- a/include/audi/functions.hpp +++ b/include/audi/functions.hpp @@ -268,7 +268,7 @@ inline gdual sqrt(const gdual &d) template inline gdual cbrt(const gdual &d) { - T alpha(T(1.)/T(3.)); + T alpha(T(1.) / T(3.)); gdual retval(1.); auto p0 = d.constant_cf(); auto cbrt_p0 = audi::cbrt(p0); @@ -317,8 +317,8 @@ inline gdual sin(const gdual &d) gdual cos_taylor(1.); gdual tmp(cos_taylor); for (auto i = 2u; i <= d.get_order(); i += 2) { - coeff = -coeff; // -1, 1, -1, 1, ... - tmp *= phat2; // phat^2, phat^4, phat^6 ... + coeff = -coeff; // -1, 1, -1, 1, ... + tmp *= phat2; // phat^2, phat^4, phat^6 ... factorial *= i * (i - 1); // 2!, 4!, 6!, ... cos_taylor += (coeff * tmp) / factorial; } @@ -328,8 +328,8 @@ inline gdual sin(const gdual &d) gdual sin_taylor(phat); tmp = sin_taylor; for (auto i = 3u; i <= d.get_order(); i += 2) { - coeff = -coeff; // -1, 1, -1, 1, ... - tmp *= phat2; // phat^3, phat^5, phat^7 ... + coeff = -coeff; // -1, 1, -1, 1, ... + tmp *= phat2; // phat^3, phat^5, phat^7 ... factorial *= i * (i - 1); // 3!, 5!, 7!, ... sin_taylor += (coeff * tmp) / factorial; } @@ -367,8 +367,8 @@ inline gdual cos(const gdual &d) gdual cos_taylor(1.); gdual tmp(cos_taylor); for (auto i = 2u; i <= d.get_order(); i += 2) { - coeff = -coeff; // -1, 1, -1, 1, ... - tmp *= phat2; // phat^2, phat^4, phat^6 ... + coeff = -coeff; // -1, 1, -1, 1, ... + tmp *= phat2; // phat^2, phat^4, phat^6 ... factorial *= i * (i - 1); // 2!, 4!, 6!, ... cos_taylor += (coeff * tmp) / factorial; } @@ -378,8 +378,8 @@ inline gdual cos(const gdual &d) gdual sin_taylor(phat); tmp = sin_taylor; for (auto i = 3u; i <= d.get_order(); i += 2) { - coeff = -coeff; // -1, 1, -1, 1, ... - tmp *= phat2; // phat^3, phat^5, phat^7 ... + coeff = -coeff; // -1, 1, -1, 1, ... + tmp *= phat2; // phat^3, phat^5, phat^7 ... factorial *= i * (i - 1); // 3!, 5!, 7!, ... sin_taylor += (coeff * tmp) / factorial; } @@ -412,8 +412,8 @@ std::array, 2> sin_and_cos(const gdual &d) gdual cos_taylor(1.); gdual tmp(cos_taylor); for (auto i = 2u; i <= d.get_order(); i += 2) { - coeff = -coeff; // -1, 1, -1, 1, ... - tmp *= phat2; // phat^2, phat^4, phat^6 ... + coeff = -coeff; // -1, 1, -1, 1, ... + tmp *= phat2; // phat^2, phat^4, phat^6 ... factorial *= i * (i - 1); // 2!, 4!, 6!, ... cos_taylor += (coeff * tmp) / factorial; } @@ -423,8 +423,8 @@ std::array, 2> sin_and_cos(const gdual &d) gdual sin_taylor(phat); tmp = sin_taylor; for (auto i = 3u; i <= d.get_order(); i += 2) { - coeff = -coeff; // -1, 1, -1, 1, ... - tmp *= phat2; // phat^3, phat^5, phat^7 ... + coeff = -coeff; // -1, 1, -1, 1, ... + tmp *= phat2; // phat^3, phat^5, phat^7 ... factorial *= i * (i - 1); // 3!, 5!, 7!, ... sin_taylor += (coeff * tmp) / factorial; } @@ -459,14 +459,14 @@ inline gdual tan(const gdual &d) auto tan_p0 = audi::tan(p0); // Pre-compute Bernoulli numbers. - std::vector bn; - boost::math::bernoulli_b2n(0, (d.get_order() + 1) / 2 + 1, + std::vector bn; + boost::math::bernoulli_b2n(0, (d.get_order() + 1) / 2 + 1, std::back_inserter(bn)); // Fill vector with even Bernoulli numbers. gdual tan_taylor = phat; // Factors - T factorial(24); - T four_k(16); + double factorial(24); + double four_k(16); for (auto k = 2u; 2 * k - 1 <= d.get_order(); ++k) { phat *= phat2; tan_taylor += bn[k] * four_k * (1 - audi::abs(four_k)) / factorial * phat; @@ -475,6 +475,14 @@ inline gdual tan(const gdual &d) } return (tan_p0 + tan_taylor) / (1. - tan_p0 * tan_taylor); } +// template specialization for the mppp::real128 type. boost::math::bernoulli_b2n can also work, but +// requires to specialize std::numeric_limits for vectorized and mppp::real128 +template <> +inline gdual tan(const gdual &d) +{ + auto sincos = sin_and_cos(d); + return sincos[0] / sincos[1]; +} /// Overload for the hyperbolic sine /** @@ -502,7 +510,7 @@ inline gdual sinh(const gdual &d) auto sinh_p0 = audi::sinh(p0); auto cosh_p0 = audi::cosh(p0); - T factorial(1.); + double factorial(1.); gdual cosh_taylor(1.); gdual tmp(cosh_taylor); for (auto i = 2u; i <= d.get_order(); i += 2) { @@ -511,7 +519,7 @@ inline gdual sinh(const gdual &d) cosh_taylor += tmp / factorial; } - factorial = T(1.); + factorial = 1.; gdual sinh_taylor(phat); tmp = sinh_taylor; for (auto i = 3u; i <= d.get_order(); i += 2) { @@ -548,7 +556,7 @@ inline gdual cosh(const gdual &d) auto sinh_p0 = audi::sinh(p0); auto cosh_p0 = audi::cosh(p0); - T factorial(1.); + double factorial(1.); gdual cosh_taylor(1.); gdual tmp(cosh_taylor); for (auto i = 2u; i <= d.get_order(); i += 2) { @@ -557,7 +565,7 @@ inline gdual cosh(const gdual &d) cosh_taylor += tmp / factorial; } - factorial = T(1.); + factorial = 1.; gdual sinh_taylor(phat); tmp = sinh_taylor; for (auto i = 3u; i <= d.get_order(); i += 2) { @@ -589,7 +597,7 @@ std::array, 2> sinh_and_cosh(const gdual &d) auto sinh_p0 = audi::sinh(p0); auto cosh_p0 = audi::cosh(p0); - T factorial(1.); + double factorial(1.); gdual cosh_taylor(1.); gdual tmp(cosh_taylor); for (auto i = 2u; i <= d.get_order(); i += 2) { @@ -598,7 +606,7 @@ std::array, 2> sinh_and_cosh(const gdual &d) cosh_taylor += tmp / factorial; } - factorial = T(1.); + factorial = 1.; gdual sinh_taylor(phat); tmp = sinh_taylor; for (auto i = 3u; i <= d.get_order(); i += 2) { @@ -637,14 +645,14 @@ inline gdual tanh(const gdual &d) auto tanh_p0 = audi::tanh(p0); // Pre-compute Bernoulli numbers. - std::vector bn; - boost::math::bernoulli_b2n(0, (d.get_order() + 1) / 2 + 1, + std::vector bn; + boost::math::bernoulli_b2n(0, (d.get_order() + 1) / 2 + 1, std::back_inserter(bn)); // Fill vector with even Bernoulli numbers. gdual tanh_taylor = phat; // Factors - T factorial(24.); - T four_k(16.); + double factorial(24.); + double four_k(16.); for (auto k = 2u; 2 * k - 1 <= d.get_order(); ++k) { phat *= phat2; tanh_taylor += bn[k] * four_k * (four_k - 1.) / factorial * phat; @@ -653,6 +661,14 @@ inline gdual tanh(const gdual &d) } return (tanh_p0 + tanh_taylor) / (1. + tanh_p0 * tanh_taylor); } +// // template specialization for the mppp::real128 type. boost::math::bernoulli_b2n can also work, but +// requires to specialize std::numeric_limits for vectorized and mppp::real128 +template <> +inline gdual tanh(const gdual &d) +{ + auto sinhcosh = sinh_and_cosh(d); + return sinhcosh[0] / sinhcosh[1]; +} /// Overload for the inverse hyperbolic tangent /** @@ -727,23 +743,23 @@ inline gdual atan(const gdual &d) auto f0 = p0 * p0; T cf_i(-1.); for (auto j = 1u; 2 * j <= k; ++j) { - binom += (binomial(k, 2u * j) * cf_i) * f0; + binom += (binomial(k, 2u * j) * cf_i) * f0; f0 *= p0 * p0; - cf_i *= -1.; + cf_i = -cf_i; } retval += binom * powphat * coeff1 / k; - coeff1 *= -1.; + coeff1 = -coeff1; } else { // This is for even powers 2..4..6 T binom(0.); auto f0 = p0; T cf_i(1.); for (auto j = 1u; 2 * j - 1 <= k; ++j) { - binom += T(binomial(k, 2u * j - 1u) * cf_i) * f0; + binom += T(binomial(k, 2u * j - 1u) * cf_i) * f0; f0 *= p0 * p0; - cf_i *= -1; + cf_i = -cf_i; } retval += binom * powphat * coeff2 / k; - coeff2 *= -1; + coeff2 = -coeff2; } powphat *= phat; } @@ -835,8 +851,14 @@ inline gdual asin(const gdual &d) template inline gdual acos(const gdual &d) { - return 0.5 * boost::math::constants::pi() - asin(d); - + return 0.5 * boost::math::constants::pi() - asin(d); +} +// template specialization for the mppp::real128 type. boost::math::constants::pi can also work, but +// requires to specialize std::numeric_limits for vectorized and mppp::real128 +template <> +inline gdual acos(const gdual &d) +{ + return 0.5 * mppp::real128_pi() - asin(d); } /// Overload for the absolute value @@ -871,7 +893,7 @@ inline gdual abs(const gdual &d) // Vectorized abs inline gdual abs(const gdual &d) { - gdual retval(d); + gdual retval(d); auto p0 = retval.constant_cf(); for (auto it = retval._container().begin(); it != retval._container().end(); ++it) { // if the coefficient has one only element copy it over to the whole length of p0 diff --git a/include/audi/real128.hpp b/include/audi/real128.hpp index a9b3fef8..b8fff59c 100644 --- a/include/audi/real128.hpp +++ b/include/audi/real128.hpp @@ -26,26 +26,9 @@ struct partial_impl { return mppp::real128{}; } }; -}} // end of piranha namespace +} // namespace math +} // namespace piranha + -// Specialization for numeric limits. Implementing the becessary ones for bernoulli numbers to work in boost -namespace std { -template<> -class numeric_limits { -public: -constexpr static int radix = 2u; -constexpr static int digits = 113u; -constexpr static int max_exponent = 16384u; -constexpr static bool is_specialized = true; -constexpr static bool has_infinity = true; -constexpr static bool has_quiet_NaN = true; -constexpr static bool has_signaling_NaN = false; -static mppp::real128 min() noexcept { return mppp::real128("3.36210314311209350626267781732175260e-4932"); } -static mppp::real128 max() noexcept { return mppp::real128("1.18973149535723176508575932662800702e4932"); } -static mppp::real128 lowest() {return mppp::real128_min();}; -static mppp::real128 quiet_NaN() {return mppp::real128(0.)/mppp::real128(0.);}; //todo: use nanq -static mppp::real128 infinity() {return mppp::real128(1.)/mppp::real128(0.);}; //todo: can this be made better? -}; -} #endif diff --git a/tests/gdual_mp.cpp b/tests/gdual_mp.cpp index 059fddc1..aedf1233 100644 --- a/tests/gdual_mp.cpp +++ b/tests/gdual_mp.cpp @@ -174,7 +174,7 @@ BOOST_AUTO_TEST_CASE(trigonometric) BOOST_CHECK((cos(acos(x)) - x).trim(1e-32) == gdual_mp(0.)); // in this computation we have an accumulating precision loss at high orders BOOST_CHECK((acos(cos(x)) - x).trim(1e-32) == gdual_mp(0.)); // in this computation we have an accumulating precision loss at high orders BOOST_CHECK((tan(atan(x)) - x).trim(1e-34) == gdual_mp(0.)); - BOOST_CHECK((atan(tan(x)) - x).trim(1e-34) == gdual_mp(0.)); + BOOST_CHECK((atan(tan(x)) - x).trim(1e-33) == gdual_mp(0.)); } From d84b7710b9a65d9be04e9f459d2c119a94775de7 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Thu, 3 May 2018 16:36:28 +0200 Subject: [PATCH 16/61] a stable code. still some tests missing and docs --- include/audi/gdual.hpp | 2 +- pyaudi/core.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/audi/gdual.hpp b/include/audi/gdual.hpp index cd55b0b3..c4e40539 100644 --- a/include/audi/gdual.hpp +++ b/include/audi/gdual.hpp @@ -677,7 +677,7 @@ class gdual bool is_zero(double tol) const { for (auto it = _container().begin(); it != _container().end(); ++it) { - if (abs(it->m_cf) > tol) // call to audi abs has precedence + if (audi::abs(it->m_cf) > tol) // call to audi abs has precedence { return false; } diff --git a/pyaudi/core.cpp b/pyaudi/core.cpp index 0c74236c..9188130c 100644 --- a/pyaudi/core.cpp +++ b/pyaudi/core.cpp @@ -32,6 +32,9 @@ BOOST_PYTHON_MODULE(core) return ::new gdual_v(pyaudi::l_to_v(value), symbol, order); })); + // We expose the gdual using the expose_gdual defined in exposed_gdual.hpp + // pyaudi::expose_gdual("real128"); + // We expose the functions bp::def("exp", +[](const gdual_d &d) { return exp(d); }, "Exponential (gdual_d)."); bp::def("exp", +[](double x) { return std::exp(x); }, "Exponential (double)."); From d004262a8469ccec7d9955a6727168d2909f36de Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 4 May 2018 10:35:53 +0200 Subject: [PATCH 17/61] simplification on temnplate logic --- include/audi/functions.hpp | 3 +- include/audi/functions_from_d.hpp | 51 ++++++++++++++++++------------- pyaudi/docstrings.hpp | 3 +- 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/include/audi/functions.hpp b/include/audi/functions.hpp index 627e8e4e..b4d26541 100644 --- a/include/audi/functions.hpp +++ b/include/audi/functions.hpp @@ -890,7 +890,8 @@ inline gdual abs(const gdual &d) } return -d; } -// Vectorized abs +// Vectorized abs specialization +template <> inline gdual abs(const gdual &d) { gdual retval(d); diff --git a/include/audi/functions_from_d.hpp b/include/audi/functions_from_d.hpp index 698b0902..e309910c 100644 --- a/include/audi/functions_from_d.hpp +++ b/include/audi/functions_from_d.hpp @@ -33,13 +33,12 @@ namespace audi * @param dg Taylor expansion of the derivative of the outer function * @param g0 Value of the outer function at the expansion point */ -template ::value && std::is_same::value, int> = 0> -inline T _compose_from_derivative(T f, T dg, V g0) +template +inline gdual _compose_from_derivative(gdual f, gdual dg, T g0) { auto ss = f.get_symbol_set(); if (ss.size() == 0) { - return T(g0); + return gdual(g0); } auto retval = (dg * f.partial(ss[0])).integrate(ss[0]); for (auto i = 1u; i < ss.size(); ++i) { @@ -61,8 +60,8 @@ inline T _compose_from_derivative(T f, T dg, V g0) * @return an audi:gdual containing the Taylor expansion of the inverse hyperbolic tangent of \p d * */ -template ::value, int> = 0> -inline T atanh_d(const T &f) +template +inline gdual atanh_d(const gdual &f) { auto f0 = f.constant_cf(); auto g0 = audi::atanh(f0); @@ -81,8 +80,8 @@ inline T atanh_d(const T &f) * @return an audi:gdual containing the Taylor expansion of the inverse tangent of \p d * */ -template ::value, int> = 0> -inline T atan_d(const T &f) +template +inline gdual atan_d(const gdual &f) { auto f0 = f.constant_cf(); auto g0 = audi::atan(f0); @@ -101,12 +100,12 @@ inline T atan_d(const T &f) * @return an audi:gdual containing the Taylor expansion of the inverse sine of \p d * */ -template ::value, int> = 0> -inline T asin_d(const T &f) +template +inline gdual asin_d(const gdual &f) { auto f0 = f.constant_cf(); auto g0 = audi::asin(f0); - auto dg = 1. / sqrt(1. - f * f); + auto dg = 1. / audi::sqrt(1. - f * f); return _compose_from_derivative(f, dg, g0); } @@ -121,12 +120,12 @@ inline T asin_d(const T &f) * @return an audi:gdual containing the Taylor expansion of the inverse hyperbolic sine of \p d * */ -template ::value, int> = 0> -inline T asinh_d(const T &f) +template +inline gdual asinh_d(const gdual &f) { auto f0 = f.constant_cf(); auto g0 = audi::asinh(f0); - auto dg = 1. / sqrt(1. + f * f); + auto dg = 1. / audi::sqrt(1. + f * f); return _compose_from_derivative(f, dg, g0); } @@ -141,12 +140,12 @@ inline T asinh_d(const T &f) * @return an audi:gdual containing the Taylor expansion of the inverse cosine of \p d * */ -template ::value, int> = 0> -inline T acos_d(const T &f) +template +inline gdual acos_d(const gdual &f) { auto f0 = f.constant_cf(); auto g0 = audi::acos(f0); - auto dg = -1. / sqrt(1. - f * f); + auto dg = -1. / audi::sqrt(1. - f * f); return _compose_from_derivative(f, dg, g0); } @@ -161,12 +160,12 @@ inline T acos_d(const T &f) * @return an audi:gdual containing the Taylor expansion of the inverse hyperbolic cosine of \p d * */ -template ::value, int> = 0> -inline T acosh_d(const T &f) +template +inline gdual acosh_d(const gdual &f) { auto f0 = f.constant_cf(); auto g0 = audi::acosh(f0); - auto dg = 1. / sqrt((f - 1.) * (f + 1.)); + auto dg = 1. / audi::sqrt((f - 1.) * (f + 1.)); return _compose_from_derivative(f, dg, g0); } @@ -181,14 +180,22 @@ inline T acosh_d(const T &f) * @return an audi:gdual containing the Taylor expansion of the error function of \p d * */ -template ::value, int> = 0> -inline T erf(const T &d) +template +inline gdual erf(const gdual &d) { auto f0 = d.constant_cf(); auto g0 = audi::erf(f0); auto dg = (2. / std::sqrt(boost::math::constants::pi())) * exp(-d * d); return _compose_from_derivative(d, dg, g0); } +//template <> +//inline gdual erf(const gdual &d) +//{ +// auto f0 = d.constant_cf(); +// auto g0 = audi::erf(f0); +// auto dg = (2. / audi::sqrt(mppp::real128_pi())) * exp(-d * d); +// return _compose_from_derivative(d, dg, g0); +//} } // end of namespace audi diff --git a/pyaudi/docstrings.hpp b/pyaudi/docstrings.hpp index 97ed2bbf..00eaec4d 100644 --- a/pyaudi/docstrings.hpp +++ b/pyaudi/docstrings.hpp @@ -8,7 +8,6 @@ namespace pyaudi // gdual std::string gdual_docstring(); std::string gdual_degree_docstring(); - -} +} // namespace pyaudi #endif From ca5a362226b005d6f442437dfd4d4d1cd446cfdd Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Mon, 14 May 2018 12:29:12 +0200 Subject: [PATCH 18/61] fix for boost 1.67 renaming of boost libs --- cmake_modules/AudiFindBoost.cmake | 13 ++++++++++--- pyaudi/CMakeLists.txt | 15 +++++++++++---- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/cmake_modules/AudiFindBoost.cmake b/cmake_modules/AudiFindBoost.cmake index 199c483b..8d5201b4 100644 --- a/cmake_modules/AudiFindBoost.cmake +++ b/cmake_modules/AudiFindBoost.cmake @@ -1,10 +1,17 @@ set(_AUDI_REQUIRED_BOOST_LIBS) list(APPEND _AUDI_REQUIRED_BOOST_LIBS timer chrono serialization system unit_test_framework) if(_AUDI_FIND_BOOST_PYTHON) - if(${PYTHON_VERSION_MAJOR} EQUAL 2) - list(APPEND _AUDI_REQUIRED_BOOST_LIBS python) + # NOTE: since Boost 1.67, the naming of the Boost.Python library has changed to include the + # major and minor python version as a suffix. See the release notes: + # https://www.boost.org/users/history/version_1_67_0.html + if(${Boost_MAJOR_VERSION} GREATER 1 OR (${Boost_MAJOR_VERSION} EQUAL 1 AND ${Boost_MINOR_VERSION} GREATER 66)) + list(APPEND _AUDI_REQUIRED_BOOST_LIBS "python${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR}") else() - list(APPEND _AUDI_REQUIRED_BOOST_LIBS python3) + if(${PYTHON_VERSION_MAJOR} EQUAL 2) + list(APPEND _AUDI_REQUIRED_BOOST_LIBS python) + else() + list(APPEND _AUDI_REQUIRED_BOOST_LIBS python3) + endif() endif() endif() message(STATUS "Required Boost libraries: ${_AUDI_REQUIRED_BOOST_LIBS}") diff --git a/pyaudi/CMakeLists.txt b/pyaudi/CMakeLists.txt index 20cafef5..8b29d5eb 100644 --- a/pyaudi/CMakeLists.txt +++ b/pyaudi/CMakeLists.txt @@ -6,11 +6,18 @@ if(UNIX) set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") endif() -# The name of the BP target to link to depends on the Python version. -if(${PYTHON_VERSION_MAJOR} EQUAL 2) -set(PYAUDI_BP_TARGET "Boost::python") +# The name of the BP target to link to depends on the Boost and Python versions. +# NOTE: since Boost 1.67, the naming of the Boost.Python library has changed to include the +# major and minor python version as a suffix. See the release notes: +# https://www.boost.org/users/history/version_1_67_0.html +if(${Boost_MAJOR_VERSION} GREATER 1 OR (${Boost_MAJOR_VERSION} EQUAL 1 AND ${Boost_MINOR_VERSION} GREATER 66)) + set(PYAUDI_BP_TARGET "Boost::python${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR}") else() -set(PYAUDI_BP_TARGET "Boost::python3") + if(${PYTHON_VERSION_MAJOR} EQUAL 2) + set(PYAUDI_BP_TARGET "Boost::python") + else() + set(PYAUDI_BP_TARGET "Boost::python3") + endif() endif() # Boost.Python version 1.64 (and possibly later?) has issues with default hidden visibility. From 35b214d18e6bac16e418467439b2ee0d80161801 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Tue, 15 May 2018 15:37:58 +0200 Subject: [PATCH 19/61] build system updated --- CMakeLists.txt | 35 ++++-- audi-config.cmake.in | 1 + cmake_modules/FindGMP.cmake | 29 +++-- cmake_modules/FindMPFR.cmake | 29 +++-- config.hpp.in | 11 ++ include/audi/audi.hpp | 15 ++- include/audi/detail/overloads.hpp | 68 +++++++----- include/audi/functions.hpp | 53 +++++---- include/audi/real128.hpp | 12 ++- include/audi/type_traits.hpp | 27 +++-- tests/CMakeLists.txt | 5 +- tests/gdual_mp.cpp | 171 ++++++++++++++++++++---------- 12 files changed, 301 insertions(+), 155 deletions(-) create mode 100644 config.hpp.in diff --git a/CMakeLists.txt b/CMakeLists.txt index af3e0909..19fda2f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,8 @@ endif() # and only one must be chosen. option(AUDI_BUILD_AUDI "Build audi." ON) option(AUDI_BUILD_PYAUDI "Build pyaudi." OFF) +option(AUDI_WITH_MPPP "Enables multiple precision support based on the mp++ project." OFF) + # Check consistency. if(AUDI_BUILD_AUDI AND AUDI_BUILD_PYAUDI) @@ -87,6 +89,12 @@ endif() list(REMOVE_ITEM AUDI_CXX_FLAGS_DEBUG "-Wduplicated-branches") list(REMOVE_ITEM AUDI_CXX_FLAGS_DEBUG "-Wold-style-cast") +# Configure config.hpp. +if(AUDI_WITH_MPPP) + set(AUDI_ENABLE_MPPP "#define AUDI_WITH_MPPP") +endif() +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/config.hpp.in" "${CMAKE_CURRENT_SOURCE_DIR}/include/audi/config.hpp" @ONLY) + if(AUDI_BUILD_PYAUDI) # audi dependencies. include(YACMAPythonSetup) @@ -125,7 +133,6 @@ if(AUDI_BUILD_AUDI) message(STATUS "GMP library found.") message(STATUS "GMP include dir is: ${GMP_INCLUDE_DIR}") message(STATUS "GMP library is: ${GMP_LIBRARIES}") - include_directories(${GMP_INCLUDE_DIR}) # MPFR setup. FIND_PACKAGE(MPFR REQUIRED) @@ -139,12 +146,20 @@ if(AUDI_BUILD_AUDI) message(FATAL_ERROR "Unsupported MPFR version, please upgrade.") endif() message(STATUS "MPFR version is ok.") - include_directories(${MPFR_INCLUDE_DIR}) + + if(AUDI_WITH_MPPP) + # MP++ SETUP + find_package(mp++ REQUIRED) + message(STATUS "mp++ library found.") + endif() # Setup of the header-only audi library. add_library(audi INTERFACE) target_link_libraries(audi INTERFACE Threads::Threads Boost::boost Boost::serialization) - target_link_libraries(audi INTERFACE Eigen3::eigen3) + target_link_libraries(audi INTERFACE Eigen3::eigen3 GMP::GMP MPFR::MPFR) + if(AUDI_WITH_MPPP) + target_link_libraries(audi INTERFACE mp++::mp++) + endif() # This sets up the include directory to be different if we build target_include_directories(audi INTERFACE @@ -154,13 +169,7 @@ if(AUDI_BUILD_AUDI) # These lines are temporary with piranha v0.10, will be simplified when this is updated target_include_directories(audi INTERFACE ${Piranha_INCLUDE_DIR}) - target_include_directories(audi INTERFACE ${MPFR_INCLUDE_DIR}) - target_include_directories(audi INTERFACE ${GMP_INCLUDE_DIR}) - # First mpfr then gmp otherwise mingw is unhappy - target_link_libraries(audi INTERFACE ${MPFR_LIBRARIES}) - target_link_libraries(audi INTERFACE ${GMP_LIBRARIES}) - - + # Builds the main file IF(AUDI_BUILD_MAIN) add_executable(main main.cpp) @@ -181,7 +190,13 @@ if(AUDI_BUILD_AUDI) # Setup of the export. install(TARGETS audi EXPORT audi_export) + # Setup of the optional deps. + set(_AUDI_CONFIG_OPTIONAL_DEPS) + if(AUDI_WITH_MPPP) + set(_AUDI_CONFIG_OPTIONAL_DEPS "${_AUDI_CONFIG_OPTIONAL_DEPS}find_package(mp++ REQUIRED)\n") + endif() configure_file("${CMAKE_CURRENT_SOURCE_DIR}/audi-config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/audi-config.cmake" @ONLY) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/audi-config.cmake" DESTINATION "lib/cmake/audi") install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/FindGMP.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/FindMPFR.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/FindPiranha.cmake" "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/AudiFindBoost.cmake" diff --git a/audi-config.cmake.in b/audi-config.cmake.in index 4bbbc2d6..bf933f35 100644 --- a/audi-config.cmake.in +++ b/audi-config.cmake.in @@ -10,6 +10,7 @@ find_package(Piranha REQUIRED) find_package(GMP REQUIRED) find_package(MPFR REQUIRED) find_package(Eigen3 REQUIRED) +@_AUDI_CONFIG_OPTIONAL_DEPS@ #Restore original module path. set(CMAKE_MODULE_PATH "${_AUDI_CONFIG_OLD_MODULE_PATH}") diff --git a/cmake_modules/FindGMP.cmake b/cmake_modules/FindGMP.cmake index 9848fc9c..e46ce4a8 100644 --- a/cmake_modules/FindGMP.cmake +++ b/cmake_modules/FindGMP.cmake @@ -2,7 +2,7 @@ # http://websvn.kde.org/trunk/KDE/kdeutils/cmake/modules/FindGMP.cmake?view=markup&pathrev=675218 # Copyright (c) 2006, Laurent Montel, -# Copyright (c) 2008-2011 Francesco Biscani, +# Copyright (c) 2008-2018 Francesco Biscani, # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -13,7 +13,7 @@ # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. -# 3. The name of the author may not be used to endorse or promote products +# 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR @@ -28,16 +28,23 @@ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ------------------------------------------------------------------------------------------ -IF(GMP_INCLUDE_DIR AND GMP_LIBRARIES) - # Already in cache, be silent - SET(GMP_FIND_QUIETLY TRUE) -ENDIF(GMP_INCLUDE_DIR AND GMP_LIBRARIES) +if(GMP_INCLUDE_DIR AND GMP_LIBRARY) + # Already in cache, be silent + set(GMP_FIND_QUIETLY TRUE) +endif() -FIND_PATH(GMP_INCLUDE_DIR NAMES gmp.h) -FIND_LIBRARY(GMP_LIBRARIES NAMES gmp) +find_path(GMP_INCLUDE_DIR NAMES gmp.h) +find_library(GMP_LIBRARY NAMES gmp) -INCLUDE(FindPackageHandleStandardArgs) +include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(GMP DEFAULT_MSG GMP_INCLUDE_DIR GMP_LIBRARIES) +find_package_handle_standard_args(GMP DEFAULT_MSG GMP_INCLUDE_DIR GMP_LIBRARY) -MARK_AS_ADVANCED(GMP_INCLUDE_DIR GMP_LIBRARIES) \ No newline at end of file +mark_as_advanced(GMP_INCLUDE_DIR GMP_LIBRARY) + +# NOTE: this has been adapted from CMake's FindPNG.cmake. +if(GMP_FOUND AND NOT TARGET GMP::GMP) + add_library(GMP::GMP UNKNOWN IMPORTED) + set_target_properties(GMP::GMP PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${GMP_INCLUDE_DIR}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" IMPORTED_LOCATION "${GMP_LIBRARY}") +endif() diff --git a/cmake_modules/FindMPFR.cmake b/cmake_modules/FindMPFR.cmake index c90dc3e4..fd382e10 100644 --- a/cmake_modules/FindMPFR.cmake +++ b/cmake_modules/FindMPFR.cmake @@ -2,7 +2,7 @@ # http://websvn.kde.org/trunk/KDE/kdeutils/cmake/modules/FindGMP.cmake?view=markup&pathrev=675218 # Copyright (c) 2006, Laurent Montel, -# Copyright (c) 2008-2011 Francesco Biscani, +# Copyright (c) 2008-2018 Francesco Biscani, # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -13,7 +13,7 @@ # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. -# 3. The name of the author may not be used to endorse or promote products +# 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR @@ -28,16 +28,23 @@ # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # ------------------------------------------------------------------------------------------ -IF(MPFR_INCLUDE_DIR AND MPFR_LIBRARIES) - # Already in cache, be silent - SET(MPFR_FIND_QUIETLY TRUE) -ENDIF(MPFR_INCLUDE_DIR AND MPFR_LIBRARIES) +if(MPFR_INCLUDE_DIR AND MPFR_LIBRARY) + # Already in cache, be silent + set(MPFR_FIND_QUIETLY TRUE) +endif() -FIND_PATH(MPFR_INCLUDE_DIR NAMES mpfr.h) -FIND_LIBRARY(MPFR_LIBRARIES NAMES mpfr) +find_path(MPFR_INCLUDE_DIR NAMES mpfr.h) +find_library(MPFR_LIBRARY NAMES mpfr) -INCLUDE(FindPackageHandleStandardArgs) +include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(MPFR DEFAULT_MSG MPFR_INCLUDE_DIR MPFR_LIBRARIES) +find_package_handle_standard_args(MPFR DEFAULT_MSG MPFR_INCLUDE_DIR MPFR_LIBRARY) -MARK_AS_ADVANCED(MPFR_INCLUDE_DIR MPFR_LIBRARIES) \ No newline at end of file +mark_as_advanced(MPFR_INCLUDE_DIR MPFR_LIBRARY) + +# NOTE: this has been adapted from CMake's FindPNG.cmake. +if(MPFR_FOUND AND NOT TARGET MPFR::MPFR) + add_library(MPFR::MPFR UNKNOWN IMPORTED) + set_target_properties(MPFR::MPFR PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${MPFR_INCLUDE_DIR}" + IMPORTED_LINK_INTERFACE_LANGUAGES "C" IMPORTED_LOCATION "${MPFR_LIBRARY}") +endif() diff --git a/config.hpp.in b/config.hpp.in new file mode 100644 index 00000000..ec8adee6 --- /dev/null +++ b/config.hpp.in @@ -0,0 +1,11 @@ +#ifndef AUDI_CONFIG_HPP +#define AUDI_CONFIG_HPP + +// Start of defines instantiated by CMake. +// clang-format off +#define AUDI_VERSION_STRING "@audi_VERSION@" +#define AUDI_VERSION_MAJOR @audi_VERSION_MAJOR@ +#define AUDI_VERSION_MINOR @audi_VERSION_MINOR@ +@AUDI_ENABLE_MPPP@ + +#endif diff --git a/include/audi/audi.hpp b/include/audi/audi.hpp index 53225a59..9074326d 100644 --- a/include/audi/audi.hpp +++ b/include/audi/audi.hpp @@ -3,21 +3,26 @@ #include -#include +#include + +#if defined(AUDI_WITH_MPPP) +#include +#endif -#include -#include #include #include +#include #include -#include +#include namespace audi { using gdual_d = audi::gdual; using gdual_v = audi::gdual; using gdual_c = audi::gdual>; +#if defined(AUDI_WITH_MPPP) using gdual_mp = audi::gdual; -} +#endif +} // namespace audi #endif diff --git a/include/audi/detail/overloads.hpp b/include/audi/detail/overloads.hpp index fe42d6d3..23fc527e 100644 --- a/include/audi/detail/overloads.hpp +++ b/include/audi/detail/overloads.hpp @@ -3,9 +3,14 @@ #include +#include + +#if defined(AUDI_WITH_MPPP) +#include +#endif + #include #include -#include #include // This is repeated here instead of including type_traits as to avoid a circular dependency @@ -28,11 +33,12 @@ struct is_arithmetic_or_complex // It is used to allow calls such as audi::cos(T) [T = double] in templated functions. #define ARITH_OR_COMPLEX_OVERLOAD(fun_name) \ template ::value, int> = 0> \ - inline auto fun_name(T in) -> decltype(std::fun_name(T(0.))) \ + inline auto fun_name(T in)->decltype(std::fun_name(T(0.))) \ { \ return std::fun_name(in); \ } +#if defined(AUDI_WITH_MPPP) // This macro writes the overload for std::fun_name af a mppp::real128. It simply calls mppp::fun_name // It is used to allow calls such as audi::cos(T) [T = double] in templated functions. #define REAL128_OVERLOAD(fun_name) \ @@ -40,83 +46,94 @@ struct is_arithmetic_or_complex { \ return mppp::fun_name(in); \ } +#endif namespace audi { +#if defined(AUDI_WITH_MPPP) + +REAL128_OVERLOAD(exp) +REAL128_OVERLOAD(erf) +REAL128_OVERLOAD(lgamma) +REAL128_OVERLOAD(log) +REAL128_OVERLOAD(sin) +REAL128_OVERLOAD(cos) +REAL128_OVERLOAD(sinh) +REAL128_OVERLOAD(tan) +REAL128_OVERLOAD(cosh) +REAL128_OVERLOAD(tanh) +REAL128_OVERLOAD(asin) +REAL128_OVERLOAD(acos) +REAL128_OVERLOAD(atan) +REAL128_OVERLOAD(asinh) +REAL128_OVERLOAD(acosh) +REAL128_OVERLOAD(atanh) +REAL128_OVERLOAD(sqrt) +REAL128_OVERLOAD(abs) +REAL128_OVERLOAD(cbrt) +template ::value || std::is_same::value, int> = 0> +inline mppp::real128 pow(const T &base, const U &d) +{ + return mppp::pow(base, d); +} +#endif + VECTORIZED_OVERLOAD(exp) ARITH_OR_COMPLEX_OVERLOAD(exp) -REAL128_OVERLOAD(exp) VECTORIZED_OVERLOAD(erf) ARITH_OR_COMPLEX_OVERLOAD(erf) -REAL128_OVERLOAD(erf) VECTORIZED_OVERLOAD(lgamma) ARITH_OR_COMPLEX_OVERLOAD(lgamma) -REAL128_OVERLOAD(lgamma) VECTORIZED_OVERLOAD(log) ARITH_OR_COMPLEX_OVERLOAD(log) -REAL128_OVERLOAD(log) VECTORIZED_OVERLOAD(sin) ARITH_OR_COMPLEX_OVERLOAD(sin) -REAL128_OVERLOAD(sin) VECTORIZED_OVERLOAD(cos) ARITH_OR_COMPLEX_OVERLOAD(cos) -REAL128_OVERLOAD(cos) VECTORIZED_OVERLOAD(tan) ARITH_OR_COMPLEX_OVERLOAD(tan) -REAL128_OVERLOAD(tan) VECTORIZED_OVERLOAD(sinh) ARITH_OR_COMPLEX_OVERLOAD(sinh) -REAL128_OVERLOAD(sinh) VECTORIZED_OVERLOAD(cosh) ARITH_OR_COMPLEX_OVERLOAD(cosh) -REAL128_OVERLOAD(cosh) VECTORIZED_OVERLOAD(tanh) ARITH_OR_COMPLEX_OVERLOAD(tanh) -REAL128_OVERLOAD(tanh) VECTORIZED_OVERLOAD(asin) ARITH_OR_COMPLEX_OVERLOAD(asin) -REAL128_OVERLOAD(asin) VECTORIZED_OVERLOAD(acos) ARITH_OR_COMPLEX_OVERLOAD(acos) -REAL128_OVERLOAD(acos) VECTORIZED_OVERLOAD(atan) ARITH_OR_COMPLEX_OVERLOAD(atan) -REAL128_OVERLOAD(atan) VECTORIZED_OVERLOAD(asinh) ARITH_OR_COMPLEX_OVERLOAD(asinh) -REAL128_OVERLOAD(asinh) VECTORIZED_OVERLOAD(acosh) ARITH_OR_COMPLEX_OVERLOAD(acosh) -REAL128_OVERLOAD(acosh) VECTORIZED_OVERLOAD(atanh) ARITH_OR_COMPLEX_OVERLOAD(atanh) -REAL128_OVERLOAD(atanh) VECTORIZED_OVERLOAD(sqrt) ARITH_OR_COMPLEX_OVERLOAD(sqrt) -REAL128_OVERLOAD(sqrt) VECTORIZED_OVERLOAD(abs) ARITH_OR_COMPLEX_OVERLOAD(abs) -REAL128_OVERLOAD(abs) VECTORIZED_OVERLOAD(cbrt) -REAL128_OVERLOAD(cbrt) template ::value, int> = 0> inline T cbrt(T in) @@ -130,12 +147,6 @@ inline T cbrt(T in) } // NON UNARY FUNCTIONS -------------------------------------------------------------------------------// -template ::value || std::is_same::value, int> = 0> -inline mppp::real128 pow(const T &base, const U &d) -{ - return mppp::pow(base, d); -} - template ::value && std::is_arithmetic::value, int> = 0> inline double pow(const U &base, const T &d) { @@ -170,6 +181,5 @@ inline vectorized_double pow(vectorized_double in, double exponent) return in; } - -} +} // namespace audi #endif diff --git a/include/audi/functions.hpp b/include/audi/functions.hpp index b4d26541..b4dc5b57 100644 --- a/include/audi/functions.hpp +++ b/include/audi/functions.hpp @@ -1,6 +1,8 @@ #ifndef AUDI_FUNCTIONS_HPP #define AUDI_FUNCTIONS_HPP +#include + #include #include #include @@ -475,14 +477,6 @@ inline gdual tan(const gdual &d) } return (tan_p0 + tan_taylor) / (1. - tan_p0 * tan_taylor); } -// template specialization for the mppp::real128 type. boost::math::bernoulli_b2n can also work, but -// requires to specialize std::numeric_limits for vectorized and mppp::real128 -template <> -inline gdual tan(const gdual &d) -{ - auto sincos = sin_and_cos(d); - return sincos[0] / sincos[1]; -} /// Overload for the hyperbolic sine /** @@ -661,14 +655,6 @@ inline gdual tanh(const gdual &d) } return (tanh_p0 + tanh_taylor) / (1. + tanh_p0 * tanh_taylor); } -// // template specialization for the mppp::real128 type. boost::math::bernoulli_b2n can also work, but -// requires to specialize std::numeric_limits for vectorized and mppp::real128 -template <> -inline gdual tanh(const gdual &d) -{ - auto sinhcosh = sinh_and_cosh(d); - return sinhcosh[0] / sinhcosh[1]; -} /// Overload for the inverse hyperbolic tangent /** @@ -853,13 +839,6 @@ inline gdual acos(const gdual &d) { return 0.5 * boost::math::constants::pi() - asin(d); } -// template specialization for the mppp::real128 type. boost::math::constants::pi can also work, but -// requires to specialize std::numeric_limits for vectorized and mppp::real128 -template <> -inline gdual acos(const gdual &d) -{ - return 0.5 * mppp::real128_pi() - asin(d); -} /// Overload for the absolute value /** @@ -910,6 +889,34 @@ inline gdual abs(const gdual &d) return retval; } +#if defined(AUDI_WITH_MPPP) +// template specialization for the mppp::real128 type. boost::math::bernoulli_b2n can also work, but +// requires to specialize std::numeric_limits for vectorized and mppp::real128 +template <> +inline gdual tan(const gdual &d) +{ + auto sincos = sin_and_cos(d); + return sincos[0] / sincos[1]; +} + +// template specialization for the mppp::real128 type. boost::math::constants::pi can also work, but +// requires to specialize std::numeric_limits for vectorized and mppp::real128 +template <> +inline gdual acos(const gdual &d) +{ + return 0.5 * mppp::real128_pi() - asin(d); +} + +// template specialization for the mppp::real128 type. boost::math::bernoulli_b2n can also work, but +// requires to specialize std::numeric_limits for vectorized and mppp::real128 +template <> +inline gdual tanh(const gdual &d) +{ + auto sinhcosh = sinh_and_cosh(d); + return sinhcosh[0] / sinhcosh[1]; +} +#endif + } // end of namespace audi #endif diff --git a/include/audi/real128.hpp b/include/audi/real128.hpp index b8fff59c..7200cef8 100644 --- a/include/audi/real128.hpp +++ b/include/audi/real128.hpp @@ -1,12 +1,16 @@ #ifndef AUDI_REAL128_HPP #define AUDI_REAL128_HPP +#include + +#if defined(AUDI_WITH_MPPP) + #include #include #include -#include - #include +#include +#include // This header adds to the mppp::real128 class the necessary methods that allow it to be // considered as a type in gdual (piranha::is_Cf, piranha::is_differentiable) @@ -29,6 +33,10 @@ struct partial_impl { } // namespace math } // namespace piranha +#else + +#error The real128.hpp header was included but audi was not configured with the AUDI_WITH_MPPP option. +#endif #endif diff --git a/include/audi/type_traits.hpp b/include/audi/type_traits.hpp index 4f67128b..1f8d0092 100644 --- a/include/audi/type_traits.hpp +++ b/include/audi/type_traits.hpp @@ -1,13 +1,17 @@ #ifndef AUDI_TYPE_TRAITS_HPP #define AUDI_TYPE_TRAITS_HPP +#include + +#if defined(AUDI_WITH_MPPP) +#include +#endif + #include -#include #include #include - namespace audi { /// Type is a gdual @@ -27,15 +31,22 @@ struct is_gdual> : std::true_type { /// Type is arithmetic (includes multiple precision floats) /** - * Checks whether T is an arithmetic type (that is, an integral type or a floating-point type that includes multiple precision floats if available) + * Checks whether T is an arithmetic type (that is, an integral type or a floating-point type that includes multiple + * precision floats if available) * * \tparam T a type to check */ +#if defined(AUDI_WITH_MPPP) template struct is_arithmetic - : std::integral_constant::value || std::is_same::value > { + : std::integral_constant::value || std::is_same::value> { }; - +#else +template +struct is_arithmetic + : std::integral_constant::value> { +}; +#endif /// Type is arithmetic or complex /** * Checks whether T is an arithmetic type (that is, an integral type or a floating-point type) or a complex @@ -55,9 +66,9 @@ struct is_arithmetic_or_complex * \tparam T a type to check */ template -struct is_gdual_cf - : std::integral_constant::value || std::is_same::value > { +struct is_gdual_cf : std::integral_constant::value + || std::is_same::value> { }; -} +} // namespace audi #endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9a7e7b38..870255d7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -30,13 +30,16 @@ ENDMACRO(ADD_AUDI_PERFORMANCE_TESTCASE) ADD_AUDI_TESTCASE(gdual_d) ADD_AUDI_TESTCASE(gdual_v) ADD_AUDI_TESTCASE(gdual_v2) -ADD_AUDI_TESTCASE(gdual_mp) ADD_AUDI_TESTCASE(vectorized_double) ADD_AUDI_TESTCASE(functions) ADD_AUDI_TESTCASE(functions_from_d) ADD_AUDI_TESTCASE(functions_floating_precision) ADD_AUDI_TESTCASE(invert_map) +if(AUDI_WITH_MPPP) + ADD_AUDI_TESTCASE(gdual_mp) +endif() + ADD_AUDI_PERFORMANCE_TESTCASE(multiplication) ADD_AUDI_PERFORMANCE_TESTCASE(division) ADD_AUDI_PERFORMANCE_TESTCASE(invert_map) diff --git a/tests/gdual_mp.cpp b/tests/gdual_mp.cpp index aedf1233..5fccec65 100644 --- a/tests/gdual_mp.cpp +++ b/tests/gdual_mp.cpp @@ -1,14 +1,12 @@ -#define BOOST_TEST_MODULE audi_gdualld_test +#define BOOST_TEST_MODULE audi_gdualmp_test #include #include #include +#include #include #include -#include "helpers.hpp" -#include - using namespace audi; BOOST_AUTO_TEST_CASE(construction) @@ -58,7 +56,7 @@ BOOST_AUTO_TEST_CASE(exponentiation) BOOST_CHECK(audi::abs(res.find_cf({2}) - onethird * (onethird - 1.) * audi::pow(onethird, onethird - 2.) / 2.) < 1e-33); BOOST_CHECK(audi::abs(res.find_cf({3}) - - onethird * (onethird - 1.) * (onethird - 2.) * audi::pow(onethird, onethird - 3.) / 6.) + - onethird * (onethird - 1.) * (onethird - 2.) * audi::pow(onethird, onethird - 3.) / 6.) < 1e-33); // exponent is a double representable as integer @@ -79,10 +77,14 @@ BOOST_AUTO_TEST_CASE(exponentiation) BOOST_CHECK(audi::abs(res.find_cf({2}) - 3 * (3 - 1.) * audi::pow(onethird, 3 - 2) / 2.) < 1e-33); BOOST_CHECK(audi::abs(res.find_cf({3}) - 3 * (3 - 1.) * (3 - 2.) * audi::pow(onethird, 3 - 3) / 6.) < 1e-33); res = pow(x, -3); - BOOST_CHECK(audi::abs(res.find_cf({0}) - audi::pow(onethird, -3)) < 1e-32); // we check for absolute error, hence the precision loss - BOOST_CHECK(audi::abs(res.find_cf({1}) + 3 * audi::pow(onethird, -3 - 1)) < 1e-31); // we check for absolute error, hence the precision loss - BOOST_CHECK(audi::abs(res.find_cf({2}) + 3 * (-3 - 1) * audi::pow(onethird, -3 - 2) / 2) < 1e-30); // we check for absolute error, hence the precision loss - BOOST_CHECK(audi::abs(res.find_cf({3}) + 3 * (-3 - 1) * (-3 - 2) * audi::pow(onethird, -3 - 3) / 6) < 1e-29); // we check for absolute error, hence the precision loss + BOOST_CHECK(audi::abs(res.find_cf({0}) - audi::pow(onethird, -3)) + < 1e-32); // we check for absolute error, hence the precision loss + BOOST_CHECK(audi::abs(res.find_cf({1}) + 3 * audi::pow(onethird, -3 - 1)) + < 1e-31); // we check for absolute error, hence the precision loss + BOOST_CHECK(audi::abs(res.find_cf({2}) + 3 * (-3 - 1) * audi::pow(onethird, -3 - 2) / 2) + < 1e-30); // we check for absolute error, hence the precision loss + BOOST_CHECK(audi::abs(res.find_cf({3}) + 3 * (-3 - 1) * (-3 - 2) * audi::pow(onethird, -3 - 3) / 6) + < 1e-29); // we check for absolute error, hence the precision loss res = pow(x, 0); BOOST_CHECK(audi::abs(res.find_cf({0}) - 1 == 0)); @@ -95,10 +97,21 @@ BOOST_AUTO_TEST_CASE(exponentiation) mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; gdual_mp x{onethird, "x", 3}; auto res = pow(x, x); - BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.693361274350634704843352274785961795445935113457754036565863693400")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("-0.0683739421375531895286241688670376535021100832441426057588451227360656")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("1.043413166985674569326084555526740070128227383299088804220207359748035")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("-1.142713640471137873959384027190746725008973893684368645673060217249986")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({0}) + - mppp::real128("0.693361274350634704843352274785961795445935113457754036565863693400")) + < 1e-33); + BOOST_CHECK( + audi::abs(res.find_cf({1}) + - mppp::real128("-0.0683739421375531895286241688670376535021100832441426057588451227360656")) + < 1e-33); + BOOST_CHECK( + audi::abs(res.find_cf({2}) + - mppp::real128("1.043413166985674569326084555526740070128227383299088804220207359748035")) + < 1e-33); + BOOST_CHECK( + audi::abs(res.find_cf({3}) + - mppp::real128("-1.142713640471137873959384027190746725008973893684368645673060217249986")) + < 1e-33); } } BOOST_AUTO_TEST_CASE(sqrt_fun) @@ -107,10 +120,21 @@ BOOST_AUTO_TEST_CASE(sqrt_fun) mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; gdual_mp x{onethird, "x", 3}; auto res = sqrt(x); - BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.577350269189625764509148780501957455647601751270126876018602326484")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("0.8660254037844386467637231707529361834714026269051903140279034897263995")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("-0.6495190528383289850727923780647021376035519701788927355209276172954492")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("0.974278579257493477609188567097053206405327955268339103281391425944148")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({0}) + - mppp::real128("0.577350269189625764509148780501957455647601751270126876018602326484")) + < 1e-33); + BOOST_CHECK( + audi::abs(res.find_cf({1}) + - mppp::real128("0.8660254037844386467637231707529361834714026269051903140279034897263995")) + < 1e-33); + BOOST_CHECK( + audi::abs(res.find_cf({2}) + - mppp::real128("-0.6495190528383289850727923780647021376035519701788927355209276172954492")) + < 1e-33); + BOOST_CHECK( + audi::abs(res.find_cf({3}) + - mppp::real128("0.974278579257493477609188567097053206405327955268339103281391425944148")) + < 1e-33); } } BOOST_AUTO_TEST_CASE(cbrt_fun) @@ -119,35 +143,54 @@ BOOST_AUTO_TEST_CASE(cbrt_fun) mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; gdual_mp x{onethird, "x", 3}; auto res = cbrt(x); - BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.693361274350634704843352274785961795445935113457754036565863693400")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("0.6933612743506347048433522747859617954459351134577540365658636934004977")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("-0.693361274350634704843352274785961795445935113457754036565863693401191")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("1.155602123917724508072253791309936325743225189096256727609772822336474")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({0}) + - mppp::real128("0.693361274350634704843352274785961795445935113457754036565863693400")) + < 1e-33); + BOOST_CHECK( + audi::abs(res.find_cf({1}) + - mppp::real128("0.6933612743506347048433522747859617954459351134577540365658636934004977")) + < 1e-33); + BOOST_CHECK( + audi::abs(res.find_cf({2}) + - mppp::real128("-0.693361274350634704843352274785961795445935113457754036565863693401191")) + < 1e-33); + BOOST_CHECK( + audi::abs(res.find_cf({3}) + - mppp::real128("1.155602123917724508072253791309936325743225189096256727609772822336474")) + < 1e-33); } } BOOST_AUTO_TEST_CASE(trigonometric) { - //sine + // sine { mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; gdual_mp x{onethird, "x", 3}; auto res = sin(x); - BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.3271946967961522441733440852676206060643014")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("0.94495694631473766438828400767588060784585271047")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("-0.16359734839807612208667204263381030303215068770")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("-0.157492824385789610731380667945980101307642118412")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.3271946967961522441733440852676206060643014")) + < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("0.94495694631473766438828400767588060784585271047")) + < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("-0.16359734839807612208667204263381030303215068770")) + < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("-0.157492824385789610731380667945980101307642118412")) + < 1e-33); } - //cosine + // cosine { mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; gdual_mp x{onethird, "x", 3}; auto res = cos(x); - BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.9449569463147376643882840076758806078458527")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("-0.32719469679615224417334408526762060606430137540")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("-0.472478473157368832194142003837940303922926355236")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("0.054532449466025374028890680877936767677383562566")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.9449569463147376643882840076758806078458527")) + < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("-0.32719469679615224417334408526762060606430137540")) + < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("-0.472478473157368832194142003837940303922926355236")) + < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("0.054532449466025374028890680877936767677383562566")) + < 1e-33); } - //sincos + // sincos { mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; gdual_mp x{onethird, "x", 3}; @@ -155,15 +198,19 @@ BOOST_AUTO_TEST_CASE(trigonometric) BOOST_CHECK(res[0] == sin(x)); BOOST_CHECK(res[1] == cos(x)); } - //tan + // tan { mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; gdual_mp x{onethird, "x", 3}; auto res = tan(x); - BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.3462535495105754910385435656097407745957039")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("1.11989152054867255286971414281622406522119684361")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("0.38776641405677346168406834694334831426784259534")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("0.50756267076436951015232120845633638256350224970")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.3462535495105754910385435656097407745957039")) + < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("1.11989152054867255286971414281622406522119684361")) + < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("0.38776641405677346168406834694334831426784259534")) + < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("0.50756267076436951015232120845633638256350224970")) + < 1e-33); } // inverse functions { @@ -171,12 +218,12 @@ BOOST_AUTO_TEST_CASE(trigonometric) gdual_mp x{onethird, "x", 3}; BOOST_CHECK((sin(asin(x)) - x).trim(1e-34) == gdual_mp(0.)); BOOST_CHECK((asin(sin(x)) - x).trim(1e-34) == gdual_mp(0.)); - BOOST_CHECK((cos(acos(x)) - x).trim(1e-32) == gdual_mp(0.)); // in this computation we have an accumulating precision loss at high orders - BOOST_CHECK((acos(cos(x)) - x).trim(1e-32) == gdual_mp(0.)); // in this computation we have an accumulating precision loss at high orders + BOOST_CHECK((cos(acos(x)) - x).trim(1e-32) + == gdual_mp(0.)); // in this computation we have an accumulating precision loss at high orders + BOOST_CHECK((acos(cos(x)) - x).trim(1e-32) + == gdual_mp(0.)); // in this computation we have an accumulating precision loss at high orders BOOST_CHECK((tan(atan(x)) - x).trim(1e-34) == gdual_mp(0.)); BOOST_CHECK((atan(tan(x)) - x).trim(1e-33) == gdual_mp(0.)); - - } } BOOST_AUTO_TEST_CASE(hyperbolic) @@ -187,9 +234,12 @@ BOOST_AUTO_TEST_CASE(hyperbolic) gdual_mp x{onethird, "x", 3}; auto res = sinh(x); BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.339540557256150139101260611338603585072")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("1.0560718678299393895268647082639832525253961")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("0.1697702786280750695506303056693017925360226")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("0.17601197797165656492114411804399720875423268")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("1.0560718678299393895268647082639832525253961")) + < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("0.1697702786280750695506303056693017925360226")) + < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("0.17601197797165656492114411804399720875423268")) + < 1e-33); } // hyperbolic cosine { @@ -197,9 +247,12 @@ BOOST_AUTO_TEST_CASE(hyperbolic) gdual_mp x{onethird, "x", 3}; auto res = cosh(x); BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("1.056071867829939389526864708263983252525")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("0.3395405572561501391012606113386035850720452")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("0.52803593391496969476343235413199162626269805")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("0.05659009287602502318354343522310059751200753")) < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("0.3395405572561501391012606113386035850720452")) + < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("0.52803593391496969476343235413199162626269805")) + < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("0.05659009287602502318354343522310059751200753")) + < 1e-33); } // hyperbolic sine and cosine { @@ -209,25 +262,33 @@ BOOST_AUTO_TEST_CASE(hyperbolic) BOOST_CHECK(res[0] == sinh(x)); BOOST_CHECK(res[1] == cosh(x)); } - //hyperbolic tan + // hyperbolic tan { mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; gdual_mp x{onethird, "x", 3}; auto res = tanh(x); - BOOST_CHECK(audi::abs(res.find_cf({0}) - mppp::real128("0.3215127375316343447194062224252064660052920025020835116798050")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({1}) - mppp::real128("0.89662955960491440420948934034124973587445145348001949661874818114")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({2}) - mppp::real128("-0.28827782426035973712472569203365039113005161345723090151632152611")) < 1e-33); - BOOST_CHECK(audi::abs(res.find_cf({3}) - mppp::real128("-0.20619152742069314951779955121670628474663040144796586567125202883")) < 1e-33); - } + BOOST_CHECK(audi::abs(res.find_cf({0}) + - mppp::real128("0.3215127375316343447194062224252064660052920025020835116798050")) + < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({1}) + - mppp::real128("0.89662955960491440420948934034124973587445145348001949661874818114")) + < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({2}) + - mppp::real128("-0.28827782426035973712472569203365039113005161345723090151632152611")) + < 1e-33); + BOOST_CHECK(audi::abs(res.find_cf({3}) + - mppp::real128("-0.20619152742069314951779955121670628474663040144796586567125202883")) + < 1e-33); + } // hyperbolic inverse functions { mppp::real128 onethird{"1.33333333333333333333333333333333333333333333333"}; gdual_mp x{onethird, "x", 3}; BOOST_CHECK((sinh(asinh(x)) - x).trim(1e-33) == gdual_mp(0.)); BOOST_CHECK((asinh(sinh(x)) - x).trim(1e-33) == gdual_mp(0.)); - BOOST_CHECK((cosh(acosh(x)) - x).trim(1e-33) == gdual_mp(0.)); + BOOST_CHECK((cosh(acosh(x)) - x).trim(1e-33) == gdual_mp(0.)); BOOST_CHECK((acosh(cosh(x)) - x).trim(1e-33) == gdual_mp(0.)); - BOOST_CHECK((tanh(atanh(x-1)) - (x-1)).trim(1e-33) == gdual_mp(0.)); + BOOST_CHECK((tanh(atanh(x - 1)) - (x - 1)).trim(1e-33) == gdual_mp(0.)); BOOST_CHECK((atanh(tanh(x)) - x).trim(1e-33) == gdual_mp(0.)); } } From 6a8011797586b8116f8f2ba01f9e249f08860866 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Tue, 15 May 2018 18:29:29 +0200 Subject: [PATCH 20/61] python exposition of gdual_real128 --- include/audi/functions_from_d.hpp | 16 +++++----- include/audi/gdual.hpp | 3 +- include/audi/real128.hpp | 52 ++++++++++++++++++++++++++++++- pyaudi/core.cpp | 40 +++++++++++++++++++++--- pyaudi/expose_gdual.hpp | 33 ++++++++++++++++++-- tests/gdual_mp.cpp | 24 ++++++++++++++ 6 files changed, 150 insertions(+), 18 deletions(-) diff --git a/include/audi/functions_from_d.hpp b/include/audi/functions_from_d.hpp index e309910c..7a220c54 100644 --- a/include/audi/functions_from_d.hpp +++ b/include/audi/functions_from_d.hpp @@ -188,14 +188,14 @@ inline gdual erf(const gdual &d) auto dg = (2. / std::sqrt(boost::math::constants::pi())) * exp(-d * d); return _compose_from_derivative(d, dg, g0); } -//template <> -//inline gdual erf(const gdual &d) -//{ -// auto f0 = d.constant_cf(); -// auto g0 = audi::erf(f0); -// auto dg = (2. / audi::sqrt(mppp::real128_pi())) * exp(-d * d); -// return _compose_from_derivative(d, dg, g0); -//} +template <> +inline gdual erf(const gdual &d) +{ + auto f0 = d.constant_cf(); + auto g0 = audi::erf(f0); + auto dg = (2. / audi::sqrt(mppp::real128_pi())) * exp(-d * d); + return _compose_from_derivative(d, dg, g0); +} } // end of namespace audi diff --git a/include/audi/gdual.hpp b/include/audi/gdual.hpp index c4e40539..cd185a6c 100644 --- a/include/audi/gdual.hpp +++ b/include/audi/gdual.hpp @@ -250,8 +250,9 @@ class gdual } template = 0> - explicit gdual(const T &value) : m_p(value), m_order(0u) + explicit gdual(const T &value) : m_p(), m_order(0u) { + m_p += Cf(value); } template diff --git a/include/audi/real128.hpp b/include/audi/real128.hpp index 7200cef8..b7d1d3c0 100644 --- a/include/audi/real128.hpp +++ b/include/audi/real128.hpp @@ -6,15 +6,42 @@ #if defined(AUDI_WITH_MPPP) #include -#include +#include +#include +#include #include #include #include +#include +#include + #include + // This header adds to the mppp::real128 class the necessary methods that allow it to be // considered as a type in gdual (piranha::is_Cf, piranha::is_differentiable) +namespace boost +{ +namespace serialization +{ +template +void save(Archive &ar, const mppp::real128 &t, unsigned int version) +{ + std::string s(t.to_string()); + ar << s; +} +template +void load(Archive &ar, mppp::real128 &t, unsigned int version) +{ + std::string s; + ar >> s; + t = mppp::real128(s); +} +} // namespace serialization +} // namespace boost +BOOST_SERIALIZATION_SPLIT_FREE(mppp::real128) + namespace piranha { namespace math @@ -30,9 +57,32 @@ struct partial_impl { return mppp::real128{}; } }; + +template +struct pow_impl { + mppp::real128 operator()(const mppp::real128 &c, const U &exp) const + { + return mppp::pow(c, exp); + }; +}; } // namespace math + +template +struct boost_save_impl : boost_save_via_boost_api { +}; + +template +struct boost_load_impl : boost_load_via_boost_api { +}; + +template <> +struct zero_is_absorbing : std::false_type { +}; + } // namespace piranha + + #else #error The real128.hpp header was included but audi was not configured with the AUDI_WITH_MPPP option. diff --git a/pyaudi/core.cpp b/pyaudi/core.cpp index 9188130c..91ee34b7 100644 --- a/pyaudi/core.cpp +++ b/pyaudi/core.cpp @@ -3,6 +3,12 @@ #include #include +#include + +#if defined(AUDI_WITH_MPPP) +#include +#endif + #include #include #include @@ -32,92 +38,116 @@ BOOST_PYTHON_MODULE(core) return ::new gdual_v(pyaudi::l_to_v(value), symbol, order); })); - // We expose the gdual using the expose_gdual defined in exposed_gdual.hpp - // pyaudi::expose_gdual("real128"); +#if defined(AUDI_WITH_MPPP) + pyaudi::expose_gdual("real128"); +#endif // We expose the functions - bp::def("exp", +[](const gdual_d &d) { return exp(d); }, "Exponential (gdual_d)."); + bp::def("exp", +[](const gdual_d &d) { return exp(d); }, "Exponential (gdual_double)."); bp::def("exp", +[](double x) { return std::exp(x); }, "Exponential (double)."); - bp::def("exp", +[](const gdual_v &d) { return exp(d); }, "Exponential (gdual_v)."); + bp::def("exp", +[](const gdual_v &d) { return exp(d); }, "Exponential (gdual_vdouble)."); + bp::def("exp", +[](const gdual_mp &d) { return exp(d); }, "Exponential (gdual_real128)."); + bp::def("log", +[](const gdual_d &d) { return log(d); }, "Natural logarithm (gdual_d)."); bp::def("log", +[](double x) { return std::log(x); }, "Natural logarithm (double)."); bp::def("log", +[](const gdual_v &d) { return log(d); }, "Natural logarithm (gdual_v)."); + bp::def("log", +[](const gdual_mp &d) { return log(d); }, "Natural logarithm (gdual_real128)."); + bp::def("sqrt", +[](const gdual_d &d) { return sqrt(d); }, "Square root (gdual_d)."); bp::def("sqrt", +[](double x) { return std::sqrt(x); }, "Square root (double)."); bp::def("sqrt", +[](const gdual_v &d) { return sqrt(d); }, "Square root (gdual_v)."); + bp::def("sqrt", +[](const gdual_mp &d) { return sqrt(d); }, "Square root (gdual_real128)."); bp::def("cbrt", +[](const gdual_d &d) { return cbrt(d); }, "Cubic root (gdual_d)."); bp::def("cbrt", +[](double x) { return std::cbrt(x); }, "Cubic root (double)."); bp::def("cbrt", +[](const gdual_v &d) { return cbrt(d); }, "Cubic root (gdual_v)."); + bp::def("cbrt", +[](const gdual_mp &d) { return cbrt(d); }, "Cubic root (gdual_real128)."); bp::def("sin", +[](const gdual_d &d) { return sin(d); }, "Sine (gdual_d)."); bp::def("sin", +[](double x) { return std::sin(x); }, "Sine (double)."); bp::def("sin", +[](const gdual_v &d) { return sin(d); }, "Sine (gdual_v)."); - // bp::def("sin",py::vectorize(+[](double x) {return std::sin(x);}),"Sine (vectorized double)."); + bp::def("sin", +[](const gdual_mp &d) { return sin(d); }, "Sine (gdual_real128)."); bp::def("asin", +[](const gdual_d &d) { return asin(d); }, "Arc sine (gdual_d)."); bp::def("asin", +[](double x) { return std::asin(x); }, "Arc sine (double)."); bp::def("asin", +[](const gdual_v &d) { return asin(d); }, "Arc sine (gdual_v)."); + bp::def("asin", +[](const gdual_mp &d) { return asin(d); }, "Arc sine (gdual_real128)."); bp::def("cos", +[](const gdual_d &d) { return cos(d); }, "Cosine (gdual_d)."); bp::def("cos", +[](double x) { return std::cos(x); }, "Cosine (double)."); bp::def("cos", +[](const gdual_v &d) { return cos(d); }, "Cosine (gdual_v)."); + bp::def("cos", +[](const gdual_mp &d) { return cos(d); }, "Cosine (gdual_real128)."); bp::def("acos", +[](const gdual_d &d) { return acos(d); }, "Arc cosine (gdual_d)."); bp::def("acos", +[](double x) { return std::acos(x); }, "Arc cosine (double)."); bp::def("acos", +[](const gdual_v &d) { return acos(d); }, "Arc cosine (gdual_v)."); + bp::def("acos", +[](const gdual_mp &d) { return acos(d); }, "Arc cosine (gdual_real128)."); bp::def("sin_and_cos", +[](const gdual_d &d) { return pyaudi::v_to_l(sin_and_cos(d)); }, "Sine and Cosine at once (gdual_d)."); bp::def("sin_and_cos", +[](const gdual_v &d) { return pyaudi::v_to_l(sin_and_cos(d)); }, "Sine and Cosine at once (gdual_v)."); + bp::def("sin_and_cos", +[](const gdual_mp &d) { return pyaudi::v_to_l(sin_and_cos(d)); }, + "Sine and Cosine at once (gdual_real128)."); bp::def("tan", +[](const gdual_d &d) { return tan(d); }, "Tangent (gdual_d)."); bp::def("tan", +[](double x) { return std::tan(x); }, "Tangent (double)."); bp::def("tan", +[](const gdual_v &d) { return tan(d); }, "Tangent (gdual_v)."); + bp::def("tan", +[](const gdual_mp &d) { return tan(d); }, "Tangent (gdual_real128)."); bp::def("atan", +[](const gdual_d &d) { return atan(d); }, "Arc tangent (gdual_d)."); bp::def("atan", +[](double x) { return std::atan(x); }, "Arc tangent (double)."); bp::def("atan", +[](const gdual_v &d) { return atan(d); }, "Arc tangent (gdual_v)."); + bp::def("atan", +[](const gdual_mp &d) { return atan(d); }, "Arc tangent (gdual_real128)."); bp::def("sinh", +[](const gdual_d &d) { return sinh(d); }, "Hyperbolic sine (gdual_d)."); bp::def("sinh", +[](double x) { return std::sinh(x); }, "Hyperbolic sine (double)."); bp::def("sinh", +[](const gdual_v &d) { return sinh(d); }, "Hyperbolic sine (gdual_v)."); + bp::def("sinh", +[](const gdual_mp &d) { return sinh(d); }, "Hyperbolic sine (gdual_real128)."); bp::def("asinh", +[](const gdual_d &d) { return asinh(d); }, "Inverse hyperbolic sine (gdual_d)."); bp::def("asinh", +[](double x) { return std::asinh(x); }, "Inverse hyperbolic sine (double)."); bp::def("asinh", +[](const gdual_v &d) { return asinh(d); }, "Inverse hyperbolic sine (gdual_v)."); + bp::def("asinh", +[](const gdual_mp &d) { return asinh(d); }, "Inverse hyperbolic sine (gdual_real128)."); bp::def("cosh", +[](const gdual_d &d) { return cosh(d); }, "Hyperbolic cosine (gdual_d)."); bp::def("cosh", +[](double x) { return std::cosh(x); }, "Hyperbolic cosine (double)."); bp::def("cosh", +[](const gdual_v &d) { return cosh(d); }, "Hyperbolic cosine (gdual_v)."); + bp::def("cosh", +[](const gdual_mp &d) { return cosh(d); }, "Hyperbolic cosine (gdual_real128)."); bp::def("acosh", +[](const gdual_d &d) { return acosh(d); }, "Inverse hyperbolic cosine (gdual_d)."); bp::def("acosh", +[](double x) { return std::acosh(x); }, "Inverse hyperbolic cosine (double)."); bp::def("acosh", +[](const gdual_v &d) { return acosh(d); }, "Inverse hyperbolic cosine (gdual_v)."); + bp::def("acosh", +[](const gdual_mp &d) { return acosh(d); }, "Inverse hyperbolic cosine (gdual_real128)."); bp::def("sinh_and_cosh", +[](const gdual_d &d) { return pyaudi::v_to_l(sinh_and_cosh(d)); }, "Hyperbolic sine and hyperbolic cosine at once (gdual_d)."); bp::def("sinh_and_cosh", +[](const gdual_v &d) { return pyaudi::v_to_l(sinh_and_cosh(d)); }, "Hyperbolic sine and hyperbolic cosine at once (gdual_v)."); + bp::def("sinh_and_cosh", +[](const gdual_mp &d) { return pyaudi::v_to_l(sinh_and_cosh(d)); }, + "Hyperbolic sine and hyperbolic cosine at once (gdual_real128)."); bp::def("tanh", +[](const gdual_d &d) { return tanh(d); }, "Hyperbolic tangent (gdual_d)."); bp::def("tanh", +[](double x) { return std::tanh(x); }, "Hyperbolic tangent (double)."); bp::def("tanh", +[](const gdual_v &d) { return tanh(d); }, "Hyperbolic tangent (gdual_v)."); + bp::def("tanh", +[](const gdual_mp &d) { return tanh(d); }, "Hyperbolic tangent (gdual_real128)."); bp::def("atanh", +[](const gdual_d &d) { return atanh(d); }, "Inverse hyperbolic arc tangent (gdual_d)."); bp::def("atanh", +[](double x) { return std::atanh(x); }, "Inverse hyperbolic arc tangent (double)."); bp::def("atanh", +[](const gdual_v &d) { return atanh(d); }, "Inverse hyperbolic arc tangent (gdual_v)."); + bp::def("atanh", +[](const gdual_mp &d) { return atanh(d); }, "Inverse hyperbolic arc tangent (gdual_real128)."); bp::def("abs", +[](const gdual_d &d) { return abs(d); }, "Absolute value (gdual_d)."); bp::def("abs", +[](double x) { return std::abs(x); }, "Absolute value (double)."); bp::def("abs", +[](const gdual_v &d) { return abs(d); }, "Absolute value (gdual_v)."); + bp::def("abs", +[](const gdual_mp &d) { return abs(d); }, "Absolute value (gdual_real128)."); bp::def("erf", +[](const gdual_d &d) { return erf(d); }, "Error function (gdual_d)."); bp::def("erf", +[](double x) { return std::erf(x); }, "Error function (double)."); bp::def("erf", +[](const gdual_v &d) { return erf(d); }, "Error function (gdual_v)."); + bp::def("erf", +[](const gdual_mp &d) { return erf(d); }, "Error function (gdual_real128)."); bp::def("invert_map", +[](const bp::object &map_in, bool verbose) { diff --git a/pyaudi/expose_gdual.hpp b/pyaudi/expose_gdual.hpp index 1870cfb2..d395480c 100644 --- a/pyaudi/expose_gdual.hpp +++ b/pyaudi/expose_gdual.hpp @@ -1,6 +1,10 @@ #ifndef AUDI_EXPOSE_GDUAL_H #define AUDI_EXPOSE_GDUAL_H +#if defined(AUDI_WITH_MPPP) +#include +#endif + #include #include #include @@ -64,7 +68,7 @@ struct gdual_pickle_suite : bp::pickle_suite { // For non vectorized_double we do not perform any conversion on in-out types template ::value, int> = 0> -inline void expose_T_dependent_stuff(bp::class_> th) +inline void expose_subs(bp::class_> th) { th.def("subs", +[](gdual &gd, const std::string &sym, const T &in) { return gd.subs(sym, in); }, "Substitutes a symbol with a value (does not remove symbol from symbol set)"); @@ -72,7 +76,7 @@ inline void expose_T_dependent_stuff(bp::class_> th) // For vectorized double we perform conversion from and to lists so we need a different active template template ::value, int> = 0> -inline void expose_T_dependent_stuff(bp::class_> th) +inline void expose_subs(bp::class_> th) { th.def( "subs", @@ -80,6 +84,28 @@ inline void expose_T_dependent_stuff(bp::class_> th) "Substitutes a symbol with a value (does not remove symbol from symbol set)"); } +#if defined(AUDI_WITH_MPPP) +// For mppp::real128 we expose additional constructors using a string representation of the values +template ::value, int> = 0> +inline void expose_additional_constructors(bp::class_> th) +{ + th.def(bp::init()); + th.def(bp::init()); + th.def(bp::init()); + th.def(bp::init()); +} + +// For !mppp::real128 we expose additional constructors using a string representation of the values +template ::value, int> = 0> +inline void expose_additional_constructors(bp::class_> th) +{ +} +#else +template +inline void expose_additional_constructors(bp::class_> th) +{ +} +#endif // This is the interface common across types template bp::class_> expose_gdual(std::string type) @@ -177,7 +203,8 @@ bp::class_> expose_gdual(std::string type) }, "Finds the derivative (i.e. the coefficient of the Taylor expansion discounted by the factorial " "factor"); - expose_T_dependent_stuff(th); + expose_subs(th); + expose_additional_constructors(th); return th; } } diff --git a/tests/gdual_mp.cpp b/tests/gdual_mp.cpp index 5fccec65..a0ff15e3 100644 --- a/tests/gdual_mp.cpp +++ b/tests/gdual_mp.cpp @@ -292,3 +292,27 @@ BOOST_AUTO_TEST_CASE(hyperbolic) BOOST_CHECK((atanh(tanh(x)) - x).trim(1e-33) == gdual_mp(0.)); } } + +BOOST_AUTO_TEST_CASE(erf_fun) +{ + { + mppp::real128 onethird{"0.33333333333333333333333333333333333333333333333"}; + gdual_mp x{onethird, "x", 3}; + auto res = erf(x); + BOOST_CHECK(audi::abs(res.find_cf({0}) + - mppp::real128("0.362648111766062933408178640147865879692141590372537239240")) + < 1e-33); + BOOST_CHECK( + audi::abs(res.find_cf({1}) + - mppp::real128("1.00971804299131606624460336666642604033678715687395758256805086446851098")) + < 1e-33); + BOOST_CHECK( + audi::abs(res.find_cf({2}) + - mppp::real128("-0.33657268099710535541486778888880868011226238562465252752268362148947000")) + < 1e-33); + BOOST_CHECK( + audi::abs(res.find_cf({3}) + - mppp::real128("-0.26177875188663749865600828024685119564287074437472974362875392782518447")) + < 1e-33); + } +} From 8f1e437cc5e4e4fa07c0bf9ed78abd7837486b19 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Wed, 16 May 2018 11:52:59 +0200 Subject: [PATCH 21/61] more elegance and consistency --- include/audi/gdual.hpp | 12 +-- pyaudi/core.cpp | 172 +++++++++++++++++++--------------------- pyaudi/expose_gdual.hpp | 25 +----- 3 files changed, 90 insertions(+), 119 deletions(-) diff --git a/include/audi/gdual.hpp b/include/audi/gdual.hpp index cd185a6c..d91c0981 100644 --- a/include/audi/gdual.hpp +++ b/include/audi/gdual.hpp @@ -72,7 +72,7 @@ class gdual // Static checks. static_assert( piranha::is_cf::value && piranha::is_differentiable::value, - "A gdual must be constructed froma coefficient satisfying piranha's conditions is_cf and is_differentiable."); + "A gdual must be constructed from a coefficient satisfying piranha's conditions is_cf and is_differentiable."); public: using cf_type = Cf; @@ -592,9 +592,9 @@ class gdual template auto get_derivative(const T &c) const -> decltype(m_p.find_cf(c)) { - double cumfact = 1; + double cumfact = 1.; for (auto i = c.begin(); i < c.end(); ++i) { - cumfact *= boost::math::factorial(static_cast(*i)); + cumfact *= boost::math::factorial(static_cast(*i)); } return this->find_cf(c) * cumfact; } @@ -618,9 +618,9 @@ class gdual template auto get_derivative(std::initializer_list l) const -> decltype(m_p.find_cf(l)) { - double cumfact = 1; + double cumfact = 1.; for (auto i = l.begin(); i < l.end(); ++i) { - cumfact *= boost::math::factorial((unsigned int)(*i)); + cumfact *= boost::math::factorial((unsigned)(*i)); } return this->find_cf(l) * cumfact; } @@ -642,7 +642,7 @@ class gdual * @throws unspecified all exceptions thrown by the templated version call. * @throws std::invalid_argument: if one of the symbols is not found in the expression */ - auto get_derivative(const std::unordered_map &dict) const + auto get_derivative(const std::unordered_map &dict) const -> decltype(std::declval().get_derivative(std::vector{})) { const auto &ss = m_p.get_symbol_set(); diff --git a/pyaudi/core.cpp b/pyaudi/core.cpp index 91ee34b7..a3470c76 100644 --- a/pyaudi/core.cpp +++ b/pyaudi/core.cpp @@ -25,11 +25,32 @@ BOOST_PYTHON_MODULE(core) // expose gdual) bp::to_python_converter(); - // We expose the gdual using the expose_gdual defined in exposed_gdual.hpp + // We expose the gdual arithmetic pyaudi::expose_gdual("double"); + bp::def("exp", +[](const gdual_d &d) { return exp(d); }, "Exponential (gdual_double)."); + bp::def("log", +[](const gdual_d &d) { return log(d); }, "Natural logarithm (gdual_d)."); + bp::def("sqrt", +[](const gdual_d &d) { return sqrt(d); }, "Square root (gdual_d)."); + bp::def("cbrt", +[](const gdual_d &d) { return cbrt(d); }, "Cubic root (gdual_d)."); + bp::def("sin", +[](const gdual_d &d) { return sin(d); }, "Sine (gdual_d)."); + bp::def("asin", +[](const gdual_d &d) { return asin(d); }, "Arc sine (gdual_d)."); + bp::def("cos", +[](const gdual_d &d) { return cos(d); }, "Cosine (gdual_d)."); + bp::def("acos", +[](const gdual_d &d) { return acos(d); }, "Arc cosine (gdual_d)."); + bp::def("sin_and_cos", +[](const gdual_d &d) { return pyaudi::v_to_l(sin_and_cos(d)); }, + "Sine and Cosine at once (gdual_d)."); + bp::def("tan", +[](const gdual_d &d) { return tan(d); }, "Tangent (gdual_d)."); + bp::def("atan", +[](const gdual_d &d) { return atan(d); }, "Arc tangent (gdual_d)."); + bp::def("sinh", +[](const gdual_d &d) { return sinh(d); }, "Hyperbolic sine (gdual_d)."); + bp::def("asinh", +[](const gdual_d &d) { return asinh(d); }, "Inverse hyperbolic sine (gdual_d)."); + bp::def("cosh", +[](const gdual_d &d) { return cosh(d); }, "Hyperbolic cosine (gdual_d)."); + bp::def("acosh", +[](const gdual_d &d) { return acosh(d); }, "Inverse hyperbolic cosine (gdual_d)."); + bp::def("sinh_and_cosh", +[](const gdual_d &d) { return pyaudi::v_to_l(sinh_and_cosh(d)); }, + "Hyperbolic sine and hyperbolic cosine at once (gdual_d)."); + bp::def("tanh", +[](const gdual_d &d) { return tanh(d); }, "Hyperbolic tangent (gdual_d)."); + bp::def("atanh", +[](const gdual_d &d) { return atanh(d); }, "Inverse hyperbolic arc tangent (gdual_d)."); + bp::def("abs", +[](const gdual_d &d) { return abs(d); }, "Absolute value (gdual_d)."); + bp::def("erf", +[](const gdual_d &d) { return erf(d); }, "Error function (gdual_d)."); - // Similarly, we expose the gdual and we add two custom constructors to allow constructing it - // from lists + // We expose the gdual arithmetic pyaudi::expose_gdual("vdouble") .def("__init__", bp::make_constructor( +[](const bp::object &value) { return ::new gdual_v(pyaudi::l_to_v(value)); })) @@ -37,118 +58,91 @@ BOOST_PYTHON_MODULE(core) bp::make_constructor(+[](const bp::object &value, const std::string &symbol, unsigned int order) { return ::new gdual_v(pyaudi::l_to_v(value), symbol, order); })); - -#if defined(AUDI_WITH_MPPP) - pyaudi::expose_gdual("real128"); -#endif - - // We expose the functions - bp::def("exp", +[](const gdual_d &d) { return exp(d); }, "Exponential (gdual_double)."); - bp::def("exp", +[](double x) { return std::exp(x); }, "Exponential (double)."); bp::def("exp", +[](const gdual_v &d) { return exp(d); }, "Exponential (gdual_vdouble)."); - bp::def("exp", +[](const gdual_mp &d) { return exp(d); }, "Exponential (gdual_real128)."); - - - bp::def("log", +[](const gdual_d &d) { return log(d); }, "Natural logarithm (gdual_d)."); - bp::def("log", +[](double x) { return std::log(x); }, "Natural logarithm (double)."); bp::def("log", +[](const gdual_v &d) { return log(d); }, "Natural logarithm (gdual_v)."); - bp::def("log", +[](const gdual_mp &d) { return log(d); }, "Natural logarithm (gdual_real128)."); - - - bp::def("sqrt", +[](const gdual_d &d) { return sqrt(d); }, "Square root (gdual_d)."); - bp::def("sqrt", +[](double x) { return std::sqrt(x); }, "Square root (double)."); bp::def("sqrt", +[](const gdual_v &d) { return sqrt(d); }, "Square root (gdual_v)."); - bp::def("sqrt", +[](const gdual_mp &d) { return sqrt(d); }, "Square root (gdual_real128)."); - - bp::def("cbrt", +[](const gdual_d &d) { return cbrt(d); }, "Cubic root (gdual_d)."); - bp::def("cbrt", +[](double x) { return std::cbrt(x); }, "Cubic root (double)."); bp::def("cbrt", +[](const gdual_v &d) { return cbrt(d); }, "Cubic root (gdual_v)."); - bp::def("cbrt", +[](const gdual_mp &d) { return cbrt(d); }, "Cubic root (gdual_real128)."); - - bp::def("sin", +[](const gdual_d &d) { return sin(d); }, "Sine (gdual_d)."); - bp::def("sin", +[](double x) { return std::sin(x); }, "Sine (double)."); bp::def("sin", +[](const gdual_v &d) { return sin(d); }, "Sine (gdual_v)."); - bp::def("sin", +[](const gdual_mp &d) { return sin(d); }, "Sine (gdual_real128)."); - - bp::def("asin", +[](const gdual_d &d) { return asin(d); }, "Arc sine (gdual_d)."); - bp::def("asin", +[](double x) { return std::asin(x); }, "Arc sine (double)."); bp::def("asin", +[](const gdual_v &d) { return asin(d); }, "Arc sine (gdual_v)."); - bp::def("asin", +[](const gdual_mp &d) { return asin(d); }, "Arc sine (gdual_real128)."); - - bp::def("cos", +[](const gdual_d &d) { return cos(d); }, "Cosine (gdual_d)."); - bp::def("cos", +[](double x) { return std::cos(x); }, "Cosine (double)."); bp::def("cos", +[](const gdual_v &d) { return cos(d); }, "Cosine (gdual_v)."); - bp::def("cos", +[](const gdual_mp &d) { return cos(d); }, "Cosine (gdual_real128)."); - - bp::def("acos", +[](const gdual_d &d) { return acos(d); }, "Arc cosine (gdual_d)."); - bp::def("acos", +[](double x) { return std::acos(x); }, "Arc cosine (double)."); bp::def("acos", +[](const gdual_v &d) { return acos(d); }, "Arc cosine (gdual_v)."); - bp::def("acos", +[](const gdual_mp &d) { return acos(d); }, "Arc cosine (gdual_real128)."); - - bp::def("sin_and_cos", +[](const gdual_d &d) { return pyaudi::v_to_l(sin_and_cos(d)); }, - "Sine and Cosine at once (gdual_d)."); bp::def("sin_and_cos", +[](const gdual_v &d) { return pyaudi::v_to_l(sin_and_cos(d)); }, "Sine and Cosine at once (gdual_v)."); - bp::def("sin_and_cos", +[](const gdual_mp &d) { return pyaudi::v_to_l(sin_and_cos(d)); }, - "Sine and Cosine at once (gdual_real128)."); - - bp::def("tan", +[](const gdual_d &d) { return tan(d); }, "Tangent (gdual_d)."); - bp::def("tan", +[](double x) { return std::tan(x); }, "Tangent (double)."); bp::def("tan", +[](const gdual_v &d) { return tan(d); }, "Tangent (gdual_v)."); - bp::def("tan", +[](const gdual_mp &d) { return tan(d); }, "Tangent (gdual_real128)."); - - bp::def("atan", +[](const gdual_d &d) { return atan(d); }, "Arc tangent (gdual_d)."); - bp::def("atan", +[](double x) { return std::atan(x); }, "Arc tangent (double)."); bp::def("atan", +[](const gdual_v &d) { return atan(d); }, "Arc tangent (gdual_v)."); - bp::def("atan", +[](const gdual_mp &d) { return atan(d); }, "Arc tangent (gdual_real128)."); - - bp::def("sinh", +[](const gdual_d &d) { return sinh(d); }, "Hyperbolic sine (gdual_d)."); - bp::def("sinh", +[](double x) { return std::sinh(x); }, "Hyperbolic sine (double)."); bp::def("sinh", +[](const gdual_v &d) { return sinh(d); }, "Hyperbolic sine (gdual_v)."); - bp::def("sinh", +[](const gdual_mp &d) { return sinh(d); }, "Hyperbolic sine (gdual_real128)."); - - bp::def("asinh", +[](const gdual_d &d) { return asinh(d); }, "Inverse hyperbolic sine (gdual_d)."); - bp::def("asinh", +[](double x) { return std::asinh(x); }, "Inverse hyperbolic sine (double)."); bp::def("asinh", +[](const gdual_v &d) { return asinh(d); }, "Inverse hyperbolic sine (gdual_v)."); - bp::def("asinh", +[](const gdual_mp &d) { return asinh(d); }, "Inverse hyperbolic sine (gdual_real128)."); - - bp::def("cosh", +[](const gdual_d &d) { return cosh(d); }, "Hyperbolic cosine (gdual_d)."); - bp::def("cosh", +[](double x) { return std::cosh(x); }, "Hyperbolic cosine (double)."); bp::def("cosh", +[](const gdual_v &d) { return cosh(d); }, "Hyperbolic cosine (gdual_v)."); - bp::def("cosh", +[](const gdual_mp &d) { return cosh(d); }, "Hyperbolic cosine (gdual_real128)."); - - bp::def("acosh", +[](const gdual_d &d) { return acosh(d); }, "Inverse hyperbolic cosine (gdual_d)."); - bp::def("acosh", +[](double x) { return std::acosh(x); }, "Inverse hyperbolic cosine (double)."); bp::def("acosh", +[](const gdual_v &d) { return acosh(d); }, "Inverse hyperbolic cosine (gdual_v)."); - bp::def("acosh", +[](const gdual_mp &d) { return acosh(d); }, "Inverse hyperbolic cosine (gdual_real128)."); + bp::def("tanh", +[](const gdual_v &d) { return tanh(d); }, "Hyperbolic tangent (gdual_v)."); + bp::def("atanh", +[](const gdual_v &d) { return atanh(d); }, "Inverse hyperbolic arc tangent (gdual_v)."); + bp::def("abs", +[](const gdual_v &d) { return abs(d); }, "Absolute value (gdual_v)."); + bp::def("erf", +[](const gdual_v &d) { return erf(d); }, "Error function (gdual_v)."); - bp::def("sinh_and_cosh", +[](const gdual_d &d) { return pyaudi::v_to_l(sinh_and_cosh(d)); }, - "Hyperbolic sine and hyperbolic cosine at once (gdual_d)."); + // We expose simple mathematical functions to work on python floats + bp::def("exp", +[](double x) { return std::exp(x); }, "Exponential (double)."); + bp::def("log", +[](double x) { return std::log(x); }, "Natural logarithm (double)."); + bp::def("sqrt", +[](double x) { return std::sqrt(x); }, "Square root (double)."); + bp::def("cbrt", +[](double x) { return std::cbrt(x); }, "Cubic root (double)."); + bp::def("sin", +[](double x) { return std::sin(x); }, "Sine (double)."); + bp::def("asin", +[](double x) { return std::asin(x); }, "Arc sine (double)."); + bp::def("cos", +[](double x) { return std::cos(x); }, "Cosine (double)."); + bp::def("acos", +[](double x) { return std::acos(x); }, "Arc cosine (double)."); + bp::def("tan", +[](double x) { return std::tan(x); }, "Tangent (double)."); + bp::def("atan", +[](double x) { return std::atan(x); }, "Arc tangent (double)."); + bp::def("sinh", +[](double x) { return std::sinh(x); }, "Hyperbolic sine (double)."); + bp::def("asinh", +[](double x) { return std::asinh(x); }, "Inverse hyperbolic sine (double)."); + bp::def("cosh", +[](double x) { return std::cosh(x); }, "Hyperbolic cosine (double)."); + bp::def("acosh", +[](double x) { return std::acosh(x); }, "Inverse hyperbolic cosine (double)."); bp::def("sinh_and_cosh", +[](const gdual_v &d) { return pyaudi::v_to_l(sinh_and_cosh(d)); }, "Hyperbolic sine and hyperbolic cosine at once (gdual_v)."); + bp::def("tanh", +[](double x) { return std::tanh(x); }, "Hyperbolic tangent (double)."); + bp::def("atanh", +[](double x) { return std::atanh(x); }, "Inverse hyperbolic arc tangent (double)."); + bp::def("abs", +[](double x) { return std::abs(x); }, "Absolute value (double)."); + bp::def("erf", +[](double x) { return std::erf(x); }, "Error function (double)."); + +//#if defined(AUDI_WITH_MPPP) + // We expose the mppp::real128 class + bp::class_("real128", "Multiple precision float (a wrapper around __float128)") + .def(bp::init()) + .def("__repr__", + +[](const mppp::real128 &g) -> std::string { + std::ostringstream oss; + oss << g; + return oss.str(); + }); + + // We expose the gdual arithmetic + pyaudi::expose_gdual("real128") + .def(bp::init()) + .def(bp::init()) + .def(bp::init()) + .def(bp::init()); + bp::def("exp", +[](const gdual_mp &d) { return exp(d); }, "Exponential (gdual_real128)."); + bp::def("log", +[](const gdual_mp &d) { return log(d); }, "Natural logarithm (gdual_real128)."); + bp::def("sqrt", +[](const gdual_mp &d) { return sqrt(d); }, "Square root (gdual_real128)."); + bp::def("cbrt", +[](const gdual_mp &d) { return cbrt(d); }, "Cubic root (gdual_real128)."); + bp::def("sin", +[](const gdual_mp &d) { return sin(d); }, "Sine (gdual_real128)."); + bp::def("asin", +[](const gdual_mp &d) { return asin(d); }, "Arc sine (gdual_real128)."); + bp::def("cos", +[](const gdual_mp &d) { return cos(d); }, "Cosine (gdual_real128)."); + bp::def("acos", +[](const gdual_mp &d) { return acos(d); }, "Arc cosine (gdual_real128)."); + bp::def("sin_and_cos", +[](const gdual_mp &d) { return pyaudi::v_to_l(sin_and_cos(d)); }, + "Sine and Cosine at once (gdual_real128)."); + bp::def("tan", +[](const gdual_mp &d) { return tan(d); }, "Tangent (gdual_real128)."); + bp::def("atan", +[](const gdual_mp &d) { return atan(d); }, "Arc tangent (gdual_real128)."); + bp::def("sinh", +[](const gdual_mp &d) { return sinh(d); }, "Hyperbolic sine (gdual_real128)."); + bp::def("asinh", +[](const gdual_mp &d) { return asinh(d); }, "Inverse hyperbolic sine (gdual_real128)."); + bp::def("cosh", +[](const gdual_mp &d) { return cosh(d); }, "Hyperbolic cosine (gdual_real128)."); + bp::def("acosh", +[](const gdual_mp &d) { return acosh(d); }, "Inverse hyperbolic cosine (gdual_real128)."); bp::def("sinh_and_cosh", +[](const gdual_mp &d) { return pyaudi::v_to_l(sinh_and_cosh(d)); }, "Hyperbolic sine and hyperbolic cosine at once (gdual_real128)."); - - bp::def("tanh", +[](const gdual_d &d) { return tanh(d); }, "Hyperbolic tangent (gdual_d)."); - bp::def("tanh", +[](double x) { return std::tanh(x); }, "Hyperbolic tangent (double)."); - bp::def("tanh", +[](const gdual_v &d) { return tanh(d); }, "Hyperbolic tangent (gdual_v)."); bp::def("tanh", +[](const gdual_mp &d) { return tanh(d); }, "Hyperbolic tangent (gdual_real128)."); - - bp::def("atanh", +[](const gdual_d &d) { return atanh(d); }, "Inverse hyperbolic arc tangent (gdual_d)."); - bp::def("atanh", +[](double x) { return std::atanh(x); }, "Inverse hyperbolic arc tangent (double)."); - bp::def("atanh", +[](const gdual_v &d) { return atanh(d); }, "Inverse hyperbolic arc tangent (gdual_v)."); bp::def("atanh", +[](const gdual_mp &d) { return atanh(d); }, "Inverse hyperbolic arc tangent (gdual_real128)."); - - bp::def("abs", +[](const gdual_d &d) { return abs(d); }, "Absolute value (gdual_d)."); - bp::def("abs", +[](double x) { return std::abs(x); }, "Absolute value (double)."); - bp::def("abs", +[](const gdual_v &d) { return abs(d); }, "Absolute value (gdual_v)."); bp::def("abs", +[](const gdual_mp &d) { return abs(d); }, "Absolute value (gdual_real128)."); - - bp::def("erf", +[](const gdual_d &d) { return erf(d); }, "Error function (gdual_d)."); - bp::def("erf", +[](double x) { return std::erf(x); }, "Error function (double)."); - bp::def("erf", +[](const gdual_v &d) { return erf(d); }, "Error function (gdual_v)."); bp::def("erf", +[](const gdual_mp &d) { return erf(d); }, "Error function (gdual_real128)."); +//#endif + // Miscellanea functions bp::def("invert_map", +[](const bp::object &map_in, bool verbose) { return pyaudi::v_to_l(invert_map(pyaudi::l_to_v(map_in), verbose)); diff --git a/pyaudi/expose_gdual.hpp b/pyaudi/expose_gdual.hpp index d395480c..15a4219b 100644 --- a/pyaudi/expose_gdual.hpp +++ b/pyaudi/expose_gdual.hpp @@ -84,28 +84,6 @@ inline void expose_subs(bp::class_> th) "Substitutes a symbol with a value (does not remove symbol from symbol set)"); } -#if defined(AUDI_WITH_MPPP) -// For mppp::real128 we expose additional constructors using a string representation of the values -template ::value, int> = 0> -inline void expose_additional_constructors(bp::class_> th) -{ - th.def(bp::init()); - th.def(bp::init()); - th.def(bp::init()); - th.def(bp::init()); -} - -// For !mppp::real128 we expose additional constructors using a string representation of the values -template ::value, int> = 0> -inline void expose_additional_constructors(bp::class_> th) -{ -} -#else -template -inline void expose_additional_constructors(bp::class_> th) -{ -} -#endif // This is the interface common across types template bp::class_> expose_gdual(std::string type) @@ -199,12 +177,11 @@ bp::class_> expose_gdual(std::string type) "factor") .def("get_derivative", +[](const gdual &g, const bp::dict &pydict) { - return g.get_derivative(pydict_to_umap(pydict)); + return g.get_derivative(pydict_to_umap(pydict)); }, "Finds the derivative (i.e. the coefficient of the Taylor expansion discounted by the factorial " "factor"); expose_subs(th); - expose_additional_constructors(th); return th; } } From c4646836522212713493c9905412d75b6d3a6744 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Wed, 16 May 2018 14:49:20 +0200 Subject: [PATCH 22/61] cosmetics --- include/audi/gdual.hpp | 2 +- pyaudi/core.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/audi/gdual.hpp b/include/audi/gdual.hpp index d91c0981..7a5b90b3 100644 --- a/include/audi/gdual.hpp +++ b/include/audi/gdual.hpp @@ -634,7 +634,7 @@ class gdual * the input should be {{"dx", 1u},{"dy",3u},{"dz",2u}} * * \note The current implementation call internally the other templated - * implementations. WHen piranha will implement the sparse monomial + * implementations. When piranha will implement the sparse monomial * this will change and be more efficient. * * @return the value of the derivative diff --git a/pyaudi/core.cpp b/pyaudi/core.cpp index a3470c76..4a053eaf 100644 --- a/pyaudi/core.cpp +++ b/pyaudi/core.cpp @@ -101,7 +101,7 @@ BOOST_PYTHON_MODULE(core) bp::def("abs", +[](double x) { return std::abs(x); }, "Absolute value (double)."); bp::def("erf", +[](double x) { return std::erf(x); }, "Error function (double)."); -//#if defined(AUDI_WITH_MPPP) +#if defined(AUDI_WITH_MPPP) // We expose the mppp::real128 class bp::class_("real128", "Multiple precision float (a wrapper around __float128)") .def(bp::init()) @@ -140,7 +140,7 @@ BOOST_PYTHON_MODULE(core) bp::def("atanh", +[](const gdual_mp &d) { return atanh(d); }, "Inverse hyperbolic arc tangent (gdual_real128)."); bp::def("abs", +[](const gdual_mp &d) { return abs(d); }, "Absolute value (gdual_real128)."); bp::def("erf", +[](const gdual_mp &d) { return erf(d); }, "Error function (gdual_real128)."); -//#endif +#endif // Miscellanea functions bp::def("invert_map", From 8b478b22567b868103c226cc5829fbdcb57a8386 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Wed, 16 May 2018 16:43:28 +0200 Subject: [PATCH 23/61] real128 python exposition finished --- pyaudi/core.cpp | 53 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/pyaudi/core.cpp b/pyaudi/core.cpp index 4a053eaf..1a94b53c 100644 --- a/pyaudi/core.cpp +++ b/pyaudi/core.cpp @@ -102,15 +102,39 @@ BOOST_PYTHON_MODULE(core) bp::def("erf", +[](double x) { return std::erf(x); }, "Error function (double)."); #if defined(AUDI_WITH_MPPP) - // We expose the mppp::real128 class - bp::class_("real128", "Multiple precision float (a wrapper around __float128)") + // We expose the mppp::real128 class. NOTE: using boost::shared_ptr as holder is necessary for proper alignement of __float128 by boost. + // Otherwise: segfault. + // See http://webcache.googleusercontent.com/search?q=cache:xhGhABO-W58J:fhtagn.net/prog/2015/04/16/quaternion_boost_python.html&num=1&client=firefox-b&hl=en&gl=de&strip=1&vwsrc=0 + bp::class_>("real128", "Multiple precision float (a wrapper around __float128)") .def(bp::init()) .def("__repr__", +[](const mppp::real128 &g) -> std::string { std::ostringstream oss; oss << g; return oss.str(); - }); + }) + .def(bp::self + bp::self) + .def(bp::self - bp::self) + .def(bp::self * bp::self) + .def(bp::self / bp::self) + .def(bp::self + double()) + .def(bp::self - double()) + .def(bp::self * double()) + .def(bp::self / double()) + .def(-bp::self) + .def(+bp::self) + .def(double() + bp::self) + .def(double() - bp::self) + .def(double() * bp::self) + .def(double() / bp::self) + .def(bp::self == bp::self) + .def(bp::self != bp::self) + .def("__pow__", +[](const mppp::real128 &gd, double x) { return audi::pow(gd, x); }, + "Exponentiation (mppp::real128, double).") + .def("__pow__", +[](const mppp::real128 &base, const mppp::real128 &gd) { return audi::pow(base, gd); }, + "Exponentiation (mppp::real128, mppp::real128).") + .def("__rpow__", +[](const mppp::real128 &gd, double x) { return audi::pow(x, gd); }, + "Exponentiation (double, mppp::real128)."); // We expose the gdual arithmetic pyaudi::expose_gdual("real128") @@ -140,6 +164,29 @@ BOOST_PYTHON_MODULE(core) bp::def("atanh", +[](const gdual_mp &d) { return atanh(d); }, "Inverse hyperbolic arc tangent (gdual_real128)."); bp::def("abs", +[](const gdual_mp &d) { return abs(d); }, "Absolute value (gdual_real128)."); bp::def("erf", +[](const gdual_mp &d) { return erf(d); }, "Error function (gdual_real128)."); + + // We expose simple mathematical functions to work on mppp::real128 + bp::def("exp", +[](mppp::real128 x) { return audi::exp(x); }, "Exponential (mppp::real128)."); + bp::def("log", +[](mppp::real128 x) { return audi::log(x); }, "Natural logarithm (mppp::real128)."); + bp::def("sqrt", +[](mppp::real128 x) { return audi::sqrt(x); }, "Square root (mppp::real128)."); + bp::def("cbrt", +[](mppp::real128 x) { return audi::cbrt(x); }, "Cubic root (mppp::real128)."); + bp::def("sin", +[](mppp::real128 x) { return audi::sin(x); }, "Sine (mppp::real128)."); + bp::def("asin", +[](mppp::real128 x) { return audi::asin(x); }, "Arc sine (mppp::real128)."); + bp::def("cos", +[](mppp::real128 x) { return audi::cos(x); }, "Cosine (mppp::real128)."); + bp::def("acos", +[](mppp::real128 x) { return audi::acos(x); }, "Arc cosine (mppp::real128)."); + bp::def("tan", +[](mppp::real128 x) { return audi::tan(x); }, "Tangent (mppp::real128)."); + bp::def("atan", +[](mppp::real128 x) { return audi::atan(x); }, "Arc tangent (mppp::real128)."); + bp::def("sinh", +[](mppp::real128 x) { return audi::sinh(x); }, "Hyperbolic sine (mppp::real128)."); + bp::def("asinh", +[](mppp::real128 x) { return audi::asinh(x); }, "Inverse hyperbolic sine (mppp::real128)."); + bp::def("cosh", +[](mppp::real128 x) { return audi::cosh(x); }, "Hyperbolic cosine (mppp::real128)."); + bp::def("acosh", +[](mppp::real128 x) { return audi::acosh(x); }, "Inverse hyperbolic cosine (mppp::real128)."); + bp::def("sinh_and_cosh", +[](const gdual_v &d) { return pyaudi::v_to_l(sinh_and_cosh(d)); }, + "Hyperbolic sine and hyperbolic cosine at once (gdual_v)."); + bp::def("tanh", +[](mppp::real128 x) { return audi::tanh(x); }, "Hyperbolic tangent (mppp::real128)."); + bp::def("atanh", +[](mppp::real128 x) { return audi::atanh(x); }, "Inverse hyperbolic arc tangent (mppp::real128)."); + bp::def("abs", +[](mppp::real128 x) { return audi::abs(x); }, "Absolute value (mppp::real128)."); + bp::def("erf", +[](mppp::real128 x) { return audi::erf(x); }, "Error function (mppp::real128)."); + #endif // Miscellanea functions From e28bacc51784cfd469051797f1394e4b04ff3da2 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Wed, 16 May 2018 16:57:22 +0200 Subject: [PATCH 24/61] Excluding mppp when not present --- include/audi/functions_from_d.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/audi/functions_from_d.hpp b/include/audi/functions_from_d.hpp index 7a220c54..10a22bbe 100644 --- a/include/audi/functions_from_d.hpp +++ b/include/audi/functions_from_d.hpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -188,6 +189,8 @@ inline gdual erf(const gdual &d) auto dg = (2. / std::sqrt(boost::math::constants::pi())) * exp(-d * d); return _compose_from_derivative(d, dg, g0); } + +#if defined(AUDI_WITH_MPPP) template <> inline gdual erf(const gdual &d) { @@ -196,6 +199,7 @@ inline gdual erf(const gdual &d) auto dg = (2. / audi::sqrt(mppp::real128_pi())) * exp(-d * d); return _compose_from_derivative(d, dg, g0); } +#endif } // end of namespace audi From 2ab1c2ec4c8ed97c98ef64317efcaaa348a84d22 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Thu, 17 May 2018 08:57:19 +0200 Subject: [PATCH 25/61] updating versions of cmake and boost in travis --- tools/install_docker.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/install_docker.sh b/tools/install_docker.sh index cc577876..af809cc9 100644 --- a/tools/install_docker.sh +++ b/tools/install_docker.sh @@ -6,9 +6,9 @@ set -x # Exit on error. set -e -CMAKE_VERSION="3.10.0" +CMAKE_VERSION="3.11.1" EIGEN3_VERSION="3.3.4" -BOOST_VERSION="1.66.0" +BOOST_VERSION="1.67.0" NLOPT_VERSION="2.4.2" if [[ ${AUDI_BUILD} == *36 ]]; then @@ -40,7 +40,7 @@ cd mkdir install cd install -# Install Boost https://dl.bintray.com/boostorg/release/1.66.0/source/boost_1_66_0.tar.bz2 +# Install Boost curl -L http://dl.bintray.com/boostorg/release/${BOOST_VERSION}/source/boost_`echo ${BOOST_VERSION}|tr "." "_"`.tar.bz2 > boost_`echo ${BOOST_VERSION}|tr "." "_"`.tar.bz2 tar xjf boost_`echo ${BOOST_VERSION}|tr "." "_"`.tar.bz2 cd boost_`echo ${BOOST_VERSION}|tr "." "_"` @@ -106,7 +106,7 @@ cd .. # Compile and install pyaudi (build directory is created by .travis.yml) cd build -cmake -DCMAKE_BUILD_TYPE=Release -DAUDI_BUILD_AUDI=no -DAUDI_BUILD_PYAUDI=yes -DAUDI_BUILD_TESTS=no -DPYTHON_EXECUTABLE=/opt/python/${PYTHON_DIR}/bin/python ../; +cmake -DCMAKE_BUILD_TYPE=Release -DAUDI_BUILD_AUDI=no -DAUDI_BUILD_PYAUDI=yes -DPYTHON_EXECUTABLE=/opt/python/${PYTHON_DIR}/bin/python ../; make -j2 install # Compile wheels From 044ef1745e315a47dcd991f4348658763948f5ba Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Thu, 17 May 2018 09:36:54 +0200 Subject: [PATCH 26/61] fixing CI #1 --- .travis.yml | 32 ++++++++++++++++---------------- CMakeLists.txt | 2 +- appveyor.yml | 10 +++++----- pyaudi/CMakeLists.txt | 4 ++-- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.travis.yml b/.travis.yml index a880e7de..b4a11628 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,22 +9,22 @@ env: matrix: include: - - env: AUDI_BUILD="manylinux64Py36" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" - sudo: required - services: - - docker - - env: AUDI_BUILD="manylinux64Py35" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" - sudo: required - services: - - docker - - env: AUDI_BUILD="manylinux64Py34" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" - sudo: required - services: - - docker - - env: AUDI_BUILD="manylinux64Py27" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" - sudo: required - services: - - docker + #- env: AUDI_BUILD="manylinux64Py36" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" + # sudo: required + # services: + # - docker + #- env: AUDI_BUILD="manylinux64Py35" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" + # sudo: required + # services: + # - docker + #- env: AUDI_BUILD="manylinux64Py34" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" + # sudo: required + # services: + # - docker + #- env: AUDI_BUILD="manylinux64Py27" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" + # sudo: required + # services: + # - docker install: - docker pull $DOCKER_IMAGE script: diff --git a/CMakeLists.txt b/CMakeLists.txt index 19fda2f6..50745b47 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -156,7 +156,7 @@ if(AUDI_BUILD_AUDI) # Setup of the header-only audi library. add_library(audi INTERFACE) target_link_libraries(audi INTERFACE Threads::Threads Boost::boost Boost::serialization) - target_link_libraries(audi INTERFACE Eigen3::eigen3 GMP::GMP MPFR::MPFR) + target_link_libraries(audi INTERFACE Eigen3::eigen3 MPFR::MPFR GMP::GMP) if(AUDI_WITH_MPPP) target_link_libraries(audi INTERFACE mp++::mp++) endif() diff --git a/appveyor.yml b/appveyor.yml index 20c5be50..913db701 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,11 +3,11 @@ environment: secure: M+qvYgRh05fEw6G9aglK4g== matrix: - BUILD_TYPE: "Python36" - - BUILD_TYPE: "Python27" - - BUILD_TYPE: "Python34" - - BUILD_TYPE: "Python35" - - BUILD_TYPE: "Release" - - BUILD_TYPE: "Debug" + #- BUILD_TYPE: "Python27" + #- BUILD_TYPE: "Python34" + #- BUILD_TYPE: "Python35" + #- BUILD_TYPE: "Release" + #- BUILD_TYPE: "Debug" global: PLATFORMTOOLSET: "v140" diff --git a/pyaudi/CMakeLists.txt b/pyaudi/CMakeLists.txt index 8b29d5eb..ab822266 100644 --- a/pyaudi/CMakeLists.txt +++ b/pyaudi/CMakeLists.txt @@ -32,13 +32,13 @@ endif() # Setup of the header-only pyaudi library. add_library(pyaudi INTERFACE) -target_link_libraries(pyaudi INTERFACE ${PYAUDI_BP_TARGET} Boost::disable_autolinking YACMA::PythonModule Audi::audi ${MPFR_LIBRARIES}) +target_link_libraries(pyaudi INTERFACE ${PYAUDI_BP_TARGET} Boost::disable_autolinking YACMA::PythonModule Audi::audi) target_include_directories(pyaudi INTERFACE $ $ $) # Setup of the pyaudi core module. YACMA_PYTHON_MODULE(core core.cpp docstrings.cpp) -target_link_libraries(core PRIVATE ${PYAUDI_BP_TARGET} pyaudi ${MPFR_LIBRARIES}) +target_link_libraries(core PRIVATE ${PYAUDI_BP_TARGET} pyaudi) target_compile_options(core PRIVATE "$<$:${AUDI_CXX_FLAGS_DEBUG}>" "$<$:${AUDI_CXX_FLAGS_RELEASE}>") set_property(TARGET core PROPERTY CXX_STANDARD 11) set_property(TARGET core PROPERTY CXX_STANDARD_REQUIRED YES) From d006059668422193fdc83e9852fe4fdada0b4c38 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Thu, 17 May 2018 09:43:23 +0200 Subject: [PATCH 27/61] fixing CI #2 --- .travis.yml | 32 ++++++++++++++++---------------- appveyor.yml | 10 +++++----- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/.travis.yml b/.travis.yml index b4a11628..a880e7de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,22 +9,22 @@ env: matrix: include: - #- env: AUDI_BUILD="manylinux64Py36" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" - # sudo: required - # services: - # - docker - #- env: AUDI_BUILD="manylinux64Py35" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" - # sudo: required - # services: - # - docker - #- env: AUDI_BUILD="manylinux64Py34" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" - # sudo: required - # services: - # - docker - #- env: AUDI_BUILD="manylinux64Py27" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" - # sudo: required - # services: - # - docker + - env: AUDI_BUILD="manylinux64Py36" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" + sudo: required + services: + - docker + - env: AUDI_BUILD="manylinux64Py35" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" + sudo: required + services: + - docker + - env: AUDI_BUILD="manylinux64Py34" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" + sudo: required + services: + - docker + - env: AUDI_BUILD="manylinux64Py27" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" + sudo: required + services: + - docker install: - docker pull $DOCKER_IMAGE script: diff --git a/appveyor.yml b/appveyor.yml index 913db701..20c5be50 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,11 +3,11 @@ environment: secure: M+qvYgRh05fEw6G9aglK4g== matrix: - BUILD_TYPE: "Python36" - #- BUILD_TYPE: "Python27" - #- BUILD_TYPE: "Python34" - #- BUILD_TYPE: "Python35" - #- BUILD_TYPE: "Release" - #- BUILD_TYPE: "Debug" + - BUILD_TYPE: "Python27" + - BUILD_TYPE: "Python34" + - BUILD_TYPE: "Python35" + - BUILD_TYPE: "Release" + - BUILD_TYPE: "Debug" global: PLATFORMTOOLSET: "v140" From dda00cbc27e53c03c2a88611e761a665216f3de3 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Thu, 17 May 2018 15:36:05 +0200 Subject: [PATCH 28/61] cosmetics and docs --- CMakeLists.txt | 6 +++--- doc/sphinx/index.rst | 4 +++- doc/sphinx/notebooks/map_inversion.ipynb | 2 +- doc/sphinx/py_gdual.rst | 8 +++++++- pyaudi/docstrings.cpp | 14 +++++++++++--- 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 50745b47..be735c4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,6 @@ +# Main audi/pyaudi project version. +set(AUDI_PROJECT_VERSION 1.3) + # CMake version check. cmake_minimum_required(VERSION 3.2) @@ -29,9 +32,6 @@ if((NOT AUDI_BUILD_AUDI) AND (NOT AUDI_BUILD_PYAUDI)) message(FATAL_ERROR "Please select if you want to build audi or pyudi.") endif() -# Main audi/pyaudi project version. -set(AUDI_PROJECT_VERSION 1.3) - if(AUDI_BUILD_AUDI) # Initial setup of a audi build. project(audi VERSION ${AUDI_PROJECT_VERSION}) diff --git a/doc/sphinx/index.rst b/doc/sphinx/index.rst index 65a20ae4..6c6147c5 100644 --- a/doc/sphinx/index.rst +++ b/doc/sphinx/index.rst @@ -2,7 +2,7 @@ Audi and pyaudi ================================ Audi (not the car, rather from latin: "listen!") is an open source, header only, C++ library -(exposed to python in the pyaudi package) that implements the algebra of Taylor truncated polynomials and +(exposed to python in the pyaudi package) that implements the differential algebra of Taylor truncated polynomials and a few algorithms useful for its applications (Differential Intelligence, automatic differentiation, Taylor Models, etc.) When used for automated differentiation only, other automated differentiation codes may be more @@ -45,6 +45,8 @@ Audi is open source (GPL3) and its code available in github >> print(f) # doctest: +SKIP [1.42012, 1.30178]*dx2+[0.118343, 0.236686]*dx1+[1.0924, 1.00137]*dx2**2+[0.846154, 0.692308]+[-1.00137, -0.819299]*dx1*dx2+[-0.0910332, -0.182066]*dx1**2 +gdual_real128: :math:`m = 2`, :math:`\mathbf a = [1.2, -0.1]`, :math:`f = \frac{x1+x2}{x1-x2}` + +>>> from pyaudi import gdual_real128 as gdual +>>> x1 = gdual("1.2", "x1", 2) +>>> x2 = gdual("-0.1", "x2", 2) +>>> f = (x1+x2) / (x1-x2) +>>> print(f) # doctest: +SKIP +1.42011834319526627218934911242603510e+00*dx2+1.18343195266272189349112426035503101e-01*dx1+1.09239872553482020937642239417387321e+00*dx2**2+8.46153846153846153846153846153845954e-01-1.00136549840691852526172052799271705e+00*dx1*dx2-9.10332271279016841147018661811561892e-02*dx1**2 .. note:: - A gdual can operate on doubles (gdual_double) or on vectorized doubles (gdual_vdouble). The second case is - immensely more efficient when applicable. + A gdual can operate on doubles (gdual_double), on vectorized doubles (gdual_vdouble) or on quadruple precision doubles + (gdual_real128). The second case is immensely more efficient when applicable. See also the docs of the C++ class :cpp:class:`gdual`. From 704cb1c8ee2c1c6fd88d75b9cc9168f1549f2ce4 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Tue, 22 May 2018 09:45:32 +0200 Subject: [PATCH 29/61] notebook added --- doc/sphinx/notebooks/mp_gdual.ipynb | 215 ++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 doc/sphinx/notebooks/mp_gdual.ipynb diff --git a/doc/sphinx/notebooks/mp_gdual.ipynb b/doc/sphinx/notebooks/mp_gdual.ipynb new file mode 100644 index 00000000..1daa7c1a --- /dev/null +++ b/doc/sphinx/notebooks/mp_gdual.ipynb @@ -0,0 +1,215 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Quadruple precision computations (new in 1.3)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Qudruple precision floats\n", + "The class real128 in pyaudi ia a multiple precision float, basically wrapping the GNU C++ *__float128* type. It can be used outside of the whole differential algebra machinery (the gduals) to perform quadruple precision computations" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from pyaudi import real128\n", + "from pyaudi import sin, acos" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3.33333333333333333333333333333333317e-01\n" + ] + } + ], + "source": [ + "# Some simple math\n", + "x = real128(\"3\")\n", + "print(1/x)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1.41120008059867222100744802808110299e-01\n" + ] + } + ], + "source": [ + "# Trigonometry\n", + "print(sin(x))" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Double precision:\t 3.141592653589793\n", + "Quad precision:\t\t 3.14159265358979323846264338327950280e+00\n" + ] + } + ], + "source": [ + "# The value of pi in double precision\n", + "print(\"Double precision:\\t\", 2*acos(0))\n", + "# The value of pi in quadruple precision\n", + "print(\"Quad precision:\\t\\t\", 2*acos(real128(\"0\")))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Qudruple precision gdual\n", + "The gdual can also perform computations in quadruple precision.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "from pyaudi import gdual_real128 as gdual\n", + "from pyaudi import sin, acos, sqrt" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "A quadruple precision gdual computation: \n" + ] + }, + { + "data": { + "text/latex": [ + "\\[ -4.35605126899062478098382207778725168e-08{dy}-3.07827623008670817856190093496965737e-08{dx}+1.13010764054002057997221799187876804e-07{dy}^{2}+9.23482869026012453568570280490897241e-09+1.45201708966354159366127402592908378e-07{dx}{dy}+5.64350642182563166069681838077770461e-08{dx}^{2}+\\mathcal{O}\\left(3\\right) \\]" + ], + "text/plain": [ + "-4.35605126899062478098382207778725168e-08*dy-3.07827623008670817856190093496965737e-08*dx+1.13010764054002057997221799187876804e-07*dy**2+9.23482869026012453568570280490897241e-09+1.45201708966354159366127402592908378e-07*dx*dy+5.64350642182563166069681838077770461e-08*dx**2" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "def easy_fun(x,y):\n", + " return (1/x/y)**10\n", + "\n", + "x = gdual(\"3\", \"x\", 2)\n", + "y = gdual(\"2.12\", \"y\", 2)\n", + "res = easy_fun(x,y)\n", + "print(\"A quadruple precision gdual computation: \")\n", + "res" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "All quantities, that is the function value and its derivatives are in quadruple precision. Lets extract $\\frac{\\partial^2 f}{\\partial x \\partial y}$:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "value: 1.45201708966354159366127402592908378e-07\n", + "type: \n" + ] + } + ], + "source": [ + "der = res.get_derivative({\"dx\": 1, \"dy\": 1})\n", + "print(\"value: \", der)\n", + "print(\"type: \", type(der))" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from IPython.display import Image\n", + "from IPython.core.display import HTML \n", + "Image(url= \"http://images6.fanpop.com/image/photos/38700000/That-s-All-Folks-the-looney-tunes-show-38740983-500-281.jpg\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 45299f4f47878a5e9baa4ba29917d0d45ddec493 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Tue, 22 May 2018 13:39:09 +0200 Subject: [PATCH 30/61] generalizing vectorized --- include/audi/audi.hpp | 4 +- include/audi/detail/overloads.hpp | 64 ------ include/audi/detail/overloads_vectorized.hpp | 62 ++++++ include/audi/functions.hpp | 8 +- include/audi/gdual.hpp | 6 +- include/audi/type_traits.hpp | 11 - .../{vectorized_double.hpp => vectorized.hpp} | 201 +++++++++--------- pyaudi/common_utils.hpp | 7 +- pyaudi/core.cpp | 6 +- pyaudi/expose_gdual.hpp | 8 +- tests/CMakeLists.txt | 2 +- tests/vectorized.cpp | 121 +++++++++++ 12 files changed, 307 insertions(+), 193 deletions(-) create mode 100644 include/audi/detail/overloads_vectorized.hpp rename include/audi/{vectorized_double.hpp => vectorized.hpp} (61%) create mode 100644 tests/vectorized.cpp diff --git a/include/audi/audi.hpp b/include/audi/audi.hpp index 9074326d..b04c73b8 100644 --- a/include/audi/audi.hpp +++ b/include/audi/audi.hpp @@ -13,12 +13,12 @@ #include #include #include -#include +#include namespace audi { using gdual_d = audi::gdual; -using gdual_v = audi::gdual; +using gdual_v = audi::gdual>; using gdual_c = audi::gdual>; #if defined(AUDI_WITH_MPPP) using gdual_mp = audi::gdual; diff --git a/include/audi/detail/overloads.hpp b/include/audi/detail/overloads.hpp index 23fc527e..e619ee41 100644 --- a/include/audi/detail/overloads.hpp +++ b/include/audi/detail/overloads.hpp @@ -10,7 +10,6 @@ #endif #include -#include #include // This is repeated here instead of including type_traits as to avoid a circular dependency @@ -19,16 +18,6 @@ struct is_arithmetic_or_complex : std::integral_constant::value || boost::is_complex::value> { }; -// This macro writes the overload for std::fun_name performing elementwise evaluations on a vectorized_double -#define VECTORIZED_OVERLOAD(fun_name) \ - inline vectorized_double fun_name(vectorized_double in) \ - { \ - for (auto &el : in) { \ - el = std::fun_name(el); \ - } \ - return in; \ - } - // This macro writes the overload for std::fun_name af an arithmetic or complex type. It simply calls std::fun_name // It is used to allow calls such as audi::cos(T) [T = double] in templated functions. #define ARITH_OR_COMPLEX_OVERLOAD(fun_name) \ @@ -79,62 +68,25 @@ inline mppp::real128 pow(const T &base, const U &d) } #endif -VECTORIZED_OVERLOAD(exp) ARITH_OR_COMPLEX_OVERLOAD(exp) - -VECTORIZED_OVERLOAD(erf) ARITH_OR_COMPLEX_OVERLOAD(erf) - -VECTORIZED_OVERLOAD(lgamma) ARITH_OR_COMPLEX_OVERLOAD(lgamma) - -VECTORIZED_OVERLOAD(log) ARITH_OR_COMPLEX_OVERLOAD(log) - -VECTORIZED_OVERLOAD(sin) ARITH_OR_COMPLEX_OVERLOAD(sin) - -VECTORIZED_OVERLOAD(cos) ARITH_OR_COMPLEX_OVERLOAD(cos) - -VECTORIZED_OVERLOAD(tan) ARITH_OR_COMPLEX_OVERLOAD(tan) - -VECTORIZED_OVERLOAD(sinh) ARITH_OR_COMPLEX_OVERLOAD(sinh) - -VECTORIZED_OVERLOAD(cosh) ARITH_OR_COMPLEX_OVERLOAD(cosh) - -VECTORIZED_OVERLOAD(tanh) ARITH_OR_COMPLEX_OVERLOAD(tanh) - -VECTORIZED_OVERLOAD(asin) ARITH_OR_COMPLEX_OVERLOAD(asin) - -VECTORIZED_OVERLOAD(acos) ARITH_OR_COMPLEX_OVERLOAD(acos) - -VECTORIZED_OVERLOAD(atan) ARITH_OR_COMPLEX_OVERLOAD(atan) - -VECTORIZED_OVERLOAD(asinh) ARITH_OR_COMPLEX_OVERLOAD(asinh) - -VECTORIZED_OVERLOAD(acosh) ARITH_OR_COMPLEX_OVERLOAD(acosh) - -VECTORIZED_OVERLOAD(atanh) ARITH_OR_COMPLEX_OVERLOAD(atanh) - -VECTORIZED_OVERLOAD(sqrt) ARITH_OR_COMPLEX_OVERLOAD(sqrt) - -VECTORIZED_OVERLOAD(abs) ARITH_OR_COMPLEX_OVERLOAD(abs) -VECTORIZED_OVERLOAD(cbrt) - template ::value, int> = 0> inline T cbrt(T in) { @@ -165,21 +117,5 @@ inline T pow(const U &base, const T &d) return std::pow(base, d); } -inline vectorized_double pow(double base, vectorized_double in) -{ - for (auto &el : in) { - el = std::pow(base, el); - } - return in; -} - -inline vectorized_double pow(vectorized_double in, double exponent) -{ - for (auto &el : in) { - el = std::pow(el, exponent); - } - return in; -} - } // namespace audi #endif diff --git a/include/audi/detail/overloads_vectorized.hpp b/include/audi/detail/overloads_vectorized.hpp new file mode 100644 index 00000000..d5aecc49 --- /dev/null +++ b/include/audi/detail/overloads_vectorized.hpp @@ -0,0 +1,62 @@ +#ifndef AUDI_OVERLOADS_VECTORIZED_HPP +#define AUDI_OVERLOADS_VECTORIZED_HPP + +#include + +#include +#include + + +// This macro writes the overload for std::fun_name performing elementwise evaluations on a vectorized +#define VECTORIZED_OVERLOAD(fun_name) \ + template \ + inline vectorized fun_name(vectorized in) \ + { \ + for (auto &el : in) { \ + el = audi::fun_name(el); \ + } \ + return in; \ + } + +namespace audi +{ +VECTORIZED_OVERLOAD(exp) +VECTORIZED_OVERLOAD(erf) +VECTORIZED_OVERLOAD(lgamma) +VECTORIZED_OVERLOAD(log) +VECTORIZED_OVERLOAD(sin) +VECTORIZED_OVERLOAD(cos) +VECTORIZED_OVERLOAD(tan) +VECTORIZED_OVERLOAD(sinh) +VECTORIZED_OVERLOAD(cosh) +VECTORIZED_OVERLOAD(tanh) +VECTORIZED_OVERLOAD(asin) +VECTORIZED_OVERLOAD(acos) +VECTORIZED_OVERLOAD(atan) +VECTORIZED_OVERLOAD(asinh) +VECTORIZED_OVERLOAD(acosh) +VECTORIZED_OVERLOAD(atanh) +VECTORIZED_OVERLOAD(sqrt) +VECTORIZED_OVERLOAD(abs) +VECTORIZED_OVERLOAD(cbrt) + +template +inline vectorized pow(double base, vectorized in) +{ + for (auto &el : in) { + el = std::pow(base, el); + } + return in; +} + +template +inline vectorized pow(vectorized in, double exponent) +{ + for (auto &el : in) { + el = std::pow(el, exponent); + } + return in; +} + +} // namespace audi +#endif diff --git a/include/audi/functions.hpp b/include/audi/functions.hpp index b4dc5b57..13cfc8af 100644 --- a/include/audi/functions.hpp +++ b/include/audi/functions.hpp @@ -13,6 +13,8 @@ #include #include #include +#include + namespace audi { @@ -870,10 +872,10 @@ inline gdual abs(const gdual &d) return -d; } // Vectorized abs specialization -template <> -inline gdual abs(const gdual &d) +template +inline gdual> abs(const gdual> &d) { - gdual retval(d); + gdual> retval(d); auto p0 = retval.constant_cf(); for (auto it = retval._container().begin(); it != retval._container().end(); ++it) { // if the coefficient has one only element copy it over to the whole length of p0 diff --git a/include/audi/gdual.hpp b/include/audi/gdual.hpp index 7a5b90b3..e416bd68 100644 --- a/include/audi/gdual.hpp +++ b/include/audi/gdual.hpp @@ -25,7 +25,9 @@ #include #include -#include //for audi::abs +#include //for audi::abs +#include //for audi::abs + /// Root namespace for AuDi symbols @@ -62,7 +64,7 @@ namespace audi * * @note The class can be instantiated with any type that is suitable to be a coefficient in a piranha polynomial ( * piranha::is_cf::value must be true). Classical examples would be double, float, std::complex, and - * the audi::vectorized_double type. If piranha::is_differentiable::value is also true then derivation + * the audi::vectorized type. If piranha::is_differentiable::value is also true then derivation * and integration are availiable. * */ diff --git a/include/audi/type_traits.hpp b/include/audi/type_traits.hpp index 1f8d0092..e38eae53 100644 --- a/include/audi/type_traits.hpp +++ b/include/audi/type_traits.hpp @@ -10,7 +10,6 @@ #include #include -#include namespace audi { @@ -59,16 +58,6 @@ struct is_arithmetic_or_complex : std::integral_constant::value || boost::is_complex::value> { }; -/// Type is allowed to be a coefficient for gduals -/** - * Checks whether T is a type from which gdual construction is allowed - * - * \tparam T a type to check - */ -template -struct is_gdual_cf : std::integral_constant::value - || std::is_same::value> { -}; } // namespace audi #endif diff --git a/include/audi/vectorized_double.hpp b/include/audi/vectorized.hpp similarity index 61% rename from include/audi/vectorized_double.hpp rename to include/audi/vectorized.hpp index 7492a1fa..d85e2a12 100644 --- a/include/audi/vectorized_double.hpp +++ b/include/audi/vectorized.hpp @@ -1,5 +1,5 @@ -#ifndef AUDI_VECTORIZED_DOUBLE_HPP -#define AUDI_VECTORIZED_DOUBLE_HPP +#ifndef AUDI_VECTORIZED_HPP +#define AUDI_VECTORIZED_HPP #include #include @@ -12,6 +12,7 @@ #include + // The streaming operator will only output the first MAX_STREAMED_COMPONENTS elements of the vector #define MAX_STREAMED_COMPONENTS 5u @@ -22,172 +23,171 @@ namespace audi // The coefficient is, essentially a vector of doubles [a0,a1,a2,...an] on which all arithmetic operations and // function calls operate element-wise. -class vectorized_double +template +class vectorized { public: - template + template using operator_enabler - = enable_if_t<(std::is_same::value || std::is_arithmetic::value), int>; + = enable_if_t<(std::is_same::value || std::is_arithmetic::value), int>; // Default constructor. Constructs [0.] - vectorized_double() : m_c({0.}){}; - // Constructor from int. Its mandatory for piranha::polynomial coefficient - explicit vectorized_double(int a) : m_c({static_cast(a)}){}; - explicit vectorized_double(unsigned a) : m_c({static_cast(a)}){}; + vectorized() : m_c({T(0.)}){}; + + // Constructor other types + template + explicit vectorized(T1 a) : m_c({static_cast(a)}){} - - // Constructor from double value a. Construct [a] - explicit vectorized_double(double a) : m_c({a}){}; // Constructor from an std::vector - explicit vectorized_double(const std::vector &c) : m_c(c) + explicit vectorized(const std::vector &c) : m_c(c) { if (m_c.size() == 0) { throw std::invalid_argument("Cannot build an empty coefficient_v (lvalue)"); } }; // Constructor from an std::vector r value - explicit vectorized_double(std::vector &&c) : m_c(c) + explicit vectorized(std::vector &&c) : m_c(c) { if (m_c.size() == 0) { throw std::invalid_argument("Cannot build an empty coefficient_v (rvalue)"); } }; - explicit vectorized_double(std::initializer_list c) : m_c(c) + explicit vectorized(std::initializer_list c1) : m_c(c1) { if (m_c.size() == 0) { throw std::invalid_argument("Cannot build an empty coefficient_v (initializer)"); } - }; + } // ------------------- Binary arithmetic operators implemented using the available +=,-=, etc. template = 0, operator_enabler = 0> - friend vectorized_double operator+(const T1 &d1v, const T2 &d2v) + friend vectorized operator+(const T1 &d1v, const T2 &d2v) { - vectorized_double d1(d1v); - vectorized_double d2(d2v); + vectorized d1(d1v); + vectorized d2(d2v); d1 += d2; return d1; } template = 0, operator_enabler = 0> - friend vectorized_double operator-(const T1 &d1v, const T2 &d2v) + friend vectorized operator-(const T1 &d1v, const T2 &d2v) { - vectorized_double d1(d1v); - vectorized_double d2(d2v); + vectorized d1(d1v); + vectorized d2(d2v); d1 -= d2; return d1; } template = 0, operator_enabler = 0> - friend vectorized_double operator*(const T1 &d1v, const T2 &d2v) + friend vectorized operator*(const T1 &d1v, const T2 &d2v) { - vectorized_double d1(d1v); - vectorized_double d2(d2v); + vectorized d1(d1v); + vectorized d2(d2v); d1 *= d2; return d1; } template = 0, operator_enabler = 0> - friend vectorized_double operator/(const T1 &d1v, const T2 &d2v) + friend vectorized operator/(const T1 &d1v, const T2 &d2v) { - vectorized_double d1(d1v); - vectorized_double d2(d2v); + vectorized d1(d1v); + vectorized d2(d2v); d1 /= d2; return d1; } // ----------------- Juice implementation of the operators. It also deals with the case [b1] op [a1,a2,..an] to // take care of scalar multiplication/division etc. - vectorized_double &operator+=(const vectorized_double &d1) + vectorized &operator+=(const vectorized &d1) { if (d1.size() == this->size()) { - std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), std::plus()); + std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), std::plus()); return *this; } else if (d1.size() == 1u) { std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), - [&d1](double x) { return x + d1.m_c[0]; }); + [&d1](T x) { return x + d1.m_c[0]; }); return *this; } else if (this->size() == 1u) { - double scalar = m_c[0]; + T scalar = m_c[0]; this->resize(d1.size()); - std::transform(d1.m_c.begin(), d1.m_c.end(), this->m_c.begin(), [scalar](double x) { return x + scalar; }); + std::transform(d1.m_c.begin(), d1.m_c.end(), this->m_c.begin(), [scalar](T x) { return x + scalar; }); return *this; } throw std::invalid_argument("Coefficients of different sizes in +"); } - vectorized_double &operator-=(const vectorized_double &d1) + vectorized &operator-=(const vectorized &d1) { if (d1.size() == this->size()) { - std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), std::minus()); + std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), std::minus()); return *this; } else if (d1.size() == 1u) { std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), - [&d1](double x) { return x - d1.m_c[0]; }); + [&d1](T x) { return x - d1.m_c[0]; }); return *this; } else if (this->size() == 1u) { - double scalar = m_c[0]; + T scalar = m_c[0]; this->resize(d1.size()); - std::transform(d1.m_c.begin(), d1.m_c.end(), this->m_c.begin(), [scalar](double x) { return scalar - x; }); + std::transform(d1.m_c.begin(), d1.m_c.end(), this->m_c.begin(), [scalar](T x) { return scalar - x; }); return *this; } throw std::invalid_argument("Coefficients of different sizes in -"); } - vectorized_double &operator*=(const vectorized_double &d1) + vectorized &operator*=(const vectorized &d1) { if (d1.size() == this->size()) { std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), - std::multiplies()); + std::multiplies()); return *this; } else if (d1.size() == 1u) { std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), - [&d1](double x) { return x * d1.m_c[0]; }); + [&d1](T x) { return x * d1.m_c[0]; }); return *this; } else if (this->size() == 1u) { - double scalar = m_c[0]; + T scalar = m_c[0]; this->resize(d1.size()); - std::transform(d1.m_c.begin(), d1.m_c.end(), this->m_c.begin(), [scalar](double x) { return scalar * x; }); + std::transform(d1.m_c.begin(), d1.m_c.end(), this->m_c.begin(), [scalar](T x) { return scalar * x; }); return *this; } throw std::invalid_argument("Coefficients of different sizes in *"); } - vectorized_double &operator/=(const vectorized_double &d1) + vectorized &operator/=(const vectorized &d1) { if (d1.size() == this->size()) { std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), - std::divides()); + std::divides()); return *this; } else if (d1.size() == 1u) { std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), - [&d1](double x) { return x / d1.m_c[0]; }); + [&d1](T x) { return x / d1.m_c[0]; }); return *this; } else if (this->size() == 1u) { - double scalar = m_c[0]; + T scalar = m_c[0]; this->resize(d1.size()); - std::transform(d1.m_c.begin(), d1.m_c.end(), this->m_c.begin(), [scalar](double x) { return scalar / x; }); + std::transform(d1.m_c.begin(), d1.m_c.end(), this->m_c.begin(), [scalar](T x) { return scalar / x; }); return *this; } throw std::invalid_argument("Coefficients of different sizes in /"); } - template - vectorized_double &operator/=(const T &d1) + template + vectorized &operator/=(const T1 &d1) { std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), - [&d1](double x) { return x / d1; }); + [&d1](T x) { return x / d1; }); return *this; } - vectorized_double operator-() const + vectorized operator-() const { - vectorized_double retval(m_c); - transform(retval.m_c.begin(), retval.m_c.end(), retval.m_c.begin(), std::negate()); + vectorized retval(m_c); + transform(retval.m_c.begin(), retval.m_c.end(), retval.m_c.begin(), std::negate()); return retval; } template = 0, operator_enabler = 0> friend bool operator==(const T1 &d1v, const T2 &d2v) { - vectorized_double d1(d1v); - vectorized_double d2(d2v); + vectorized d1(d1v); + vectorized d2(d2v); if (d1.size() == d2.size()) { return d1.m_c == d2.m_c; } else if (d1.size() == 1u) { - return std::all_of(d2.begin(), d2.end(), [d1](double x) { return x == d1[0]; }); + return std::all_of(d2.begin(), d2.end(), [d1](T x) { return x == d1[0]; }); } else if (d2.size() == 1u) { - return std::all_of(d1.begin(), d1.end(), [d2](double x) { return x == d2[0]; }); + return std::all_of(d1.begin(), d1.end(), [d2](T x) { return x == d2[0]; }); } return false; } @@ -199,14 +199,14 @@ class vectorized_double template = 0, operator_enabler = 0> friend bool operator>(const T1 &d1v, const T2 &d2v) { - vectorized_double d1(d1v); - vectorized_double d2(d2v); + vectorized d1(d1v); + vectorized d2(d2v); if (d1.size() == d2.size()) { return d1.m_c > d2.m_c; } else if (d1.size() == 1u) { - return std::all_of(d2.begin(), d2.end(), [d1](double x) { return d1[0] > x; }); + return std::all_of(d2.begin(), d2.end(), [d1](T x) { return d1[0] > x; }); } else if (d2.size() == 1u) { - return std::all_of(d1.begin(), d1.end(), [d2](double x) { return x > d2[0]; }); + return std::all_of(d1.begin(), d1.end(), [d2](T x) { return x > d2[0]; }); } return false; } @@ -214,14 +214,14 @@ class vectorized_double template = 0, operator_enabler = 0> friend bool operator<(const T1 &d1v, const T2 &d2v) { - vectorized_double d1(d1v); - vectorized_double d2(d2v); + vectorized d1(d1v); + vectorized d2(d2v); if (d1.size() == d2.size()) { return d1.m_c < d2.m_c; } else if (d1.size() == 1u) { - return std::all_of(d2.begin(), d2.end(), [d1](double x) { return d1[0] < x; }); + return std::all_of(d2.begin(), d2.end(), [d1](T x) { return d1[0] < x; }); } else if (d2.size() == 1u) { - return std::all_of(d1.begin(), d1.end(), [d2](double x) { return x < d2[0]; }); + return std::all_of(d1.begin(), d1.end(), [d2](T x) { return x < d2[0]; }); } return false; } @@ -230,7 +230,7 @@ class vectorized_double // std::transform(in.m_c.begin(), in.m_c.end(), in.m_c.begin(), [](const double &x) { return std::abs(x); }); // return in; //} - friend std::ostream &operator<<(std::ostream &os, const vectorized_double &d) + friend std::ostream &operator<<(std::ostream &os, const vectorized &d) { os << "["; if (d.size() <= MAX_STREAMED_COMPONENTS) { @@ -246,46 +246,46 @@ class vectorized_double } return os; } - std::vector::size_type size() const + typename std::vector::size_type size() const { return m_c.size(); } - std::vector::const_iterator begin() const + typename std::vector::const_iterator begin() const { return m_c.begin(); } - std::vector::const_iterator end() const + typename std::vector::const_iterator end() const { return m_c.end(); } - std::vector::iterator begin() + typename std::vector::iterator begin() { return m_c.begin(); } - std::vector::iterator end() + typename std::vector::iterator end() { return m_c.end(); } - void resize(std::vector::size_type new_size) + void resize(typename std::vector::size_type new_size) { m_c.resize(new_size); } - void resize(std::vector::size_type new_size, double val) + void resize(typename std::vector::size_type new_size, T val) { m_c.resize(new_size, val); } - double operator[](const std::vector::size_type idx) const + T operator[](const typename std::vector::size_type idx) const { if (m_c.size() == 1u) { return m_c[0]; } return m_c[idx]; } - void set_value(const std::vector::size_type idx, double val) + void set_value(const typename std::vector::size_type idx, T val) { m_c[idx] = val; } - const std::vector &get_v() const + const std::vector &get_v() const { return m_c; } @@ -298,7 +298,7 @@ class vectorized_double ar &m_c; } - std::vector m_c; + std::vector m_c; }; } // namespace audi @@ -310,15 +310,15 @@ namespace math // --------------------- impl functions needed for vectorized_double to pass piranha::is_cf type trait template -struct is_zero_impl::value>::type> { - bool operator()(const T &v) const +struct is_zero_impl> { + bool operator()(const audi::vectorized &v) const { - return std::all_of(v.begin(), v.end(), [](double x) { return x == 0.; }); + return std::all_of(v.begin(), v.end(), [](T x) { return x == 0.; }); } }; template -struct mul3_impl::value>::type> { +struct mul3_impl> { /// Call operator. /** * @param out the output value. @@ -327,25 +327,25 @@ struct mul3_impl &out, const audi::vectorized &a, const audi::vectorized &b) const { if (a.size() == b.size()) { if (out.size() != a.size()) { out.resize(a.size()); } - std::transform(a.begin(), a.end(), b.begin(), out.begin(), std::multiplies()); + std::transform(a.begin(), a.end(), b.begin(), out.begin(), std::multiplies()); return; } else if (a.size() == 1u) { if (out.size() != b.size()) { out.resize(b.size()); } - std::transform(b.begin(), b.end(), out.begin(), [a](double item) { return item * a[0]; }); + std::transform(b.begin(), b.end(), out.begin(), [a](T item) { return item * a[0]; }); return; } else if (b.size() == 1u) { if (out.size() != a.size()) { out.resize(a.size()); } - std::transform(a.begin(), a.end(), out.begin(), [b](double item) { return item * b[0]; }); + std::transform(a.begin(), a.end(), out.begin(), [b](T item) { return item * b[0]; }); return; } throw std::invalid_argument("Coefficients of different sizes in mul3"); @@ -354,48 +354,49 @@ struct mul3_impl -struct partial_impl::value>::type> { +struct partial_impl> { /// Call operator. /** * @return an instance of piranha::mp_integer constructed from zero. */ - T operator()(const T &in, const std::string &) const + audi::vectorized operator()(const audi::vectorized &in, const std::string &) const { - return T(std::vector(in.size(), 0.)); + return audi::vectorized(std::vector(in.size(), 0.)); } }; template -struct pow_impl::value>::type> { +struct pow_impl, U> { /// Call operator. /** * @param c the input * @param exp the exponent * @return the exp operator applied to all elements of the input */ - T operator()(const T &c, const U &exp) const + audi::vectorized operator()(const audi::vectorized &c, const U &exp) const { auto retval(c); std::transform(retval.begin(), retval.end(), retval.begin(), - [exp](double x) { return piranha::math::pow(x, exp); }); + [exp](T x) { return piranha::math::pow(x, exp); }); return retval; }; }; -} // namespace math +} // end of math namespace -template -struct boost_save_impl : boost_save_via_boost_api { +template +struct boost_save_impl> : boost_save_via_boost_api> { }; -template -struct boost_load_impl : boost_load_via_boost_api { +template +struct boost_load_impl> : boost_load_via_boost_api> { }; -template <> -struct zero_is_absorbing : std::false_type { +template +struct zero_is_absorbing> : std::false_type { }; -} // namespace piranha +} // end of piranha namespace + #undef MAX_STREAMED_COMPONENTS #endif diff --git a/pyaudi/common_utils.hpp b/pyaudi/common_utils.hpp index bb79da12..6d703f4f 100644 --- a/pyaudi/common_utils.hpp +++ b/pyaudi/common_utils.hpp @@ -87,9 +87,10 @@ inline std::vector l_to_v(const bp::object &iterable) return std::vector(bp::stl_input_iterator(iterable), bp::stl_input_iterator()); } -// Used to register the vectorized_double to list converter -struct vectorized_double_to_python_list { - static PyObject *convert(const audi::vectorized_double &vd) +// Used to register the vectorized to list converter +template +struct vectorized_to_python_list { + static PyObject *convert(const audi::vectorized &vd) { bp::list list; for (auto iter = vd.begin(); iter != vd.end(); ++iter) { diff --git a/pyaudi/core.cpp b/pyaudi/core.cpp index 1a94b53c..28000eef 100644 --- a/pyaudi/core.cpp +++ b/pyaudi/core.cpp @@ -23,7 +23,7 @@ BOOST_PYTHON_MODULE(core) { // We register a converter between vectorized_double and a python list (handy to avoid a long separate interface in // expose gdual) - bp::to_python_converter(); + bp::to_python_converter, pyaudi::vectorized_to_python_list>(); // We expose the gdual arithmetic pyaudi::expose_gdual("double"); @@ -50,8 +50,8 @@ BOOST_PYTHON_MODULE(core) bp::def("abs", +[](const gdual_d &d) { return abs(d); }, "Absolute value (gdual_d)."); bp::def("erf", +[](const gdual_d &d) { return erf(d); }, "Error function (gdual_d)."); - // We expose the gdual arithmetic - pyaudi::expose_gdual("vdouble") + // We expose the gdual> arithmetic + pyaudi::expose_gdual>("vdouble") .def("__init__", bp::make_constructor( +[](const bp::object &value) { return ::new gdual_v(pyaudi::l_to_v(value)); })) .def("__init__", diff --git a/pyaudi/expose_gdual.hpp b/pyaudi/expose_gdual.hpp index 15a4219b..e923ad00 100644 --- a/pyaudi/expose_gdual.hpp +++ b/pyaudi/expose_gdual.hpp @@ -67,7 +67,7 @@ struct gdual_pickle_suite : bp::pickle_suite { }; // For non vectorized_double we do not perform any conversion on in-out types -template ::value, int> = 0> +template inline void expose_subs(bp::class_> th) { th.def("subs", +[](gdual &gd, const std::string &sym, const T &in) { return gd.subs(sym, in); }, @@ -75,12 +75,12 @@ inline void expose_subs(bp::class_> th) } // For vectorized double we perform conversion from and to lists so we need a different active template -template ::value, int> = 0> -inline void expose_subs(bp::class_> th) +template <> +inline void expose_subs(bp::class_>> th) { th.def( "subs", - +[](gdual &gd, const std::string &sym, const bp::object &in) { return gd.subs(sym, T(l_to_v(in))); }, + +[](gdual> &gd, const std::string &sym, const bp::object &in) { return gd.subs(sym, gdual>(l_to_v(in))); }, "Substitutes a symbol with a value (does not remove symbol from symbol set)"); } diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 870255d7..375874be 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -30,7 +30,7 @@ ENDMACRO(ADD_AUDI_PERFORMANCE_TESTCASE) ADD_AUDI_TESTCASE(gdual_d) ADD_AUDI_TESTCASE(gdual_v) ADD_AUDI_TESTCASE(gdual_v2) -ADD_AUDI_TESTCASE(vectorized_double) +ADD_AUDI_TESTCASE(vectorized) ADD_AUDI_TESTCASE(functions) ADD_AUDI_TESTCASE(functions_from_d) ADD_AUDI_TESTCASE(functions_floating_precision) diff --git a/tests/vectorized.cpp b/tests/vectorized.cpp new file mode 100644 index 00000000..a3079a6b --- /dev/null +++ b/tests/vectorized.cpp @@ -0,0 +1,121 @@ +#define BOOST_TEST_MODULE audi_gdual_test +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + + + +using namespace audi; + +template +void test_construction() { + // Default Constructor + { + vectorized x; + BOOST_CHECK(x.size() == 1); + BOOST_CHECK(*x.begin() == 0); + } + // Constructor from int. + { + vectorized x{123}; + BOOST_CHECK(x.size() == 1); + BOOST_CHECK(*x.begin() == 123); + } + // Constructor from T. + { + vectorized x{T(123.)}; + BOOST_CHECK(x.size() == 1); + BOOST_CHECK(*x.begin() == 123.); + } + // Constructor from an std::vector + { + std::vector in{T(1.), T(2.), T(3.), T(4.), T(2.2)}; + vectorized x(in); + BOOST_CHECK(x.size() == 5); + BOOST_CHECK(std::equal(in.begin(), in.end(), x.begin())); + std::vector empty; + // rvalue + BOOST_CHECK_THROW(vectorized(std::vector{}), std::invalid_argument); + // lvalue + BOOST_CHECK_THROW(vectorized{empty}, std::invalid_argument); + // initializer list + BOOST_CHECK_THROW(vectorized({}), std::invalid_argument); + } +} + +template +void test_math() { + { + vectorized x1{T(1.), T(1.), T(2.), T(-3.), T(4.)}; + vectorized x2{T(1.), T(1.), T(2.), T(3.), T(4.)}; + vectorized x3{T(-100.), T(-100.), T(-100.), T(-100.), T(-100.)}; + vectorized x4{T(100.), T(100.), T(100.), T(100.), T(100.)}; + BOOST_CHECK(abs(x1) == x2); + BOOST_CHECK(x3 < x1); + BOOST_CHECK(x1 > x3); + BOOST_CHECK(x2 < x4); + BOOST_CHECK(x4 > x2); + BOOST_CHECK(x1 < 100.); + BOOST_CHECK(-100 < x1); + BOOST_CHECK(100. > x1); + BOOST_CHECK(x1 > -100); + BOOST_CHECK(x1 != x2); + BOOST_CHECK(x1 == x1); + BOOST_CHECK(x3 == -100); + BOOST_CHECK(x4 == 100); + BOOST_CHECK(x3 != 32); + BOOST_CHECK(x4 != 32); + BOOST_CHECK(abs(x1) == x2); + BOOST_CHECK(abs(x2) != x1); + BOOST_CHECK(x1 - 1. == (vectorized{T(0.), T(0.), T(1.), T(-4.), T(3.)})); + } + { + vectorized x1{T(1.), T(2.)}; + vectorized x2{T(3.), T(3.)}; + // Interoperability against arith types + BOOST_CHECK(x1 * 2. == (vectorized{T(2.), T(4.)})); + BOOST_CHECK(x1 / 2. == (vectorized{T(0.5), T(1.)})); + BOOST_CHECK(x1 + 2. == (vectorized{T(3.), T(4.)})); + BOOST_CHECK(x1 - 2. == (vectorized{T(-1.), T(0.)})); + BOOST_CHECK(x1 * 2 == (vectorized{T(2.), T(4.)})); + BOOST_CHECK(x1 / 2 == (vectorized{T(0.5), T(1.)})); + BOOST_CHECK(x1 + 2 == (vectorized{T(3.), T(4.)})); + BOOST_CHECK(x1 - 2 == (vectorized{T(-1.), T(0.)})); + BOOST_CHECK(2 * x1 == (vectorized{T(2.), T(4.)})); + BOOST_CHECK(2 / x1 == (vectorized{T(2.), T(1.)})); + BOOST_CHECK(2 + x1 == (vectorized{T(3.), T(4.)})); + BOOST_CHECK(2 - x1 == (vectorized{T(1.), T(0.)})); + BOOST_CHECK(2 * x1 == (vectorized{T(2.), T(4.)})); + BOOST_CHECK(2 / x1 == (vectorized{T(2.), T(1.)})); + BOOST_CHECK(2 + x1 == (vectorized{T(3.), T(4.)})); + BOOST_CHECK(2 - x1 == (vectorized{T(1.), T(0.)})); + BOOST_CHECK(x1 != 1.); + BOOST_CHECK(x2 == 3.); + BOOST_CHECK(x1 > -1.); + BOOST_CHECK(x1 < 3.); + // operators with vectorized-vectorized + BOOST_CHECK(x1 + x2 == (vectorized{T(4.), T(5.)})); + BOOST_CHECK(x1 - x2 == (vectorized{T(-2.), T(-1.)})); + BOOST_CHECK(x1 / x2 == (vectorized{T(1.)/T(3.), T(2.)/T(3.)})); + BOOST_CHECK(x1 * x2 == (vectorized{T(3.), T(6.)})); + } +} + +BOOST_AUTO_TEST_CASE(construction) +{ + test_construction(); + test_construction(); +} +BOOST_AUTO_TEST_CASE(math) +{ + test_math(); + test_math(); +} From 48d1ca87569d87a8df90ec6227fb432e9e26f71a Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Tue, 22 May 2018 14:53:45 +0200 Subject: [PATCH 31/61] attempt to workaround CI issue --- include/audi/vectorized.hpp | 48 ++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/include/audi/vectorized.hpp b/include/audi/vectorized.hpp index d85e2a12..c6c72db1 100644 --- a/include/audi/vectorized.hpp +++ b/include/audi/vectorized.hpp @@ -59,41 +59,41 @@ class vectorized } // ------------------- Binary arithmetic operators implemented using the available +=,-=, etc. template = 0, operator_enabler = 0> - friend vectorized operator+(const T1 &d1v, const T2 &d2v) + friend vectorized operator+(const T1 &d1v, const T2 &d2v) { - vectorized d1(d1v); - vectorized d2(d2v); + vectorized d1(d1v); + vectorized d2(d2v); d1 += d2; return d1; } template = 0, operator_enabler = 0> friend vectorized operator-(const T1 &d1v, const T2 &d2v) { - vectorized d1(d1v); - vectorized d2(d2v); + vectorized d1(d1v); + vectorized d2(d2v); d1 -= d2; return d1; } template = 0, operator_enabler = 0> - friend vectorized operator*(const T1 &d1v, const T2 &d2v) + friend vectorized operator*(const T1 &d1v, const T2 &d2v) { - vectorized d1(d1v); - vectorized d2(d2v); + vectorized d1(d1v); + vectorized d2(d2v); d1 *= d2; return d1; } template = 0, operator_enabler = 0> - friend vectorized operator/(const T1 &d1v, const T2 &d2v) + friend vectorized operator/(const T1 &d1v, const T2 &d2v) { - vectorized d1(d1v); - vectorized d2(d2v); + vectorized d1(d1v); + vectorized d2(d2v); d1 /= d2; return d1; } // ----------------- Juice implementation of the operators. It also deals with the case [b1] op [a1,a2,..an] to // take care of scalar multiplication/division etc. - vectorized &operator+=(const vectorized &d1) + vectorized &operator+=(const vectorized &d1) { if (d1.size() == this->size()) { std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), std::plus()); @@ -110,7 +110,7 @@ class vectorized } throw std::invalid_argument("Coefficients of different sizes in +"); } - vectorized &operator-=(const vectorized &d1) + vectorized &operator-=(const vectorized &d1) { if (d1.size() == this->size()) { std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), std::minus()); @@ -127,7 +127,7 @@ class vectorized } throw std::invalid_argument("Coefficients of different sizes in -"); } - vectorized &operator*=(const vectorized &d1) + vectorized &operator*=(const vectorized &d1) { if (d1.size() == this->size()) { std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), @@ -145,7 +145,7 @@ class vectorized } throw std::invalid_argument("Coefficients of different sizes in *"); } - vectorized &operator/=(const vectorized &d1) + vectorized &operator/=(const vectorized &d1) { if (d1.size() == this->size()) { std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), @@ -164,24 +164,24 @@ class vectorized throw std::invalid_argument("Coefficients of different sizes in /"); } template - vectorized &operator/=(const T1 &d1) + vectorized &operator/=(const T1 &d1) { std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), [&d1](T x) { return x / d1; }); return *this; } - vectorized operator-() const + vectorized operator-() const { - vectorized retval(m_c); + vectorized retval(m_c); transform(retval.m_c.begin(), retval.m_c.end(), retval.m_c.begin(), std::negate()); return retval; } template = 0, operator_enabler = 0> friend bool operator==(const T1 &d1v, const T2 &d2v) { - vectorized d1(d1v); - vectorized d2(d2v); + vectorized d1(d1v); + vectorized d2(d2v); if (d1.size() == d2.size()) { return d1.m_c == d2.m_c; } else if (d1.size() == 1u) { @@ -199,8 +199,8 @@ class vectorized template = 0, operator_enabler = 0> friend bool operator>(const T1 &d1v, const T2 &d2v) { - vectorized d1(d1v); - vectorized d2(d2v); + vectorized d1(d1v); + vectorized d2(d2v); if (d1.size() == d2.size()) { return d1.m_c > d2.m_c; } else if (d1.size() == 1u) { @@ -214,8 +214,8 @@ class vectorized template = 0, operator_enabler = 0> friend bool operator<(const T1 &d1v, const T2 &d2v) { - vectorized d1(d1v); - vectorized d2(d2v); + vectorized d1(d1v); + vectorized d2(d2v); if (d1.size() == d2.size()) { return d1.m_c < d2.m_c; } else if (d1.size() == 1u) { From 0a7887cf7606d8d47640c412169e8a09e390d78a Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Tue, 22 May 2018 15:22:03 +0200 Subject: [PATCH 32/61] fix eigen url --- include/audi/CMakeLists.txt | 25 -------------------- include/audi/{detail => }/complex.hpp | 0 include/audi/detail/overloads_vectorized.hpp | 2 +- include/audi/vectorized.hpp | 2 +- tools/install_docker.sh | 2 +- 5 files changed, 3 insertions(+), 28 deletions(-) delete mode 100644 include/audi/CMakeLists.txt rename include/audi/{detail => }/complex.hpp (100%) diff --git a/include/audi/CMakeLists.txt b/include/audi/CMakeLists.txt deleted file mode 100644 index a1f18446..00000000 --- a/include/audi/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -set(HEADERS_LIST - functions.hpp - functions_from_d.hpp - audi.hpp - gdual.hpp - type_traits.hpp - vectorized_double.hpp - back_compatibility.hpp -) -set(HEADERS_LIST_DETAIL - detail/complex.hpp - detail/overloads.hpp -) -set(HEADERS_LIST_PYAUDI - ../pyaudi/expose_gdual.hpp -) - -# NOTE: this dummy cpp file is here with the sole purpose of getting the headers -# inside the project files generated by CMake. -add_library(audi_dummy STATIC audi_dummy.cpp ${HEADERS_LIST}) - -# TODO header installation. -install(FILES ${HEADERS_LIST} DESTINATION include/audi) -install(FILES ${HEADERS_LIST_DETAIL} DESTINATION include/audi/detail) -install(FILES ${HEADERS_LIST_PYAUDI} DESTINATION include/audi/pyaudi) diff --git a/include/audi/detail/complex.hpp b/include/audi/complex.hpp similarity index 100% rename from include/audi/detail/complex.hpp rename to include/audi/complex.hpp diff --git a/include/audi/detail/overloads_vectorized.hpp b/include/audi/detail/overloads_vectorized.hpp index d5aecc49..e5331c4a 100644 --- a/include/audi/detail/overloads_vectorized.hpp +++ b/include/audi/detail/overloads_vectorized.hpp @@ -4,7 +4,7 @@ #include #include -#include +#include // to find audi::fun_name(el) // This macro writes the overload for std::fun_name performing elementwise evaluations on a vectorized diff --git a/include/audi/vectorized.hpp b/include/audi/vectorized.hpp index c6c72db1..b13bb712 100644 --- a/include/audi/vectorized.hpp +++ b/include/audi/vectorized.hpp @@ -33,7 +33,7 @@ class vectorized // Default constructor. Constructs [0.] vectorized() : m_c({T(0.)}){}; - // Constructor other types + // Constructor from other, compatible, types template explicit vectorized(T1 a) : m_c({static_cast(a)}){} diff --git a/tools/install_docker.sh b/tools/install_docker.sh index af809cc9..c1079c18 100644 --- a/tools/install_docker.sh +++ b/tools/install_docker.sh @@ -76,7 +76,7 @@ gmake install > /dev/null cd .. # Install Eigen -curl -L https://github.com/RLovelett/eigen/archive/${EIGEN3_VERSION}.tar.gz > ${EIGEN3_VERSION} +curl -L http://bitbucket.org/eigen/eigen/get/${EIGEN3_VERSION}.tar.gz > ${EIGEN3_VERSION} tar xzf ${EIGEN3_VERSION} > /dev/null 2>&1 cd eigen-${EIGEN3_VERSION} mkdir build From 29df0918cc401b83e50f1b698f7d749bc2763e11 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Tue, 22 May 2018 17:43:15 +0200 Subject: [PATCH 33/61] fixing eigen dir name --- tools/install_docker.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/install_docker.sh b/tools/install_docker.sh index c1079c18..c0a6b5ec 100644 --- a/tools/install_docker.sh +++ b/tools/install_docker.sh @@ -78,7 +78,7 @@ cd .. # Install Eigen curl -L http://bitbucket.org/eigen/eigen/get/${EIGEN3_VERSION}.tar.gz > ${EIGEN3_VERSION} tar xzf ${EIGEN3_VERSION} > /dev/null 2>&1 -cd eigen-${EIGEN3_VERSION} +cd eigen* mkdir build cd build cmake ../ > /dev/null From a75ecda10ff32102e6f342551c8d247f6e338d79 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Tue, 22 May 2018 18:14:29 +0200 Subject: [PATCH 34/61] fixing eigen dir name --- include/audi/vectorized.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/audi/vectorized.hpp b/include/audi/vectorized.hpp index b13bb712..f74ce4fe 100644 --- a/include/audi/vectorized.hpp +++ b/include/audi/vectorized.hpp @@ -29,7 +29,7 @@ class vectorized public: template using operator_enabler - = enable_if_t<(std::is_same::value || std::is_arithmetic::value), int>; + = enable_if_t<(std::is_same>::value || std::is_arithmetic::value), int>; // Default constructor. Constructs [0.] vectorized() : m_c({T(0.)}){}; From 34635df59f5fe2794c9d274bec75157339ebf543 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Thu, 24 May 2018 14:36:19 +0200 Subject: [PATCH 35/61] [skip ci] fix for template gcc 4.8 bug --- include/audi/vectorized.hpp | 154 +++++++++++++++++++++++------------- pyaudi/expose_gdual.hpp | 2 +- 2 files changed, 99 insertions(+), 57 deletions(-) diff --git a/include/audi/vectorized.hpp b/include/audi/vectorized.hpp index f74ce4fe..4791657b 100644 --- a/include/audi/vectorized.hpp +++ b/include/audi/vectorized.hpp @@ -24,9 +24,9 @@ namespace audi // function calls operate element-wise. template -class vectorized +struct vectorized { -public: + using v_type = T; template using operator_enabler = enable_if_t<(std::is_same>::value || std::is_arithmetic::value), int>; @@ -177,59 +177,7 @@ class vectorized transform(retval.m_c.begin(), retval.m_c.end(), retval.m_c.begin(), std::negate()); return retval; } - template = 0, operator_enabler = 0> - friend bool operator==(const T1 &d1v, const T2 &d2v) - { - vectorized d1(d1v); - vectorized d2(d2v); - if (d1.size() == d2.size()) { - return d1.m_c == d2.m_c; - } else if (d1.size() == 1u) { - return std::all_of(d2.begin(), d2.end(), [d1](T x) { return x == d1[0]; }); - } else if (d2.size() == 1u) { - return std::all_of(d1.begin(), d1.end(), [d2](T x) { return x == d2[0]; }); - } - return false; - } - template = 0, operator_enabler = 0> - friend bool operator!=(const T1 &d1, const T2 &d2) - { - return !(d1 == d2); - } - template = 0, operator_enabler = 0> - friend bool operator>(const T1 &d1v, const T2 &d2v) - { - vectorized d1(d1v); - vectorized d2(d2v); - if (d1.size() == d2.size()) { - return d1.m_c > d2.m_c; - } else if (d1.size() == 1u) { - return std::all_of(d2.begin(), d2.end(), [d1](T x) { return d1[0] > x; }); - } else if (d2.size() == 1u) { - return std::all_of(d1.begin(), d1.end(), [d2](T x) { return x > d2[0]; }); - } - return false; - } - template = 0, operator_enabler = 0> - friend bool operator<(const T1 &d1v, const T2 &d2v) - { - vectorized d1(d1v); - vectorized d2(d2v); - if (d1.size() == d2.size()) { - return d1.m_c < d2.m_c; - } else if (d1.size() == 1u) { - return std::all_of(d2.begin(), d2.end(), [d1](T x) { return d1[0] < x; }); - } else if (d2.size() == 1u) { - return std::all_of(d1.begin(), d1.end(), [d2](T x) { return x < d2[0]; }); - } - return false; - } - //friend vectorized_double abs(vectorized_double in) - //{ - // std::transform(in.m_c.begin(), in.m_c.end(), in.m_c.begin(), [](const double &x) { return std::abs(x); }); - // return in; - //} friend std::ostream &operator<<(std::ostream &os, const vectorized &d) { os << "["; @@ -290,8 +238,6 @@ class vectorized return m_c; } -private: - friend class boost::serialization::access; template void serialize(Archive &ar, const unsigned int) { @@ -301,6 +247,102 @@ class vectorized std::vector m_c; }; +/// Type is a vectorized +/** + * Checks whether T is a vectorized type. Provides the member constant value which is equal to true, + * if T is the type vectorized for any U. + * + * \tparam T a type to check + */ + +template +struct is_vectorized : std::false_type { +}; +template +struct is_vectorized> : std::true_type { +}; + +// Binary operators +template ::value && is_vectorized::value), int> = 0> +bool operator==(const T1 &d1, const T2 &d2) +{ + if (d1.size() == d2.size()) { + return d1.m_c == d2.m_c; + } else if (d1.size() == 1u) { + return std::all_of(d2.begin(), d2.end(), [d1](typename T1::v_type x) { return x == d1[0]; }); + } else if (d2.size() == 1u) { + return std::all_of(d1.begin(), d1.end(), [d2](typename T1::v_type x) { return x == d2[0]; }); + } + return false; +} +template ::value && !is_vectorized::value), int> = 0> +bool operator==(const T1 &d1, const T2 &d2v) +{ + T1 d2(d2v); + return d1==d2; +} +template ::value && is_vectorized::value), int> = 0> +bool operator==(const T1 &d1v, const T2 &d2) +{ + T2 d1(d1v); + return d1==d2; +} + +template ::value || is_vectorized::value), int> = 0> +bool operator!=(const T1 &d1, const T2 &d2) +{ + return !(d1 == d2); +} + +template ::value && is_vectorized::value), int> = 0> +bool operator>(const T1 &d1, const T2 &d2) +{ + if (d1.size() == d2.size()) { + return d1.m_c > d2.m_c; + } else if (d1.size() == 1u) { + return std::all_of(d2.begin(), d2.end(), [d1](typename T1::v_type x) { return d1[0] > x; }); + } else if (d2.size() == 1u) { + return std::all_of(d1.begin(), d1.end(), [d2](typename T1::v_type x) { return x > d2[0]; }); + } + return false; +} +template ::value && !is_vectorized::value), int> = 0> +bool operator>(const T1 &d1, const T2 &d2v) +{ + T1 d2(d2v); + return d1>d2; +} +template ::value && is_vectorized::value), int> = 0> +bool operator>(const T1 &d1v, const T2 &d2) +{ + T2 d1(d1v); + return d1>d2; +} + +template ::value && is_vectorized::value), int> = 0> +bool operator<(const T1 &d1, const T2 &d2) +{ + if (d1.size() == d2.size()) { + return d1.m_c < d2.m_c; + } else if (d1.size() == 1u) { + return std::all_of(d2.begin(), d2.end(), [d1](typename T1::v_type x) { return d1[0] < x; }); + } else if (d2.size() == 1u) { + return std::all_of(d1.begin(), d1.end(), [d2](typename T1::v_type x) { return x < d2[0]; }); + } + return false; +} +template ::value && !is_vectorized::value), int> = 0> +bool operator<(const T1 &d1, const T2 &d2v) +{ + T1 d2(d2v); + return d1::value && is_vectorized::value), int> = 0> +bool operator<(const T1 &d1v, const T2 &d2) +{ + T2 d1(d1v); + return d1 struct gdual_pickle_suite : bp::pickle_suite { - static bp::tuple getinitargs(const gdual &w) + static bp::tuple getinitargs(const gdual &) { return bp::make_tuple(); } From fd36aaeac38c8815b21e89270f8a5b5675c599ee Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Thu, 24 May 2018 15:37:54 +0200 Subject: [PATCH 36/61] vectorize works finished. operators moved out of class --- include/audi/vectorized.hpp | 175 ++++++++++++++++++++++-------------- 1 file changed, 106 insertions(+), 69 deletions(-) diff --git a/include/audi/vectorized.hpp b/include/audi/vectorized.hpp index 4791657b..531d209e 100644 --- a/include/audi/vectorized.hpp +++ b/include/audi/vectorized.hpp @@ -12,6 +12,7 @@ #include +#include // The streaming operator will only output the first MAX_STREAMED_COMPONENTS elements of the vector #define MAX_STREAMED_COMPONENTS 5u @@ -24,18 +25,19 @@ namespace audi // function calls operate element-wise. template -struct vectorized -{ +struct vectorized { using v_type = T; template using operator_enabler = enable_if_t<(std::is_same>::value || std::is_arithmetic::value), int>; // Default constructor. Constructs [0.] vectorized() : m_c({T(0.)}){}; - + // Constructor from other, compatible, types - template - explicit vectorized(T1 a) : m_c({static_cast(a)}){} + template + explicit vectorized(T1 a) : m_c({static_cast(a)}) + { + } // Constructor from an std::vector explicit vectorized(const std::vector &c) : m_c(c) @@ -57,40 +59,6 @@ struct vectorized throw std::invalid_argument("Cannot build an empty coefficient_v (initializer)"); } } - // ------------------- Binary arithmetic operators implemented using the available +=,-=, etc. - template = 0, operator_enabler = 0> - friend vectorized operator+(const T1 &d1v, const T2 &d2v) - { - vectorized d1(d1v); - vectorized d2(d2v); - d1 += d2; - return d1; - } - template = 0, operator_enabler = 0> - friend vectorized operator-(const T1 &d1v, const T2 &d2v) - { - vectorized d1(d1v); - vectorized d2(d2v); - d1 -= d2; - return d1; - } - template = 0, operator_enabler = 0> - friend vectorized operator*(const T1 &d1v, const T2 &d2v) - { - vectorized d1(d1v); - vectorized d2(d2v); - d1 *= d2; - return d1; - } - template = 0, operator_enabler = 0> - friend vectorized operator/(const T1 &d1v, const T2 &d2v) - { - vectorized d1(d1v); - vectorized d2(d2v); - d1 /= d2; - return d1; - } - // ----------------- Juice implementation of the operators. It also deals with the case [b1] op [a1,a2,..an] to // take care of scalar multiplication/division etc. vectorized &operator+=(const vectorized &d1) @@ -99,8 +67,7 @@ struct vectorized std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), std::plus()); return *this; } else if (d1.size() == 1u) { - std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), - [&d1](T x) { return x + d1.m_c[0]; }); + std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), [&d1](T x) { return x + d1.m_c[0]; }); return *this; } else if (this->size() == 1u) { T scalar = m_c[0]; @@ -116,8 +83,7 @@ struct vectorized std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), std::minus()); return *this; } else if (d1.size() == 1u) { - std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), - [&d1](T x) { return x - d1.m_c[0]; }); + std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), [&d1](T x) { return x - d1.m_c[0]; }); return *this; } else if (this->size() == 1u) { T scalar = m_c[0]; @@ -130,12 +96,10 @@ struct vectorized vectorized &operator*=(const vectorized &d1) { if (d1.size() == this->size()) { - std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), - std::multiplies()); + std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), std::multiplies()); return *this; } else if (d1.size() == 1u) { - std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), - [&d1](T x) { return x * d1.m_c[0]; }); + std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), [&d1](T x) { return x * d1.m_c[0]; }); return *this; } else if (this->size() == 1u) { T scalar = m_c[0]; @@ -148,12 +112,10 @@ struct vectorized vectorized &operator/=(const vectorized &d1) { if (d1.size() == this->size()) { - std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), - std::divides()); + std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), std::divides()); return *this; } else if (d1.size() == 1u) { - std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), - [&d1](T x) { return x / d1.m_c[0]; }); + std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), [&d1](T x) { return x / d1.m_c[0]; }); return *this; } else if (this->size() == 1u) { T scalar = m_c[0]; @@ -166,10 +128,8 @@ struct vectorized template vectorized &operator/=(const T1 &d1) { - std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), - [&d1](T x) { return x / d1; }); - return *this; - + std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), [&d1](T x) { return x / d1; }); + return *this; } vectorized operator-() const { @@ -177,7 +137,6 @@ struct vectorized transform(retval.m_c.begin(), retval.m_c.end(), retval.m_c.begin(), std::negate()); return retval; } - friend std::ostream &operator<<(std::ostream &os, const vectorized &d) { os << "["; @@ -237,7 +196,6 @@ struct vectorized { return m_c; } - template void serialize(Archive &ar, const unsigned int) { @@ -262,7 +220,88 @@ template struct is_vectorized> : std::true_type { }; -// Binary operators +// ------------------- Binary arithmetic operators implemented using the available +=,-=, etc. +template ::value && is_vectorized::value), int> = 0> +T1 operator+(T1 d1v, T2 d2) +{ + T1 d1(d1v); + d1 += d2; + return d1; +} +template ::value && !is_vectorized::value), int> = 0> +T1 operator+(T1 d1, T2 d2v) +{ + T1 d2(d2v); + return d1 + d2; +} +template ::value && is_vectorized::value), int> = 0> +T2 operator+(T1 d1v, T2 d2) +{ + T2 d1(d1v); + return d1 + d2; +} + +template ::value && is_vectorized::value), int> = 0> +T1 operator-(T1 d1v, T2 d2) +{ + T1 d1(d1v); + d1 -= d2; + return d1; +} +template ::value && !is_vectorized::value), int> = 0> +T1 operator-(T1 d1, T2 d2v) +{ + T1 d2(d2v); + return d1 - d2; +} +template ::value && is_vectorized::value), int> = 0> +T2 operator-(T1 d1v, T2 d2) +{ + T2 d1(d1v); + return d1 - d2; +} + +template ::value && is_vectorized::value), int> = 0> +T1 operator*(T1 d1v, T2 d2) +{ + T1 d1(d1v); + d1 *= d2; + return d1; +} +template ::value && !is_vectorized::value), int> = 0> +T1 operator*(T1 d1, T2 d2v) +{ + T1 d2(d2v); + return d1 * d2; +} +template ::value && is_vectorized::value), int> = 0> +T2 operator*(T1 d1v, T2 d2) +{ + T2 d1(d1v); + return d1 * d2; +} + +template ::value && is_vectorized::value), int> = 0> +T1 operator/(T1 d1v, T2 d2) +{ + T1 d1(d1v); + d1 /= d2; + return d1; +} +template ::value && !is_vectorized::value), int> = 0> +T1 operator/(T1 d1, T2 d2v) +{ + T1 d2(d2v); + return d1 / d2; +} +template ::value && is_vectorized::value), int> = 0> +T2 operator/(T1 d1v, T2 d2) +{ + T2 d1(d1v); + return d1 / d2; +} + +// Various comparison operators template ::value && is_vectorized::value), int> = 0> bool operator==(const T1 &d1, const T2 &d2) { @@ -279,13 +318,13 @@ template ::value && !is bool operator==(const T1 &d1, const T2 &d2v) { T1 d2(d2v); - return d1==d2; + return d1 == d2; } template ::value && is_vectorized::value), int> = 0> bool operator==(const T1 &d1v, const T2 &d2) { T2 d1(d1v); - return d1==d2; + return d1 == d2; } template ::value || is_vectorized::value), int> = 0> @@ -310,13 +349,13 @@ template ::value && !is bool operator>(const T1 &d1, const T2 &d2v) { T1 d2(d2v); - return d1>d2; + return d1 > d2; } template ::value && is_vectorized::value), int> = 0> bool operator>(const T1 &d1v, const T2 &d2) { T2 d1(d1v); - return d1>d2; + return d1 > d2; } template ::value && is_vectorized::value), int> = 0> @@ -335,13 +374,13 @@ template ::value && !is bool operator<(const T1 &d1, const T2 &d2v) { T1 d2(d2v); - return d1::value && is_vectorized::value), int> = 0> bool operator<(const T1 &d1v, const T2 &d2) { T2 d1(d1v); - return d1, U> { audi::vectorized operator()(const audi::vectorized &c, const U &exp) const { auto retval(c); - std::transform(retval.begin(), retval.end(), retval.begin(), - [exp](T x) { return piranha::math::pow(x, exp); }); + std::transform(retval.begin(), retval.end(), retval.begin(), [exp](T x) { return piranha::math::pow(x, exp); }); return retval; }; }; -} // end of math namespace +} // namespace math template struct boost_save_impl> : boost_save_via_boost_api> { @@ -437,8 +475,7 @@ template struct zero_is_absorbing> : std::false_type { }; -} // end of piranha namespace - +} // namespace piranha #undef MAX_STREAMED_COMPONENTS #endif From fe1a15fe6198b3904c62451b47aa6f448cebd1bf Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Thu, 24 May 2018 15:45:30 +0200 Subject: [PATCH 37/61] vectorize works finished. operators moved out of class --- include/audi/type_traits.hpp | 15 --------------- include/audi/vectorized.hpp | 20 ++++++++++---------- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/include/audi/type_traits.hpp b/include/audi/type_traits.hpp index e38eae53..66ddd683 100644 --- a/include/audi/type_traits.hpp +++ b/include/audi/type_traits.hpp @@ -13,21 +13,6 @@ namespace audi { -/// Type is a gdual -/** - * Checks whether T is a gdual type. Provides the member constant value which is equal to true, - * if T is the type gdual for any U. - * - * \tparam T a type to check - */ - -template -struct is_gdual : std::false_type { -}; -template -struct is_gdual> : std::true_type { -}; - /// Type is arithmetic (includes multiple precision floats) /** * Checks whether T is an arithmetic type (that is, an integral type or a floating-point type that includes multiple diff --git a/include/audi/vectorized.hpp b/include/audi/vectorized.hpp index 531d209e..71eaeebd 100644 --- a/include/audi/vectorized.hpp +++ b/include/audi/vectorized.hpp @@ -12,7 +12,7 @@ #include -#include +#include // The streaming operator will only output the first MAX_STREAMED_COMPONENTS elements of the vector #define MAX_STREAMED_COMPONENTS 5u @@ -29,7 +29,7 @@ struct vectorized { using v_type = T; template using operator_enabler - = enable_if_t<(std::is_same>::value || std::is_arithmetic::value), int>; + = enable_if_t<(std::is_same>::value || audi::is_arithmetic::value), int>; // Default constructor. Constructs [0.] vectorized() : m_c({T(0.)}){}; @@ -228,13 +228,13 @@ T1 operator+(T1 d1v, T2 d2) d1 += d2; return d1; } -template ::value && !is_vectorized::value), int> = 0> +template ::value && audi::is_arithmetic::value), int> = 0> T1 operator+(T1 d1, T2 d2v) { T1 d2(d2v); return d1 + d2; } -template ::value && is_vectorized::value), int> = 0> +template ::value && is_vectorized::value), int> = 0> T2 operator+(T1 d1v, T2 d2) { T2 d1(d1v); @@ -248,13 +248,13 @@ T1 operator-(T1 d1v, T2 d2) d1 -= d2; return d1; } -template ::value && !is_vectorized::value), int> = 0> +template ::value && audi::is_arithmetic::value), int> = 0> T1 operator-(T1 d1, T2 d2v) { T1 d2(d2v); return d1 - d2; } -template ::value && is_vectorized::value), int> = 0> +template ::value && is_vectorized::value), int> = 0> T2 operator-(T1 d1v, T2 d2) { T2 d1(d1v); @@ -268,13 +268,13 @@ T1 operator*(T1 d1v, T2 d2) d1 *= d2; return d1; } -template ::value && !is_vectorized::value), int> = 0> +template ::value && audi::is_arithmetic::value), int> = 0> T1 operator*(T1 d1, T2 d2v) { T1 d2(d2v); return d1 * d2; } -template ::value && is_vectorized::value), int> = 0> +template ::value && is_vectorized::value), int> = 0> T2 operator*(T1 d1v, T2 d2) { T2 d1(d1v); @@ -288,13 +288,13 @@ T1 operator/(T1 d1v, T2 d2) d1 /= d2; return d1; } -template ::value && !is_vectorized::value), int> = 0> +template ::value && audi::is_arithmetic::value), int> = 0> T1 operator/(T1 d1, T2 d2v) { T1 d2(d2v); return d1 / d2; } -template ::value && is_vectorized::value), int> = 0> +template ::value && is_vectorized::value), int> = 0> T2 operator/(T1 d1v, T2 d2) { T2 d1(d1v); From 429af2593b347c4cacea911d61eacd723a0ae7da Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Thu, 24 May 2018 16:14:10 +0200 Subject: [PATCH 38/61] CI fix try 1 --- include/audi/type_traits.hpp | 6 +++--- include/audi/vectorized.hpp | 16 ++++++++-------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/audi/type_traits.hpp b/include/audi/type_traits.hpp index 66ddd683..5b9ec03b 100644 --- a/include/audi/type_traits.hpp +++ b/include/audi/type_traits.hpp @@ -1,15 +1,15 @@ #ifndef AUDI_TYPE_TRAITS_HPP #define AUDI_TYPE_TRAITS_HPP +#include +#include + #include #if defined(AUDI_WITH_MPPP) #include #endif -#include - -#include namespace audi { diff --git a/include/audi/vectorized.hpp b/include/audi/vectorized.hpp index 71eaeebd..8b853d8f 100644 --- a/include/audi/vectorized.hpp +++ b/include/audi/vectorized.hpp @@ -59,8 +59,7 @@ struct vectorized { throw std::invalid_argument("Cannot build an empty coefficient_v (initializer)"); } } - // ----------------- Juice implementation of the operators. It also deals with the case [b1] op [a1,a2,..an] to - // take care of scalar multiplication/division etc. + // ----------------- Juice implementation of the operators. It deals with the case [b1] op [a1,a2,..an]. vectorized &operator+=(const vectorized &d1) { if (d1.size() == this->size()) { @@ -314,13 +313,14 @@ bool operator==(const T1 &d1, const T2 &d2) } return false; } -template ::value && !is_vectorized::value), int> = 0> + +template ::value && audi::is_arithmetic::value), int> = 0> bool operator==(const T1 &d1, const T2 &d2v) { T1 d2(d2v); return d1 == d2; } -template ::value && is_vectorized::value), int> = 0> +template ::value && is_vectorized::value), int> = 0> bool operator==(const T1 &d1v, const T2 &d2) { T2 d1(d1v); @@ -345,13 +345,13 @@ bool operator>(const T1 &d1, const T2 &d2) } return false; } -template ::value && !is_vectorized::value), int> = 0> +template ::value && audi::is_arithmetic::value), int> = 0> bool operator>(const T1 &d1, const T2 &d2v) { T1 d2(d2v); return d1 > d2; } -template ::value && is_vectorized::value), int> = 0> +template ::value && is_vectorized::value), int> = 0> bool operator>(const T1 &d1v, const T2 &d2) { T2 d1(d1v); @@ -370,13 +370,13 @@ bool operator<(const T1 &d1, const T2 &d2) } return false; } -template ::value && !is_vectorized::value), int> = 0> +template ::value && audi::is_arithmetic::value), int> = 0> bool operator<(const T1 &d1, const T2 &d2v) { T1 d2(d2v); return d1 < d2; } -template ::value && is_vectorized::value), int> = 0> +template ::value && is_vectorized::value), int> = 0> bool operator<(const T1 &d1v, const T2 &d2) { T2 d1(d1v); From 6af735b0c7408ecc38e8ba4653e8b3566090b65b Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Thu, 24 May 2018 16:48:21 +0200 Subject: [PATCH 39/61] headers resolution improved --- include/audi/functions.hpp | 1 + include/audi/vectorized.hpp | 111 ++++++++++++++++++------------------ tests/vectorized.cpp | 6 +- 3 files changed, 58 insertions(+), 60 deletions(-) diff --git a/include/audi/functions.hpp b/include/audi/functions.hpp index 13cfc8af..4b9bd2ba 100644 --- a/include/audi/functions.hpp +++ b/include/audi/functions.hpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #include diff --git a/include/audi/vectorized.hpp b/include/audi/vectorized.hpp index 8b853d8f..ba9f95bb 100644 --- a/include/audi/vectorized.hpp +++ b/include/audi/vectorized.hpp @@ -26,10 +26,14 @@ namespace audi template struct vectorized { + // type to be vectorized using v_type = T; + + // enables operators between vectorized types and arithmetic types (extended to include mppp::real128) template using operator_enabler = enable_if_t<(std::is_same>::value || audi::is_arithmetic::value), int>; + // Default constructor. Constructs [0.] vectorized() : m_c({T(0.)}){}; @@ -59,19 +63,19 @@ struct vectorized { throw std::invalid_argument("Cannot build an empty coefficient_v (initializer)"); } } - // ----------------- Juice implementation of the operators. It deals with the case [b1] op [a1,a2,..an]. + // ----------------- Juice implementation of operators. It deals with the case [b1] op [a1,a2,..an]. vectorized &operator+=(const vectorized &d1) { if (d1.size() == this->size()) { std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), std::plus()); return *this; } else if (d1.size() == 1u) { - std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), [&d1](T x) { return x + d1.m_c[0]; }); + std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), [&d1](const T &x) { return x + d1.m_c[0]; }); return *this; } else if (this->size() == 1u) { T scalar = m_c[0]; this->resize(d1.size()); - std::transform(d1.m_c.begin(), d1.m_c.end(), this->m_c.begin(), [scalar](T x) { return x + scalar; }); + std::transform(d1.m_c.begin(), d1.m_c.end(), this->m_c.begin(), [scalar](const T &x) { return x + scalar; }); return *this; } throw std::invalid_argument("Coefficients of different sizes in +"); @@ -82,12 +86,12 @@ struct vectorized { std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), std::minus()); return *this; } else if (d1.size() == 1u) { - std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), [&d1](T x) { return x - d1.m_c[0]; }); + std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), [&d1](const T &x) { return x - d1.m_c[0]; }); return *this; } else if (this->size() == 1u) { T scalar = m_c[0]; this->resize(d1.size()); - std::transform(d1.m_c.begin(), d1.m_c.end(), this->m_c.begin(), [scalar](T x) { return scalar - x; }); + std::transform(d1.m_c.begin(), d1.m_c.end(), this->m_c.begin(), [scalar](const T &x) { return scalar - x; }); return *this; } throw std::invalid_argument("Coefficients of different sizes in -"); @@ -98,12 +102,12 @@ struct vectorized { std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), std::multiplies()); return *this; } else if (d1.size() == 1u) { - std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), [&d1](T x) { return x * d1.m_c[0]; }); + std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), [&d1](const T &x) { return x * d1.m_c[0]; }); return *this; } else if (this->size() == 1u) { T scalar = m_c[0]; this->resize(d1.size()); - std::transform(d1.m_c.begin(), d1.m_c.end(), this->m_c.begin(), [scalar](T x) { return scalar * x; }); + std::transform(d1.m_c.begin(), d1.m_c.end(), this->m_c.begin(), [scalar](const T &x) { return scalar * x; }); return *this; } throw std::invalid_argument("Coefficients of different sizes in *"); @@ -114,12 +118,12 @@ struct vectorized { std::transform(this->m_c.begin(), this->m_c.end(), d1.m_c.begin(), this->m_c.begin(), std::divides()); return *this; } else if (d1.size() == 1u) { - std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), [&d1](T x) { return x / d1.m_c[0]; }); + std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), [&d1](const T &x) { return x / d1.m_c[0]; }); return *this; } else if (this->size() == 1u) { T scalar = m_c[0]; this->resize(d1.size()); - std::transform(d1.m_c.begin(), d1.m_c.end(), this->m_c.begin(), [scalar](T x) { return scalar / x; }); + std::transform(d1.m_c.begin(), d1.m_c.end(), this->m_c.begin(), [scalar](const T &x) { return scalar / x; }); return *this; } throw std::invalid_argument("Coefficients of different sizes in /"); @@ -127,7 +131,7 @@ struct vectorized { template vectorized &operator/=(const T1 &d1) { - std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), [&d1](T x) { return x / d1; }); + std::transform(this->m_c.begin(), this->m_c.end(), this->m_c.begin(), [&d1](const T &x) { return x / d1; }); return *this; } vectorized operator-() const @@ -136,6 +140,13 @@ struct vectorized { transform(retval.m_c.begin(), retval.m_c.end(), retval.m_c.begin(), std::negate()); return retval; } + T operator[](const typename std::vector::size_type idx) const + { + if (m_c.size() == 1u) { + return m_c[0]; + } + return m_c[idx]; + } friend std::ostream &operator<<(std::ostream &os, const vectorized &d) { os << "["; @@ -180,13 +191,6 @@ struct vectorized { { m_c.resize(new_size, val); } - T operator[](const typename std::vector::size_type idx) const - { - if (m_c.size() == 1u) { - return m_c[0]; - } - return m_c[idx]; - } void set_value(const typename std::vector::size_type idx, T val) { m_c[idx] = val; @@ -201,8 +205,9 @@ struct vectorized { ar &m_c; } + // The container std::vector m_c; -}; +}; // end of struct vectorized /// Type is a vectorized /** @@ -219,82 +224,78 @@ template struct is_vectorized> : std::true_type { }; -// ------------------- Binary arithmetic operators implemented using the available +=,-=, etc. +// ------------------- Binary arithmetic operators implemented using the available operators +=,-=, etc. template ::value && is_vectorized::value), int> = 0> -T1 operator+(T1 d1v, T2 d2) +inline T1 operator+(T1 d1, const T2 &d2) { - T1 d1(d1v); d1 += d2; return d1; } template ::value && audi::is_arithmetic::value), int> = 0> -T1 operator+(T1 d1, T2 d2v) +inline T1 operator+(T1 d1, const T2 &d2v) { T1 d2(d2v); return d1 + d2; } template ::value && is_vectorized::value), int> = 0> -T2 operator+(T1 d1v, T2 d2) +T2 operator+(T1 d1v, const T2 &d2) { T2 d1(d1v); return d1 + d2; } template ::value && is_vectorized::value), int> = 0> -T1 operator-(T1 d1v, T2 d2) +inline T1 operator-(T1 d1, const T2 &d2) { - T1 d1(d1v); d1 -= d2; return d1; } template ::value && audi::is_arithmetic::value), int> = 0> -T1 operator-(T1 d1, T2 d2v) +inline T1 operator-(T1 d1, const T2 &d2v) { T1 d2(d2v); return d1 - d2; } template ::value && is_vectorized::value), int> = 0> -T2 operator-(T1 d1v, T2 d2) +inline T2 operator-(T1 d1v, const T2 &d2) { T2 d1(d1v); return d1 - d2; } template ::value && is_vectorized::value), int> = 0> -T1 operator*(T1 d1v, T2 d2) +inline T1 operator*(T1 d1, const T2 &d2) { - T1 d1(d1v); d1 *= d2; return d1; } template ::value && audi::is_arithmetic::value), int> = 0> -T1 operator*(T1 d1, T2 d2v) +inline T1 operator*(T1 d1, const T2 &d2v) { T1 d2(d2v); return d1 * d2; } template ::value && is_vectorized::value), int> = 0> -T2 operator*(T1 d1v, T2 d2) +inline T2 operator*(T1 d1v, const T2 &d2) { T2 d1(d1v); return d1 * d2; } template ::value && is_vectorized::value), int> = 0> -T1 operator/(T1 d1v, T2 d2) +inline T1 operator/(T1 d1, const T2 &d2) { - T1 d1(d1v); d1 /= d2; return d1; } template ::value && audi::is_arithmetic::value), int> = 0> -T1 operator/(T1 d1, T2 d2v) +inline T1 operator/(T1 d1, const T2 &d2v) { T1 d2(d2v); return d1 / d2; } template ::value && is_vectorized::value), int> = 0> -T2 operator/(T1 d1v, T2 d2) +inline T2 operator/(T1 d1v, const T2 &d2) { T2 d1(d1v); return d1 / d2; @@ -302,82 +303,82 @@ T2 operator/(T1 d1v, T2 d2) // Various comparison operators template ::value && is_vectorized::value), int> = 0> -bool operator==(const T1 &d1, const T2 &d2) +inline bool operator==(const T1 &d1, const T2 &d2) { if (d1.size() == d2.size()) { return d1.m_c == d2.m_c; } else if (d1.size() == 1u) { - return std::all_of(d2.begin(), d2.end(), [d1](typename T1::v_type x) { return x == d1[0]; }); + return std::all_of(d2.begin(), d2.end(), [d1](const typename T1::v_type &x) { return x == d1[0]; }); } else if (d2.size() == 1u) { - return std::all_of(d1.begin(), d1.end(), [d2](typename T1::v_type x) { return x == d2[0]; }); + return std::all_of(d1.begin(), d1.end(), [d2](const typename T1::v_type &x) { return x == d2[0]; }); } return false; } template ::value && audi::is_arithmetic::value), int> = 0> -bool operator==(const T1 &d1, const T2 &d2v) +inline bool operator==(const T1 &d1, const T2 &d2v) { T1 d2(d2v); return d1 == d2; } template ::value && is_vectorized::value), int> = 0> -bool operator==(const T1 &d1v, const T2 &d2) +inline bool operator==(const T1 &d1v, const T2 &d2) { T2 d1(d1v); return d1 == d2; } template ::value || is_vectorized::value), int> = 0> -bool operator!=(const T1 &d1, const T2 &d2) +inline bool operator!=(const T1 &d1, const T2 &d2) { return !(d1 == d2); } template ::value && is_vectorized::value), int> = 0> -bool operator>(const T1 &d1, const T2 &d2) +inline bool operator>(const T1 &d1, const T2 &d2) { if (d1.size() == d2.size()) { return d1.m_c > d2.m_c; } else if (d1.size() == 1u) { - return std::all_of(d2.begin(), d2.end(), [d1](typename T1::v_type x) { return d1[0] > x; }); + return std::all_of(d2.begin(), d2.end(), [d1](const typename T1::v_type &x) { return d1[0] > x; }); } else if (d2.size() == 1u) { - return std::all_of(d1.begin(), d1.end(), [d2](typename T1::v_type x) { return x > d2[0]; }); + return std::all_of(d1.begin(), d1.end(), [d2](const typename T1::v_type &x) { return x > d2[0]; }); } return false; } template ::value && audi::is_arithmetic::value), int> = 0> -bool operator>(const T1 &d1, const T2 &d2v) +inline bool operator>(const T1 &d1, const T2 &d2v) { T1 d2(d2v); return d1 > d2; } template ::value && is_vectorized::value), int> = 0> -bool operator>(const T1 &d1v, const T2 &d2) +inline bool operator>(const T1 &d1v, const T2 &d2) { T2 d1(d1v); return d1 > d2; } template ::value && is_vectorized::value), int> = 0> -bool operator<(const T1 &d1, const T2 &d2) +inline bool operator<(const T1 &d1, const T2 &d2) { if (d1.size() == d2.size()) { return d1.m_c < d2.m_c; } else if (d1.size() == 1u) { - return std::all_of(d2.begin(), d2.end(), [d1](typename T1::v_type x) { return d1[0] < x; }); + return std::all_of(d2.begin(), d2.end(), [d1](const typename T1::v_type &x) { return d1[0] < x; }); } else if (d2.size() == 1u) { - return std::all_of(d1.begin(), d1.end(), [d2](typename T1::v_type x) { return x < d2[0]; }); + return std::all_of(d1.begin(), d1.end(), [d2](const typename T1::v_type &x) { return x < d2[0]; }); } return false; } template ::value && audi::is_arithmetic::value), int> = 0> -bool operator<(const T1 &d1, const T2 &d2v) +inline bool operator<(const T1 &d1, const T2 &d2v) { T1 d2(d2v); return d1 < d2; } template ::value && is_vectorized::value), int> = 0> -bool operator<(const T1 &d1v, const T2 &d2) +inline bool operator<(const T1 &d1v, const T2 &d2) { T2 d1(d1v); return d1 < d2; @@ -394,7 +395,7 @@ template struct is_zero_impl> { bool operator()(const audi::vectorized &v) const { - return std::all_of(v.begin(), v.end(), [](T x) { return x == 0.; }); + return std::all_of(v.begin(), v.end(), [](const T &x) { return x == 0.; }); } }; @@ -420,13 +421,13 @@ struct mul3_impl> { if (out.size() != b.size()) { out.resize(b.size()); } - std::transform(b.begin(), b.end(), out.begin(), [a](T item) { return item * a[0]; }); + std::transform(b.begin(), b.end(), out.begin(), [a](const T &item) { return item * a[0]; }); return; } else if (b.size() == 1u) { if (out.size() != a.size()) { out.resize(a.size()); } - std::transform(a.begin(), a.end(), out.begin(), [b](T item) { return item * b[0]; }); + std::transform(a.begin(), a.end(), out.begin(), [b](const T &item) { return item * b[0]; }); return; } throw std::invalid_argument("Coefficients of different sizes in mul3"); @@ -456,7 +457,7 @@ struct pow_impl, U> { audi::vectorized operator()(const audi::vectorized &c, const U &exp) const { auto retval(c); - std::transform(retval.begin(), retval.end(), retval.begin(), [exp](T x) { return piranha::math::pow(x, exp); }); + std::transform(retval.begin(), retval.end(), retval.begin(), [exp](const T &x) { return piranha::math::pow(x, exp); }); return retval; }; }; diff --git a/tests/vectorized.cpp b/tests/vectorized.cpp index a3079a6b..ab313465 100644 --- a/tests/vectorized.cpp +++ b/tests/vectorized.cpp @@ -7,11 +7,7 @@ #include #include -#include -#include -#include - - +#include using namespace audi; From d682c7d9480363aac964f15946e2a489f1db63f9 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Thu, 24 May 2018 18:23:08 +0200 Subject: [PATCH 40/61] test CI appveyor debug --- appveyor.yml | 10 +++++----- tests/vectorized.cpp | 16 +++++++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 20c5be50..f3f7410c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,11 +2,11 @@ environment: TWINE_PASSWORD: secure: M+qvYgRh05fEw6G9aglK4g== matrix: - - BUILD_TYPE: "Python36" - - BUILD_TYPE: "Python27" - - BUILD_TYPE: "Python34" - - BUILD_TYPE: "Python35" - - BUILD_TYPE: "Release" + #- BUILD_TYPE: "Python36" + #- BUILD_TYPE: "Python27" + #- BUILD_TYPE: "Python34" + #- BUILD_TYPE: "Python35" + #- BUILD_TYPE: "Release" - BUILD_TYPE: "Debug" global: PLATFORMTOOLSET: "v140" diff --git a/tests/vectorized.cpp b/tests/vectorized.cpp index ab313465..8e5deeec 100644 --- a/tests/vectorized.cpp +++ b/tests/vectorized.cpp @@ -11,8 +11,9 @@ using namespace audi; -template -void test_construction() { +template +void test_construction() +{ // Default Constructor { vectorized x; @@ -47,8 +48,9 @@ void test_construction() { } } -template -void test_math() { +template +void test_math() +{ { vectorized x1{T(1.), T(1.), T(2.), T(-3.), T(4.)}; vectorized x2{T(1.), T(1.), T(2.), T(3.), T(4.)}; @@ -100,7 +102,7 @@ void test_math() { // operators with vectorized-vectorized BOOST_CHECK(x1 + x2 == (vectorized{T(4.), T(5.)})); BOOST_CHECK(x1 - x2 == (vectorized{T(-2.), T(-1.)})); - BOOST_CHECK(x1 / x2 == (vectorized{T(1.)/T(3.), T(2.)/T(3.)})); + BOOST_CHECK(x1 / x2 == (vectorized{T(1.) / T(3.), T(2.) / T(3.)})); BOOST_CHECK(x1 * x2 == (vectorized{T(3.), T(6.)})); } } @@ -108,10 +110,14 @@ void test_math() { BOOST_AUTO_TEST_CASE(construction) { test_construction(); +#if defined(AUDI_WITH_MPPP) test_construction(); +#endif } BOOST_AUTO_TEST_CASE(math) { test_math(); +#if defined(AUDI_WITH_MPPP) test_math(); +#endif } From 34f03ab0d04c4488705dd34d3c7a411a1ffac22b Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Thu, 24 May 2018 19:39:51 +0200 Subject: [PATCH 41/61] test CI appveyor debug --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index f3f7410c..31efb6cd 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -25,5 +25,5 @@ artifacts: # Enable this to be able to login to the build worker. You can use the # `remmina` program in Ubuntu, or Microsoft Remote Desktop app in osx # use the login information that the line below prints into the log. -#on_finish: -# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) +on_finish: + - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) From b9a02b6b979bb9a0bb5d55ce5d8e7a479f6e5236 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 09:18:56 +0200 Subject: [PATCH 42/61] trial on appveyor for function stuff --- .travis.yml | 32 ++++++++++++++++---------------- appveyor.yml | 4 ++-- tests/functions.cpp | 4 ++++ tools/install_appveyor.py | 3 +++ 4 files changed, 25 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index a880e7de..b4a11628 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,22 +9,22 @@ env: matrix: include: - - env: AUDI_BUILD="manylinux64Py36" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" - sudo: required - services: - - docker - - env: AUDI_BUILD="manylinux64Py35" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" - sudo: required - services: - - docker - - env: AUDI_BUILD="manylinux64Py34" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" - sudo: required - services: - - docker - - env: AUDI_BUILD="manylinux64Py27" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" - sudo: required - services: - - docker + #- env: AUDI_BUILD="manylinux64Py36" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" + # sudo: required + # services: + # - docker + #- env: AUDI_BUILD="manylinux64Py35" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" + # sudo: required + # services: + # - docker + #- env: AUDI_BUILD="manylinux64Py34" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" + # sudo: required + # services: + # - docker + #- env: AUDI_BUILD="manylinux64Py27" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" + # sudo: required + # services: + # - docker install: - docker pull $DOCKER_IMAGE script: diff --git a/appveyor.yml b/appveyor.yml index 31efb6cd..f3f7410c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -25,5 +25,5 @@ artifacts: # Enable this to be able to login to the build worker. You can use the # `remmina` program in Ubuntu, or Microsoft Remote Desktop app in osx # use the login information that the line below prints into the log. -on_finish: - - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) +#on_finish: +# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) diff --git a/tests/functions.cpp b/tests/functions.cpp index 3a13ca80..b5358a09 100644 --- a/tests/functions.cpp +++ b/tests/functions.cpp @@ -67,6 +67,10 @@ BOOST_AUTO_TEST_CASE(square_root) auto p2 = x * x * y - x * y * x * x * x - 3 * y * y * y * y * x * y * x; // negative coefficient BOOST_CHECK(EPSILON_COMPARE(sqrt(p1) * sqrt(p1), p1, 1e-12) == true); BOOST_CHECK(EPSILON_COMPARE(sqrt(p2) * sqrt(p2), p2, 1e-12) == true); + +print(p2,"\n"); +print(sqrt(p2),"\n"); +print(sqrt(p2)*sqrt(p2),"\n"); } BOOST_AUTO_TEST_CASE(cubic_root) diff --git a/tools/install_appveyor.py b/tools/install_appveyor.py index 3811870d..13069a74 100644 --- a/tools/install_appveyor.py +++ b/tools/install_appveyor.py @@ -153,6 +153,9 @@ def run_command(raw_command, directory=None, verbose=True): r' -DAUDI_BUILD_TESTS=yes ' + common_cmake_opts run_command(r'cmake -G "MinGW Makefiles" .. ' + cmake_opts) run_command(r'mingw32-make install VERBOSE=1 -j2') + os.chdir('tests') + run_command(r'functions.exe') + os.chdir('../') run_command(r'ctest') else: raise RuntimeError('Unsupported build type: ' + BUILD_TYPE) From f975c4d439936d88d425fbdab1df77518ae9d5aa Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 09:21:25 +0200 Subject: [PATCH 43/61] trial on appveyor for function stuff N.2 --- include/audi/functions.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/audi/functions.hpp b/include/audi/functions.hpp index 4b9bd2ba..08065747 100644 --- a/include/audi/functions.hpp +++ b/include/audi/functions.hpp @@ -237,15 +237,15 @@ inline gdual sqrt(const gdual &d) { T alpha(0.5); gdual retval(1.); - auto p0 = d.constant_cf(); - auto sqrt_p0 = audi::sqrt(p0); + T p0 = d.constant_cf(); + T sqrt_p0 = audi::sqrt(p0); - auto phat = d - p0; + gdual phat = d - p0; phat = phat / p0; gdual tmp(phat); retval += alpha * phat; - for (auto i = 2u; i <= d.get_order(); ++i) { + for (decltype(d.get_order()) i = 2u; i <= d.get_order(); ++i) { phat *= tmp; retval += binomial(alpha, i) * phat; } @@ -275,15 +275,15 @@ inline gdual cbrt(const gdual &d) { T alpha(T(1.) / T(3.)); gdual retval(1.); - auto p0 = d.constant_cf(); - auto cbrt_p0 = audi::cbrt(p0); + T p0 = d.constant_cf(); + T cbrt_p0 = audi::cbrt(p0); - auto phat = d - p0; + gdual phat = d - p0; phat = phat / p0; gdual tmp(phat); retval += alpha * phat; - for (auto i = 2u; i <= d.get_order(); ++i) { + for (decltype(d.get_order()) i = 2u; i <= d.get_order(); ++i) { phat *= tmp; retval += binomial(alpha, i) * phat; } From 30529edd48f26e0f0e089c48e68a81c6689aaece Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 09:27:11 +0200 Subject: [PATCH 44/61] trial on appveyor for function stuff N.3 --- tests/functions.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/functions.cpp b/tests/functions.cpp index b5358a09..1c8a3132 100644 --- a/tests/functions.cpp +++ b/tests/functions.cpp @@ -9,6 +9,8 @@ #include #include +#include + using namespace audi; using gdual_d = gdual; From 94171930dd7295a6e54bfd93871004c68a5688f8 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 09:36:45 +0200 Subject: [PATCH 45/61] trial on appveyor for function stuff N.4 --- tests/functions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/functions.cpp b/tests/functions.cpp index 1c8a3132..51e0b8e7 100644 --- a/tests/functions.cpp +++ b/tests/functions.cpp @@ -47,7 +47,7 @@ BOOST_AUTO_TEST_CASE(exponentiation) // We check the implementation of pow(gdual_d, double) with respect to the behaviour in 0. // We compute the Taylor expansion of f = x^3.1 around 0. Which is T_f = 0. + 0.dx + 0.dx^2 + 0.dx^3 + inf dx^4-inf // dx^5 ... - + gdual_d x(0., "x", 7); auto f = pow(x, 3.1); BOOST_CHECK_EQUAL(f.find_cf({0}), 0.); From caf776ccd6dada662caea730a597dca7364f3115 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 09:53:29 +0200 Subject: [PATCH 46/61] trial on appveyor for function stuff N.5 --- tests/functions.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/functions.cpp b/tests/functions.cpp index 51e0b8e7..81459982 100644 --- a/tests/functions.cpp +++ b/tests/functions.cpp @@ -70,9 +70,10 @@ BOOST_AUTO_TEST_CASE(square_root) BOOST_CHECK(EPSILON_COMPARE(sqrt(p1) * sqrt(p1), p1, 1e-12) == true); BOOST_CHECK(EPSILON_COMPARE(sqrt(p2) * sqrt(p2), p2, 1e-12) == true); -print(p2,"\n"); -print(sqrt(p2),"\n"); -print(sqrt(p2)*sqrt(p2),"\n"); +print("p2: ", p2,"\n"); +print("sqrt(p2): ", sqrt(p2),"\n"); +print("p2: ", sqrt(p2)*sqrt(p2),"\n"); +print("sqrt : ", sqrt(-154.554),"\n"); } BOOST_AUTO_TEST_CASE(cubic_root) From 47f96c4942dcff7c0e511cf3a65cec14ad13bd74 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 10:04:16 +0200 Subject: [PATCH 47/61] trial on appveyor for function stuff N.6 --- tests/functions.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/functions.cpp b/tests/functions.cpp index 81459982..1984be7f 100644 --- a/tests/functions.cpp +++ b/tests/functions.cpp @@ -73,7 +73,9 @@ BOOST_AUTO_TEST_CASE(square_root) print("p2: ", p2,"\n"); print("sqrt(p2): ", sqrt(p2),"\n"); print("p2: ", sqrt(p2)*sqrt(p2),"\n"); -print("sqrt : ", sqrt(-154.554),"\n"); +print("sqrt (std): ", std::sqrt(-154.554),"\n"); +print("sqrt (audi): ", audi::sqrt(-154.554),"\n"); + } BOOST_AUTO_TEST_CASE(cubic_root) From a63c66206c5a56f7c03cd1883676f0c5c10f0ebb Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 11:02:12 +0200 Subject: [PATCH 48/61] trial on appveyor for function stuff N.7 --- tests/functions.cpp | 10 +++------- tools/install_appveyor.py | 3 --- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/tests/functions.cpp b/tests/functions.cpp index 1984be7f..f3033f80 100644 --- a/tests/functions.cpp +++ b/tests/functions.cpp @@ -68,14 +68,10 @@ BOOST_AUTO_TEST_CASE(square_root) auto p1 = x * x * y - x * y * x * x * x + 3 * y * y * y * y * x * y * x; // positive p0 auto p2 = x * x * y - x * y * x * x * x - 3 * y * y * y * y * x * y * x; // negative coefficient BOOST_CHECK(EPSILON_COMPARE(sqrt(p1) * sqrt(p1), p1, 1e-12) == true); +// The following test fails under old version of mingw as sqrt(-a) returns a!!! (https://sourceforge.net/p/mingw-w64/bugs/567/) +#ifndef __MINGW32__ BOOST_CHECK(EPSILON_COMPARE(sqrt(p2) * sqrt(p2), p2, 1e-12) == true); - -print("p2: ", p2,"\n"); -print("sqrt(p2): ", sqrt(p2),"\n"); -print("p2: ", sqrt(p2)*sqrt(p2),"\n"); -print("sqrt (std): ", std::sqrt(-154.554),"\n"); -print("sqrt (audi): ", audi::sqrt(-154.554),"\n"); - +#endif } BOOST_AUTO_TEST_CASE(cubic_root) diff --git a/tools/install_appveyor.py b/tools/install_appveyor.py index 13069a74..3811870d 100644 --- a/tools/install_appveyor.py +++ b/tools/install_appveyor.py @@ -153,9 +153,6 @@ def run_command(raw_command, directory=None, verbose=True): r' -DAUDI_BUILD_TESTS=yes ' + common_cmake_opts run_command(r'cmake -G "MinGW Makefiles" .. ' + cmake_opts) run_command(r'mingw32-make install VERBOSE=1 -j2') - os.chdir('tests') - run_command(r'functions.exe') - os.chdir('../') run_command(r'ctest') else: raise RuntimeError('Unsupported build type: ' + BUILD_TYPE) From be345009e5f29aa6e633d97ce958c7acf6ef849e Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 11:16:40 +0200 Subject: [PATCH 49/61] activating mppp --- tools/install_appveyor.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tools/install_appveyor.py b/tools/install_appveyor.py index 3811870d..552e7bce 100644 --- a/tools/install_appveyor.py +++ b/tools/install_appveyor.py @@ -89,6 +89,20 @@ def run_command(raw_command, directory=None, verbose=True): os.chdir('../../') print("Piranha sucessfully installed .. continuing") +# Download mppp 0.11 https://github.com/bluescarni/mppp/archive/v0.11.zip +wget(r'https://github.com/bluescarni/mppp/archive/v0.11.zip', 'mpppv10.zip') +run_command(r'unzip mpppv10.zip', verbose=False) +# Move to the directory created and make piranha install its headers +os.chdir('mppp-0.11') +os.makedirs('build') +os.chdir('build') +print("Installing mppp") +run_command( + r'cmake -G "MinGW Makefiles" .. -DMPPP_WITH_QUADMATH=yes -DCMAKE_INSTALL_PREFIX=c:\\local ', verbose=False) +run_command(r'mingw32-make install VERBOSE=1', verbose=False) +os.chdir('../../') +print("mppp sucessfully installed .. continuing") + # Setup of the dependencies for a Python build. if is_python_build: if BUILD_TYPE == 'Python34': @@ -131,7 +145,7 @@ def run_command(raw_command, directory=None, verbose=True): os.environ['PATH'] = os.environ['PATH'] + r';c:\\local\\lib' # Proceed to the build. -common_cmake_opts = r'-DCMAKE_PREFIX_PATH=c:\\local -DCMAKE_INSTALL_PREFIX=c:\\local' +common_cmake_opts = r'-DCMAKE_PREFIX_PATH=c:\\local -DCMAKE_INSTALL_PREFIX=c:\\local -DAUDI_WITH_MPPP=yes' # Configuration step. if is_python_build: From 4bfb4cac5ebfa630e0d719d8bba6383bbc62a06a Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 11:34:05 +0200 Subject: [PATCH 50/61] activating mppp #2 --- tools/install_appveyor.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/install_appveyor.py b/tools/install_appveyor.py index 552e7bce..677fdb84 100644 --- a/tools/install_appveyor.py +++ b/tools/install_appveyor.py @@ -153,20 +153,20 @@ def run_command(raw_command, directory=None, verbose=True): os.chdir('build_audi') run_command( r'cmake -G "MinGW Makefiles" .. -DCMAKE_BUILD_TYPE=Release -DAUDI_BUILD_TESTS=no -DAUDI_BUILD_AUDI=yes -DAUDI_BUILD_PYAUDI=no' + ' ' + common_cmake_opts) - run_command(r'mingw32-make install VERBOSE=1 -j2') + run_command(r'mingw32-make install VERBOSE=1') os.chdir('..') os.makedirs('build_pyaudi') os.chdir('build_pyaudi') run_command(r'cmake -G "MinGW Makefiles" .. -DPYAUDI_INSTALL_PATH=c:\\local -DAUDI_BUILD_AUDI=no -DAUDI_BUILD_PYAUDI=yes -DCMAKE_BUILD_TYPE=Release ' + common_cmake_opts + r' -DBoost_PYTHON_LIBRARY_RELEASE=c:\\local\\lib\\libboost_python' + (python_version[0] if python_version[0] == '3' else r'') + r'-mgw62-mt-1_63.dll -DPYTHON_EXECUTABLE=C:\\Python' + python_version + r'\\python.exe -DPYTHON_LIBRARY=C:\\Python' + python_version + r'\\libs\\python' + python_version + r'.dll') - run_command(r'mingw32-make install VERBOSE=1 -j2') + run_command(r'mingw32-make install VERBOSE=1') elif BUILD_TYPE in ['Release', 'Debug']: os.makedirs('build_audi') os.chdir('build_audi') cmake_opts = r'-DCMAKE_BUILD_TYPE=' + BUILD_TYPE + \ r' -DAUDI_BUILD_TESTS=yes ' + common_cmake_opts run_command(r'cmake -G "MinGW Makefiles" .. ' + cmake_opts) - run_command(r'mingw32-make install VERBOSE=1 -j2') + run_command(r'mingw32-make install VERBOSE=1 -Wa -mbig-obj') run_command(r'ctest') else: raise RuntimeError('Unsupported build type: ' + BUILD_TYPE) From 7e57fc6172047e9696603179449fc47530674bbc Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 11:39:06 +0200 Subject: [PATCH 51/61] activating mppp #3 --- tools/install_appveyor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/install_appveyor.py b/tools/install_appveyor.py index 677fdb84..0e3a980f 100644 --- a/tools/install_appveyor.py +++ b/tools/install_appveyor.py @@ -166,7 +166,7 @@ def run_command(raw_command, directory=None, verbose=True): cmake_opts = r'-DCMAKE_BUILD_TYPE=' + BUILD_TYPE + \ r' -DAUDI_BUILD_TESTS=yes ' + common_cmake_opts run_command(r'cmake -G "MinGW Makefiles" .. ' + cmake_opts) - run_command(r'mingw32-make install VERBOSE=1 -Wa -mbig-obj') + run_command(r'mingw32-make install VERBOSE=1') run_command(r'ctest') else: raise RuntimeError('Unsupported build type: ' + BUILD_TYPE) From 86057c3cf5281ad2348ba6d1d4182383fab5d293 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 11:45:39 +0200 Subject: [PATCH 52/61] activating mppp #4 --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index be735c4e..6ef344b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,8 +81,8 @@ endif() if(MINGW) # Flag needed to deal with big binaries in MinGW. message(STATUS "Enabling the '-Wa,-mbig-obj' flag in MinGW builds.") - list(APPEND AUDI_CXX_FLAGS_DEBUG "-Wa,-mbig-obj") - list(APPEND AUDI_CXX_FLAGS_RELEASE "-Wa,-mbig-obj") + list(APPEND AUDI_CXX_FLAGS_DEBUG "-Wa -mbig-obj") + list(APPEND AUDI_CXX_FLAGS_RELEASE "-Wa -mbig-obj") endif() # Some flags that generate warnings due to Eigen or Piranha obsolete versions From dec95ac6e79a9c77cb08054886b8e4f89ad4487d Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 11:51:55 +0200 Subject: [PATCH 53/61] activating mppp #5 --- CMakeLists.txt | 4 ++-- tests/gdual_v.cpp | 1 - tests/gdual_v2.cpp | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ef344b9..be735c4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,8 +81,8 @@ endif() if(MINGW) # Flag needed to deal with big binaries in MinGW. message(STATUS "Enabling the '-Wa,-mbig-obj' flag in MinGW builds.") - list(APPEND AUDI_CXX_FLAGS_DEBUG "-Wa -mbig-obj") - list(APPEND AUDI_CXX_FLAGS_RELEASE "-Wa -mbig-obj") + list(APPEND AUDI_CXX_FLAGS_DEBUG "-Wa,-mbig-obj") + list(APPEND AUDI_CXX_FLAGS_RELEASE "-Wa,-mbig-obj") endif() # Some flags that generate warnings due to Eigen or Piranha obsolete versions diff --git a/tests/gdual_v.cpp b/tests/gdual_v.cpp index 9fc3c2dc..f79e4d76 100644 --- a/tests/gdual_v.cpp +++ b/tests/gdual_v.cpp @@ -6,7 +6,6 @@ #include #include -#include "helpers.hpp" #include using namespace audi; diff --git a/tests/gdual_v2.cpp b/tests/gdual_v2.cpp index 633f95c1..989e2f05 100644 --- a/tests/gdual_v2.cpp +++ b/tests/gdual_v2.cpp @@ -6,7 +6,6 @@ #include #include -#include "helpers.hpp" #include using namespace audi; From cf5d2733cbd3adf621d4cf310e9d2471a9a9c287 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 12:01:59 +0200 Subject: [PATCH 54/61] activating mppp #6 --- include/audi/vectorized.hpp | 1 - tests/gdual_v2.cpp | 13 ++++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/audi/vectorized.hpp b/include/audi/vectorized.hpp index ba9f95bb..de85d31a 100644 --- a/include/audi/vectorized.hpp +++ b/include/audi/vectorized.hpp @@ -11,7 +11,6 @@ #include #include - #include // The streaming operator will only output the first MAX_STREAMED_COMPONENTS elements of the vector diff --git a/tests/gdual_v2.cpp b/tests/gdual_v2.cpp index 989e2f05..3d18ab83 100644 --- a/tests/gdual_v2.cpp +++ b/tests/gdual_v2.cpp @@ -6,7 +6,18 @@ #include #include -#include +#include + +#if defined(AUDI_WITH_MPPP) +#include +#endif + +#include +#include +#include + +using gdual_v = audi::gdual>; + using namespace audi; From d6560c34796f74459242bbfe4827dca0452e6bc3 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 12:03:37 +0200 Subject: [PATCH 55/61] activating mppp #7 --- tests/gdual_v2.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/gdual_v2.cpp b/tests/gdual_v2.cpp index 3d18ab83..e7a531ff 100644 --- a/tests/gdual_v2.cpp +++ b/tests/gdual_v2.cpp @@ -1,6 +1,4 @@ #define BOOST_TEST_MODULE audi_gdualv2_test -#include -#include #include #include From 42eafff2cb411f0382dc995205735c3e7f17c805 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 12:15:02 +0200 Subject: [PATCH 56/61] activating mppp #8 --- tests/gdual_v.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tests/gdual_v.cpp b/tests/gdual_v.cpp index f79e4d76..621e4c20 100644 --- a/tests/gdual_v.cpp +++ b/tests/gdual_v.cpp @@ -1,15 +1,24 @@ #define BOOST_TEST_MODULE audi_gdualv_test -#include -#include + #include #include #include -#include +#include + +#if defined(AUDI_WITH_MPPP) +#include +#endif + +#include +#include +#include using namespace audi; +using gdual_v = audi::gdual>; + BOOST_AUTO_TEST_CASE(construction) { // Constructing a vectorized constant From afa9f6127ac2497907b09ab72e6739a3fc2c19aa Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 12:45:02 +0200 Subject: [PATCH 57/61] Reactivating all builds --- .travis.yml | 32 ++++++++++++++++---------------- tests/gdual_v.cpp | 1 + tests/gdual_v2.cpp | 1 - tools/install_appveyor.py | 6 +++--- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.travis.yml b/.travis.yml index b4a11628..a880e7de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,22 +9,22 @@ env: matrix: include: - #- env: AUDI_BUILD="manylinux64Py36" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" - # sudo: required - # services: - # - docker - #- env: AUDI_BUILD="manylinux64Py35" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" - # sudo: required - # services: - # - docker - #- env: AUDI_BUILD="manylinux64Py34" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" - # sudo: required - # services: - # - docker - #- env: AUDI_BUILD="manylinux64Py27" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" - # sudo: required - # services: - # - docker + - env: AUDI_BUILD="manylinux64Py36" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" + sudo: required + services: + - docker + - env: AUDI_BUILD="manylinux64Py35" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" + sudo: required + services: + - docker + - env: AUDI_BUILD="manylinux64Py34" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" + sudo: required + services: + - docker + - env: AUDI_BUILD="manylinux64Py27" DOCKER_IMAGE="quay.io/pypa/manylinux1_x86_64" + sudo: required + services: + - docker install: - docker pull $DOCKER_IMAGE script: diff --git a/tests/gdual_v.cpp b/tests/gdual_v.cpp index 621e4c20..3b675ffe 100644 --- a/tests/gdual_v.cpp +++ b/tests/gdual_v.cpp @@ -19,6 +19,7 @@ using namespace audi; using gdual_v = audi::gdual>; + BOOST_AUTO_TEST_CASE(construction) { // Constructing a vectorized constant diff --git a/tests/gdual_v2.cpp b/tests/gdual_v2.cpp index e7a531ff..3295401f 100644 --- a/tests/gdual_v2.cpp +++ b/tests/gdual_v2.cpp @@ -16,7 +16,6 @@ using gdual_v = audi::gdual>; - using namespace audi; BOOST_AUTO_TEST_CASE(substitution) diff --git a/tools/install_appveyor.py b/tools/install_appveyor.py index 0e3a980f..552e7bce 100644 --- a/tools/install_appveyor.py +++ b/tools/install_appveyor.py @@ -153,20 +153,20 @@ def run_command(raw_command, directory=None, verbose=True): os.chdir('build_audi') run_command( r'cmake -G "MinGW Makefiles" .. -DCMAKE_BUILD_TYPE=Release -DAUDI_BUILD_TESTS=no -DAUDI_BUILD_AUDI=yes -DAUDI_BUILD_PYAUDI=no' + ' ' + common_cmake_opts) - run_command(r'mingw32-make install VERBOSE=1') + run_command(r'mingw32-make install VERBOSE=1 -j2') os.chdir('..') os.makedirs('build_pyaudi') os.chdir('build_pyaudi') run_command(r'cmake -G "MinGW Makefiles" .. -DPYAUDI_INSTALL_PATH=c:\\local -DAUDI_BUILD_AUDI=no -DAUDI_BUILD_PYAUDI=yes -DCMAKE_BUILD_TYPE=Release ' + common_cmake_opts + r' -DBoost_PYTHON_LIBRARY_RELEASE=c:\\local\\lib\\libboost_python' + (python_version[0] if python_version[0] == '3' else r'') + r'-mgw62-mt-1_63.dll -DPYTHON_EXECUTABLE=C:\\Python' + python_version + r'\\python.exe -DPYTHON_LIBRARY=C:\\Python' + python_version + r'\\libs\\python' + python_version + r'.dll') - run_command(r'mingw32-make install VERBOSE=1') + run_command(r'mingw32-make install VERBOSE=1 -j2') elif BUILD_TYPE in ['Release', 'Debug']: os.makedirs('build_audi') os.chdir('build_audi') cmake_opts = r'-DCMAKE_BUILD_TYPE=' + BUILD_TYPE + \ r' -DAUDI_BUILD_TESTS=yes ' + common_cmake_opts run_command(r'cmake -G "MinGW Makefiles" .. ' + cmake_opts) - run_command(r'mingw32-make install VERBOSE=1') + run_command(r'mingw32-make install VERBOSE=1 -j2') run_command(r'ctest') else: raise RuntimeError('Unsupported build type: ' + BUILD_TYPE) From 61a87af2dfff291a0192becd5398672bd2a6d117 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 12:59:30 +0200 Subject: [PATCH 58/61] Peace is restored in the galaxygit push --- appveyor.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index f3f7410c..20c5be50 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,11 +2,11 @@ environment: TWINE_PASSWORD: secure: M+qvYgRh05fEw6G9aglK4g== matrix: - #- BUILD_TYPE: "Python36" - #- BUILD_TYPE: "Python27" - #- BUILD_TYPE: "Python34" - #- BUILD_TYPE: "Python35" - #- BUILD_TYPE: "Release" + - BUILD_TYPE: "Python36" + - BUILD_TYPE: "Python27" + - BUILD_TYPE: "Python34" + - BUILD_TYPE: "Python35" + - BUILD_TYPE: "Release" - BUILD_TYPE: "Debug" global: PLATFORMTOOLSET: "v140" From 52d70cd82e73854dab6eb81f1063a3da77035099 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 13:22:14 +0200 Subject: [PATCH 59/61] Peace is restored in the galaxy N2 --- tools/mingw_wheel_libs_python3.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/mingw_wheel_libs_python3.txt b/tools/mingw_wheel_libs_python3.txt index 836333cf..67d4c6c4 100644 --- a/tools/mingw_wheel_libs_python3.txt +++ b/tools/mingw_wheel_libs_python3.txt @@ -3,3 +3,4 @@ c:\local\lib\libboost_serialization-mgw62-mt-1_63.dll c:\mingw64\bin\libgcc_s_seh-1.dll c:\mingw64\bin\libstdc++-6.dll c:\mingw64\bin\libwinpthread-1.dll +c:\mingw64\bin\libquadmath-0.dll From cc609f14a3ca187ecd9559b057812a3063fa9151 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 13:22:34 +0200 Subject: [PATCH 60/61] Peace is restored in the galaxy N3 --- tools/mingw_wheel_libs_python2.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/mingw_wheel_libs_python2.txt b/tools/mingw_wheel_libs_python2.txt index 55c52f12..6375567e 100644 --- a/tools/mingw_wheel_libs_python2.txt +++ b/tools/mingw_wheel_libs_python2.txt @@ -3,3 +3,4 @@ c:\local\lib\libboost_serialization-mgw62-mt-1_63.dll c:\mingw64\bin\libgcc_s_seh-1.dll c:\mingw64\bin\libstdc++-6.dll c:\mingw64\bin\libwinpthread-1.dll +c:\mingw64\bin\libquadmath-0.dll From 2c68c58e940957921c89baa67fab09366ab67eb3 Mon Sep 17 00:00:00 2001 From: Dario Izzo Date: Fri, 25 May 2018 13:24:11 +0200 Subject: [PATCH 61/61] Peace is restored in the galaxy N4 --- tools/mingw_wheel_libs_python2.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/mingw_wheel_libs_python2.txt b/tools/mingw_wheel_libs_python2.txt index 6375567e..c0fbf8e9 100644 --- a/tools/mingw_wheel_libs_python2.txt +++ b/tools/mingw_wheel_libs_python2.txt @@ -3,4 +3,4 @@ c:\local\lib\libboost_serialization-mgw62-mt-1_63.dll c:\mingw64\bin\libgcc_s_seh-1.dll c:\mingw64\bin\libstdc++-6.dll c:\mingw64\bin\libwinpthread-1.dll -c:\mingw64\bin\libquadmath-0.dll +c:\mingw64\bin\libquadmath-0.dll \ No newline at end of file