Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ah_parallel_example.cc
Go to the documentation of this file.
1
79#include <ah-parallel.H>
80#include <iostream>
81#include <iomanip>
82#include <vector>
83#include <cmath>
84#include <chrono>
85#include <numeric>
86#include <random>
87#include <string>
88
89using namespace Aleph;
90using namespace std::chrono_literals;
91
92// Helper to print section headers
93void print_header(const std::string& title)
94{
95 std::cout << "\n";
96 std::cout << "+" << std::string(65, '-') << "+\n";
97 std::cout << "| " << std::left << std::setw(63) << title << " |\n";
98 std::cout << "+" << std::string(65, '-') << "+\n\n";
99}
100
101// =============================================================================
102// EXAMPLE 1: Parallel Map (pmaps)
103// =============================================================================
104//
105// pmaps applies a function to each element in parallel, returning a new vector.
106// This is the parallel equivalent of std::transform or Haskell's map.
107//
108// SIGNATURE:
109// pmaps<ResultT>(pool, container, func) → std::vector<ResultT>
110// pmaps(pool, container, func) → std::vector<auto> (type deduced)
111//
112
114{
115 print_header("Example 1: Parallel Map (pmaps)");
116
117 std::cout << "GOAL: Transform a large dataset in parallel.\n\n";
118
119 ThreadPool pool(std::thread::hardware_concurrency());
120 std::cout << "Using ThreadPool with " << pool.num_threads() << " workers\n\n";
121
122 // Create input data: 1 million integers
123 std::vector<int> numbers(1000000);
124 std::iota(numbers.begin(), numbers.end(), 1);
125
126 std::cout << "Input: " << numbers.size() << " integers\n";
127
128 // PARALLEL MAP: Square each number (with type conversion)
129 auto start = std::chrono::high_resolution_clock::now();
130
131 // Type deduction: returns vector<long long> because lambda returns long long
132 auto squares = pmaps(pool, numbers, [](int x) {
133 return static_cast<long long>(x) * x;
134 });
135
136 auto end = std::chrono::high_resolution_clock::now();
137 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
138
139 std::cout << "Output: " << squares.size() << " squared values\n\n";
140
141 // Show sample results
142 std::cout << "First 5 results: ";
143 for (size_t i = 0; i < 5; ++i)
144 std::cout << squares[i] << " ";
145 std::cout << "\n";
146
147 std::cout << "Last 5 results: ";
148 for (size_t i = squares.size() - 5; i < squares.size(); ++i)
149 std::cout << squares[i] << " ";
150 std::cout << "\n\n";
151
152 std::cout << "✓ Completed in " << ms << " ms\n";
153}
154
155// =============================================================================
156// EXAMPLE 2: Parallel Filter (pfilter)
157// =============================================================================
158//
159// pfilter selects elements satisfying a predicate, preserving order.
160// Elements are tested in parallel chunks, then merged sequentially.
161//
162
164{
165 print_header("Example 2: Parallel Filter (pfilter)");
166
167 std::cout << "GOAL: Find all prime numbers in a range using parallel filtering.\n\n";
168
169 ThreadPool pool(std::thread::hardware_concurrency());
170
171 // Generate numbers 2 to 100000
172 std::vector<int> candidates(99999);
173 std::iota(candidates.begin(), candidates.end(), 2);
174
175 std::cout << "Checking " << candidates.size() << " candidates for primality...\n";
176
177 // Primality test (intentionally slow for demo)
178 auto is_prime = [](int n) {
179 if (n < 2) return false;
180 if (n == 2) return true;
181 if (n % 2 == 0) return false;
182 for (int i = 3; i * i <= n; i += 2)
183 if (n % i == 0) return false;
184 return true;
185 };
186
187 auto start = std::chrono::high_resolution_clock::now();
188
189 auto primes = pfilter(pool, candidates, is_prime);
190
191 auto end = std::chrono::high_resolution_clock::now();
192 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
193
194 std::cout << "Found " << primes.size() << " primes\n\n";
195
196 // Show some primes
197 std::cout << "First 10: ";
198 for (size_t i = 0; i < 10 && i < primes.size(); ++i)
199 std::cout << primes[i] << " ";
200 std::cout << "\n";
201
202 std::cout << "Last 10: ";
203 for (size_t i = primes.size() > 10 ? primes.size() - 10 : 0; i < primes.size(); ++i)
204 std::cout << primes[i] << " ";
205 std::cout << "\n\n";
206
207 std::cout << "✓ Completed in " << ms << " ms\n";
208}
209
210// =============================================================================
211// EXAMPLE 3: Parallel Fold (pfoldl)
212// =============================================================================
213//
214// pfoldl reduces a container using a binary operation.
215// IMPORTANT: The operation must be ASSOCIATIVE for correct parallel results.
216//
217// Works by:
218// 1. Each chunk computes a partial result
219// 2. Partial results are combined
220//
221
223{
224 print_header("Example 3: Parallel Fold (pfoldl)");
225
226 std::cout << "GOAL: Compute sum and product of a large dataset in parallel.\n\n";
227
228 ThreadPool pool(std::thread::hardware_concurrency());
229
230 // Create data
231 std::vector<double> data(100000);
232 for (size_t i = 0; i < data.size(); ++i)
233 data[i] = 1.0 + 1.0 / (i + 1); // 2, 1.5, 1.333..., etc.
234
235 std::cout << "Data size: " << data.size() << " elements\n\n";
236
237 // SUM with pfoldl
238 auto sum = pfoldl(pool, data, 0.0, std::plus<double>());
239 std::cout << "Sum: " << std::fixed << std::setprecision(2) << sum << "\n";
240
241 // Using psum (convenience function)
242 auto sum2 = psum(pool, data);
243 std::cout << "Sum (psum): " << sum2 << "\n\n";
244
245 // CONCATENATION of strings (associative)
246 std::vector<std::string> words = {"Parallel", " ", "functional", " ",
247 "programming", " ", "is", " ", "powerful!"};
248
249 auto sentence = pfoldl(pool, words, std::string{}, std::plus<std::string>());
250 std::cout << "Concatenated: \"" << sentence << "\"\n\n";
251
252 std::cout << "✓ Fold operations completed\n";
253}
254
255// =============================================================================
256// EXAMPLE 4: Parallel Predicates (pall, pexists, pnone, pcount_if)
257// =============================================================================
258//
259// These functions test conditions on all elements:
260// - pall: true if ALL elements satisfy the predicate
261// - pexists: true if ANY element satisfies the predicate
262// - pnone: true if NO element satisfies the predicate
263// - pcount_if: counts elements satisfying the predicate
264//
265// pall and pexists use SHORT-CIRCUIT evaluation - they stop early when possible.
266//
267
269{
270 print_header("Example 4: Parallel Predicates");
271
272 std::cout << "GOAL: Test conditions on large datasets efficiently.\n\n";
273
274 ThreadPool pool(std::thread::hardware_concurrency());
275
276 // Create test data
277 std::vector<int> data(1000000);
278 std::iota(data.begin(), data.end(), 1); // 1, 2, 3, ..., 1000000
279
280 std::cout << "Dataset: integers 1 to " << data.size() << "\n\n";
281
282 // pall - All positive?
283 bool all_positive = pall(pool, data, [](int x) { return x > 0; });
284 std::cout << "All positive? " << (all_positive ? "YES" : "NO") << "\n";
285
286 // pall - All even? (will short-circuit on first odd)
287 bool all_even = pall(pool, data, [](int x) { return x % 2 == 0; });
288 std::cout << "All even? " << (all_even ? "YES" : "NO") << " (short-circuits early!)\n";
289
290 // pexists - Any divisible by 12345?
291 bool has_special = pexists(pool, data, [](int x) { return x % 12345 == 0; });
292 std::cout << "Has number divisible by 12345? " << (has_special ? "YES" : "NO") << "\n";
293
294 // pnone - No negatives?
295 bool no_negatives = pnone(pool, data, [](int x) { return x < 0; });
296 std::cout << "No negatives? " << (no_negatives ? "YES" : "NO") << "\n";
297
298 // pcount_if - Count multiples of 7
299 size_t sevens = pcount_if(pool, data, [](int x) { return x % 7 == 0; });
300 std::cout << "Multiples of 7: " << sevens << "\n\n";
301
302 std::cout << "✓ Predicate tests completed\n";
303}
304
305// =============================================================================
306// EXAMPLE 5: Parallel Find (pfind, pfind_value)
307// =============================================================================
308//
309// Parallel search with short-circuit optimization.
310// - pfind: returns std::optional<size_t> (index of first match)
311// - pfind_value: returns std::optional<T> (the matched element)
312//
313
315{
316 print_header("Example 5: Parallel Find (pfind, pfind_value)");
317
318 std::cout << "GOAL: Search for elements in parallel with early termination.\n\n";
319
320 ThreadPool pool(std::thread::hardware_concurrency());
321
322 // Create shuffled data
323 std::vector<int> data(1000000);
324 std::iota(data.begin(), data.end(), 0);
325 std::mt19937 rng(42);
326 std::shuffle(data.begin(), data.end(), rng);
327
328 std::cout << "Shuffled dataset of " << data.size() << " elements\n\n";
329
330 // Find index of value 500000
331 auto idx = pfind(pool, data, [](int x) { return x == 500000; });
332 if (idx)
333 std::cout << "Value 500000 found at index " << *idx << "\n";
334 else
335 std::cout << "Value 500000 not found\n";
336
337 // Find first value > 999990
338 auto val = pfind_value(pool, data, [](int x) { return x > 999990; });
339 if (val)
340 std::cout << "First value > 999990: " << *val << "\n";
341 else
342 std::cout << "No value > 999990\n";
343
344 // Search for non-existent value
345 auto missing = pfind(pool, data, [](int x) { return x == -1; });
346 std::cout << "Value -1: " << (missing ? "found" : "not found") << "\n\n";
347
348 std::cout << "✓ Search operations completed\n";
349}
350
351// =============================================================================
352// EXAMPLE 6: Parallel Aggregations (psum, pproduct, pmin, pmax, pminmax)
353// =============================================================================
354//
355// Convenience functions for common reductions.
356//
357
359{
360 print_header("Example 6: Parallel Aggregations");
361
362 std::cout << "GOAL: Compute statistics on large datasets in parallel.\n\n";
363
364 ThreadPool pool(std::thread::hardware_concurrency());
365
366 // Create random data
367 std::vector<double> data(500000);
368 std::mt19937 rng(123);
369 std::uniform_real_distribution<double> dist(-1000.0, 1000.0);
370 for (auto& x : data)
371 x = dist(rng);
372
373 std::cout << "Dataset: " << data.size() << " random doubles in [-1000, 1000]\n\n";
374
375 // Aggregations
376 auto sum = psum(pool, data);
377 auto min_opt = pmin(pool, data);
378 auto max_opt = pmax(pool, data);
379 auto minmax_opt = pminmax(pool, data);
380
381 std::cout << std::fixed << std::setprecision(4);
382 std::cout << "Sum: " << sum << "\n";
383
384 if (min_opt)
385 std::cout << "Min: " << *min_opt << "\n";
386 if (max_opt)
387 std::cout << "Max: " << *max_opt << "\n";
388 if (minmax_opt)
389 std::cout << "MinMax: (" << minmax_opt->first << ", " << minmax_opt->second << ")\n";
390
391 double mean = sum / data.size();
392 std::cout << "Mean: " << mean << "\n\n";
393
394 std::cout << "✓ Aggregation operations completed\n";
395}
396
397// =============================================================================
398// EXAMPLE 7: Parallel Sort (psort)
399// =============================================================================
400//
401// Parallel merge sort: chunks are sorted in parallel, then merged.
402//
403
405{
406 print_header("Example 7: Parallel Sort (psort)");
407
408 std::cout << "GOAL: Sort large datasets using parallel merge sort.\n\n";
409
410 ThreadPool pool(std::thread::hardware_concurrency());
411
412 // Create random data
413 std::vector<int> data(500000);
414 std::mt19937 rng(456);
415 for (auto& x : data)
416 x = rng() % 1000000;
417
418 std::cout << "Dataset: " << data.size() << " random integers\n";
419 std::cout << "First 10 (unsorted): ";
420 for (size_t i = 0; i < 10; ++i)
421 std::cout << data[i] << " ";
422 std::cout << "\n\n";
423
424 auto start = std::chrono::high_resolution_clock::now();
425
426 psort(pool, data); // In-place parallel sort
427
428 auto end = std::chrono::high_resolution_clock::now();
429 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
430
431 std::cout << "First 10 (sorted): ";
432 for (size_t i = 0; i < 10; ++i)
433 std::cout << data[i] << " ";
434 std::cout << "\n";
435
436 std::cout << "Last 10 (sorted): ";
437 for (size_t i = data.size() - 10; i < data.size(); ++i)
438 std::cout << data[i] << " ";
439 std::cout << "\n\n";
440
441 // Verify sorted
442 bool is_sorted = std::is_sorted(data.begin(), data.end());
443 std::cout << "Correctly sorted? " << (is_sorted ? "YES" : "NO") << "\n";
444 std::cout << "Time: " << ms << " ms\n\n";
445
446 std::cout << "✓ Parallel sort completed\n";
447}
448
449// =============================================================================
450// EXAMPLE 8: Parallel Zip Operations (2 containers)
451// =============================================================================
452//
453// pzip_for_each: Apply function to pairs of elements
454// pzip_maps: Map pairs to a new container
455// pzip_foldl: Reduce pairs (e.g., dot product)
456//
457
459{
460 print_header("Example 8: Parallel Zip Operations (2 containers)");
461
462 std::cout << "GOAL: Process corresponding elements from two containers.\n\n";
463
464 ThreadPool pool(std::thread::hardware_concurrency());
465
466 // Create two vectors
467 std::vector<double> a(100000);
468 std::vector<double> b(100000);
469 for (size_t i = 0; i < a.size(); ++i)
470 {
471 a[i] = static_cast<double>(i);
472 b[i] = static_cast<double>(i) * 2;
473 }
474
475 std::cout << "Vectors a and b, each with " << a.size() << " elements\n\n";
476
477 // pzip_maps: Element-wise product
478 auto products = pzip_maps(pool, a, b, [](double x, double y) {
479 return x * y;
480 });
481
482 std::cout << "Element-wise products (first 5): ";
483 for (size_t i = 0; i < 5; ++i)
484 std::cout << products[i] << " ";
485 std::cout << "\n\n";
486
487 // pzip_foldl: Dot product
488 double dot_product = pzip_foldl(pool, a, b, 0.0,
489 [](double acc, double x, double y) { return acc + x * y; });
490
491 std::cout << "Dot product: " << std::fixed << std::setprecision(0)
492 << dot_product << "\n\n";
493
494 // pzip_for_each with side effects
495 std::atomic<double> sum{0};
496 pzip_for_each(pool, a, b, [&sum](double x, double y) {
497 sum += x + y;
498 });
499
500 std::cout << "Sum of all pairs: " << sum.load() << "\n\n";
501
502 std::cout << "✓ Zip operations completed\n";
503}
504
505// =============================================================================
506// EXAMPLE 9: Variadic Zip (N containers) - pzip_*_n functions
507// =============================================================================
508//
509// For 3+ containers, use the _n suffix functions:
510// - pzip_for_each_n
511// - pzip_maps_n
512// - pzip_foldl_n (requires a combiner function)
513// - pzip_all_n, pzip_exists_n, pzip_count_if_n
514//
515
517{
518 print_header("Example 9: Variadic Zip (N containers)");
519
520 std::cout << "GOAL: Process corresponding elements from 3+ containers.\n\n";
521
522 ThreadPool pool(std::thread::hardware_concurrency());
523
524 // Three vectors
525 std::vector<int> x = {1, 2, 3, 4, 5};
526 std::vector<int> y = {10, 20, 30, 40, 50};
527 std::vector<int> z = {100, 200, 300, 400, 500};
528
529 std::cout << "x = {1, 2, 3, 4, 5}\n";
530 std::cout << "y = {10, 20, 30, 40, 50}\n";
531 std::cout << "z = {100, 200, 300, 400, 500}\n\n";
532
533 // pzip_maps_n: Sum triplets
534 auto sums = pzip_maps_n(pool, [](int a, int b, int c) {
535 return a + b + c;
536 }, x, y, z);
537
538 std::cout << "x + y + z = ";
539 for (auto v : sums)
540 std::cout << v << " ";
541 std::cout << "\n\n";
542
543 // pzip_all_n: Check if all triplets satisfy condition
544 bool all_ordered = pzip_all_n(pool, [](int a, int b, int c) {
545 return a < b && b < c;
546 }, x, y, z);
547
548 std::cout << "All x[i] < y[i] < z[i]? " << (all_ordered ? "YES" : "NO") << "\n";
549
550 // pzip_count_if_n: Count triplets with sum > 100
551 size_t count = pzip_count_if_n(pool, [](int a, int b, int c) {
552 return a + b + c > 100;
553 }, x, y, z);
554
555 std::cout << "Triplets with sum > 100: " << count << "\n\n";
556
557 // Four vectors example
558 std::vector<double> v1 = {1.0, 2.0, 3.0};
559 std::vector<double> v2 = {1.0, 2.0, 3.0};
560 std::vector<double> v3 = {1.0, 2.0, 3.0};
561 std::vector<double> v4 = {1.0, 2.0, 3.0};
562
563 auto products = pzip_maps_n(pool, [](double a, double b, double c, double d) {
564 return a * b * c * d;
565 }, v1, v2, v3, v4);
566
567 std::cout << "v1 * v2 * v3 * v4 = ";
568 for (auto v : products)
569 std::cout << v << " ";
570 std::cout << "\n\n";
571
572 std::cout << "✓ Variadic zip operations completed\n";
573}
574
575// =============================================================================
576// EXAMPLE 10: Parallel Enumerate
577// =============================================================================
578//
579// Like Python's enumerate(), but parallel:
580// - penumerate_for_each: Apply function to (index, element) pairs
581// - penumerate_maps: Map (index, element) pairs to results
582//
583
585{
586 print_header("Example 10: Parallel Enumerate");
587
588 std::cout << "GOAL: Process elements along with their indices in parallel.\n\n";
589
590 ThreadPool pool(std::thread::hardware_concurrency());
591
592 // Initialize vector with indices
593 std::vector<int> data(10, 0);
594
595 // penumerate_for_each: Set each element to its index * 10
596 penumerate_for_each(pool, data, [](size_t i, int& x) {
597 x = static_cast<int>(i * 10);
598 });
599
600 std::cout << "After penumerate_for_each (x = i * 10): ";
601 for (auto x : data)
602 std::cout << x << " ";
603 std::cout << "\n\n";
604
605 // penumerate_maps: Create indexed strings
606 std::vector<std::string> words = {"apple", "banana", "cherry", "date", "elderberry"};
607
608 auto indexed = penumerate_maps(pool, words,
609 [](size_t i, const std::string& s) {
610 return "[" + std::to_string(i) + "] " + s;
611 });
612
613 std::cout << "Indexed strings:\n";
614 for (const auto& s : indexed)
615 std::cout << " " << s << "\n";
616 std::cout << "\n";
617
618 std::cout << "✓ Enumerate operations completed\n";
619}
620
621// =============================================================================
622// EXAMPLE 11: Performance Comparison
623// =============================================================================
624
626{
627 print_header("Example 11: Performance Comparison");
628
629 std::cout << "GOAL: Compare parallel vs sequential execution times.\n\n";
630
631 ThreadPool pool(std::thread::hardware_concurrency());
632
633 // Large dataset
634 std::vector<double> data(2000000);
635 std::iota(data.begin(), data.end(), 1.0);
636
637 std::cout << "Dataset: " << data.size() << " elements\n";
638 std::cout << "Threads: " << pool.num_threads() << "\n\n";
639
640 // CPU-intensive operation
641 auto expensive = [](double x) {
642 double result = x;
643 for (int i = 0; i < 50; ++i)
644 result = std::sin(result) * std::cos(result) + std::sqrt(std::abs(result));
645 return result;
646 };
647
648 // SEQUENTIAL
649 std::cout << "Running sequential map...\n";
650 auto seq_start = std::chrono::high_resolution_clock::now();
651
652 std::vector<double> seq_result(data.size());
653 std::transform(data.begin(), data.end(), seq_result.begin(), expensive);
654
655 auto seq_end = std::chrono::high_resolution_clock::now();
656 auto seq_ms = std::chrono::duration_cast<std::chrono::milliseconds>(seq_end - seq_start).count();
657
658 // PARALLEL
659 std::cout << "Running parallel map (pmaps)...\n\n";
660 auto par_start = std::chrono::high_resolution_clock::now();
661
662 auto par_result = pmaps(pool, data, expensive);
663
664 auto par_end = std::chrono::high_resolution_clock::now();
665 auto par_ms = std::chrono::duration_cast<std::chrono::milliseconds>(par_end - par_start).count();
666
667 // Results
668 double speedup = (par_ms > 0) ? static_cast<double>(seq_ms) / par_ms : 0;
669
670 std::cout << "┌────────────────────────────────────────┐\n";
671 std::cout << "│ PERFORMANCE RESULTS │\n";
672 std::cout << "├────────────────────────────────────────┤\n";
673 std::cout << "│ Sequential: " << std::setw(20) << seq_ms << " ms │\n";
674 std::cout << "│ Parallel: " << std::setw(20) << par_ms << " ms │\n";
675 std::cout << "├────────────────────────────────────────┤\n";
676 std::cout << "│ SPEEDUP: " << std::setw(20) << std::fixed
677 << std::setprecision(2) << speedup << "x │\n";
678 std::cout << "└────────────────────────────────────────┘\n";
679
680 // Verify correctness
681 bool match = std::equal(seq_result.begin(), seq_result.end(), par_result.begin(),
682 [](double a, double b) { return std::abs(a - b) < 1e-10; });
683 std::cout << "\n✓ Results match: " << (match ? "YES" : "NO") << "\n";
684}
685
686// =============================================================================
687// MAIN
688// =============================================================================
689
690int main()
691{
692 std::cout << "\n";
693 std::cout << "╔════════════════════════════════════════════════════════════════════╗\n";
694 std::cout << "║ ║\n";
695 std::cout << "║ ALEPH-W PARALLEL FUNCTIONAL PROGRAMMING EXAMPLES ║\n";
696 std::cout << "║ ║\n";
697 std::cout << "║ ML-style operations (map, filter, fold, zip, etc.) ║\n";
698 std::cout << "║ accelerated with multi-threading via ThreadPool ║\n";
699 std::cout << "║ ║\n";
700 std::cout << "╚════════════════════════════════════════════════════════════════════╝\n";
701
702 std::cout << "\nThis program demonstrates 11 parallel functional programming patterns.\n";
703 std::cout << "Read the source code comments for detailed explanations.\n";
704
716
717 std::cout << "\n";
718 std::cout << "╔════════════════════════════════════════════════════════════════════╗\n";
719 std::cout << "║ ✓ ALL EXAMPLES COMPLETED SUCCESSFULLY ║\n";
720 std::cout << "║ ║\n";
721 std::cout << "║ QUICK REFERENCE: ║\n";
722 std::cout << "║ pmaps(pool, c, f) → parallel map ║\n";
723 std::cout << "║ pfilter(pool, c, pred) → parallel filter ║\n";
724 std::cout << "║ pfoldl(pool, c, init, op) → parallel fold ║\n";
725 std::cout << "║ pfor_each(pool, c, f) → parallel for_each ║\n";
726 std::cout << "║ pall/pexists/pnone → parallel predicates ║\n";
727 std::cout << "║ pfind/pfind_value → parallel search ║\n";
728 std::cout << "║ psum/pproduct/pmin/pmax → parallel aggregations ║\n";
729 std::cout << "║ psort → parallel merge sort ║\n";
730 std::cout << "║ pzip_* → parallel zip (2 containers) ║\n";
731 std::cout << "║ pzip_*_n → parallel zip (N containers) ║\n";
732 std::cout << "║ penumerate_* → parallel enumerate ║\n";
733 std::cout << "╚════════════════════════════════════════════════════════════════════╝\n\n";
734
735 return 0;
736}
Parallel functional programming operations using ThreadPool.
void example_parallel_filter()
void example_parallel_sort()
void example_parallel_map()
void example_parallel_find()
void example_parallel_zip()
void example_parallel_aggregations()
void example_parallel_predicates()
void example_performance_comparison()
void example_variadic_zip()
void example_parallel_fold()
void example_parallel_enumerate()
int main()
static size_t primes[]
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
A reusable thread pool for efficient parallel task execution.
size_t num_threads() const noexcept
Get the number of worker threads.
iterator end() noexcept
Return an STL-compatible end iterator.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
static mt19937 rng
static mpfr_t y
Definition mpfr_mul_d.c:3
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
bool pall(ThreadPool &pool, const Container &c, Pred pred, size_t chunk_size=0)
Parallel all predicate (short-circuit).
bool is_sorted(const Container< T > &cont, const Compare &cmp=Compare())
Check if a container is sorted in ascending order.
bool pnone(ThreadPool &pool, const Container &c, Pred pred, size_t chunk_size=0)
Parallel none predicate.
auto pmaps(ThreadPool &pool, const Container &c, Op op, size_t chunk_size=0)
Parallel map operation.
auto pmin(ThreadPool &pool, const Container &c, size_t chunk_size=0)
Parallel minimum element.
T pzip_foldl(ThreadPool &pool, const Container1 &c1, const Container2 &c2, T init, Op op, size_t chunk_size=0)
Parallel zip + fold.
void pzip_for_each(ThreadPool &pool, const Container1 &c1, const Container2 &c2, Op op, size_t chunk_size=0)
Parallel zip + for_each.
auto penumerate_maps(ThreadPool &pool, const Container &c, Op op, size_t chunk_size=0)
Parallel enumerate with map.
void penumerate_for_each(ThreadPool &pool, Container &c, Op op, size_t chunk_size=0)
Parallel for_each with index (enumerate).
bool pzip_all_n(ThreadPool &pool, Pred pred, const Containers &... cs)
Parallel all predicate over N zipped containers (variadic).
size_t pcount_if(ThreadPool &pool, const Container &c, Pred pred, size_t chunk_size=0)
Parallel count_if operation.
std::optional< size_t > pfind(ThreadPool &pool, const Container &c, Pred pred, size_t chunk_size=0)
Parallel find operation (returns index).
void psort(ThreadPool &pool, Container &c, Compare cmp=Compare{}, const size_t min_parallel_size=1024)
Parallel sort (in-place).
auto pfilter(ThreadPool &pool, const Container &c, Pred pred, size_t chunk_size=0)
Parallel filter operation.
auto mean(const Container &data) -> std::decay_t< decltype(*std::begin(data))>
Compute the arithmetic mean.
Definition stat_utils.H:183
auto pmax(ThreadPool &pool, const Container &c, size_t chunk_size=0)
Parallel maximum element.
auto pzip_maps_n(ThreadPool &pool, Op op, const Containers &... cs)
Parallel map over N zipped containers (variadic).
T pfoldl(ThreadPool &pool, const Container &c, T init, BinaryOp op, size_t chunk_size=0)
Parallel left fold (reduce).
auto pfind_value(ThreadPool &pool, const Container &c, Pred pred, size_t chunk_size=0)
Parallel find with value return.
auto pzip_maps(ThreadPool &pool, const Container1 &c1, const Container2 &c2, Op op, size_t chunk_size=0)
Parallel zip + map.
T psum(ThreadPool &pool, const Container &c, T init=T{}, size_t chunk_size=0)
Parallel sum of elements.
auto pminmax(ThreadPool &pool, const Container &c, size_t chunk_size=0)
Parallel min and max elements.
size_t pzip_count_if_n(ThreadPool &pool, Pred pred, const Containers &... cs)
Parallel count over N zipped containers (variadic).
bool pexists(ThreadPool &pool, const Container &c, Pred pred, size_t chunk_size=0)
Parallel exists predicate (short-circuit).
DynList< T > maps(const C &c, Op op)
Classic map operation.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
void print_header()
bool is_prime(int n)