Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ranges_example.C
Go to the documentation of this file.
1
140#include <iostream>
141#include <iomanip>
142#include <string>
143#include <vector>
144#include <cmath>
145
146#include <tclap/CmdLine.h>
147
148#include <htlist.H>
149#include <tpl_dynArray.H>
150#include <tpl_dynDlist.H>
151#include <ah-ranges.H>
152
153using namespace std;
154using namespace Aleph;
155
156// =============================================================================
157// Helper functions
158// =============================================================================
159
160void print_section(const string& title)
161{
162 cout << "\n" << string(60, '=') << "\n";
163 cout << " " << title << "\n";
164 cout << string(60, '=') << "\n\n";
165}
166
167void print_subsection(const string& title)
168{
169 cout << "\n--- " << title << " ---\n";
170}
171
172template <typename Container>
173void print_container(const string& label, const Container& c)
174{
175 cout << label << ": [";
176 bool first = true;
177 for (auto it = c.get_it(); it.has_curr(); it.next())
178 {
179 if (not first) cout << ", ";
180 cout << it.get_curr();
181 first = false;
182 }
183 cout << "]" << endl;
184}
185
186// =============================================================================
187// 1. Lazy Range Generation
188// =============================================================================
189
190#if ALEPH_HAS_RANGES
191
192void demo_lazy_ranges()
193{
194 print_section("LAZY RANGE GENERATION");
195
196 cout << "Unlike traditional range() which allocates immediately,\n";
197 cout << "lazy_range() generates values on demand.\n\n";
198
199 // Basic lazy range
200 print_subsection("lazy_range(start, end)");
201
202 cout << "lazy_range(1, 10): ";
203 for (auto x : lazy_range(1, 10))
204 cout << x << " ";
205 cout << endl;
206
207 cout << "lazy_range(5): "; // 0 to 4
208 for (auto x : lazy_range(5))
209 cout << x << " ";
210 cout << endl;
211
212 // Demonstrate laziness
213 print_subsection("Laziness demonstration");
214
215 cout << "Processing lazy_range(1, 1000000) but stopping at 5:\n";
216 int count = 0;
217 for (auto x : lazy_range(1, 1000000))
218 {
219 cout << x << " ";
220 if (++count >= 5) break;
221 }
222 cout << "\n(Only 5 values were generated, not 1 million!)\n";
223
224 // Infinite range with lazy_iota
225 print_subsection("lazy_iota() - infinite range");
226
227 cout << "First 10 values from lazy_iota(100): ";
228 count = 0;
229 for (auto x : lazy_iota(100))
230 {
231 cout << x << " ";
232 if (++count >= 10) break;
233 }
234 cout << endl;
235}
236
237// =============================================================================
238// 2. Range Views
239// =============================================================================
240
241void demo_views()
242{
243 print_section("RANGE VIEWS (std::views)");
244
245 cout << "Views are lazy, composable transformations.\n";
246 cout << "No allocation until you iterate or materialize.\n\n";
247
248 // Filter view
249 print_subsection("filter - keep elements matching predicate");
250
251 cout << "Even numbers in [1, 20]: ";
252 for (auto x : lazy_range(1, 21) | std::views::filter([](int x) { return x % 2 == 0; }))
253 cout << x << " ";
254 cout << endl;
255
256 // Transform view
257 print_subsection("transform - apply function to each element");
258
259 cout << "Squares of [1, 10]: ";
260 for (auto x : lazy_range(1, 11) | std::views::transform([](int x) { return x * x; }))
261 cout << x << " ";
262 cout << endl;
263
264 // Take and drop
265 print_subsection("take and drop");
266
267 cout << "First 5 of [1, 100]: ";
268 for (auto x : lazy_range(1, 101) | std::views::take(5))
269 cout << x << " ";
270 cout << endl;
271
272 cout << "Skip first 95 of [1, 100]: ";
273 for (auto x : lazy_range(1, 101) | std::views::drop(95))
274 cout << x << " ";
275 cout << endl;
276
277 // Composition
278 print_subsection("Composing views");
279
280 cout << "First 5 primes (brute force): ";
281 auto is_prime = [](int n) {
282 if (n < 2) return false;
283 for (int i = 2; i <= sqrt(n); i++)
284 if (n % i == 0) return false;
285 return true;
286 };
287
288 for (auto x : lazy_iota(2) | std::views::filter(is_prime) | std::views::take(5))
289 cout << x << " ";
290 cout << endl;
291}
292
293// =============================================================================
294// 3. Materializing to Aleph Containers
295// =============================================================================
296
297void demo_materialize()
298{
299 print_section("MATERIALIZING TO ALEPH CONTAINERS");
300
301 cout << "Convert lazy ranges to Aleph containers using pipe adaptors.\n\n";
302
303 // to_dynlist_v
304 print_subsection("to_dynlist_v");
305
306 auto list = lazy_range(1, 6)
307 | std::views::transform([](int x) { return x * 10; })
308 | to_dynlist_v;
309
310 print_container("DynList from [10, 20, 30, 40, 50]", list);
311
312 // to_dynarray_v
313 print_subsection("to_dynarray_v");
314
315 auto arr = lazy_range(1, 6)
316 | std::views::filter([](int x) { return x % 2 == 1; })
318
319 print_container("DynArray of odd numbers [1, 3, 5]", arr);
320
321 // to_dyndlist_v
322 print_subsection("to_dyndlist_v");
323
324 auto dlist = lazy_range(1, 4) | to_dyndlist_v;
325 print_container("DynDlist [1, 2, 3]", dlist);
326
327 // Generic to<>()
328 print_subsection("Generic to<Container>()");
329
330 auto result = lazy_range(1, 5) | to<DynList<int>>();
331 print_container("Using to<DynList<int>>()", result);
332
333 // collect function
334 print_subsection("collect<Container>() function");
335
337 lazy_range(1, 5) | std::views::transform([](int x) { return x * 0.5; })
338 );
339 print_container("Collected DynArray<double>", collected);
340}
341
342// =============================================================================
343// 4. Working with Aleph Containers
344// =============================================================================
345
347{
348 print_section("RANGES WITH ALEPH CONTAINERS");
349
350 cout << "Aleph containers work with std::ranges algorithms.\n\n";
351
352 // Create a DynList
354 for (int i = 1; i <= 10; i++)
355 numbers.append(i);
356
357 print_container("Original DynList", numbers);
358
359 // std::ranges algorithms
360 print_subsection("std::ranges algorithms");
361
362 bool has_even = std::ranges::any_of(numbers, [](int x) { return x % 2 == 0; });
363 cout << "Has even number? " << (has_even ? "yes" : "no") << endl;
364
365 bool all_positive = std::ranges::all_of(numbers, [](int x) { return x > 0; });
366 cout << "All positive? " << (all_positive ? "yes" : "no") << endl;
367
368 auto count_gt5 = std::ranges::count_if(numbers, [](int x) { return x > 5; });
369 cout << "Count > 5: " << count_gt5 << endl;
370
371 // Using views on DynList
372 print_subsection("Views on DynList");
373
374 cout << "Filtered (even): ";
375 for (auto x : numbers | std::views::filter([](int x) { return x % 2 == 0; }))
376 cout << x << " ";
377 cout << endl;
378
379 cout << "Transformed (squared): ";
380 for (auto x : numbers | std::views::transform([](int x) { return x * x; }))
381 cout << x << " ";
382 cout << endl;
383
384 cout << "First 3: ";
385 for (auto x : numbers | std::views::take(3))
386 cout << x << " ";
387 cout << endl;
388}
389
390// =============================================================================
391// 5. Practical Examples
392// =============================================================================
393
394void demo_practical()
395{
396 print_section("PRACTICAL EXAMPLES");
397
398 // Fibonacci sequence
399 print_subsection("Fibonacci (first 15 numbers)");
400
401 // Using transform with state (via mutable lambda)
402 int a = 0, b = 1;
403 auto fib = lazy_range(15) | std::views::transform([&a, &b](int) mutable {
404 int result = a;
405 int next = a + b;
406 a = b;
407 b = next;
408 return result;
409 });
410
411 cout << "Fibonacci: ";
412 for (auto x : fib)
413 cout << x << " ";
414 cout << endl;
415
416 // FizzBuzz
417 print_subsection("FizzBuzz (1-20)");
418
419 for (auto n : lazy_range(1, 21))
420 {
421 if (n % 15 == 0) cout << "FizzBuzz ";
422 else if (n % 3 == 0) cout << "Fizz ";
423 else if (n % 5 == 0) cout << "Buzz ";
424 else cout << n << " ";
425 }
426 cout << endl;
427
428 // Data pipeline
429 print_subsection("Data pipeline: Process sensor readings");
430
431 // Simulated sensor readings (some invalid, marked as -1)
433 readings.append(23.5); readings.append(-1); readings.append(24.1);
434 readings.append(25.0); readings.append(-1); readings.append(23.8);
435 readings.append(24.5); readings.append(-1); readings.append(24.0);
436
437 cout << "Raw readings: ";
438 for (auto it = readings.get_it(); it.has_curr(); it.next())
439 cout << it.get_curr() << " ";
440 cout << endl;
441
442 // Pipeline: filter valid -> convert to Fahrenheit -> collect
443 auto fahrenheit = readings
444 | std::views::filter([](double x) { return x >= 0; })
445 | std::views::transform([](double c) { return c * 9/5 + 32; })
446 | to_dynlist_v;
447
448 cout << "Valid readings in Fahrenheit: ";
449 for (auto it = fahrenheit.get_it(); it.has_curr(); it.next())
450 cout << fixed << setprecision(1) << it.get_curr() << " ";
451 cout << endl;
452
453 // Statistics using ranges
454 double sum = 0;
455 size_t count = 0;
456 for (auto x : readings | std::views::filter([](double x) { return x >= 0; }))
457 {
458 sum += x;
459 count++;
460 }
461 cout << "Average (Celsius): " << fixed << setprecision(2) << (sum / count) << endl;
462}
463
464// =============================================================================
465// 6. Performance Comparison
466// =============================================================================
467
468void demo_performance()
469{
470 print_section("LAZY vs EAGER EVALUATION");
471
472 cout << "Lazy evaluation can be more efficient when:\n";
473 cout << "- You don't need all elements\n";
474 cout << "- You're chaining multiple operations\n";
475 cout << "- Working with large or infinite sequences\n\n";
476
477 print_subsection("Example: Find first square > 1000");
478
479 // Lazy approach - stops when found
480 cout << "Lazy: ";
481 for (auto x : lazy_iota(1)
482 | std::views::transform([](int x) { return x * x; })
483 | std::views::filter([](int x) { return x > 1000; })
484 | std::views::take(1))
485 {
486 cout << x << " (computed ~32 squares)" << endl;
487 }
488
489 // Show the work
490 cout << "\nWith lazy evaluation, we only compute what's needed.\n";
491 cout << "No intermediate containers are created.\n";
492}
493
494#else // !ALEPH_HAS_RANGES
495
497{
498 print_section("C++20 RANGES NOT AVAILABLE");
499
500 cout << "Your compiler does not support C++20 ranges.\n\n";
501 cout << "Requirements:\n";
502 cout << " - C++20 or later (-std=c++20)\n";
503 cout << " - GCC 12+ with libstdc++, OR\n";
504 cout << " - Clang 14+ with libc++ (-stdlib=libc++)\n\n";
505
506 cout << "Alternative: Use ahFunctional.H for functional operations:\n";
507 cout << " - range(start, end) - eager range generation\n";
508 cout << " - filter(container, pred)\n";
509 cout << " - maps(container, func)\n";
510 cout << " - foldl(container, init, op)\n";
511}
512
513#endif // ALEPH_HAS_RANGES
514
515// =============================================================================
516// Main
517// =============================================================================
518
519int main(int argc, char* argv[])
520{
521 try
522 {
523 TCLAP::CmdLine cmd(
524 "C++20 Ranges example for Aleph-w.\n"
525 "Demonstrates lazy evaluation and range adaptors.",
526 ' ', "1.0"
527 );
528
529 TCLAP::ValueArg<string> sectionArg(
530 "s", "section",
531 "Run only specific section: lazy, views, materialize, aleph, "
532 "practical, perf, or 'all'",
533 false, "all", "section", cmd
534 );
535
536 cmd.parse(argc, argv);
537
538 string section = sectionArg.getValue();
539
540 cout << "\n";
541 cout << "============================================================\n";
542 cout << " ALEPH-W C++20 RANGES EXAMPLE\n";
543 cout << "============================================================\n";
544
545#if ALEPH_HAS_RANGES
546 cout << "\nALEPH_HAS_RANGES = 1 (C++20 ranges supported)\n";
547
548 if (section == "all" or section == "lazy")
550
551 if (section == "all" or section == "views")
552 demo_views();
553
554 if (section == "all" or section == "materialize")
556
557 if (section == "all" or section == "aleph")
559
560 if (section == "all" or section == "practical")
562
563 if (section == "all" or section == "perf")
565#else
566 cout << "\nALEPH_HAS_RANGES = 0 (C++20 ranges not available)\n";
568#endif
569
570 cout << "\n" << string(60, '=') << "\n";
571 cout << "Ranges demo completed!\n";
572 cout << string(60, '=') << "\n\n";
573
574 return 0;
575 }
576 catch (TCLAP::ArgException& e)
577 {
578 cerr << "Error: " << e.error() << " for argument " << e.argId() << endl;
579 return 1;
580 }
581 catch (exception& e)
582 {
583 cerr << "Error: " << e.what() << endl;
584 return 1;
585 }
586}
587
C++20 Ranges support and adaptors for Aleph-w containers.
int main()
void demo_performance()
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:190
void demo_practical()
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_sqrt_function > > sqrt(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4058
Singly linked list implementations with head-tail access.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Container2< typename Container1::Item_Type > filter(Container1 &container, Operation &operation)
Filter elements that satisfy operation.
Itor2 transform(Itor1 sourceBeg, Itor1 sourceEnd, Itor2 destBeg, UnaryFunc op)
Transform elements using a unary operation.
Definition ahAlgo.H:632
void next()
Advance all underlying iterators (bounds-checked).
Definition ah-zip.H:175
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.
STL namespace.
void print_subsection(const string &title)
void demo_no_ranges()
void print_section(const string &title)
void print_container(const string &label, const Container &c)
bool is_prime(int n)
Lazy and scalable dynamic array implementation.
Dynamic doubly linked list implementation.