#include <boost/array.hpp>
#include <boost/timer.hpp>
#include <boost/fusion/algorithm/iteration/accumulate.hpp>
#include <boost/fusion/algorithm/transformation/transform.hpp>
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/algorithm/transformation/zip.hpp>
#include <boost/fusion/sequence/intrinsic/at.hpp>
#include <boost/fusion/adapted/array.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <algorithm>
#include <numeric>
#include <functional>
#include <iostream>
#include <cmath>
#include <limits>
#ifdef _MSC_VER
# pragma inline_recursion(on)
# pragma inline_depth(255)
#endif
int const REPEAT_COUNT = 10;
double const duration = 0.5;
namespace
{
template<int N>
double time_for_std_accumulate(int& j)
{
boost::timer tim;
int i = 0;
long long iter = 65536;
long long counter, repeats;
double result = (std::numeric_limits<double>::max)();
double runtime = 0;
double run;
boost::array<int, N> arr;
std::generate(arr.begin(), arr.end(), rand);
do
{
tim.restart();
for(counter = 0; counter < iter; ++counter)
{
i = std::accumulate(arr.begin(), arr.end(), 0);
static_cast<void>(i);
}
runtime = tim.elapsed();
iter *= 2;
} while(runtime < duration);
iter /= 2;
for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
{
tim.restart();
for(counter = 0; counter < iter; ++counter)
{
i = std::accumulate(arr.begin(), arr.end(), 0);
j += i;
}
run = tim.elapsed();
result = (std::min)(run, result);
}
std::cout << i << std::endl;
return result / iter;
}
struct poly_add
{
template<typename Sig>
struct result;
template<typename Lhs, typename Rhs>
struct result<poly_add(Lhs,Rhs)>
: boost::remove_reference<Lhs>
{};
template<typename Lhs, typename Rhs>
Lhs operator()(const Lhs& lhs, const Rhs& rhs) const
{
return lhs + rhs;
}
};
struct poly_mult
{
template<typename Sig>
struct result;
template<typename Lhs, typename Rhs>
struct result<poly_mult(Lhs, Rhs)>
: boost::remove_reference<Lhs>
{};
template<typename Lhs, typename Rhs>
Lhs operator()(const Lhs& lhs, const Rhs& rhs) const
{
return lhs * rhs;
}
};
template<int N>
double time_for_fusion_accumulate(int& j)
{
boost::timer tim;
int i = 0;
long long iter = 65536;
long long counter, repeats;
double result = (std::numeric_limits<double>::max)();
double runtime = 0;
double run;
boost::array<int, N> arr;
std::generate(arr.begin(), arr.end(), rand);
do
{
tim.restart();
for(counter = 0; counter < iter; ++counter)
{
i = boost::fusion::accumulate(arr, 0, poly_add());
static_cast<void>(i);
}
runtime = tim.elapsed();
iter *= 2;
} while(runtime < duration);
iter /= 2;
std::cout << iter << " iterations" << std::endl;
for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
{
tim.restart();
for(counter = 0; counter < iter; ++counter)
{
i = boost::fusion::accumulate(arr, 0, poly_add());
j += i;
}
run = tim.elapsed();
result = (std::min)(run, result);
std::cout << ".";
std::cout.flush();
}
std::cout << i << std::endl;
return result / iter;
}
#if 0#endif
}
int main()
{
int total = 0;
int res;
std::cout << "short accumulate std test " << time_for_std_accumulate<8>(res) << std::endl;
total += res;
std::cout << "short accumulate fusion test " << time_for_fusion_accumulate<8>(res) << std::endl;
total += res;
std::cout << "medium accumulate std test " << time_for_std_accumulate<64>(res) << std::endl;
total += res;
std::cout << "medium accumulate fusion test " << time_for_fusion_accumulate<64>(res) << std::endl;
total += res;
std::cout << "long accumulate std test " << time_for_std_accumulate<128>(res) << std::endl;
total += res;
std::cout << "long accumulate fusion test " << time_for_fusion_accumulate<128>(res) << std::endl;
total += res;
#if 0#endif
return total;
}