Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
bitarray_example.C
Go to the documentation of this file.
1
71#include <iostream>
72#include <iomanip>
73#include <string>
74#include <cmath>
75
76#include <tclap/CmdLine.h>
77
78#include <bitArray.H>
79#include <htlist.H>
80#include <ahFunctional.H>
81
82using namespace std;
83using namespace Aleph;
84
85// =============================================================================
86// Helper functions
87// =============================================================================
88
89void print_section(const string& title)
90{
91 cout << "\n" << string(60, '=') << "\n";
92 cout << " " << title << "\n";
93 cout << string(60, '=') << "\n\n";
94}
95
96void print_subsection(const string& title)
97{
98 cout << "\n--- " << title << " ---\n";
99}
100
101void print_bits(const string& label, const BitArray& ba, size_t max_show = 64)
102{
103 cout << label << " (size=" << ba.size() << "): ";
104 size_t to_show = min(ba.size(), max_show);
105 for (size_t i = 0; i < to_show; ++i)
106 cout << (ba.read_bit(i) ? '1' : '0');
107 if (to_show < ba.size())
108 cout << "... (truncated)";
109 cout << endl;
110}
111
112// =============================================================================
113// 1. Basic Operations
114// =============================================================================
115
117{
118 print_section("BASIC OPERATIONS");
119
120 // Creating BitArrays
121 print_subsection("Creating BitArrays");
122
123 BitArray ba1(16); // 16 bits, all zeros
124 cout << "Created BitArray with 16 bits (all zeros)" << endl;
125 print_bits("ba1", ba1);
126
127 // Setting bits
128 print_subsection("Setting individual bits");
129 ba1.write_bit(0, 1);
130 ba1.write_bit(3, 1);
131 ba1.write_bit(7, 1);
132 ba1.write_bit(15, 1);
133
134 cout << "After setting bits 0, 3, 7, 15:" << endl;
135 print_bits("ba1", ba1);
136
137 // Reading bits
138 print_subsection("Reading bits");
139 cout << "bit[0] = " << ba1.read_bit(0) << endl;
140 cout << "bit[1] = " << ba1.read_bit(1) << endl;
141 cout << "bit[3] = " << ba1.read_bit(3) << endl;
142 cout << "bit[7] = " << ba1.read_bit(7) << endl;
143
144 // Alternative access with [] operator
145 print_subsection("Using [] operator");
146 cout << "ba1[0] = " << (int)ba1[0] << endl;
147 cout << "ba1[3] = " << (int)ba1[3] << endl;
148
149 // Toggle (flip) bits manually
150 print_subsection("Toggling bits");
151 cout << "Before toggle: bit[3] = " << ba1.read_bit(3) << endl;
152 ba1.write_bit(3, ba1.read_bit(3) ? 0 : 1); // Manual toggle
153 cout << "After toggle: bit[3] = " << ba1.read_bit(3) << endl;
154 ba1.write_bit(3, ba1.read_bit(3) ? 0 : 1); // Toggle back
155
156 // Fill with ones and zeros
157 print_subsection("Fill operations");
158 BitArray ba2(8);
159 // Set all bits to 1
160 for (size_t i = 0; i < ba2.size(); ++i)
161 ba2.write_bit(i, 1);
162 print_bits("All ones", ba2);
163 // Clear all bits to 0
164 for (size_t i = 0; i < ba2.size(); ++i)
165 ba2.write_bit(i, 0);
166 print_bits("All zeros", ba2);
167}
168
169// =============================================================================
170// 2. Bitwise Operations
171// =============================================================================
172
174{
175 print_section("BITWISE OPERATIONS");
176
177 BitArray a(8);
178 BitArray b(8);
179
180 // Setup: a = 11110000, b = 11001100
181 a.write_bit(0, 1); a.write_bit(1, 1); a.write_bit(2, 1); a.write_bit(3, 1);
182 b.write_bit(0, 1); b.write_bit(1, 1); b.write_bit(4, 1); b.write_bit(5, 1);
183
184 print_bits("a", a);
185 print_bits("b", b);
186
187 // AND
188 print_subsection("AND operation");
190 for (size_t i = 0; i < 8; ++i)
191 if (not b.read_bit(i))
192 and_result.write_bit(i, 0);
193 print_bits("a AND b", and_result);
194
195 // OR
196 print_subsection("OR operation");
198 for (size_t i = 0; i < 8; ++i)
199 if (b.read_bit(i))
200 or_result.write_bit(i, 1);
201 print_bits("a OR b", or_result);
202
203 // XOR
204 print_subsection("XOR operation");
206 for (size_t i = 0; i < 8; ++i)
207 xor_result.write_bit(i, a.read_bit(i) != b.read_bit(i) ? 1 : 0);
208 print_bits("a XOR b", xor_result);
209
210 // NOT
211 print_subsection("NOT operation");
212 BitArray not_a(8);
213 for (size_t i = 0; i < 8; ++i)
214 not_a.write_bit(i, a.read_bit(i) ? 0 : 1);
215 print_bits("NOT a", not_a);
216
217 // Population count
218 print_subsection("Population count (number of 1s)");
219 size_t count_a = 0;
220 for (size_t i = 0; i < a.size(); ++i)
221 if (a.read_bit(i)) count_a++;
222 cout << "popcount(a) = " << count_a << endl;
223
224 size_t count_b = 0;
225 for (size_t i = 0; i < b.size(); ++i)
226 if (b.read_bit(i)) count_b++;
227 cout << "popcount(b) = " << count_b << endl;
228}
229
230// =============================================================================
231// 3. Set Operations
232// =============================================================================
233
235{
236 print_section("SET OPERATIONS (using bits as sets)");
237
238 cout << "Universal set U = {0, 1, 2, 3, 4, 5, 6, 7}" << endl;
239
240 // Set A = {0, 1, 2, 3}
241 BitArray setA(8);
242 setA.write_bit(0, 1); setA.write_bit(1, 1);
243 setA.write_bit(2, 1); setA.write_bit(3, 1);
244
245 // Set B = {2, 3, 4, 5}
246 BitArray setB(8);
247 setB.write_bit(2, 1); setB.write_bit(3, 1);
248 setB.write_bit(4, 1); setB.write_bit(5, 1);
249
250 auto bits_to_set = [](const BitArray& ba) {
251 cout << "{";
252 bool first = true;
253 for (size_t i = 0; i < ba.size(); ++i)
254 {
255 if (ba.read_bit(i))
256 {
257 if (not first) cout << ", ";
258 cout << i;
259 first = false;
260 }
261 }
262 cout << "}";
263 };
264
265 cout << "A = "; bits_to_set(setA); cout << endl;
266 cout << "B = "; bits_to_set(setB); cout << endl;
267
268 // Union (A OR B)
269 print_subsection("Union A ∪ B");
270 BitArray unionAB(8);
271 for (size_t i = 0; i < 8; ++i)
272 unionAB.write_bit(i, setA.read_bit(i) or setB.read_bit(i) ? 1 : 0);
273 cout << "A ∪ B = "; bits_to_set(unionAB); cout << endl;
274
275 // Intersection (A AND B)
276 print_subsection("Intersection A ∩ B");
278 for (size_t i = 0; i < 8; ++i)
279 intersectAB.write_bit(i, setA.read_bit(i) and setB.read_bit(i) ? 1 : 0);
280 cout << "A ∩ B = "; bits_to_set(intersectAB); cout << endl;
281
282 // Difference (A - B = A AND NOT B)
283 print_subsection("Difference A - B");
284 BitArray diffAB(8);
285 for (size_t i = 0; i < 8; ++i)
286 diffAB.write_bit(i, setA.read_bit(i) and not setB.read_bit(i) ? 1 : 0);
287 cout << "A - B = "; bits_to_set(diffAB); cout << endl;
288
289 // Symmetric difference (A XOR B)
290 print_subsection("Symmetric Difference A △ B");
292 for (size_t i = 0; i < 8; ++i)
293 symDiffAB.write_bit(i, (setA.read_bit(i) != setB.read_bit(i)) ? 1 : 0);
294 cout << "A △ B = "; bits_to_set(symDiffAB); cout << endl;
295
296 // Complement
297 print_subsection("Complement A'");
298 BitArray compA(8);
299 for (size_t i = 0; i < 8; ++i)
300 compA.write_bit(i, setA.read_bit(i) ? 0 : 1);
301 cout << "A' = "; bits_to_set(compA); cout << endl;
302}
303
304// =============================================================================
305// 4. Practical Applications
306// =============================================================================
307
309{
310 print_section("SIEVE OF ERATOSTHENES");
311
312 cout << "Finding all primes up to " << n << endl << endl;
313
314 // true = composite, false = prime (initially all false)
315 BitArray is_composite(n + 1);
316
317 // 0 and 1 are not prime
318 is_composite.write_bit(0, 1);
319 is_composite.write_bit(1, 1);
320
321 // Sieve
322 size_t sqrt_n = static_cast<size_t>(sqrt(static_cast<double>(n)));
323 for (size_t i = 2; i <= sqrt_n; ++i)
324 {
325 if (not is_composite.read_bit(i))
326 {
327 // Mark all multiples of i as composite
328 for (size_t j = i * i; j <= n; j += i)
329 is_composite.write_bit(j, 1);
330 }
331 }
332
333 // Collect and display primes
335 for (size_t i = 2; i <= n; ++i)
336 if (not is_composite.read_bit(i))
337 primes.append(i);
338
339 cout << "Found " << primes.size() << " primes:\n";
340 cout << "[";
341 bool first = true;
342 size_t shown = 0;
343 primes.for_each([&first, &shown](size_t p) {
344 if (shown < 50)
345 {
346 if (not first) cout << ", ";
347 cout << p;
348 first = false;
349 shown++;
350 }
351 });
352 if (primes.size() > 50)
353 cout << ", ... (showing first 50)";
354 cout << "]\n";
355
356 // Memory efficiency
357 cout << "\nMemory used: " << (n + 1 + 7) / 8 << " bytes" << endl;
358 cout << "vs. bool array: " << (n + 1) << " bytes" << endl;
359 cout << "Space savings: " << 100 * (1 - 1.0/8) << "%" << endl;
360}
361
363{
364 print_section("SUBSET ENUMERATION");
365
367 universe.append("apple");
368 universe.append("banana");
369 universe.append("cherry");
370
371 cout << "Universe: {apple, banana, cherry}" << endl;
372 cout << "\nAll possible subsets (2^3 = 8):\n" << endl;
373
374 size_t n = 3;
375 size_t total_subsets = 1 << n; // 2^n
376
377 for (size_t mask = 0; mask < total_subsets; ++mask)
378 {
379 BitArray subset(n);
380 // Convert mask to BitArray
381 for (size_t i = 0; i < n; ++i)
382 if (mask & (1 << i))
383 subset.write_bit(i, 1);
384
385 cout << " {";
386 bool first = true;
387 size_t idx = 0;
388 universe.for_each([&](const string& item) {
389 if (subset.read_bit(idx))
390 {
391 if (not first) cout << ", ";
392 cout << item;
393 first = false;
394 }
395 idx++;
396 });
397 cout << "}" << endl;
398 }
399}
400
402{
403 print_section("SIMPLE BLOOM FILTER CONCEPT");
404
405 size_t filter_size = 32;
407
408 cout << "Bloom filter size: " << filter_size << " bits\n" << endl;
409
410 // Simple hash functions
411 auto hash1 = [filter_size](const string& s) {
412 size_t h = 0;
413 for (char c : s) h = h * 31 + c;
414 return h % filter_size;
415 };
416
417 auto hash2 = [filter_size](const string& s) {
418 size_t h = 0;
419 for (char c : s) h = h * 37 + c;
420 return h % filter_size;
421 };
422
423 // Add items to filter
424 auto add = [&](const string& item) {
425 bloom.write_bit(hash1(item), 1);
426 bloom.write_bit(hash2(item), 1);
427 cout << "Added \"" << item << "\" -> bits " << hash1(item)
428 << ", " << hash2(item) << endl;
429 };
430
431 // Check if item might be in filter
432 auto might_contain = [&](const string& item) {
433 return bloom.read_bit(hash1(item)) and bloom.read_bit(hash2(item));
434 };
435
436 // Add some items
437 cout << "Adding items:\n";
438 add("hello");
439 add("world");
440 add("aleph");
441
442 print_bits("\nBloom filter", bloom);
443
444 // Test membership
445 cout << "\nMembership tests:" << endl;
447 tests.append("hello");
448 tests.append("world");
449 tests.append("aleph");
450 tests.append("test");
451 tests.append("foo");
452 tests.append("bar");
453
454 tests.for_each([&](const string& item) {
455 bool result = might_contain(item);
456 cout << " \"" << item << "\": "
457 << (result ? "probably in set" : "definitely NOT in set") << endl;
458 });
459
460 cout << "\nNote: Bloom filters may have false positives, but never false negatives." << endl;
461}
462
463// =============================================================================
464// 5. Performance Comparison
465// =============================================================================
466
468{
469 print_section("MEMORY EFFICIENCY");
470
471 cout << "Comparison of memory usage:\n\n";
472
473 cout << setw(20) << "Size"
474 << setw(20) << "BitArray (bytes)"
475 << setw(20) << "bool[] (bytes)"
476 << setw(15) << "Savings" << endl;
477 cout << string(75, '-') << endl;
478
480 sizes.append(100);
481 sizes.append(1000);
482 sizes.append(10000);
483 sizes.append(100000);
484 sizes.append(1000000);
485
486 sizes.for_each([](size_t n) {
487 size_t bitarray_bytes = (n + 7) / 8;
488 size_t bool_bytes = n;
489 double savings = 100.0 * (1.0 - static_cast<double>(bitarray_bytes) / bool_bytes);
490
491 cout << setw(20) << n
492 << setw(20) << bitarray_bytes
493 << setw(20) << bool_bytes
494 << setw(14) << fixed << setprecision(1) << savings << "%" << endl;
495 });
496
497 cout << "\nBitArray uses 8x less memory than bool arrays!" << endl;
498}
499
500// =============================================================================
501// Main
502// =============================================================================
503
504int main(int argc, char* argv[])
505{
506 try
507 {
508 TCLAP::CmdLine cmd(
509 "BitArray example for Aleph-w.\n"
510 "Demonstrates bit manipulation, set operations, and practical applications.",
511 ' ', "1.0"
512 );
513
514 TCLAP::ValueArg<size_t> sieveArg(
515 "n", "sieve-size",
516 "Size for Sieve of Eratosthenes demo (default: 100)",
517 false, 100, "size", cmd
518 );
519
520 cmd.parse(argc, argv);
521
522 size_t sieve_size = sieveArg.getValue();
523
524 cout << "\n";
525 cout << "============================================================\n";
526 cout << " ALEPH-W BITARRAY EXAMPLE\n";
527 cout << "============================================================\n";
528
536
537 cout << "\n" << string(60, '=') << "\n";
538 cout << "BitArray demo completed!\n";
539 cout << string(60, '=') << "\n\n";
540
541 return 0;
542 }
543 catch (TCLAP::ArgException& e)
544 {
545 cerr << "Error: " << e.error() << " for argument " << e.argId() << endl;
546 return 1;
547 }
548 catch (exception& e)
549 {
550 cerr << "Error: " << e.what() << endl;
551 return 1;
552 }
553}
554
Functional programming utilities for Aleph-w containers.
int main()
static size_t primes[]
Space-efficient bit array implementation.
void demo_performance()
void print_subsection(const string &title)
void demo_bitwise_operations()
void demo_sieve_of_eratosthenes(size_t n)
void demo_simple_bloom_filter()
void demo_basic_operations()
void demo_set_operations()
void print_section(const string &title)
void demo_subset_enumeration()
void print_bits(const string &label, const BitArray &ba, size_t max_show=64)
long double h
Definition btreepic.C:154
Contiguous array of bits.
Definition bitArray.H:189
int read_bit(const size_t i) const
Read bit i.
Definition bitArray.H:377
void write_bit(const size_t i, const unsigned int value)
Write bit i with the value.
Definition bitArray.H:392
constexpr size_t size() const noexcept
Returns the dimension of the bit array.
Definition bitArray.H:334
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
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
void for_each(Operation &operation)
Traverse all the container and performs an operation on each element.
Definition ah-dry.H:685
__gmp_expr< T, __gmp_unary_expr< __gmp_expr< T, U >, __gmp_sqrt_function > > sqrt(const __gmp_expr< T, U > &expr)
Definition gmpfrxx.h:4058
__gmp_expr< typename __gmp_resolve_expr< T, V >::value_type, __gmp_binary_expr< __gmp_expr< T, U >, __gmp_expr< V, W >, __gmp_min_function > > min(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4111
Singly linked list implementations with head-tail access.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.