#include <cstdlib>
#include <vector>
#include <algorithm>
#include <thread>
#include <future>
#include <boost/functional/hash.hpp>
#include <iostream>
int main()
{
std::vector<int> v(1ul<<27);
auto const chunk = v.size()/4;
auto f(begin(v)), l(end(v));
std::generate(f, l, rand);
#if 1
std::sort(f,l);
#elif 0
auto t1 = std::thread([&] () mutable { std::sort(f+chunk*0,f+chunk*1); } );
auto t2 = std::thread([&] () mutable { std::sort(f+chunk*1,f+chunk*2); } );
auto t3 = std::thread([&] () mutable { std::sort(f+chunk*2,f+chunk*3); } );
auto t4 = std::thread([&] () mutable { std::sort(f+chunk*3,l ); } );
t1.join();
t2.join();
t3.join();
t4.join();
#else
auto f1 = std::async(std::launch::async, [&] () mutable { std::sort(f+chunk*0,f+chunk*1); } );
auto f2 = std::async(std::launch::async, [&] () mutable { std::sort(f+chunk*1,f+chunk*2); } );
auto f3 = std::async(std::launch::async, [&] () mutable { std::sort(f+chunk*2,f+chunk*3); } );
auto f4 = std::async(std::launch::async, [&] () mutable { std::sort(f+chunk*3,l ); } );
f1.get();
f2.get();
f3.get();
f4.get();
#endif
std::inplace_merge(f,f+chunk*1,f+chunk*2);
std::inplace_merge(f+chunk*2,f+chunk*3,l);
std::inplace_merge(f,f+chunk*2,l);
auto h = boost::hash_range(f,l);
std::cout << h;
}
I2luY2x1ZGUgPGNzdGRsaWI+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDxhbGdvcml0aG0+CiNpbmNsdWRlIDx0aHJlYWQ+CiNpbmNsdWRlIDxmdXR1cmU+CiNpbmNsdWRlIDxib29zdC9mdW5jdGlvbmFsL2hhc2guaHBwPgojaW5jbHVkZSA8aW9zdHJlYW0+CgppbnQgbWFpbigpCnsKICAgIHN0ZDo6dmVjdG9yPGludD4gdigxdWw8PDI3KTsKCiAgICBhdXRvIGNvbnN0IGNodW5rID0gdi5zaXplKCkvNDsKCiAgICBhdXRvIGYoYmVnaW4odikpLCBsKGVuZCh2KSk7CiAgICBzdGQ6OmdlbmVyYXRlKGYsIGwsIHJhbmQpOwoKI2lmIDEKICAgIHN0ZDo6c29ydChmLGwpOwojZWxpZiAwCiAgICBhdXRvIHQxID0gc3RkOjp0aHJlYWQoWyZdICgpIG11dGFibGUgeyBzdGQ6OnNvcnQoZitjaHVuayowLGYrY2h1bmsqMSk7IH0gKTsKICAgIGF1dG8gdDIgPSBzdGQ6OnRocmVhZChbJl0gKCkgbXV0YWJsZSB7IHN0ZDo6c29ydChmK2NodW5rKjEsZitjaHVuayoyKTsgfSApOwogICAgYXV0byB0MyA9IHN0ZDo6dGhyZWFkKFsmXSAoKSBtdXRhYmxlIHsgc3RkOjpzb3J0KGYrY2h1bmsqMixmK2NodW5rKjMpOyB9ICk7CiAgICBhdXRvIHQ0ID0gc3RkOjp0aHJlYWQoWyZdICgpIG11dGFibGUgeyBzdGQ6OnNvcnQoZitjaHVuayozLGwgICAgICAgICk7IH0gKTsKICAgIHQxLmpvaW4oKTsKICAgIHQyLmpvaW4oKTsKICAgIHQzLmpvaW4oKTsKICAgIHQ0LmpvaW4oKTsKI2Vsc2UKICAgIGF1dG8gZjEgPSBzdGQ6OmFzeW5jKHN0ZDo6bGF1bmNoOjphc3luYywgWyZdICgpIG11dGFibGUgeyBzdGQ6OnNvcnQoZitjaHVuayowLGYrY2h1bmsqMSk7IH0gKTsKICAgIGF1dG8gZjIgPSBzdGQ6OmFzeW5jKHN0ZDo6bGF1bmNoOjphc3luYywgWyZdICgpIG11dGFibGUgeyBzdGQ6OnNvcnQoZitjaHVuayoxLGYrY2h1bmsqMik7IH0gKTsKICAgIGF1dG8gZjMgPSBzdGQ6OmFzeW5jKHN0ZDo6bGF1bmNoOjphc3luYywgWyZdICgpIG11dGFibGUgeyBzdGQ6OnNvcnQoZitjaHVuayoyLGYrY2h1bmsqMyk7IH0gKTsKICAgIGF1dG8gZjQgPSBzdGQ6OmFzeW5jKHN0ZDo6bGF1bmNoOjphc3luYywgWyZdICgpIG11dGFibGUgeyBzdGQ6OnNvcnQoZitjaHVuayozLGwgICAgICAgICk7IH0gKTsKICAgIGYxLmdldCgpOwogICAgZjIuZ2V0KCk7CiAgICBmMy5nZXQoKTsKICAgIGY0LmdldCgpOwojZW5kaWYKCiAgICBzdGQ6OmlucGxhY2VfbWVyZ2UoZixmK2NodW5rKjEsZitjaHVuayoyKTsKICAgIHN0ZDo6aW5wbGFjZV9tZXJnZShmK2NodW5rKjIsZitjaHVuayozLGwpOwogICAgc3RkOjppbnBsYWNlX21lcmdlKGYsZitjaHVuayoyLGwpOwoKICAgIGF1dG8gaCA9IGJvb3N0OjpoYXNoX3JhbmdlKGYsbCk7CiAgICBzdGQ6OmNvdXQgPDwgaDsKfQo=