exonware-xwnode 0.0.1.12__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (132) hide show
  1. exonware/__init__.py +14 -0
  2. exonware/xwnode/__init__.py +127 -0
  3. exonware/xwnode/base.py +676 -0
  4. exonware/xwnode/config.py +178 -0
  5. exonware/xwnode/contracts.py +730 -0
  6. exonware/xwnode/errors.py +503 -0
  7. exonware/xwnode/facade.py +460 -0
  8. exonware/xwnode/strategies/__init__.py +158 -0
  9. exonware/xwnode/strategies/advisor.py +463 -0
  10. exonware/xwnode/strategies/edges/__init__.py +32 -0
  11. exonware/xwnode/strategies/edges/adj_list.py +227 -0
  12. exonware/xwnode/strategies/edges/adj_matrix.py +391 -0
  13. exonware/xwnode/strategies/edges/base.py +169 -0
  14. exonware/xwnode/strategies/flyweight.py +328 -0
  15. exonware/xwnode/strategies/impls/__init__.py +13 -0
  16. exonware/xwnode/strategies/impls/_base_edge.py +403 -0
  17. exonware/xwnode/strategies/impls/_base_node.py +307 -0
  18. exonware/xwnode/strategies/impls/edge_adj_list.py +353 -0
  19. exonware/xwnode/strategies/impls/edge_adj_matrix.py +445 -0
  20. exonware/xwnode/strategies/impls/edge_bidir_wrapper.py +455 -0
  21. exonware/xwnode/strategies/impls/edge_block_adj_matrix.py +539 -0
  22. exonware/xwnode/strategies/impls/edge_coo.py +533 -0
  23. exonware/xwnode/strategies/impls/edge_csc.py +447 -0
  24. exonware/xwnode/strategies/impls/edge_csr.py +492 -0
  25. exonware/xwnode/strategies/impls/edge_dynamic_adj_list.py +503 -0
  26. exonware/xwnode/strategies/impls/edge_flow_network.py +555 -0
  27. exonware/xwnode/strategies/impls/edge_hyperedge_set.py +516 -0
  28. exonware/xwnode/strategies/impls/edge_neural_graph.py +650 -0
  29. exonware/xwnode/strategies/impls/edge_octree.py +574 -0
  30. exonware/xwnode/strategies/impls/edge_property_store.py +655 -0
  31. exonware/xwnode/strategies/impls/edge_quadtree.py +519 -0
  32. exonware/xwnode/strategies/impls/edge_rtree.py +820 -0
  33. exonware/xwnode/strategies/impls/edge_temporal_edgeset.py +558 -0
  34. exonware/xwnode/strategies/impls/edge_tree_graph_basic.py +271 -0
  35. exonware/xwnode/strategies/impls/edge_weighted_graph.py +411 -0
  36. exonware/xwnode/strategies/manager.py +775 -0
  37. exonware/xwnode/strategies/metrics.py +538 -0
  38. exonware/xwnode/strategies/migration.py +432 -0
  39. exonware/xwnode/strategies/nodes/__init__.py +50 -0
  40. exonware/xwnode/strategies/nodes/_base_node.py +307 -0
  41. exonware/xwnode/strategies/nodes/adjacency_list.py +267 -0
  42. exonware/xwnode/strategies/nodes/aho_corasick.py +345 -0
  43. exonware/xwnode/strategies/nodes/array_list.py +209 -0
  44. exonware/xwnode/strategies/nodes/base.py +247 -0
  45. exonware/xwnode/strategies/nodes/deque.py +200 -0
  46. exonware/xwnode/strategies/nodes/hash_map.py +135 -0
  47. exonware/xwnode/strategies/nodes/heap.py +307 -0
  48. exonware/xwnode/strategies/nodes/linked_list.py +232 -0
  49. exonware/xwnode/strategies/nodes/node_aho_corasick.py +520 -0
  50. exonware/xwnode/strategies/nodes/node_array_list.py +175 -0
  51. exonware/xwnode/strategies/nodes/node_avl_tree.py +371 -0
  52. exonware/xwnode/strategies/nodes/node_b_plus_tree.py +542 -0
  53. exonware/xwnode/strategies/nodes/node_bitmap.py +420 -0
  54. exonware/xwnode/strategies/nodes/node_bitset_dynamic.py +513 -0
  55. exonware/xwnode/strategies/nodes/node_bloom_filter.py +347 -0
  56. exonware/xwnode/strategies/nodes/node_btree.py +357 -0
  57. exonware/xwnode/strategies/nodes/node_count_min_sketch.py +470 -0
  58. exonware/xwnode/strategies/nodes/node_cow_tree.py +473 -0
  59. exonware/xwnode/strategies/nodes/node_cuckoo_hash.py +392 -0
  60. exonware/xwnode/strategies/nodes/node_fenwick_tree.py +301 -0
  61. exonware/xwnode/strategies/nodes/node_hash_map.py +269 -0
  62. exonware/xwnode/strategies/nodes/node_heap.py +191 -0
  63. exonware/xwnode/strategies/nodes/node_hyperloglog.py +407 -0
  64. exonware/xwnode/strategies/nodes/node_linked_list.py +409 -0
  65. exonware/xwnode/strategies/nodes/node_lsm_tree.py +400 -0
  66. exonware/xwnode/strategies/nodes/node_ordered_map.py +390 -0
  67. exonware/xwnode/strategies/nodes/node_ordered_map_balanced.py +565 -0
  68. exonware/xwnode/strategies/nodes/node_patricia.py +512 -0
  69. exonware/xwnode/strategies/nodes/node_persistent_tree.py +378 -0
  70. exonware/xwnode/strategies/nodes/node_radix_trie.py +452 -0
  71. exonware/xwnode/strategies/nodes/node_red_black_tree.py +497 -0
  72. exonware/xwnode/strategies/nodes/node_roaring_bitmap.py +570 -0
  73. exonware/xwnode/strategies/nodes/node_segment_tree.py +289 -0
  74. exonware/xwnode/strategies/nodes/node_set_hash.py +354 -0
  75. exonware/xwnode/strategies/nodes/node_set_tree.py +480 -0
  76. exonware/xwnode/strategies/nodes/node_skip_list.py +316 -0
  77. exonware/xwnode/strategies/nodes/node_splay_tree.py +393 -0
  78. exonware/xwnode/strategies/nodes/node_suffix_array.py +487 -0
  79. exonware/xwnode/strategies/nodes/node_treap.py +387 -0
  80. exonware/xwnode/strategies/nodes/node_tree_graph_hybrid.py +1434 -0
  81. exonware/xwnode/strategies/nodes/node_trie.py +252 -0
  82. exonware/xwnode/strategies/nodes/node_union_find.py +187 -0
  83. exonware/xwnode/strategies/nodes/node_xdata_optimized.py +369 -0
  84. exonware/xwnode/strategies/nodes/priority_queue.py +209 -0
  85. exonware/xwnode/strategies/nodes/queue.py +161 -0
  86. exonware/xwnode/strategies/nodes/sparse_matrix.py +206 -0
  87. exonware/xwnode/strategies/nodes/stack.py +152 -0
  88. exonware/xwnode/strategies/nodes/trie.py +274 -0
  89. exonware/xwnode/strategies/nodes/union_find.py +283 -0
  90. exonware/xwnode/strategies/pattern_detector.py +603 -0
  91. exonware/xwnode/strategies/performance_monitor.py +487 -0
  92. exonware/xwnode/strategies/queries/__init__.py +24 -0
  93. exonware/xwnode/strategies/queries/base.py +236 -0
  94. exonware/xwnode/strategies/queries/cql.py +201 -0
  95. exonware/xwnode/strategies/queries/cypher.py +181 -0
  96. exonware/xwnode/strategies/queries/datalog.py +70 -0
  97. exonware/xwnode/strategies/queries/elastic_dsl.py +70 -0
  98. exonware/xwnode/strategies/queries/eql.py +70 -0
  99. exonware/xwnode/strategies/queries/flux.py +70 -0
  100. exonware/xwnode/strategies/queries/gql.py +70 -0
  101. exonware/xwnode/strategies/queries/graphql.py +240 -0
  102. exonware/xwnode/strategies/queries/gremlin.py +181 -0
  103. exonware/xwnode/strategies/queries/hiveql.py +214 -0
  104. exonware/xwnode/strategies/queries/hql.py +70 -0
  105. exonware/xwnode/strategies/queries/jmespath.py +219 -0
  106. exonware/xwnode/strategies/queries/jq.py +66 -0
  107. exonware/xwnode/strategies/queries/json_query.py +66 -0
  108. exonware/xwnode/strategies/queries/jsoniq.py +248 -0
  109. exonware/xwnode/strategies/queries/kql.py +70 -0
  110. exonware/xwnode/strategies/queries/linq.py +238 -0
  111. exonware/xwnode/strategies/queries/logql.py +70 -0
  112. exonware/xwnode/strategies/queries/mql.py +68 -0
  113. exonware/xwnode/strategies/queries/n1ql.py +210 -0
  114. exonware/xwnode/strategies/queries/partiql.py +70 -0
  115. exonware/xwnode/strategies/queries/pig.py +215 -0
  116. exonware/xwnode/strategies/queries/promql.py +70 -0
  117. exonware/xwnode/strategies/queries/sparql.py +220 -0
  118. exonware/xwnode/strategies/queries/sql.py +275 -0
  119. exonware/xwnode/strategies/queries/xml_query.py +66 -0
  120. exonware/xwnode/strategies/queries/xpath.py +223 -0
  121. exonware/xwnode/strategies/queries/xquery.py +258 -0
  122. exonware/xwnode/strategies/queries/xwnode_executor.py +332 -0
  123. exonware/xwnode/strategies/queries/xwquery_strategy.py +424 -0
  124. exonware/xwnode/strategies/registry.py +604 -0
  125. exonware/xwnode/strategies/simple.py +273 -0
  126. exonware/xwnode/strategies/utils.py +532 -0
  127. exonware/xwnode/types.py +912 -0
  128. exonware/xwnode/version.py +78 -0
  129. exonware_xwnode-0.0.1.12.dist-info/METADATA +169 -0
  130. exonware_xwnode-0.0.1.12.dist-info/RECORD +132 -0
  131. exonware_xwnode-0.0.1.12.dist-info/WHEEL +4 -0
  132. exonware_xwnode-0.0.1.12.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,513 @@
1
+ """
2
+ Dynamic Bitset Node Strategy Implementation
3
+
4
+ This module implements the BITSET_DYNAMIC strategy for dynamic bitset
5
+ operations with automatic resizing and bit manipulation capabilities.
6
+ """
7
+
8
+ from typing import Any, Iterator, List, Dict, Optional, Tuple, Union
9
+ from .base import ANodeMatrixStrategy
10
+ from ...types import NodeMode, NodeTrait
11
+
12
+
13
+ class BitsetDynamicStrategy(ANodeMatrixStrategy):
14
+ """
15
+ Dynamic Bitset node strategy for bit manipulation operations.
16
+
17
+ Provides efficient set operations, bit manipulation, and automatic
18
+ resizing for large-scale boolean data processing.
19
+ """
20
+
21
+ def __init__(self, traits: NodeTrait = NodeTrait.NONE, **options):
22
+ """Initialize the Dynamic Bitset strategy."""
23
+ super().__init__(NodeMode.BITSET_DYNAMIC, traits, **options)
24
+
25
+ self.initial_capacity = options.get('initial_capacity', 64)
26
+ self.growth_factor = options.get('growth_factor', 2.0)
27
+ self.auto_trim = options.get('auto_trim', True)
28
+
29
+ # Core dynamic bitset
30
+ self._bits: List[int] = [0] * ((self.initial_capacity + 63) // 64) # 64-bit chunks
31
+ self._capacity = len(self._bits) * 64
32
+ self._size = 0 # Number of set bits
33
+ self._highest_bit = -1 # Highest set bit index
34
+
35
+ # Statistics
36
+ self._total_operations = 0
37
+ self._resize_count = 0
38
+ self._trim_count = 0
39
+ self._bit_flips = 0
40
+
41
+ def get_supported_traits(self) -> NodeTrait:
42
+ """Get the traits supported by the dynamic bitset strategy."""
43
+ return (NodeTrait.INDEXED | NodeTrait.COMPRESSED)
44
+
45
+ def _ensure_capacity(self, bit_index: int) -> None:
46
+ """Ensure bitset can accommodate the given bit index."""
47
+ required_capacity = bit_index + 1
48
+
49
+ if required_capacity > self._capacity:
50
+ # Calculate new capacity
51
+ new_capacity = self._capacity
52
+ while new_capacity < required_capacity:
53
+ new_capacity = int(new_capacity * self.growth_factor)
54
+
55
+ # Extend bits array
56
+ old_chunks = len(self._bits)
57
+ new_chunks = (new_capacity + 63) // 64
58
+ self._bits.extend([0] * (new_chunks - old_chunks))
59
+ self._capacity = new_chunks * 64
60
+ self._resize_count += 1
61
+
62
+ def _trim_if_needed(self) -> None:
63
+ """Trim unused capacity if auto_trim is enabled."""
64
+ if not self.auto_trim or self._highest_bit == -1:
65
+ return
66
+
67
+ required_chunks = (self._highest_bit // 64) + 1
68
+ current_chunks = len(self._bits)
69
+
70
+ # Trim if we have more than 2x the required chunks
71
+ if current_chunks > required_chunks * 2:
72
+ self._bits = self._bits[:required_chunks]
73
+ self._capacity = len(self._bits) * 64
74
+ self._trim_count += 1
75
+
76
+ def _update_highest_bit(self) -> None:
77
+ """Update the highest set bit index."""
78
+ self._highest_bit = -1
79
+ for i in range(len(self._bits) - 1, -1, -1):
80
+ if self._bits[i] != 0:
81
+ # Find highest bit in this chunk
82
+ chunk = self._bits[i]
83
+ bit_pos = i * 64
84
+ while chunk > 0:
85
+ if chunk & 1:
86
+ self._highest_bit = bit_pos
87
+ chunk >>= 1
88
+ bit_pos += 1
89
+ break
90
+
91
+ def _set_bit(self, bit_index: int, value: bool) -> bool:
92
+ """Set bit at index to value. Returns True if bit changed."""
93
+ self._ensure_capacity(bit_index)
94
+
95
+ chunk_index = bit_index // 64
96
+ bit_position = bit_index % 64
97
+ mask = 1 << bit_position
98
+
99
+ old_value = bool(self._bits[chunk_index] & mask)
100
+
101
+ if value:
102
+ if not old_value:
103
+ self._bits[chunk_index] |= mask
104
+ self._size += 1
105
+ self._highest_bit = max(self._highest_bit, bit_index)
106
+ self._bit_flips += 1
107
+ return True
108
+ else:
109
+ if old_value:
110
+ self._bits[chunk_index] &= ~mask
111
+ self._size -= 1
112
+ if bit_index == self._highest_bit:
113
+ self._update_highest_bit()
114
+ self._bit_flips += 1
115
+ return True
116
+
117
+ return False
118
+
119
+ def _get_bit(self, bit_index: int) -> bool:
120
+ """Get bit value at index."""
121
+ if bit_index < 0 or bit_index >= self._capacity:
122
+ return False
123
+
124
+ chunk_index = bit_index // 64
125
+ if chunk_index >= len(self._bits):
126
+ return False
127
+
128
+ bit_position = bit_index % 64
129
+ mask = 1 << bit_position
130
+ return bool(self._bits[chunk_index] & mask)
131
+
132
+ def _find_next_set_bit(self, start_index: int = 0) -> int:
133
+ """Find next set bit starting from start_index."""
134
+ for i in range(start_index, self._highest_bit + 1):
135
+ if self._get_bit(i):
136
+ return i
137
+ return -1
138
+
139
+ def _find_next_clear_bit(self, start_index: int = 0) -> int:
140
+ """Find next clear bit starting from start_index."""
141
+ i = start_index
142
+ while i <= self._highest_bit + 64: # Search a bit beyond current range
143
+ if not self._get_bit(i):
144
+ return i
145
+ i += 1
146
+ return i
147
+
148
+ # ============================================================================
149
+ # CORE OPERATIONS
150
+ # ============================================================================
151
+
152
+ def put(self, key: Any, value: Any = None) -> None:
153
+ """Set bit at key index."""
154
+ self._total_operations += 1
155
+
156
+ if isinstance(key, str) and key.isdigit():
157
+ bit_index = int(key)
158
+ elif isinstance(key, int):
159
+ bit_index = key
160
+ else:
161
+ bit_index = hash(str(key)) % (2**20) # Limit to reasonable range
162
+
163
+ # Interpret value as boolean
164
+ if value is None:
165
+ bit_value = True # Default to setting the bit
166
+ elif isinstance(value, bool):
167
+ bit_value = value
168
+ elif isinstance(value, (int, float)):
169
+ bit_value = bool(value)
170
+ else:
171
+ bit_value = bool(value)
172
+
173
+ self._set_bit(abs(bit_index), bit_value)
174
+ self._trim_if_needed()
175
+
176
+ def get(self, key: Any, default: Any = None) -> Any:
177
+ """Get bit value at key index."""
178
+ key_str = str(key)
179
+
180
+ if key_str == "bitset_info":
181
+ return {
182
+ 'size': self._size,
183
+ 'capacity': self._capacity,
184
+ 'highest_bit': self._highest_bit,
185
+ 'total_operations': self._total_operations,
186
+ 'resize_count': self._resize_count,
187
+ 'bit_flips': self._bit_flips,
188
+ 'utilization': self._size / max(1, self._capacity) * 100
189
+ }
190
+ elif key_str == "bit_count":
191
+ return self._size
192
+ elif key_str == "all_set_bits":
193
+ return self.get_set_bits()
194
+ elif key_str == "bit_pattern":
195
+ return self.to_bit_string()
196
+
197
+ if key_str.isdigit():
198
+ bit_index = int(key_str)
199
+ return self._get_bit(bit_index)
200
+ elif isinstance(key, int):
201
+ return self._get_bit(key)
202
+ else:
203
+ bit_index = hash(str(key)) % (2**20)
204
+ return self._get_bit(abs(bit_index))
205
+
206
+ def has(self, key: Any) -> bool:
207
+ """Check if bit at key index is set."""
208
+ key_str = str(key)
209
+
210
+ if key_str in ["bitset_info", "bit_count", "all_set_bits", "bit_pattern"]:
211
+ return True
212
+
213
+ if key_str.isdigit():
214
+ bit_index = int(key_str)
215
+ return self._get_bit(bit_index)
216
+ elif isinstance(key, int):
217
+ return self._get_bit(key)
218
+ else:
219
+ bit_index = hash(str(key)) % (2**20)
220
+ return self._get_bit(abs(bit_index))
221
+
222
+ def remove(self, key: Any) -> bool:
223
+ """Clear bit at key index."""
224
+ if isinstance(key, str) and key.isdigit():
225
+ bit_index = int(key)
226
+ elif isinstance(key, int):
227
+ bit_index = key
228
+ else:
229
+ bit_index = hash(str(key)) % (2**20)
230
+
231
+ return self._set_bit(abs(bit_index), False)
232
+
233
+ def delete(self, key: Any) -> bool:
234
+ """Clear bit at key index (alias for remove)."""
235
+ return self.remove(key)
236
+
237
+ def clear(self) -> None:
238
+ """Clear all bits."""
239
+ self._bits = [0] * ((self.initial_capacity + 63) // 64)
240
+ self._capacity = len(self._bits) * 64
241
+ self._size = 0
242
+ self._highest_bit = -1
243
+ self._total_operations = 0
244
+ self._resize_count = 0
245
+ self._trim_count = 0
246
+ self._bit_flips = 0
247
+
248
+ def keys(self) -> Iterator[str]:
249
+ """Get all set bit indices as strings."""
250
+ for i in range(self._highest_bit + 1):
251
+ if self._get_bit(i):
252
+ yield str(i)
253
+
254
+ def values(self) -> Iterator[Any]:
255
+ """Get all set bit values (always True)."""
256
+ for i in range(self._highest_bit + 1):
257
+ if self._get_bit(i):
258
+ yield True
259
+
260
+ def items(self) -> Iterator[tuple[str, Any]]:
261
+ """Get all set bit indices and values."""
262
+ for i in range(self._highest_bit + 1):
263
+ if self._get_bit(i):
264
+ yield (str(i), True)
265
+
266
+ def __len__(self) -> int:
267
+ """Get number of set bits."""
268
+ return self._size
269
+
270
+ def to_native(self) -> Dict[str, bool]:
271
+ """Convert to native Python dict of set bits."""
272
+ return {str(i): True for i in range(self._highest_bit + 1) if self._get_bit(i)}
273
+
274
+ @property
275
+ def is_list(self) -> bool:
276
+ """This can behave like a list for indexed access."""
277
+ return True
278
+
279
+ @property
280
+ def is_dict(self) -> bool:
281
+ """This behaves like a dict."""
282
+ return True
283
+
284
+ # ============================================================================
285
+ # BITSET SPECIFIC OPERATIONS
286
+ # ============================================================================
287
+
288
+ def set_bit(self, index: int, value: bool = True) -> None:
289
+ """Set specific bit to value."""
290
+ self._set_bit(abs(index), value)
291
+ self._trim_if_needed()
292
+
293
+ def clear_bit(self, index: int) -> None:
294
+ """Clear specific bit."""
295
+ self._set_bit(abs(index), False)
296
+ self._trim_if_needed()
297
+
298
+ def flip_bit(self, index: int) -> None:
299
+ """Flip specific bit."""
300
+ current_value = self._get_bit(abs(index))
301
+ self._set_bit(abs(index), not current_value)
302
+ self._trim_if_needed()
303
+
304
+ def get_set_bits(self) -> List[int]:
305
+ """Get list of all set bit indices."""
306
+ result = []
307
+ for i in range(self._highest_bit + 1):
308
+ if self._get_bit(i):
309
+ result.append(i)
310
+ return result
311
+
312
+ def get_clear_bits(self, max_index: Optional[int] = None) -> List[int]:
313
+ """Get list of clear bit indices up to max_index."""
314
+ if max_index is None:
315
+ max_index = self._highest_bit + 10 # Some reasonable limit
316
+
317
+ result = []
318
+ for i in range(min(max_index + 1, self._capacity)):
319
+ if not self._get_bit(i):
320
+ result.append(i)
321
+ return result
322
+
323
+ def count_bits(self, start: int = 0, end: Optional[int] = None) -> int:
324
+ """Count set bits in range [start, end)."""
325
+ if end is None:
326
+ end = self._highest_bit + 1
327
+
328
+ count = 0
329
+ for i in range(start, min(end, self._highest_bit + 1)):
330
+ if self._get_bit(i):
331
+ count += 1
332
+ return count
333
+
334
+ def find_first_set(self) -> int:
335
+ """Find index of first set bit (-1 if none)."""
336
+ return self._find_next_set_bit(0)
337
+
338
+ def find_last_set(self) -> int:
339
+ """Find index of last set bit (-1 if none)."""
340
+ return self._highest_bit if self._size > 0 else -1
341
+
342
+ def find_next_set(self, start: int) -> int:
343
+ """Find next set bit after start index."""
344
+ return self._find_next_set_bit(start + 1)
345
+
346
+ def find_next_clear(self, start: int) -> int:
347
+ """Find next clear bit after start index."""
348
+ return self._find_next_clear_bit(start)
349
+
350
+ def set_range(self, start: int, end: int, value: bool = True) -> None:
351
+ """Set range of bits [start, end) to value."""
352
+ for i in range(start, end):
353
+ self._set_bit(i, value)
354
+ self._trim_if_needed()
355
+
356
+ def flip_range(self, start: int, end: int) -> None:
357
+ """Flip range of bits [start, end)."""
358
+ for i in range(start, end):
359
+ current = self._get_bit(i)
360
+ self._set_bit(i, not current)
361
+ self._trim_if_needed()
362
+
363
+ def logical_and(self, other: 'xBitsetDynamicStrategy') -> 'xBitsetDynamicStrategy':
364
+ """Perform logical AND with another bitset."""
365
+ result = xBitsetDynamicStrategy()
366
+ max_index = max(self._highest_bit, other._highest_bit)
367
+
368
+ for i in range(max_index + 1):
369
+ if self._get_bit(i) and other._get_bit(i):
370
+ result._set_bit(i, True)
371
+
372
+ return result
373
+
374
+ def logical_or(self, other: 'xBitsetDynamicStrategy') -> 'xBitsetDynamicStrategy':
375
+ """Perform logical OR with another bitset."""
376
+ result = xBitsetDynamicStrategy()
377
+ max_index = max(self._highest_bit, other._highest_bit)
378
+
379
+ for i in range(max_index + 1):
380
+ if self._get_bit(i) or other._get_bit(i):
381
+ result._set_bit(i, True)
382
+
383
+ return result
384
+
385
+ def logical_xor(self, other: 'xBitsetDynamicStrategy') -> 'xBitsetDynamicStrategy':
386
+ """Perform logical XOR with another bitset."""
387
+ result = xBitsetDynamicStrategy()
388
+ max_index = max(self._highest_bit, other._highest_bit)
389
+
390
+ for i in range(max_index + 1):
391
+ if self._get_bit(i) != other._get_bit(i):
392
+ result._set_bit(i, True)
393
+
394
+ return result
395
+
396
+ def logical_not(self, max_index: Optional[int] = None) -> 'xBitsetDynamicStrategy':
397
+ """Perform logical NOT (up to max_index)."""
398
+ if max_index is None:
399
+ max_index = self._highest_bit + 64 # Reasonable extension
400
+
401
+ result = xBitsetDynamicStrategy()
402
+ for i in range(max_index + 1):
403
+ if not self._get_bit(i):
404
+ result._set_bit(i, True)
405
+
406
+ return result
407
+
408
+ def is_subset_of(self, other: 'xBitsetDynamicStrategy') -> bool:
409
+ """Check if this bitset is a subset of another."""
410
+ for i in range(self._highest_bit + 1):
411
+ if self._get_bit(i) and not other._get_bit(i):
412
+ return False
413
+ return True
414
+
415
+ def is_superset_of(self, other: 'xBitsetDynamicStrategy') -> bool:
416
+ """Check if this bitset is a superset of another."""
417
+ return other.is_subset_of(self)
418
+
419
+ def intersects(self, other: 'xBitsetDynamicStrategy') -> bool:
420
+ """Check if this bitset intersects with another."""
421
+ max_index = min(self._highest_bit, other._highest_bit)
422
+ for i in range(max_index + 1):
423
+ if self._get_bit(i) and other._get_bit(i):
424
+ return True
425
+ return False
426
+
427
+ def to_bit_string(self, max_length: int = 64) -> str:
428
+ """Convert to binary string representation."""
429
+ if self._highest_bit == -1:
430
+ return "0"
431
+
432
+ length = min(self._highest_bit + 1, max_length)
433
+ bits = []
434
+ for i in range(length - 1, -1, -1): # MSB first
435
+ bits.append('1' if self._get_bit(i) else '0')
436
+
437
+ result = ''.join(bits)
438
+ if length < self._highest_bit + 1:
439
+ result = "..." + result # Indicate truncation
440
+
441
+ return result
442
+
443
+ def from_bit_string(self, bit_string: str) -> None:
444
+ """Load from binary string representation."""
445
+ self.clear()
446
+
447
+ # Remove any truncation indicator
448
+ if bit_string.startswith("..."):
449
+ bit_string = bit_string[3:]
450
+
451
+ for i, bit_char in enumerate(reversed(bit_string)):
452
+ if bit_char == '1':
453
+ self._set_bit(i, True)
454
+
455
+ def get_statistics(self) -> Dict[str, Any]:
456
+ """Get comprehensive bitset statistics."""
457
+ chunks_used = (self._highest_bit // 64) + 1 if self._highest_bit >= 0 else 0
458
+
459
+ return {
460
+ 'size': self._size,
461
+ 'capacity': self._capacity,
462
+ 'highest_bit': self._highest_bit,
463
+ 'chunks_allocated': len(self._bits),
464
+ 'chunks_used': chunks_used,
465
+ 'utilization': self._size / max(1, self._capacity) * 100,
466
+ 'density': self._size / max(1, self._highest_bit + 1) * 100 if self._highest_bit >= 0 else 0,
467
+ 'total_operations': self._total_operations,
468
+ 'resize_count': self._resize_count,
469
+ 'trim_count': self._trim_count,
470
+ 'bit_flips': self._bit_flips,
471
+ 'memory_efficiency': chunks_used / max(1, len(self._bits)) * 100
472
+ }
473
+
474
+ # ============================================================================
475
+ # PERFORMANCE CHARACTERISTICS
476
+ # ============================================================================
477
+
478
+ @property
479
+ def backend_info(self) -> Dict[str, Any]:
480
+ """Get backend implementation info."""
481
+ return {
482
+ 'strategy': 'BITSET_DYNAMIC',
483
+ 'backend': 'Dynamic bitset with 64-bit chunks',
484
+ 'initial_capacity': self.initial_capacity,
485
+ 'growth_factor': self.growth_factor,
486
+ 'auto_trim': self.auto_trim,
487
+ 'complexity': {
488
+ 'set_bit': 'O(1) amortized',
489
+ 'get_bit': 'O(1)',
490
+ 'clear_bit': 'O(1)',
491
+ 'flip_bit': 'O(1)',
492
+ 'find_next': 'O(n)', # n = bit range
493
+ 'logical_ops': 'O(max(m,n))', # m,n = highest bits
494
+ 'space': 'O(capacity/64)',
495
+ 'resize': 'O(old_capacity) when triggered'
496
+ }
497
+ }
498
+
499
+ @property
500
+ def metrics(self) -> Dict[str, Any]:
501
+ """Get performance metrics."""
502
+ stats = self.get_statistics()
503
+
504
+ return {
505
+ 'size': stats['size'],
506
+ 'capacity': stats['capacity'],
507
+ 'highest_bit': stats['highest_bit'],
508
+ 'utilization': f"{stats['utilization']:.1f}%",
509
+ 'density': f"{stats['density']:.1f}%",
510
+ 'total_operations': stats['total_operations'],
511
+ 'bit_flips': stats['bit_flips'],
512
+ 'memory_usage': f"{len(self._bits) * 8} bytes"
513
+ }