double correlation_parallel(const VD& data1, const VD& data2)
{
    if (data1.size() != data2.size())
        return 0;
    std::promise<corr_intermediate> sum1_promise;
    std::future<corr_intermediate> sum1_future = sum1_promise.get_future();
    std::thread sum1_thread(
        correlation_parallel_helper,
        data1.begin(), data1.end(),
        std::move(sum1_promise));
    std::promise<corr_intermediate> sum2_promise;
    std::future<corr_intermediate> sum2_future = sum2_promise.get_future();
    std::thread sum2_thread(
        correlation_parallel_helper,
        data2.begin(), data2.end(),
        std::move(sum2_promise));

    corr_intermediate itm1 = std::move(sum1_future.get());
    corr_intermediate itm2 = std::move(sum2_future.get());
    sum1_thread.join();
    sum2_thread.join();
    if (!itm1.stdev || !itm2.stdev)
        return 0;
    return std::inner_product(itm1.Y.constBegin(), itm1.Y.constEnd(), itm2.Y.constBegin(), 0);
}
void init(VD & t, int & n, PDD * p, PDD & a, PDD & b) {
	t.clear();
	double tmp;
	for (int i = 0; i < n; ++i) {
		scanf("%lf", &tmp);
		t.PB(tmp);
	}
	std::sort(t.begin(), t.end());
	t.erase(std::unique(t.begin(), t.end()), t.end());
	n = t.size();
	for (int i = 0; i < n; ++i) {
		p[i] = at(a, b, t[i]);
	}
}
void MLComputeTest::correlation_benchmark_parallel()
{
    VD data;
    data.resize(10000);
    std::iota(data.begin(), data.end(), 1);
    QBENCHMARK
    {
        correlation_parallel(data, data);
    }
}
void MLComputeTest::correlation_benchmark_alternative()
{
    VD data;
    data.resize(10000);
    std::iota(data.begin(), data.end(), 1);
    QBENCHMARK
    {
        correlation_helper(data, data);
    }
}
void MLComputeTest::stdev_benchmark()
{
    VD data;
    data.resize(10000);
    std::iota(data.begin(), data.end(), 1);
    QBENCHMARK
    {
        MLCompute::stdev(data);
    }
}
void MLComputeTest::mean_benchmark_alternative()
{
    VD data;
    data.resize(10000);
    std::iota(data.begin(), data.end(), 1);
    QBENCHMARK
    {
        (void)(std::accumulate(data.constBegin(), data.constEnd(), 0) / data.size());
    }
}
void MLComputeTest::dotProduct_benchmark_inner_product()
{
    VD data;
    data.resize(10000);
    std::iota(data.begin(), data.end(), 1);
    QBENCHMARK
    {
        std::inner_product(data.constBegin(), data.constEnd(), data.constBegin(), 0);
    }
}
void MLComputeTest::dotProduct_benchmark_arrays()
{
    VD data;
    data.resize(10000);
    std::iota(data.begin(), data.end(), 1);
    QBENCHMARK
    {
        MLCompute::dotProduct(data.size(), data.data(), data.data());
    }
}
void MLComputeTest::dotProduct_benchmark_vector()
{
    VD data;
    data.resize(10000);
    std::iota(data.begin(), data.end(), 1);
    QBENCHMARK
    {
        MLCompute::dotProduct(data, data);
    }
}
void MLComputeTest::sum_benchmark_accumulate()
{
    VD data;
    data.resize(10000);
    std::iota(data.begin(), data.end(), 1);
    QBENCHMARK
    {
        std::accumulate(data.constBegin(), data.constEnd(), 0);
    }
}