math/reporting/performance/test_polynomial.cpp
2017-08-20 08:28:41 +01:00

264 lines
9.2 KiB
C++

///////////////////////////////////////////////////////////////
// Copyright 2017 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
#define BOOST_CHRONO_HEADER_ONLY
#ifdef _MSC_VER
# define _SCL_SECURE_NO_WARNINGS
#endif
#include "performance.hpp"
#include "table_helper.hpp"
#include <boost/random.hpp>
#include <boost/math/tools/polynomial.hpp>
#include <boost/multiprecision/cpp_int.hpp>
unsigned max_reps = 1000;
template <class T>
struct tester
{
tester()
{
a.assign(500, T());
for(int i = 0; i < 500; ++i)
{
b.push_back(generate_random(false));
c.push_back(generate_random(false));
small.push_back(generate_random(true));
}
}
double test_add()
{
stopwatch<boost::chrono::high_resolution_clock> w;
for (unsigned repeats = 0; repeats < max_reps; ++repeats)
{
for(unsigned i = 0; i < b.size(); ++i)
a[i] = b[i] + c[i];
}
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
}
double test_subtract()
{
stopwatch<boost::chrono::high_resolution_clock> w;
for (unsigned repeats = 0; repeats < max_reps; ++repeats)
{
for(unsigned i = 0; i < b.size(); ++i)
a[i] = b[i] - c[i];
}
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
}
double test_add_int()
{
stopwatch<boost::chrono::high_resolution_clock> w;
for (unsigned repeats = 0; repeats < max_reps; ++repeats)
{
for(unsigned i = 0; i < b.size(); ++i)
a[i] = b[i] + 1;
}
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
}
double test_subtract_int()
{
stopwatch<boost::chrono::high_resolution_clock> w;
for (unsigned repeats = 0; repeats < max_reps; ++repeats)
{
for(unsigned i = 0; i < b.size(); ++i)
a[i] = b[i] - 1;
}
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
}
double test_multiply()
{
stopwatch<boost::chrono::high_resolution_clock> w;
for (unsigned repeats = 0; repeats < max_reps; ++repeats)
{
for(unsigned k = 0; k < b.size(); ++k)
a[k] = b[k] * c[k];
}
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
}
double test_multiply_int()
{
stopwatch<boost::chrono::high_resolution_clock> w;
for (unsigned repeats = 0; repeats < max_reps; ++repeats)
{
for(unsigned i = 0; i < b.size(); ++i)
a[i] = b[i] * 3;
}
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
}
double test_divide()
{
stopwatch<boost::chrono::high_resolution_clock> w;
for (unsigned repeats = 0; repeats < max_reps; ++repeats)
{
for(unsigned i = 0; i < b.size(); ++i)
a[i] = b[i] / small[i];
}
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
}
double test_divide_int()
{
stopwatch<boost::chrono::high_resolution_clock> w;
for (unsigned repeats = 0; repeats < max_reps; ++repeats)
{
for(unsigned i = 0; i < b.size(); ++i)
a[i] = b[i] / 3;
}
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
}
double test_gcd()
{
using boost::integer::gcd;
stopwatch<boost::chrono::high_resolution_clock> w;
for (unsigned repeats = 0; repeats < max_reps; ++repeats)
{
for(unsigned i = 0; i < b.size(); ++i)
a[i] = gcd(b[i], c[i]);
}
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
}
double test_inplace_add()
{
stopwatch<boost::chrono::high_resolution_clock> w;
for (unsigned repeats = 0; repeats < max_reps; ++repeats)
{
for (unsigned i = 0; i < b.size(); ++i)
b[i] += c[i];
}
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
}
double test_inplace_subtract()
{
stopwatch<boost::chrono::high_resolution_clock> w;
for (unsigned repeats = 0; repeats < max_reps; ++repeats)
{
for (unsigned i = 0; i < b.size(); ++i)
b[i] -= c[i];
}
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
}
double test_inplace_add_int()
{
stopwatch<boost::chrono::high_resolution_clock> w;
for (unsigned repeats = 0; repeats < max_reps; ++repeats)
{
for (unsigned i = 0; i < b.size(); ++i)
b[i] += 1;
}
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
}
double test_inplace_subtract_int()
{
stopwatch<boost::chrono::high_resolution_clock> w;
for (unsigned repeats = 0; repeats < max_reps; ++repeats)
{
for (unsigned i = 0; i < b.size(); ++i)
b[i] -= 1;
}
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
}
double test_inplace_multiply()
{
stopwatch<boost::chrono::high_resolution_clock> w;
for (unsigned repeats = 0; repeats < max_reps; ++repeats)
{
for (unsigned k = 0; k < b.size(); ++k)
b[k] *= c[k];
}
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
}
double test_inplace_multiply_int()
{
stopwatch<boost::chrono::high_resolution_clock> w;
for (unsigned repeats = 0; repeats < max_reps; ++repeats)
{
for (unsigned i = 0; i < b.size(); ++i)
b[i] *= 3;
}
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
}
double test_inplace_divide()
{
stopwatch<boost::chrono::high_resolution_clock> w;
for (unsigned repeats = 0; repeats < max_reps; ++repeats)
{
for (unsigned i = 0; i < b.size(); ++i)
a[i] /= small[i];
}
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
}
double test_inplace_divide_int()
{
stopwatch<boost::chrono::high_resolution_clock> w;
for (unsigned repeats = 0; repeats < max_reps; ++repeats)
{
for (unsigned i = 0; i < b.size(); ++i)
b[i] /= 3;
}
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
}
private:
T generate_random(bool issmall)
{
boost::uniform_int<> ui(2, issmall ? 5 : 40), ui2(1, 10000);
std::size_t len = ui(gen);
std::vector<typename T::value_type> values;
for (std::size_t i = 0; i < len; ++i)
{
values.push_back(static_cast<typename T::value_type>(ui2(gen)));
}
return T(values.begin(), values.end());
}
std::vector<T> a, b, c, small;
static boost::random::mt19937 gen;
};
template <class N>
boost::random::mt19937 tester<N>::gen;
template <class Number>
void test(const char* type)
{
std::cout << "Testing type: " << type << std::endl;
tester<boost::math::tools::polynomial<Number> > t;
int count = 500 * max_reps;
std::string table_name = "Polynomial Arithmetic (" + compiler_name() + ", " + platform_name() + ")";
//
// Now the actual tests:
//
report_execution_time(t.test_add() / count, table_name, "operator +", type);
report_execution_time(t.test_subtract() / count, table_name, "operator -", type);
report_execution_time(t.test_multiply() / count, table_name, "operator *", type);
report_execution_time(t.test_divide() / count, table_name, "operator /", type);
report_execution_time(t.test_add_int() / count, table_name, "operator + (int)", type);
report_execution_time(t.test_subtract_int() / count, table_name, "operator - (int)", type);
report_execution_time(t.test_multiply_int() / count, table_name, "operator * (int)", type);
report_execution_time(t.test_divide_int() / count, table_name, "operator / (int)", type);
report_execution_time(t.test_inplace_add() / count, table_name, "operator +=", type);
report_execution_time(t.test_inplace_subtract() / count, table_name, "operator -=", type);
report_execution_time(t.test_inplace_multiply() / count, table_name, "operator *=", type);
report_execution_time(t.test_inplace_divide() / count, table_name, "operator /=", type);
report_execution_time(t.test_inplace_add_int() / count, table_name, "operator += (int)", type);
report_execution_time(t.test_inplace_subtract_int() / count, table_name, "operator -= (int)", type);
report_execution_time(t.test_inplace_multiply_int() / count, table_name, "operator *= (int)", type);
report_execution_time(t.test_inplace_divide_int() / count, table_name, "operator /= (int)", type);
//report_execution_time(t.test_gcd() / count, table_name, "gcd", type);
}
int main()
{
test<boost::uint64_t>("boost::uint64_t");
test<double>("double");
max_reps = 100;
test<boost::multiprecision::cpp_int>("cpp_int");
return 0;
}