1+ #include < algorithm>
2+ #include < cstdint>
3+ #include < iostream>
4+ #include < numeric>
5+ #include < random>
6+ #include < thread>
7+ #include < vector>
8+
9+ static std::uint64_t
10+ count_hits (std::uint64_t n, std::uint64_t seed)
11+ {
12+ std::mt19937_64 rng (seed);
13+ std::uniform_real_distribution<double > dist (0.0 , 1.0 );
14+
15+ std::uint64_t hits = 0 ;
16+ for (std::uint64_t i = 0 ; i < n; ++i) {
17+ const double x = dist (rng);
18+ const double y = dist (rng);
19+ if (x * x + y * y <= 1.0 )
20+ ++hits;
21+ }
22+ return hits;
23+ }
24+
25+ int
26+ main (int argc, char * argv[])
27+ {
28+ int threads = 2 ;
29+ std::uint64_t n = 1'000'000 ;
30+
31+ if (argc > 1 )
32+ threads = std::max (1 , std::atoi (argv[1 ]));
33+ if (argc > 2 )
34+ n = std::max<std::uint64_t >(1 , std::strtoull (argv[2 ], nullptr , 10 ));
35+
36+ const std::uint64_t base = n / threads;
37+ const std::uint64_t rem = n % threads;
38+
39+ std::vector<std::thread> pool;
40+ std::vector<std::uint64_t > hits (threads, 0 );
41+
42+ // a single nondeterministic seed source; each thread gets a different seed
43+ std::random_device rd;
44+ const std::uint64_t master_seed = (static_cast <std::uint64_t >(rd ()) << 32 ) ^ static_cast <std::uint64_t >(rd ());
45+
46+ for (int i = 0 ; i < threads; ++i) {
47+ const std::uint64_t points = base + (static_cast <std::uint64_t >(i) < rem ? 1 : 0 );
48+ const std::uint64_t seed = master_seed + 0x9e3779b97f4a7c15ULL * static_cast <std::uint64_t >(i + 1 );
49+
50+ pool.emplace_back ([&, i, points, seed] { hits[i] = count_hits (points, seed); });
51+ }
52+
53+ for (auto & t : pool)
54+ t.join ();
55+
56+ const std::uint64_t total_hits = std::accumulate (hits.begin (), hits.end (), std::uint64_t {0 });
57+ const long double pi = 4.0 * static_cast <long double >(total_hits) / static_cast <long double >(n);
58+
59+ std::cout << pi << " \n " ;
60+ return 0 ;
61+ }
0 commit comments