bool-hybrid-array 9.10.10__py3-none-any.whl → 9.11.1__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.
bool_hybrid_array/core.py CHANGED
@@ -1,857 +1,904 @@
1
- from __future__ import annotations
2
- import builtins
3
- import array,bisect,numpy as np
4
- from collections.abc import MutableSequence,Iterable,Generator,Iterator,Sequence
5
- import itertools,copy,sys,math,weakref,random,mmap,os
6
- from functools import reduce
7
- import operator,ctypes,gc,abc,types
8
- from functools import lru_cache
9
- from typing import Union,_GenericAlias
10
- hybrid_array_cache = []
11
- if 'UnionType' in types.__dict__:
12
- class Union:
13
- def __getitem__(self,*args):
14
- return reduce(operator.or_, args)
15
- Union = Union()
16
- if 'GenericAlias' in types.__dict__:
17
- _GenericAlias = types.GenericAlias
18
- class ResurrectMeta(abc.ABCMeta,metaclass=abc.ABCMeta):
19
- __module__ = 'bool_hybrid_array'
20
- name = 'ResurrectMeta'
21
- def __new__(cls, name, bases, namespace):
22
- meta_bases = tuple(type(base) for base in bases)
23
- if cls not in meta_bases:
24
- meta_bases = (cls,) + meta_bases
25
- obj = super().__new__(cls, name, bases, namespace)
26
- super_cls = super(ResurrectMeta, obj)
27
- super_cls.__setattr__('x',None)
28
- super_cls.__setattr__('name', name)
29
- super_cls.__setattr__('bases', bases)
30
- super_cls.__setattr__('namespace', namespace)
31
- super_cls.__setattr__('original_dict', dict(obj.__dict__))
32
- del obj.original_dict["__abstractmethods__"]
33
- del obj.original_dict["_abc_impl"]
34
- return obj
35
- @lru_cache
36
- def __str__(cls):
37
- return super().__repr__()[8:][:-2]
38
- @lru_cache
39
- def __repr__(cls,detailed = False):
40
- if detailed:
41
- name, bases, namespace = cls.name,cls.bases,cls.namespace
42
- return f'ResurrectMeta(cls = {cls},{name = },{bases = },{namespace = })'
43
- return str(cls)
44
- def __del__(cls):
45
- exec(f"builtins.{cls.__name__} = cls")
46
- if not sys.is_finalizing():
47
- print(f'警告:禁止删除常变量:{cls}!')
48
- raise TypeError(f'禁止删除常变量:{cls}')
49
- def __hash__(cls):
50
- return hash(cls.name+cls.__module__)
51
- def __setattr__(cls,name,value):
52
- if not hasattr(cls, 'x'):
53
- super().__setattr__(name,value)
54
- return
55
- if hasattr(cls, 'name') and cls.name == 'BHA_Bool' and repr(value) in {'T','F'} and name in {'T','F'}:
56
- super().__setattr__(name,value)
57
- return
58
- if hasattr(cls, 'original_dict') and name in cls.original_dict:
59
- raise AttributeError(f'禁止修改属性:{name}')
60
- else:
61
- super().__setattr__(name,value)
62
- def __delattr__(cls,name):
63
- if name in cls.original_dict:
64
- raise AttributeError(f'禁止删除属性:{name}')
65
- else:
66
- super().__delattr__(name)
67
- if 'UnionType' not in types.__dict__:
68
- def __or__(self,other):
69
- return Union[self,other]
70
- __ror__ = __or__
71
- def __getitem__(self,*args):
72
- return _GenericAlias(self,args)
73
- x = None
74
- original_dict = {"__delattr__":__delattr__,"__getitem__":__getitem__,"__setattr__":__setattr__,"__hash__":__hash__,
75
- "__new__":__new__,"__del__":__del__,"__str__":__str__,"__repr__":__repr__,"__class__":abc.ABCMeta,"original_dict":None}
76
- try:
77
- original_dict["original_dict"] = original_dict
78
- original_dict["__ror__"] = __ror__
79
- original_dict["__or__"] = __or__
80
- except:
81
- pass
82
- ResurrectMeta.__class__ = ResurrectMeta
83
- class BHA_Function(metaclass=ResurrectMeta):
84
- def __init__(self,v):
85
- self.data,self.module = v,__name__
86
- def __call__(self,*a,**b):
87
- return self.data(*a,**b)
88
- def __getattr__(self,name):
89
- return getattr(self.data,name)
90
- @classmethod
91
- def string_define(cls, name, text, positional, default):
92
- param_strs = list(positional)
93
- param_strs.extend([f"{k}={v!r}" for k, v in default.items()])
94
- params = ", ".join(param_strs)
95
- func_code = f"""
96
- def {name}({params}):
97
- {text}
98
- """
99
- local_namespace = {}
100
- exec(func_code, globals(), local_namespace)
101
- dynamic_func = local_namespace[name]
102
- return cls(dynamic_func)
103
- class BoolHybridArray(MutableSequence,Exception,metaclass=ResurrectMeta):
104
- __module__ = 'bool_hybrid_array'
105
- class _CompactBoolArray(Sequence,Exception):
106
- def __init__(self, size: int):
107
- self.size = size
108
- self.n_uint8 = (size + 7) >> 3
109
- self.data = np.zeros(self.n_uint8, dtype=np.uint8)
110
- def __setitem__(self, index: int | slice, value):
111
- ctypes_arr = self.data.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte))
112
- if isinstance(index, slice):
113
- start, stop, step = index.indices(self.size)
114
- indices = list(range(start, stop, step))
115
- if isinstance(value, (list, tuple)):
116
- if len(value)!= len(indices):
117
- raise ValueError("值的数量与切片长度不匹配")
118
- for i, val in zip(indices, value):
119
- self._set_single(i, bool(val), ctypes_arr)
120
- else:
121
- val_bool = bool(value)
122
- for i in indices:
123
- self._set_single(i, val_bool, ctypes_arr)
124
- self.data = np.ctypeslib.as_array(ctypes_arr, shape=(self.n_uint8,))
125
- return
126
- if not (0 <= index < self.size):
127
- raise IndexError(f"密集区索引 {index} 超出范围 [0, {self.size})")
128
- self._set_single(index, bool(value), ctypes_arr)
129
- self.data = np.ctypeslib.as_array(ctypes_arr, shape=(self.n_uint8,))
130
- self.data = self.data.view()
131
- def _set_single(self, index: int, value: bool, ctypes_arr):
132
- uint8_pos = index >> 3
133
- bit_offset = index & 7
134
- ctypes_arr[uint8_pos] &= ~(1 << bit_offset) & 0xFF
135
- if value:
136
- ctypes_arr[uint8_pos] |= (1 << bit_offset)
137
- def __getitem__(self, index: int | slice) -> bool | list[bool]:
138
- if isinstance(index, slice):
139
- start, stop, step = index.indices(self.size)
140
- result = []
141
- for i in range(start, stop, step):
142
- uint8_pos = i >> 3
143
- bit_offset = i & 7
144
- result.append(bool((self.data[uint8_pos] >> bit_offset) & 1))
145
- return result
146
- if not (0 <= index < self.size):
147
- raise IndexError(f"密集区索引 {index} 超出范围 [0, {self.size})")
148
- uint8_pos = index >> 3
149
- bit_offset = index & 7
150
- return bool((self.data[uint8_pos] >> bit_offset) & 1)
151
- def __len__(self):
152
- return self.size
153
- def set_all(self, value: bool):
154
- ctypes_arr = self.data.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte))
155
- length = len(self.data)
156
- if value:ctypes.memset(ctypes_arr, 0xff, length)
157
- else:ctypes.memset(ctypes_arr, 0, length)
158
- def copy(self):
159
- new_instance = self.__class__(size=self.size)
160
- new_instance.data = self.data.copy()
161
- return new_instance
162
- def __init__(self, split_index: int, size=None, is_sparse=False ,Type:Callable = None,hash_ = True) -> None:
163
- self.Type = Type if Type is not None else builtins.BHA_Bool
164
- self.split_index = int(split_index)
165
- self.size = size or 0
166
- self.is_sparse = is_sparse
167
- self.small = self._CompactBoolArray(self.split_index + 1)
168
- self.small.set_all(not is_sparse)
169
- self.large = array.array('I') if size < 1<<32 else array.array('Q')
170
- self.generator = iter(self)
171
- self.hash_ = hash_
172
- if hash_:
173
- global hybrid_array_cache
174
- hybrid_array_cache = [
175
- (ref, h) for ref, h in hybrid_array_cache
176
- if ref() is not None
177
- ]
178
- for ref, existing_hash in hybrid_array_cache:
179
- existing_array = ref()
180
- try:
181
- if self.size != existing_array.size:
182
- continue
183
- elif self == existing_array:
184
- self._cached_hash = existing_hash
185
- return
186
- except Exception:
187
- continue
188
- new_hash = id(self)
189
- self._cached_hash = new_hash
190
- hybrid_array_cache.append((weakref.ref(self), new_hash))
191
- def __call__(self, func):
192
- func.self = self
193
- def wrapper(*args, **kwargs):
194
- return func(self, *args, **kwargs)
195
- setattr(self, func.__name__, wrapper)
196
- return func
197
- def __hash__(self):
198
- return self._cached_hash
199
- def accessor(self, i: int, value: bool|None = None) -> bool|None:
200
- def _get_sparse_info(index: int) -> tuple[int, bool]:
201
- pos = bisect.bisect_left(self.large, index)
202
- exists = pos < len(self.large) and self.large[pos] == index
203
- return pos, exists
204
- if value is None:
205
- if i <= self.split_index:
206
- return self.small[i]
207
- else:
208
- _, exists = _get_sparse_info(i)
209
- return exists if self.is_sparse else not exists
210
- else:
211
- if i <= self.split_index:
212
- self.small[i] = value
213
- return None
214
- else:
215
- pos, exists = _get_sparse_info(i)
216
- condition = not value or exists
217
- if self.is_sparse != condition:
218
- self.large.insert(pos, i)
219
- else:
220
- if pos < len(self.large):
221
- del self.large[pos]
222
- return None
223
- def __getitem__(self, key:int|slice) -> BoolHybridArray:
224
- if isinstance(key, slice):
225
- start, stop, step = key.indices(self.size)
226
- return BoolHybridArr((self[i] for i in range(start, stop, step)),hash_ = self.hash_)
227
- key = key if key >=0 else key + self.size
228
- if 0 <= key < self.size:
229
- return self.Type(self.accessor(key))
230
- raise IndexError("索引超出范围")
231
- def __setitem__(self, key: int | slice, value) -> None:
232
- if isinstance(key, int):
233
- adjusted_key = key if key >= 0 else key + self.size
234
- if not (0 <= adjusted_key < self.size):
235
- raise IndexError("索引超出范围")
236
- self.accessor(adjusted_key, bool(value))
237
- return
238
- if isinstance(key, slice):
239
- original_size = self.size
240
- start, stop, step = key.indices(original_size)
241
- value_list = list(value)
242
- new_len = len(value_list)
243
- if step != 1:
244
- slice_indices = list(range(start, stop, step))
245
- if new_len != len(slice_indices):
246
- raise ValueError(f"值长度与切片长度不匹配:{new_len} vs {len(slice_indices)}")
247
- for i, val in zip(slice_indices, value_list):
248
- self[i] = val
249
- return
250
- for i in range(stop - 1, start - 1, -1):
251
- if i <= self.split_index:
252
- if i >= len(self.small):
253
- self.small = np.pad(
254
- self.small,
255
- (0, i - len(self.small) + 1),
256
- constant_values=not self.is_sparse
257
- )
258
- del self[i]
259
- for idx, val in enumerate(value_list):
260
- self.insert(start + idx, bool(val))
261
- return
262
- raise TypeError("索引必须是整数或切片")
263
- def __repr__(self) -> str:
264
- return(f"BoolHybridArray(split_index={self.split_index}, size={self.size}, "
265
- +f"is_sparse={self.is_sparse}, small_len={len(self.small)}, large_len={len(self.large)})")
266
- def __delitem__(self, key: int) -> None:
267
- key = key if key >= 0 else key + self.size
268
- if not (0 <= key < self.size):
269
- raise IndexError(f"索引 {key} 超出范围 [0, {self.size})")
270
- if key <= self.split_index:
271
- if key >= len(self.small):
272
- raise IndexError(f"小索引 {key} 超出small数组范围(长度{len(self.small)})")
273
- self.small = np.delete(self.small, key)
274
- self.small = np.append(self.small, not self.is_sparse)
275
- self.split_index -= min(self.split_index, len(self.small) - 1)
276
- else:
277
- pos = bisect.bisect_left(self.large, key)
278
- if pos < len(self.large) and self.large[pos] == key:
279
- del self.large[pos]
280
- adjust_pos = bisect.bisect_right(self.large, key)
281
- for i in range(adjust_pos, len(self.large)):
282
- self.large[i] -= 1
283
- self.size -= 1
284
- def __str__(self) -> str:
285
- return f"BoolHybridArr([{','.join(map(str,self))}])"
286
- def insert(self, key: int, value: bool) -> None:
287
- value = bool(value)
288
- key = key if key >= 0 else key + self.size
289
- key = max(0, min(key, self.size))
290
- if key <= self.split_index:
291
- if key > len(self.small):
292
- self.small = np.pad(
293
- self.small,
294
- (0, key - len(self.small) + 1),
295
- constant_values=not self.is_sparse
296
- )
297
- self.small = np.insert(self.small, key, value)
298
- self.split_index = min(self.split_index + 1, len(self.small) - 1)
299
- else:
300
- pos = bisect.bisect_left(self.large, key)
301
- for i in range(pos, len(self.large)):
302
- self.large[i] += 1
303
- if (self.is_sparse and value) or (not self.is_sparse and not value):
304
- self.large.insert(pos, key)
305
- self.size += 1
306
- def __len__(self) -> int:
307
- return self.size
308
- def __iter__(self):
309
- return BHA_Iterator(map(self.__getitem__,range(self.size)))
310
- def __next__(self):
311
- return next(self.generator)
312
- def __contains__(self, value) -> bool:
313
- if not isinstance(value, (bool,np.bool_,self.Type,BHA_bool)):return False
314
- if not self.size:return False
315
- for i in range(10):
316
- if self[random.randint(0,self.size-1)] == value:
317
- return True
318
- b = any(1 for i in range(self.small.size+1>>1) if value==self.small[i] or value==self.small[self.small.size-i-1])
319
- if value == self.is_sparse:
320
- return self.large or b
321
- else:
322
- return len(self.large) == self.size-self.split_index-1 or b
323
- def __bool__(self) -> bool:
324
- return self.size
325
- def __any__(self):
326
- return T in self
327
- def __all__(self):
328
- return F not in self
329
- def __eq__(self, other) -> bool:
330
- if not isinstance(other, (BoolHybridArray, list, tuple, np.ndarray, array.array)):
331
- return False
332
- if len(self) != len(other):
333
- return False
334
- return all(a == b for a, b in zip(self, other))
335
- def __ne__(self, other) -> bool:
336
- return not self.__eq__(other)
337
- def __and__(self, other) -> BoolHybridArray:
338
- if type(other) == int:
339
- other = abs(other)
340
- other = bin(other)[2:]
341
- if len(self) != len(other):
342
- raise ValueError(f"与运算要求数组长度相同({len(self)} vs {len(other)})")
343
- return BoolHybridArr(map(operator.and_, self, other),hash_ = self.hash_)
344
- def __int__(self):
345
- if not self.size:
346
- return 0
347
- return reduce(lambda acc, val: operator.or_(operator.lshift(acc, 1), int(val)),self,0)
348
- def __or__(self, other) -> BoolHybridArray:
349
- if type(other) == int:
350
- other = bin(other)[2:]
351
- if self.size != len(other):
352
- raise ValueError(f"或运算要求数组长度相同({len(self)} vs {len(other)})")
353
- return BoolHybridArr(map(operator.or_, self, other),hash_ = self.hash_)
354
- def __ror__(self, other) -> BoolHybridArray:
355
- if type(other) == int:
356
- other = abs(other)
357
- other = bin(other)[2:]
358
- return self | other
359
- def __rshift__(self, other) -> BoolHybridArray:
360
- arr = BoolHybridArr(self)
361
- arr >>= other
362
- return arr
363
- def __irshift__(self, other) -> BoolHybridArray:
364
- if int(other) < 0:
365
- self <<= -other
366
- return self
367
- for i in range(int(other)):
368
- if self.size < 1:
369
- return self
370
- self.pop(-1)
371
- return self
372
- def __ilshift__(self ,other) -> BoolHybridArray:
373
- if int(other) < 0:
374
- self >>= -other
375
- return self
376
- if not self.is_sparse:
377
- self += FalsesArray(int(other))
378
- self.optimize()
379
- else:
380
- self.size += int(other)
381
- return self
382
- def __lshift__(self ,other) -> BoolHybridArray:
383
- if int(other) < 0:
384
- return self >> -other
385
- return self+FalsesArray(int(other))
386
- def __add__(self, other) -> BoolHybridArray:
387
- arr = self.copy()
388
- arr += other
389
- arr.optimize()
390
- return arr
391
- def __invert__(self) -> BoolHybridArray:
392
- return BoolHybridArr(not val for val in self)
393
- def __rand__(self, other) -> BoolHybridArray:
394
- if type(other) == int:
395
- other = bin(other)[2:]
396
- return self & other
397
- def __xor__(self, other) -> BoolHybridArray:
398
- if len(self) != len(other):
399
- raise ValueError(f"异或运算要求数组长度相同({len(self)} vs {len(other)})")
400
- return BoolHybridArr(map(operator.xor, self, other),hash_ = self.hash_)
401
- def __rxor__(self, other) -> BoolHybridArray:
402
- return self^other
403
- def __invert__(self) -> BoolHybridArray:
404
- return BoolHybridArr(not a for a in self)
405
- def copy(self) -> BoolHybridArray:
406
- arr = BoolHybridArray(split_index = self.split_index,size = self.size)
407
- arr.large,arr.small,arr.split_index,arr.is_sparse,arr.Type,arr.size = (array.array(self.large.typecode, self.large),self.small.copy(),
408
- self.split_index,BHA_Bool(self.is_sparse),self.Type,self.size)
409
- return arr
410
- def __copy__(self) -> BoolHybridArray:
411
- return self.copy()
412
- def find(self,value):
413
- return BHA_List([i for i in range(len(self)) if self[i]==value])
414
- def extend(self, iterable:Iterable) -> None:
415
- if isinstance(iterable, (Iterator, Generator, map)):
416
- iterable,copy = itertools.tee(iterable, 2)
417
- len_ = sum(1 for _ in copy)
418
- else:
419
- len_ = len(iterable)
420
- self.size += len_
421
- for i,j in zip(range(len_),iterable):
422
- self[-i-1] = j
423
- def append(self,v):
424
- self.size += 1
425
- self[-1] = v
426
- def index(self, value) -> int:
427
- if self.size == 0:
428
- raise ValueError('无法在空的 BoolHybridArray 中查找元素!')
429
- value = bool(value)
430
- x = 'not find'
431
- for i in range(self.size):
432
- if self[i] == value:
433
- return i
434
- if self[-i] == value:
435
- x = self.size-i
436
- if len(self)-i == i:
437
- break
438
- if x != 'not find':
439
- return x
440
- raise ValueError(f"{value} not in BoolHybridArray")
441
- def rindex(self, value) -> int:
442
- if self.size == 0:
443
- raise ValueError('无法在空的 BoolHybridArray 中查找元素!')
444
- value = bool(value)
445
- x = 'not find'
446
- for i in range(self.size):
447
- if self[-i] == value:
448
- return -i
449
- if self[i] == value:
450
- x = -(self.size-i)
451
- if len(self)-i == i:
452
- break
453
- if x != 'not find':
454
- return x
455
- raise ValueError(f"{value} not in BoolHybridArray")
456
- def count(self, value) -> int:
457
- value = bool(value)
458
- return sum(v == value for v in self)
459
- def optimize(self) -> None:
460
- arr = BoolHybridArr(self)
461
- self.large,self.small,self.split_index,self.is_sparse = (arr.large,arr.small,
462
- arr.split_index,arr.is_sparse)
463
- gc.collect()
464
- return self
465
- def memory_usage(self, detail=False) -> dict | int:
466
- small_mem = self.small.size // 8 + 32
467
- large_mem = len(self.large) * 4 + 32
468
- equivalent_list_mem = 40 + 8 * self.size
469
- equivalent_numpy_mem = 96 + self.size
470
- total = small_mem+large_mem
471
- if not detail:
472
- return total
473
- need_optimize = False
474
- optimize_reason = ""
475
- sparse_ratio = len(self.large) / max(len(self), 1)
476
- if sparse_ratio > 0.4 and len(self) > 500: # 阈值可根据测试调整
477
- need_optimize = True
478
- optimize_reason = "稀疏区索引密度过高,优化后可转为密集存储提升速度"
479
- elif len(self) < 32 and total > len(self):
480
- need_optimize = True
481
- optimize_reason = "小尺寸数组存储冗余,优化后将用int位存储进一步省内存"
482
- elif np.count_nonzero(np.array(self.small)) / max(len(self.small), 1) < 0.05 and len(self) > 1000:
483
- need_optimize = True
484
- optimize_reason = "密集区有效值占比过低,优化后可转为稀疏存储节省内存"
485
- return {
486
- "总占用(字节)": total,
487
- "密集区占用": small_mem,
488
- "稀疏区占用": large_mem,
489
- "对比原生list节省": f"{(1 - total/equivalent_list_mem)*100:.6f}%",
490
- "对比numpy节省": f"{(1 - total/equivalent_numpy_mem)*100:.6f}%" if equivalent_numpy_mem > 0 else "N/A",
491
- "是否需要优化": "是" if need_optimize else "否",
492
- "优化理由/说明": optimize_reason if need_optimize else "当前存储模式已适配数据特征,无需优化"
493
- }
494
- def get_shape(self):
495
- return (self.size,)
496
- def __array__(self,dtype = np.bool_,copy = None):
497
- arr = np.fromiter(map(np.bool_,self), dtype=np.bool_)
498
- return arr.copy() if copy else arr.view()
499
- def view(self):
500
- arr = TruesArray(0)
501
- arr.__dict__ = self.__dict__
502
- return arr
503
- class BoolHybridArr(BoolHybridArray,metaclass=ResurrectMeta):
504
- __module__ = 'bool_hybrid_array'
505
- def __new__(cls, lst: Iterable, is_sparse=None, Type = None, hash_ = True) -> BoolHybridArray:
506
- a = isinstance(lst, (Iterator, Generator, map))
507
- if a:
508
- lst, copy1, copy2 = itertools.tee(lst, 3)
509
- size = sum(1 for _ in copy1)
510
- true_count = sum(bool(val) for val in copy2)
511
- else:
512
- size = len(lst)
513
- true_count = sum(bool(val) for val in lst)
514
- if size == 0:
515
- return BoolHybridArray(0, 0, is_sparse=False if is_sparse is None else is_sparse)
516
- if is_sparse is None:
517
- is_sparse = true_count <= (size - true_count)
518
- split_index = int(min(size * 0.8, math.sqrt(size) * 100))
519
- split_index = math.isqrt(size) if true_count>size/3*2 or true_count<size/3 else max(split_index, 1)
520
- split_index = int(split_index) if split_index < 150e+7*2 else int(145e+7*2)
521
- arr = BoolHybridArray(split_index = split_index, size = size, is_sparse = is_sparse, Type = Type, hash_ = F)
522
- small_max_idx = min(split_index, size - 1)
523
- if a:
524
- small_data = []
525
- large_indices = []
526
- for i, val in enumerate(lst):
527
- val_bool = bool(val)
528
- if i <= small_max_idx:
529
- small_data.append(val_bool)
530
- else:
531
- if (is_sparse and val_bool) or (not is_sparse and not val_bool):
532
- large_indices.append(i)
533
- if small_data:
534
- arr.small[:len(small_data)] = small_data
535
- if large_indices:
536
- arr.large.extend(large_indices)
537
- else:
538
- if small_max_idx >= 0:
539
- arr.small[:small_max_idx + 1] = [bool(val) for val in lst[:small_max_idx + 1]]
540
- large_indices = [
541
- i for i in range(split_index + 1, size)
542
- if (is_sparse and bool(lst[i])) or (not is_sparse and not bool(lst[i]))
543
- ]
544
- arr.large.extend(large_indices)
545
- arr.large = sorted(arr.large)
546
- type_ = 'I' if size < 1 << 32 else 'Q'
547
- arr.large = array.array(type_, arr.large)
548
- if hash_:
549
- global hybrid_array_cache
550
- del hybrid_array_cache[-1]
551
- hybrid_array_cache = [
552
- (ref, h) for ref, h in hybrid_array_cache
553
- if ref() is not None
554
- ]
555
- for ref, existing_hash in hybrid_array_cache:
556
- existing_array = ref()
557
- try:
558
- if arr.size != existing_array.size:
559
- continue
560
- elif arr == existing_array:
561
- arr._cached_hash = existing_hash
562
- return arr
563
- except:
564
- continue
565
- return arr
566
- def TruesArray(size, Type = None, hash_ = True):
567
- split_index = min(size//10, math.isqrt(size))
568
- split_index = max(split_index, 1)
569
- split_index = int(split_index) if split_index < 150e+7*2 else int(145e+7*2)
570
- return BoolHybridArray(split_index,size,Type = Type,hash_ = hash_)
571
- def FalsesArray(size, Type = None,hash_ = True):
572
- split_index = min(size//10, math.isqrt(size))
573
- split_index = max(split_index, 1)
574
- split_index = int(split_index) if split_index < 150e+7*2 else int(145e+7*2)
575
- return BoolHybridArray(split_index,size,True,Type = Type,hash_ = hash_)
576
- Bool_Array = np.arange(2,dtype = np.uint8)
577
- class BHA_bool(int,metaclass=ResurrectMeta):
578
- __module__ = 'bool_hybrid_array'
579
- def __new__(cls, value):
580
- core_value = bool(value)
581
- instance = super().__new__(cls, core_value)
582
- instance.data = Bool_Array[1] if core_value else Bool_Array[0]
583
- instance.value = core_value
584
- return instance
585
- @lru_cache
586
- def __str__(self):
587
- return 'True' if self else 'False'
588
- @lru_cache
589
- def __repr__(self):
590
- return 'T' if self else 'F'
591
- @lru_cache
592
- def __bool__(self):
593
- return self.value
594
- @lru_cache
595
- def __int__(self):
596
- return int(self.data)
597
- @lru_cache
598
- def __or__(self,other):
599
- return BHA_Bool(self.value|other)
600
- @lru_cache
601
- def __and__(self,other):
602
- return BHA_Bool(self.value&other)
603
- @lru_cache
604
- def __xor__(self,other):
605
- return BHA_Bool(self.value^other)
606
- def __hash__(self):
607
- return hash(self.data)
608
- def __len__(self):
609
- raise TypeError("'BHA_bool' object has no attribute '__len__'")
610
- def __del__(self):
611
- if not sys.is_finalizing():
612
- print(f'你删除或修改了1个常变量:{repr(self)}!')
613
- if self:builtins.T = BHA_bool(1)
614
- else:builtins.F = BHA_bool(0)
615
- raise TypeError(f'禁止删除或修改常变量{repr(self)}!')
616
- __rand__,__ror__,__rxor__ = __and__,__or__,__xor__
617
- class BHA_Bool(BHA_bool,metaclass=ResurrectMeta):
618
- __module__ = 'bool_hybrid_array'
619
- @lru_cache
620
- def __new__(cls,v):
621
- if(builtins.T == True)and(builtins.F == False):
622
- return builtins.T if v else builtins.F
623
- else:
624
- builtins.T,builtins.F = BHA_Bool.T,BHA_Bool.F
625
- return BHA_Bool.T if v else BHA_Bool.F
626
- class BHA_List(list,metaclass=ResurrectMeta):
627
- __module__ = 'bool_hybrid_array'
628
- def __init__(self,arr):
629
- def Temp(v):
630
- if isinstance(v,(list,tuple)):
631
- v = (BoolHybridArr(v) if all(isinstance(i,
632
- (bool,BHA_bool,np.bool_)) for i in v)
633
- else BHA_List(v))
634
- if isinstance(v,BoolHybridArray):
635
- return v
636
- elif isinstance(v,(bool,np.bool_)):
637
- return BHA_Bool(v)
638
- else:
639
- return v
640
- super().__init__(map(Temp,arr))
641
- try:self.hash_value = sum(map(hash,self))
642
- except Exception as e:return hash(e)
643
- def __hash__(self):
644
- return self.hash_value
645
- def __call__(self, func):
646
- func.self = self
647
- def wrapper(self, *args, **kwargs):
648
- return func(self, *args, **kwargs)
649
- setattr(self, func.__name__, wrapper)
650
- return wrapper
651
- def __str__(self):
652
- def Temp(v):
653
- if isinstance(v,(BoolHybridArray,np.ndarray,BHA_List,array.array)):
654
- return str(v)+',\n'
655
- else:
656
- return repr(v)+','
657
- return f"BHA_List([\n{''.join(map(Temp,self))}])"
658
- def __repr__(self):
659
- return str(self)
660
- def __or__(self,other):
661
- return BHA_List(map(operator.or_, self, other))
662
- def __and__(self,other):
663
- return BHA_List(map(operator.and_, self, other))
664
- def __xor__(self,other):
665
- return BHA_List(map(operator.xor, self, other))
666
- def __rxor__(self,other):
667
- return self^other
668
- def __ror__(self,other):
669
- return self|other
670
- def __rand__(self,other):
671
- return self&other
672
- def optimize(self):
673
- for val in self:
674
- val.optimize()
675
- def memory_usage(self,detail=False):
676
- total = sum(val.memory_usage() for val in self) + 32
677
- if not detail:
678
- return total
679
- else:
680
- temp = sum(val.size for val in self)
681
- return {
682
- "占用(字节)": total,
683
- "对比原生list节省": f"{(1 - total / (temp * 8 + 40))*100:.6f}%",
684
- "对比numpy节省": f"{(1 - total / (temp + 96)) * 100:.6f}%"}
685
- def __iter__(self):
686
- return BHA_Iterator(super().__iter__())
687
- class BHA_Iterator(Iterator,metaclass=ResurrectMeta):
688
- __module__ = 'bool_hybrid_array'
689
- def __init__(self,data):
690
- self.data,self.copy_data = itertools.tee(iter(data),2)
691
- def __next__(self):
692
- try:return next(self.data)
693
- except Exception as e:
694
- self.__init__(self.copy_data)
695
- raise e
696
- def __iter__(self):
697
- return self
698
- def __or__(self,other):
699
- return BHA_Iterator(map(operator.or_, self, other))
700
- def __and__(self,other):
701
- return BHA_Iterator(map(operator.and_, self, other))
702
- def __xor__(self,other):
703
- return BHA_Iterator(map(operator.xor, self, other))
704
- def __array__(self,dtype = None,copy = None):
705
- arr = np.fromiter(self, dtype=dtype)
706
- return arr.copy() if copy else arr.view()
707
- __rand__,__ror__,__rxor__ = __and__,__or__,__xor__
708
- class ProtectedBuiltinsDict(dict,metaclass=ResurrectMeta):
709
- def __init__(self, *args, protected_names = ["T", "F", "BHA_Bool", "BHA_List", "BoolHybridArray", "BoolHybridArr",
710
- "TruesArray", "FalsesArray", "ProtectedBuiltinsDict", "builtins",
711
- "__builtins__", "__dict__","ResurrectMeta","math",
712
- "np","protected_names","BHA_Function",
713
- "__class__","Ask_BHA","Create_BHA","Ask_arr","numba_opt"],
714
- name = 'builtins', **kwargs):
715
- super().__init__(*args, **kwargs)
716
- if name == 'builtins':
717
- super().__setattr__('__dict__',self)
718
- super().__setattr__('builtins',self)
719
- super().__setattr__('__builtins__',self)
720
- self.name = name
721
- self.protected_names = protected_names
722
- def __setitem__(self, name, value):
723
- if name in ["T", "F"]:
724
- current_T = self.get("T")
725
- current_F = self.get("F")
726
- if isinstance(current_T, BHA_bool) and isinstance(current_F, BHA_bool):
727
- is_swap = (name == "T" and isinstance(value, BHA_bool) and value.value == current_F.value)or(name == "F" and isinstance(value, BHA_bool) and value.value == current_T.value)
728
- if is_swap:
729
- print(f"""警告:禁止交换内置常量 __{self.name}__["{name}"] 和 __builtins__["{'F' if name == 'T' else 'T'}"]!""")
730
- raise AttributeError(f"""禁止交换内置常量 __{self.name}__["{name}"] 和 __{self.name}__["{'F' if name == 'T' else 'T'}"]""")
731
- if name in self.protected_names and name not in ["T", "F"]:
732
- print(f"警告:禁止修改内置常量 __{self.name}__['{name}']!")
733
- raise AttributeError(f"禁止修改内置常量 __{self.name}__['{name}']")
734
- super().__setitem__(name, value)
735
- def __delitem__(self, name):
736
- if name in self.protected_names:
737
- print(f"警告:禁止删除内置常量 __builtins__['{name}']!")
738
- raise AttributeError(f"禁止删除内置常量 __builtins__['{name}']")
739
- if name in self:
740
- super().__delitem__(name)
741
- def __delattr__(self, name):
742
- if name in self.protected_names:
743
- raise AttributeError(f'禁止删除内置常量:{self.name}.{name}')
744
- else:
745
- del self[name]
746
- def __getattr__(self, name):
747
- if name in self:
748
- return self[name]
749
- else:
750
- raise AttributeError(f"module 'builtins' has no attribute '{name}'")
751
- def __setattr__(self,name,value):
752
- try:protected = self.protected_names
753
- except Exception:protected = self
754
- if(name in protected)and(not sys.is_finalizing())and(name != '_'):
755
- raise AttributeError(f'禁止修改内置常量:{self.name}.{name}')
756
- else:
757
- super().__setattr__(name,value)
758
- def Ask_arr(arr):
759
- if isinstance(arr,BHA_List):
760
- return '\n'.join(map(Ask_arr,arr))
761
- elif isinstance(arr,BoolHybridArray):
762
- h = hex(int(arr))[2:]
763
- h = '0'*(arr.size - len(bin(int(arr)))+2)+h
764
- return h
765
- else:
766
- return str(arr)
767
- def Ask_BHA(path):
768
- if '.bha' not in path.lower():
769
- path += '.bha'
770
- with open(path, 'a+b') as f:
771
- f.seek(0)
772
- file_size = os.fstat(f.fileno()).st_size
773
- if not file_size:
774
- return TruesArray(0)
775
- if os.name == 'nt':
776
- mm = mmap.mmap(f.fileno(), file_size, access=mmap.ACCESS_READ)
777
- else:
778
- mm = mmap.mmap(f.fileno(), file_size, flags=mmap.MAP_PRIVATE, prot=mmap.PROT_READ)
779
- with mm:
780
- temp = mm.read().decode('utf-8').strip()
781
- temp = temp.split()
782
- temp2 = lambda x:BoolHybridArr(map(int,'0'*(len(x) - len(x.lstrip('0')))+bin(int(x,base = 16))[2:]),hash_ = F)
783
- temp = BHA_List(map(temp2,temp))
784
- if len(temp) == 1:
785
- return temp[0]
786
- return temp
787
- def Create_BHA(path,arr):
788
- if '.bha' not in path.lower():
789
- path += '.bha'
790
- temp = Ask_arr(arr).strip().encode('utf-8')
791
- with open(path, "w+b") as f:
792
- f.truncate(len(temp))
793
- if not len(temp):
794
- return
795
- with mmap.mmap(
796
- f.fileno(),
797
- length=len(temp),
798
- access=mmap.ACCESS_WRITE
799
- ) as mm:
800
- mm[:] = temp
801
- mm.flush()
802
- def numba_opt():
803
- import numba
804
- sig = numba.types.Union([
805
- numba.types.intp(
806
- numba.types.Array(numba.types.uint32, 1, 'C'),
807
- numba.types.uint32,
808
- numba.types.uint32,
809
- numba.types.Optional(numba.types.uint32)
810
- ),
811
- numba.types.intp(
812
- numba.types.Array(numba.types.uint64, 1, 'C'),
813
- numba.types.uint64,
814
- numba.types.uint64,
815
- numba.types.Optional(numba.types.uint64)
816
- ),
817
- numba.types.intp(
818
- numba.types.Any,
819
- numba.types.Any,
820
- numba.types.Any,
821
- numba.types.Optional(numba.types.Any)
822
- )
823
- ])
824
- bisect.bisect_left = numba.njit(sig, cache=True)(bisect.bisect_left)
825
- bisect.bisect_right = numba.njit(sig, cache=True)(bisect.bisect_right)
826
- builtins.np = np
827
- builtins.T = BHA_bool(1)
828
- builtins.F = BHA_bool(0)
829
- builtins.BHA_Bool = BHA_Bool
830
- builtins.BHA_List = BHA_List
831
- builtins.FalsesArray = FalsesArray
832
- builtins.TruesArray = TruesArray
833
- builtins.BoolHybridArr = BoolHybridArr
834
- builtins.BHA_Iterator = BHA_Iterator
835
- builtins.BoolHybridArray = BoolHybridArray
836
- builtins.BHA_Bool.T,builtins.BHA_Bool.F = BHA_bool(1),BHA_bool(0)
837
- builtins.ResurrectMeta = ResurrectMeta
838
- builtins.ProtectedBuiltinsDict = ProtectedBuiltinsDict
839
- builtins.BHA_Function = BHA_Function
840
- builtins.Ask_BHA = Ask_BHA
841
- builtins.Create_BHA = Create_BHA
842
- builtins.numba_opt = numba_opt
843
- Tid,Fid = id(T),id(F)
844
- original_id = builtins.id
845
- def fake_id(obj):
846
- if isinstance(obj, BHA_bool):return Tid if obj else Fid
847
- else:return original_id(obj)
848
- builtins.id = fake_id
849
- original_builtins_dict = builtins.__dict__.copy()
850
- __builtins__ = ProtectedBuiltinsDict(original_builtins_dict)
851
- builtins = __builtins__
852
- sys.modules['builtins'] = builtins
853
- builtins.name = 'builtins'
854
- try:
855
- sys.flags.optimize = 2
856
- except:
1
+ from __future__ import annotations
2
+ import builtins
3
+ from types import MappingProxyType
4
+ import array,bisect,numpy as np
5
+ from collections.abc import MutableSequence,Iterable,Generator,Iterator,Sequence
6
+ import itertools,copy,sys,math,weakref,random,mmap,os
7
+ from functools import reduce
8
+ import operator,ctypes,gc,abc,types
9
+ from functools import lru_cache
10
+ from typing import Union,_GenericAlias
11
+ hybrid_array_cache = []
12
+ try:
13
+ msvcrt = ctypes.CDLL('msvcrt.dll')
14
+ memcpy = msvcrt.memcpy
15
+ except:
16
+ libc = ctypes.CDLL('libc.so.6')
17
+ memcpy = libc.memcpy
18
+ memcpy.argtypes = (ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t)
19
+ memcpy.restype = ctypes.c_void_p
20
+ if 'UnionType' in types.__dict__:
21
+ class Union:
22
+ def __getitem__(self,*args):
23
+ return reduce(operator.or_, args)
24
+ Union = Union()
25
+ if 'GenericAlias' in types.__dict__:
26
+ _GenericAlias = types.GenericAlias
27
+ class ResurrectMeta(abc.ABCMeta,metaclass=abc.ABCMeta):
28
+ __module__ = 'bool_hybrid_array'
29
+ name = 'ResurrectMeta'
30
+ def __new__(cls, name, bases, namespace):
31
+ meta_bases = tuple(type(base) for base in bases)
32
+ if cls not in meta_bases:
33
+ meta_bases = (cls,) + meta_bases
34
+ obj = super().__new__(cls, name, bases, namespace)
35
+ super_cls = super(ResurrectMeta, obj)
36
+ super_cls.__setattr__('x',None)
37
+ super_cls.__setattr__('name', name)
38
+ super_cls.__setattr__('bases', bases)
39
+ super_cls.__setattr__('namespace', namespace)
40
+ super_cls.__setattr__('original_dict', dict(obj.__dict__))
41
+ try:del obj.original_dict["__abstractmethods__"]
42
+ except:pass
43
+ try:del obj.original_dict["_abc_impl"]
44
+ except:pass
45
+ try:del obj.original_dict['_abc_registry']
46
+ except:pass
47
+ try:del obj.original_dict['_abc_cache']
48
+ except:pass
49
+ try:del obj.original_dict['_abc_negative_cache']
50
+ except:pass
51
+ try:del obj.original_dict['_abc_negative_cache_version']
52
+ except:pass
53
+ super_cls.__setattr__('original_dict', MappingProxyType(obj.original_dict))
54
+ return obj
55
+ @lru_cache
56
+ def __str__(cls):
57
+ return f'{cls.__module__}.{cls.name}'
58
+ @lru_cache
59
+ def __repr__(cls,detailed = False):
60
+ if detailed:
61
+ name, bases, namespace = cls.name,cls.bases,cls.namespace
62
+ return f'ResurrectMeta(cls = {cls},{name = },{bases = },{namespace = })'
63
+ return str(cls)
64
+ def __del__(cls):
65
+ exec(f"builtins.{cls.__name__} = cls")
66
+ if not sys.is_finalizing():
67
+ print(f'警告:禁止删除常变量:{cls}!')
68
+ raise TypeError(f'禁止删除常变量:{cls}')
69
+ def __hash__(cls):
70
+ return hash(cls.name+cls.__module__)
71
+ def __setattr__(cls,name,value):
72
+ if not hasattr(cls, 'x'):
73
+ super().__setattr__(name,value)
74
+ return
75
+ if hasattr(cls, 'name') and cls.name == 'BHA_Bool' and repr(value) in {'T','F'} and name in {'T','F'}:
76
+ super().__setattr__(name,value)
77
+ return
78
+ if hasattr(cls, 'original_dict') and name in cls.original_dict:
79
+ raise AttributeError(f'禁止修改属性:{name}')
80
+ else:
81
+ super().__setattr__(name,value)
82
+ def __delattr__(cls,name):
83
+ if name in cls.original_dict:
84
+ raise AttributeError(f'禁止删除属性:{name}')
85
+ else:
86
+ super().__delattr__(name)
87
+ if 'UnionType' not in types.__dict__:
88
+ def __or__(self,other):
89
+ return Union[self,other]
90
+ __ror__ = __or__
91
+ def __getitem__(self,*args):
92
+ return _GenericAlias(self,args)
93
+ x = None
94
+ original_dict = {"__delattr__":__delattr__,"__getitem__":__getitem__,"__setattr__":__setattr__,"__hash__":__hash__,
95
+ "__new__":__new__,"__del__":__del__,"__str__":__str__,"__repr__":__repr__,"__class__":abc.ABCMeta,"original_dict":None}
96
+ try:
97
+ original_dict["original_dict"] = original_dict
98
+ original_dict["__ror__"] = __ror__
99
+ original_dict["__or__"] = __or__
100
+ except:
101
+ pass
102
+ original_dict = MappingProxyType(original_dict)
103
+ ResurrectMeta.__class__ = ResurrectMeta
104
+ class BHA_Function(metaclass=ResurrectMeta):
105
+ def __init__(self,v):
106
+ self.data,self.module = v,__name__
107
+ def __call__(self,*a,**b):
108
+ return self.data(*a,**b)
109
+ def __getattr__(self,name):
110
+ return getattr(self.data,name)
111
+ @classmethod
112
+ def string_define(cls, name, text, positional, default):
113
+ param_strs = list(positional)
114
+ param_strs.extend([f"{k}={v!r}" for k, v in default.items()])
115
+ params = ", ".join(param_strs)
116
+ func_code = f"""
117
+ def {name}({params}):
118
+ {text}
119
+ """
120
+ local_namespace = {}
121
+ exec(func_code, globals(), local_namespace)
122
+ dynamic_func = local_namespace[name]
123
+ return cls(dynamic_func)
124
+ class BoolHybridArray(MutableSequence,Exception,metaclass=ResurrectMeta):
125
+ __module__ = 'bool_hybrid_array'
126
+ class _CompactBoolArray(Sequence,Exception):
127
+ def __init__(self, size: int):
128
+ self.size = size
129
+ self.n_uint8 = (size + 7) >> 3
130
+ self.data = np.zeros(self.n_uint8, dtype=np.uint8)
131
+ def __setitem__(self, index: int | slice, value):
132
+ ctypes_arr = self.data.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte))
133
+ if isinstance(index, slice):
134
+ start, stop, step = index.indices(self.size)
135
+ indices = list(range(start, stop, step))
136
+ if isinstance(value, (list, tuple)):
137
+ if len(value)!= len(indices):
138
+ raise ValueError("值的数量与切片长度不匹配")
139
+ for i, val in zip(indices, value):
140
+ self._set_single(i, bool(val), ctypes_arr)
141
+ else:
142
+ val_bool = bool(value)
143
+ for i in indices:
144
+ self._set_single(i, val_bool, ctypes_arr)
145
+ self.data = np.ctypeslib.as_array(ctypes_arr, shape=(self.n_uint8,))
146
+ return
147
+ if not (0 <= index < self.size):
148
+ raise IndexError(f"密集区索引 {index} 超出范围 [0, {self.size})")
149
+ self._set_single(index, bool(value), ctypes_arr)
150
+ self.data = np.ctypeslib.as_array(ctypes_arr, shape=(self.n_uint8,))
151
+ self.data = self.data.view()
152
+ def _set_single(self, index: int, value: bool, ctypes_arr):
153
+ uint8_pos = index >> 3
154
+ bit_offset = index & 7
155
+ ctypes_arr[uint8_pos] &= ~(1 << bit_offset) & 0xFF
156
+ if value:
157
+ ctypes_arr[uint8_pos] |= (1 << bit_offset)
158
+ def __getitem__(self, index: int | slice) -> bool | list[bool]:
159
+ if isinstance(index, slice):
160
+ start, stop, step = index.indices(self.size)
161
+ result = []
162
+ for i in range(start, stop, step):
163
+ uint8_pos = i >> 3
164
+ bit_offset = i & 7
165
+ result.append(bool((self.data[uint8_pos] >> bit_offset) & 1))
166
+ return result
167
+ if not (0 <= index < self.size):
168
+ raise IndexError(f"密集区索引 {index} 超出范围 [0, {self.size})")
169
+ uint8_pos = index >> 3
170
+ bit_offset = index & 7
171
+ return bool((self.data[uint8_pos] >> bit_offset) & 1)
172
+ def __len__(self):
173
+ return self.size
174
+ def set_all(self, value: bool):
175
+ ctypes_arr = self.data.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte))
176
+ length = len(self.data)
177
+ if value:ctypes.memset(ctypes_arr, 0xff, length)
178
+ else:ctypes.memset(ctypes_arr, 0, length)
179
+ def copy(self):
180
+ new_instance = self.__class__(size=self.size)
181
+ new_instance.data = self.data.copy()
182
+ return new_instance
183
+ def __init__(self, split_index: int, size=None, is_sparse=False ,Type:Callable = None,hash_ = True) -> None:
184
+ self.Type = Type if Type is not None else builtins.BHA_Bool
185
+ self.split_index = int(split_index)
186
+ self.size = size or 0
187
+ self.is_sparse = is_sparse
188
+ self.small = self._CompactBoolArray(self.split_index + 1)
189
+ self.small.set_all(not is_sparse)
190
+ self.large = array.array('I') if size < 1<<32 else array.array('Q')
191
+ self.generator = iter(self)
192
+ self.hash_ = hash_
193
+ if hash_:
194
+ global hybrid_array_cache
195
+ hybrid_array_cache = [
196
+ (ref, h) for ref, h in hybrid_array_cache
197
+ if ref() is not None
198
+ ]
199
+ for ref, existing_hash in hybrid_array_cache:
200
+ existing_array = ref()
201
+ try:
202
+ if self.size != existing_array.size:
203
+ continue
204
+ elif self == existing_array:
205
+ self._cached_hash = existing_hash
206
+ return
207
+ except Exception:
208
+ continue
209
+ new_hash = id(self)
210
+ self._cached_hash = new_hash
211
+ hybrid_array_cache.append((weakref.ref(self), new_hash))
212
+ def __call__(self, func):
213
+ func.self = self
214
+ def wrapper(*args, **kwargs):
215
+ return func(self, *args, **kwargs)
216
+ setattr(self, func.__name__, wrapper)
217
+ return func
218
+ def __hash__(self):
219
+ return self._cached_hash
220
+ def accessor(self, i: int, value: bool|None = None) -> bool|None:
221
+ def _get_sparse_info(index: int) -> tuple[int, bool]:
222
+ pos = bisect.bisect_left(self.large, index)
223
+ exists = pos < len(self.large) and self.large[pos] == index
224
+ return pos, exists
225
+ if value is None:
226
+ if i <= self.split_index:
227
+ return self.small[i]
228
+ else:
229
+ _, exists = _get_sparse_info(i)
230
+ return exists if self.is_sparse else not exists
231
+ else:
232
+ if i <= self.split_index:
233
+ self.small[i] = value
234
+ return None
235
+ else:
236
+ pos, exists = _get_sparse_info(i)
237
+ condition = not value or exists
238
+ if self.is_sparse != condition:
239
+ self.large.insert(pos, i)
240
+ else:
241
+ if pos < len(self.large):
242
+ del self.large[pos]
243
+ return None
244
+ def __getitem__(self, key:int|slice) -> BoolHybridArray:
245
+ if isinstance(key, slice):
246
+ start, stop, step = key.indices(self.size)
247
+ return BoolHybridArr((self[i] for i in range(start, stop, step)),hash_ = self.hash_)
248
+ key = key if key >=0 else key + self.size
249
+ if 0 <= key < self.size:
250
+ return self.Type(self.accessor(key))
251
+ raise IndexError("索引超出范围")
252
+ def __setitem__(self, key: int | slice, value) -> None:
253
+ if isinstance(key, int):
254
+ adjusted_key = key if key >= 0 else key + self.size
255
+ if not (0 <= adjusted_key < self.size):
256
+ raise IndexError("索引超出范围")
257
+ self.accessor(adjusted_key, bool(value))
258
+ return
259
+ if isinstance(key, slice):
260
+ original_size = self.size
261
+ start, stop, step = key.indices(original_size)
262
+ value_list = list(value)
263
+ new_len = len(value_list)
264
+ if step != 1:
265
+ slice_indices = list(range(start, stop, step))
266
+ if new_len != len(slice_indices):
267
+ raise ValueError(f"值长度与切片长度不匹配:{new_len} vs {len(slice_indices)}")
268
+ for i, val in zip(slice_indices, value_list):
269
+ self[i] = val
270
+ return
271
+ for i in range(stop - 1, start - 1, -1):
272
+ if i <= self.split_index:
273
+ if i >= len(self.small):
274
+ self.small = np.pad(
275
+ self.small,
276
+ (0, i - len(self.small) + 1),
277
+ constant_values=not self.is_sparse
278
+ )
279
+ del self[i]
280
+ for idx, val in enumerate(value_list):
281
+ self.insert(start + idx, bool(val))
282
+ return
283
+ raise TypeError("索引必须是整数或切片")
284
+ def __repr__(self) -> str:
285
+ return(f"BoolHybridArray(split_index={self.split_index}, size={self.size}, "
286
+ +f"is_sparse={self.is_sparse}, small_len={len(self.small)}, large_len={len(self.large)})")
287
+ def __delitem__(self, key: int) -> None:
288
+ key = key if key >= 0 else key + self.size
289
+ if not (0 <= key < self.size):
290
+ raise IndexError(f"索引 {key} 超出范围 [0, {self.size})")
291
+ if key <= self.split_index:
292
+ if key >= len(self.small):
293
+ raise IndexError(f"小索引 {key} 超出small数组范围(长度{len(self.small)})")
294
+ self.small = np.delete(self.small, key)
295
+ self.small = np.append(self.small, not self.is_sparse)
296
+ self.split_index -= min(self.split_index, len(self.small) - 1)
297
+ else:
298
+ pos = bisect.bisect_left(self.large, key)
299
+ if pos < len(self.large) and self.large[pos] == key:
300
+ del self.large[pos]
301
+ adjust_pos = bisect.bisect_right(self.large, key)
302
+ for i in range(adjust_pos, len(self.large)):
303
+ self.large[i] -= 1
304
+ self.size -= 1
305
+ def __str__(self) -> str:
306
+ return f"BoolHybridArr([{','.join(map(str,self))}])"
307
+ def insert(self, key: int, value: bool) -> None:
308
+ value = bool(value)
309
+ key = key if key >= 0 else key + self.size
310
+ key = max(0, min(key, self.size))
311
+ if key <= self.split_index:
312
+ if key > len(self.small):
313
+ self.small = np.pad(
314
+ self.small,
315
+ (0, key - len(self.small) + 1),
316
+ constant_values=not self.is_sparse
317
+ )
318
+ self.small = np.insert(self.small, key, value)
319
+ self.split_index = min(self.split_index + 1, len(self.small) - 1)
320
+ else:
321
+ pos = bisect.bisect_left(self.large, key)
322
+ for i in range(pos, len(self.large)):
323
+ self.large[i] += 1
324
+ if (self.is_sparse and value) or (not self.is_sparse and not value):
325
+ self.large.insert(pos, key)
326
+ self.size += 1
327
+ def __len__(self) -> int:
328
+ return self.size
329
+ def __iter__(self):
330
+ return BHA_Iterator(map(self.__getitem__,range(self.size)))
331
+ def __next__(self):
332
+ return next(self.generator)
333
+ def __contains__(self, value) -> bool:
334
+ if not isinstance(value, (bool,np.bool_,self.Type,BHA_bool)):return False
335
+ if not self.size:return False
336
+ for i in range(10):
337
+ if self[random.randint(0,self.size-1)] == value:
338
+ return True
339
+ b = any(1 for i in range(self.small.size+1>>1) if value==self.small[i] or value==self.small[self.small.size-i-1])
340
+ if value == self.is_sparse:
341
+ return self.large or b
342
+ else:
343
+ return len(self.large) == self.size-self.split_index-1 or b
344
+ def __bool__(self) -> bool:
345
+ return self.size
346
+ def __any__(self):
347
+ return T in self
348
+ def __all__(self):
349
+ return F not in self
350
+ def __eq__(self, other) -> bool:
351
+ if not isinstance(other, (BoolHybridArray, list, tuple, np.ndarray, array.array)):
352
+ return False
353
+ if len(self) != len(other):
354
+ return False
355
+ return all(a == b for a, b in zip(self, other))
356
+ def __ne__(self, other) -> bool:
357
+ return not self == other
358
+ def __and__(self, other) -> BoolHybridArray:
359
+ if type(other) == int:
360
+ other = abs(other)
361
+ other = bin(other)[2:]
362
+ if len(self) != len(other):
363
+ raise ValueError(f"与运算要求数组长度相同({len(self)} vs {len(other)})")
364
+ return BoolHybridArr(map(operator.and_, self, other),hash_ = self.hash_)
365
+ def __int__(self):
366
+ if not self.size:
367
+ return 0
368
+ return reduce(lambda acc, val: operator.or_(operator.lshift(acc, 1), int(val)),self,0)
369
+ def __or__(self, other) -> BoolHybridArray:
370
+ if type(other) == int:
371
+ other = bin(other)[2:]
372
+ if self.size != len(other):
373
+ raise ValueError(f"或运算要求数组长度相同({len(self)} vs {len(other)})")
374
+ return BoolHybridArr(map(operator.or_, self, other),hash_ = self.hash_)
375
+ def __ror__(self, other) -> BoolHybridArray:
376
+ if type(other) == int:
377
+ other = abs(other)
378
+ other = bin(other)[2:]
379
+ return self | other
380
+ def __rshift__(self, other) -> BoolHybridArray:
381
+ arr = BoolHybridArr(self)
382
+ arr >>= other
383
+ return arr
384
+ def __irshift__(self, other) -> BoolHybridArray:
385
+ if int(other) < 0:
386
+ self <<= -other
387
+ return self
388
+ for i in range(int(other)):
389
+ if self.size < 1:
390
+ return self
391
+ self.pop(-1)
392
+ return self
393
+ def __ilshift__(self ,other) -> BoolHybridArray:
394
+ if int(other) < 0:
395
+ self >>= -other
396
+ return self
397
+ if not self.is_sparse:
398
+ self += FalsesArray(int(other))
399
+ self.optimize()
400
+ else:
401
+ self.size += int(other)
402
+ return self
403
+ def __lshift__(self ,other) -> BoolHybridArray:
404
+ if int(other) < 0:
405
+ return self >> -other
406
+ return self+FalsesArray(int(other))
407
+ def __add__(self, other) -> BoolHybridArray:
408
+ arr = self.copy()
409
+ arr += other
410
+ arr.optimize()
411
+ return arr
412
+ def __invert__(self) -> BoolHybridArray:
413
+ return BoolHybridArr(not val for val in self)
414
+ def __rand__(self, other) -> BoolHybridArray:
415
+ if type(other) == int:
416
+ other = bin(other)[2:]
417
+ return self & other
418
+ def __xor__(self, other) -> BoolHybridArray:
419
+ if len(self) != len(other):
420
+ raise ValueError(f"异或运算要求数组长度相同({len(self)} vs {len(other)})")
421
+ return BoolHybridArr(map(operator.xor, self, other),hash_ = self.hash_)
422
+ def __rxor__(self, other) -> BoolHybridArray:
423
+ return self^other
424
+ def __invert__(self) -> BoolHybridArray:
425
+ return BoolHybridArr(not a for a in self)
426
+ def copy(self) -> BoolHybridArray:
427
+ arr = BoolHybridArray(split_index = self.split_index,size = self.size)
428
+ arr.large,arr.small,arr.split_index,arr.is_sparse,arr.Type,arr.size = (array.array(self.large.typecode, self.large),self.small.copy(),
429
+ self.split_index,BHA_Bool(self.is_sparse),self.Type,self.size)
430
+ return arr
431
+ def __copy__(self) -> BoolHybridArray:
432
+ return self.copy()
433
+ def find(self,value):
434
+ from .int_array import IntHybridArray
435
+ return IntHybridArray([i for i in range(len(self)) if self[i]==value])
436
+ def extend(self, iterable:Iterable) -> None:
437
+ if isinstance(iterable, (Iterator, Generator, map)):
438
+ iterable,copy = itertools.tee(iterable, 2)
439
+ len_ = sum(1 for _ in copy)
440
+ else:
441
+ len_ = len(iterable)
442
+ self.size += len_
443
+ for i,j in zip(range(len_),iterable):
444
+ self[-i-1] = j
445
+ def append(self,v):
446
+ self.size += 1
447
+ self[-1] = v
448
+ def index(self, value) -> int:
449
+ if self.size == 0:
450
+ raise ValueError('无法在空的 BoolHybridArray 中查找元素!')
451
+ value = bool(value)
452
+ x = 'not find'
453
+ for i in range(self.size):
454
+ if self[i] == value:
455
+ return i
456
+ if self[-i] == value:
457
+ x = self.size-i
458
+ if len(self)-i == i:
459
+ break
460
+ if x != 'not find':
461
+ return x
462
+ raise ValueError(f"{value} not in BoolHybridArray")
463
+ def rindex(self, value) -> int:
464
+ if self.size == 0:
465
+ raise ValueError('无法在空的 BoolHybridArray 中查找元素!')
466
+ value = bool(value)
467
+ x = 'not find'
468
+ for i in range(self.size):
469
+ if self[-i] == value:
470
+ return -i
471
+ if self[i] == value:
472
+ x = -(self.size-i)
473
+ if len(self)-i == i:
474
+ break
475
+ if x != 'not find':
476
+ return x
477
+ raise ValueError(f"{value} not in BoolHybridArray")
478
+ def count(self, value) -> int:
479
+ value = bool(value)
480
+ return sum(v == value for v in self)
481
+ def optimize(self) -> None:
482
+ arr = BoolHybridArr(self)
483
+ self.large,self.small,self.split_index,self.is_sparse = (arr.large,arr.small,
484
+ arr.split_index,arr.is_sparse)
485
+ gc.collect()
486
+ return self
487
+ def memory_usage(self, detail=False) -> dict | int:
488
+ small_mem = self.small.size // 8 + 32
489
+ large_mem = len(self.large) * 4 + 32
490
+ equivalent_list_mem = 40 + 8 * self.size
491
+ equivalent_numpy_mem = 96 + self.size
492
+ total = small_mem+large_mem
493
+ if not detail:
494
+ return total
495
+ need_optimize = False
496
+ optimize_reason = ""
497
+ sparse_ratio = len(self.large) / max(len(self), 1)
498
+ if sparse_ratio > 0.4 and len(self) > 500: # 阈值可根据测试调整
499
+ need_optimize = True
500
+ optimize_reason = "稀疏区索引密度过高,优化后可转为密集存储提升速度"
501
+ elif len(self) < 32 and total > len(self):
502
+ need_optimize = True
503
+ optimize_reason = "小尺寸数组存储冗余,优化后将用int位存储进一步省内存"
504
+ elif np.count_nonzero(np.array(self.small)) / max(len(self.small), 1) < 0.05 and len(self) > 1000:
505
+ need_optimize = True
506
+ optimize_reason = "密集区有效值占比过低,优化后可转为稀疏存储节省内存"
507
+ return {
508
+ "总占用(字节)": total,
509
+ "密集区占用": small_mem,
510
+ "稀疏区占用": large_mem,
511
+ "对比原生list节省": f"{(1 - total/equivalent_list_mem)*100:.6f}%",
512
+ "对比numpy节省": f"{(1 - total/equivalent_numpy_mem)*100:.6f}%" if equivalent_numpy_mem > 0 else "N/A",
513
+ "是否需要优化": "是" if need_optimize else "否",
514
+ "优化理由/说明": optimize_reason if need_optimize else "当前存储模式已适配数据特征,无需优化"
515
+ }
516
+ def get_shape(self):
517
+ return (self.size,)
518
+ def __array__(self,dtype = np.bool_,copy = None):
519
+ arr = np.fromiter(map(np.bool_,self), dtype=dtype)
520
+ return arr.copy() if copy else arr.view()
521
+ def view(self):
522
+ arr = TruesArray(0)
523
+ arr.__dict__ = self.__dict__
524
+ return arr
525
+ def __reduce__(self):
526
+ return BoolHybridArr,(np.asarray(self),self.is_sparse,self.Type,self.hash_,),
527
+ class BoolHybridArr(BoolHybridArray,metaclass=ResurrectMeta):
528
+ __module__ = 'bool_hybrid_array'
529
+ def __new__(cls, lst: Iterable, is_sparse=None, Type = None, hash_ = True) -> BoolHybridArray:
530
+ a = isinstance(lst, (Iterator, Generator, map))
531
+ if a:
532
+ lst, copy1, copy2 = itertools.tee(lst, 3)
533
+ size = sum(1 for _ in copy1)
534
+ true_count = sum(bool(val) for val in copy2)
535
+ else:
536
+ size = len(lst)
537
+ true_count = sum(bool(val) for val in lst)
538
+ if size == 0:
539
+ return BoolHybridArray(0, 0, is_sparse=False if is_sparse is None else is_sparse)
540
+ if is_sparse is None:
541
+ is_sparse = true_count <= (size - true_count)
542
+ split_index = int(min(size * 0.8, math.sqrt(size) * 100))
543
+ split_index = math.isqrt(size) if true_count>size/3*2 or true_count<size/3 else max(split_index, 1)
544
+ split_index = int(split_index) if split_index < 150e+7*2 else int(145e+7*2)
545
+ arr = BoolHybridArray(split_index = split_index, size = size, is_sparse = is_sparse, Type = Type, hash_ = F)
546
+ small_max_idx = min(split_index, size - 1)
547
+ if a:
548
+ small_data = []
549
+ large_indices = []
550
+ for i, val in enumerate(lst):
551
+ val_bool = bool(val)
552
+ if i <= small_max_idx:
553
+ small_data.append(val_bool)
554
+ else:
555
+ if (is_sparse and val_bool) or (not is_sparse and not val_bool):
556
+ large_indices.append(i)
557
+ if small_data:
558
+ arr.small[:len(small_data)] = small_data
559
+ if large_indices:
560
+ arr.large.extend(large_indices)
561
+ else:
562
+ if small_max_idx >= 0:
563
+ arr.small[:small_max_idx + 1] = [bool(val) for val in lst[:small_max_idx + 1]]
564
+ large_indices = [
565
+ i for i in range(split_index + 1, size)
566
+ if (is_sparse and bool(lst[i])) or (not is_sparse and not bool(lst[i]))
567
+ ]
568
+ arr.large.extend(large_indices)
569
+ arr.large = sorted(arr.large)
570
+ type_ = 'I' if size < 1 << 32 else 'Q'
571
+ arr.large = array.array(type_, arr.large)
572
+ if hash_:
573
+ global hybrid_array_cache
574
+ del hybrid_array_cache[-1]
575
+ hybrid_array_cache = [
576
+ (ref, h) for ref, h in hybrid_array_cache
577
+ if ref() is not None
578
+ ]
579
+ for ref, existing_hash in hybrid_array_cache:
580
+ existing_array = ref()
581
+ try:
582
+ if arr.size != existing_array.size:
583
+ continue
584
+ elif arr == existing_array:
585
+ arr._cached_hash = existing_hash
586
+ return arr
587
+ except:
588
+ continue
589
+ return arr
590
+ def TruesArray(size, Type = None, hash_ = True):
591
+ split_index = min(size//10, math.isqrt(size))
592
+ split_index = max(split_index, 1)
593
+ split_index = int(split_index) if split_index < 150e+7*2 else int(145e+7*2)
594
+ return BoolHybridArray(split_index,size,Type = Type,hash_ = hash_)
595
+ def FalsesArray(size, Type = None,hash_ = True):
596
+ split_index = min(size//10, math.isqrt(size))
597
+ split_index = max(split_index, 1)
598
+ split_index = int(split_index) if split_index < 150e+7*2 else int(145e+7*2)
599
+ return BoolHybridArray(split_index,size,True,Type = Type,hash_ = hash_)
600
+ Bool_Array = np.arange(2,dtype = np.uint8)
601
+ class BHA_bool(int,metaclass=ResurrectMeta):
602
+ __module__ = 'bool_hybrid_array'
603
+ def __new__(cls, value):
604
+ core_value = bool(value)
605
+ instance = super().__new__(cls, core_value)
606
+ instance.data = Bool_Array[1] if core_value else Bool_Array[0]
607
+ instance.value = core_value
608
+ return instance
609
+ @lru_cache
610
+ def __str__(self):
611
+ return 'True' if self else 'False'
612
+ @lru_cache
613
+ def __repr__(self):
614
+ return 'T' if self else 'F'
615
+ @lru_cache
616
+ def __bool__(self):
617
+ return self.value
618
+ @lru_cache
619
+ def __int__(self):
620
+ return int(self.data)
621
+ @lru_cache
622
+ def __or__(self,other):
623
+ return BHA_Bool(self.value|other)
624
+ @lru_cache
625
+ def __and__(self,other):
626
+ return BHA_Bool(self.value&other)
627
+ @lru_cache
628
+ def __xor__(self,other):
629
+ return BHA_Bool(self.value^other)
630
+ def __hash__(self):
631
+ return hash(self.data)
632
+ def __len__(self):
633
+ raise TypeError("'BHA_bool' object has no attribute '__len__'")
634
+ __rand__,__ror__,__rxor__ = __and__,__or__,__xor__
635
+ class BHA_Bool(BHA_bool,metaclass=ResurrectMeta):
636
+ __module__ = 'bool_hybrid_array'
637
+ @lru_cache
638
+ def __new__(cls,v):
639
+ if(builtins.T == True)and(builtins.F == False):
640
+ return builtins.T if v else builtins.F
641
+ else:
642
+ builtins.T,builtins.F = BHA_Bool.T,BHA_Bool.F
643
+ return BHA_Bool.T if v else BHA_Bool.F
644
+ class BHA_List(list,metaclass=ResurrectMeta):
645
+ __module__ = 'bool_hybrid_array'
646
+ def __init__(self,arr):
647
+ def Temp(v):
648
+ if isinstance(v,(list,tuple)):
649
+ v = (BoolHybridArr(v) if all(isinstance(i,
650
+ (bool,BHA_bool,np.bool_)) for i in v)
651
+ else BHA_List(v))
652
+ if isinstance(v,BoolHybridArray):
653
+ return v
654
+ elif isinstance(v,(bool,np.bool_)):
655
+ return BHA_Bool(v)
656
+ else:
657
+ return v
658
+ super().__init__(map(Temp,arr))
659
+ try:self.hash_value = sum(map(hash,self))
660
+ except Exception as e:return hash(e)
661
+ def __hash__(self):
662
+ return self.hash_value
663
+ def __call__(self, func):
664
+ func.self = self
665
+ def wrapper(*args, **kwargs):
666
+ return func(self, *args, **kwargs)
667
+ setattr(self, func.__name__, wrapper)
668
+ return func
669
+ def __str__(self):
670
+ def Temp(v):
671
+ if isinstance(v,(BoolHybridArray,np.ndarray,BHA_List,array.array)):
672
+ return str(v)+',\n'
673
+ else:
674
+ return repr(v)+','
675
+ return f"BHA_List([\n{''.join(map(Temp,self))}])"
676
+ def __repr__(self):
677
+ return str(self)
678
+ def __or__(self,other):
679
+ return BHA_List(map(operator.or_, self, other))
680
+ def __and__(self,other):
681
+ return BHA_List(map(operator.and_, self, other))
682
+ def __xor__(self,other):
683
+ return BHA_List(map(operator.xor, self, other))
684
+ def __rxor__(self,other):
685
+ return self^other
686
+ def __ror__(self,other):
687
+ return self|other
688
+ def __rand__(self,other):
689
+ return self&other
690
+ def optimize(self):
691
+ for val in self:
692
+ val.optimize()
693
+ def memory_usage(self,detail=False):
694
+ total = sum(val.memory_usage() for val in self) + 32
695
+ if not detail:
696
+ return total
697
+ else:
698
+ temp = sum(val.size for val in self)
699
+ return {
700
+ "占用(字节)": total,
701
+ "对比原生list节省": f"{(1 - total / (temp * 8 + 40))*100:.6f}%",
702
+ "对比numpy节省": f"{(1 - total / (temp + 96)) * 100:.6f}%"}
703
+ def __iter__(self):
704
+ return BHA_Iterator(super().__iter__())
705
+ def to_ascii_art(self, width=20):
706
+ art = '\n'.join([''.join(['■' if j else ' ' for j in i]) for i in self])
707
+ return '\n'.join(art)
708
+ class BHA_Iterator(Iterator,metaclass=ResurrectMeta):
709
+ __module__ = 'bool_hybrid_array'
710
+ def __init__(self,data):
711
+ self.data,self.copy_data = itertools.tee(iter(data),2)
712
+ def __next__(self):
713
+ try:return next(self.data)
714
+ except Exception as e:
715
+ self.__init__(self.copy_data)
716
+ raise e
717
+ def __iter__(self):
718
+ return self
719
+ def __or__(self,other):
720
+ return BHA_Iterator(map(operator.or_, self, other))
721
+ def __and__(self,other):
722
+ return BHA_Iterator(map(operator.and_, self, other))
723
+ def __xor__(self,other):
724
+ return BHA_Iterator(map(operator.xor, self, other))
725
+ def __array__(self,dtype = None,copy = None):
726
+ arr = np.fromiter(self, dtype=dtype)
727
+ return arr.copy() if copy else arr.view()
728
+ __rand__,__ror__,__rxor__ = __and__,__or__,__xor__
729
+ class ProtectedBuiltinsDict(dict,metaclass=ResurrectMeta):
730
+ def __init__(self, *args, protected_names = ("T", "F", "BHA_Bool", "BHA_List", "BoolHybridArray", "BoolHybridArr",
731
+ "TruesArray", "FalsesArray", "ProtectedBuiltinsDict", "builtins",
732
+ "__builtins__", "__dict__","ResurrectMeta","math",
733
+ "np","protected_names","BHA_Function",
734
+ "__class__","Ask_BHA","Create_BHA","Ask_arr","numba_opt"),
735
+ name = 'builtins', **kwargs):
736
+ super().__init__(*args, **kwargs)
737
+ if name == 'builtins':
738
+ super().__setattr__('__dict__',self)
739
+ super().__setattr__('builtins',self)
740
+ super().__setattr__('__builtins__',self)
741
+ self.name = name
742
+ super().__setattr__("protected_names",protected_names)
743
+ def __setitem__(self, name, value):
744
+ if not hasattr(self,"protected_names"):
745
+ super().__setitem__(name, value)
746
+ return
747
+ try:
748
+ if name in ["T", "F"]:
749
+ current_T = self.get("T")
750
+ current_F = self.get("F")
751
+ if isinstance(current_T, BHA_bool) and isinstance(current_F, BHA_bool):
752
+ is_swap = (name == "T" and isinstance(value, BHA_bool) and value.value == current_F.value)or(name == "F" and isinstance(value, BHA_bool) and value.value == current_T.value)
753
+ if is_swap:
754
+ print(f"""警告:禁止交换内置常量 __{self.name}__["{name}"] __builtins__["{'F' if name == 'T' else 'T'}"]!""")
755
+ raise AttributeError(f"""禁止交换内置常量 __{self.name}__["{name}"] 和 __{self.name}__["{'F' if name == 'T' else 'T'}"]""")
756
+ if name in self.protected_names and name not in ["T", "F"]:
757
+ print(f"警告:禁止修改内置常量 __{self.name}__['{name}']!")
758
+ raise AttributeError(f"禁止修改内置常量 __{self.name}__['{name}']")
759
+ except:
760
+ if sys.implementation.name == 'cpython':
761
+ raise
762
+ finally:super().__setitem__(name, value)
763
+ def __delitem__(self, name):
764
+ if name in self.protected_names:
765
+ print(f"警告:禁止删除内置常量 __builtins__['{name}']!")
766
+ raise AttributeError(f"禁止删除内置常量 __builtins__['{name}']")
767
+ if name in self:
768
+ super().__delitem__(name)
769
+ def __delattr__(self, name):
770
+ if name in self.protected_names:
771
+ raise AttributeError(f'禁止删除内置常量:{self.name}.{name}')
772
+ else:
773
+ del self[name]
774
+ def __getattr__(self, name):
775
+ try:
776
+ return super().__getattribute__(name)
777
+ except AttributeError:
778
+ if name in self:
779
+ return self[name]
780
+ raise AttributeError(f"module 'builtins' has no attribute '{name}'") from None
781
+ def __setattr__(self,name,value):
782
+ try:protected = self.protected_names
783
+ except Exception:protected = self
784
+ if(name in protected)and(not sys.is_finalizing())and(name != '_'):
785
+ raise AttributeError(f'禁止修改内置常量:{self.name}.{name}')
786
+ else:
787
+ super().__setattr__(name,value)
788
+ def __import__(self, name, globals=None, locals=None, fromlist=(), level=0):
789
+ if fromlist:
790
+ result = []
791
+ for key in fromlist:
792
+ if key not in self:
793
+ raise AttributeError(f"'ImportableDict' object has no attribute '{key}'")
794
+ result.append(self[key])
795
+ return result[0] if len(result) == 1 else tuple(result)
796
+ return self
797
+ def Ask_arr(arr):
798
+ if isinstance(arr,BHA_List):
799
+ return '\n'.join(map(Ask_arr,arr))
800
+ elif isinstance(arr,BoolHybridArray):
801
+ h = hex(int(arr))[2:]
802
+ h = '0'*(arr.size - len(bin(int(arr)))+2)+h
803
+ return h
804
+ else:
805
+ return str(arr)
806
+ def Ask_BHA(path):
807
+ if '.bha' not in path.lower():
808
+ path += '.bha'
809
+ with open(path, 'a+b') as f:
810
+ f.seek(0)
811
+ file_size = os.fstat(f.fileno()).st_size
812
+ if not file_size:
813
+ return TruesArray(0)
814
+ if os.name == 'nt':
815
+ mm = mmap.mmap(f.fileno(), file_size, access=mmap.ACCESS_READ)
816
+ else:
817
+ mm = mmap.mmap(f.fileno(), file_size, flags=mmap.MAP_PRIVATE, prot=mmap.PROT_READ)
818
+ with mm:
819
+ temp = mm.read().decode('utf-8').strip()
820
+ temp = temp.split()
821
+ temp2 = lambda x: BoolHybridArr(
822
+ (
823
+ bit_stream := bytes(0 if k < lead_zero else (n >> ((total_len - 1) - k)) & 1 for k in range(total_len)),
824
+ arr := array.array('B', FalsesArray(total_len)),
825
+ memcpy(arr.buffer_info()[0], bit_stream, total_len),arr)[-1]
826
+ if(n := int(x, base=16),
827
+ lead_zero := len(x) - len(x.lstrip('0')),
828
+ total_len := lead_zero + (n.bit_length() if n else 1))
829
+ else array.array('B'))
830
+ temp = BHA_List(map(temp2,temp))
831
+ if len(temp) == 1:
832
+ return temp[0]
833
+ return temp
834
+ def Create_BHA(path,arr):
835
+ if '.bha' not in path.lower():
836
+ path += '.bha'
837
+ temp = Ask_arr(arr).strip().encode('utf-8')
838
+ with open(path, "w+b") as f:
839
+ f.truncate(len(temp))
840
+ if not len(temp):
841
+ return
842
+ with mmap.mmap(
843
+ f.fileno(),
844
+ length=len(temp),
845
+ access=mmap.ACCESS_WRITE
846
+ ) as mm:
847
+ mm[:] = temp
848
+ mm.flush()
849
+ def numba_opt():
850
+ import numba
851
+ sig = numba.types.Union([
852
+ numba.types.intp(
853
+ numba.types.Array(numba.types.uint32, 1, 'C'),
854
+ numba.types.uint32,
855
+ numba.types.uint32,
856
+ numba.types.Optional(numba.types.uint32)
857
+ ),
858
+ numba.types.intp(
859
+ numba.types.Array(numba.types.uint64, 1, 'C'),
860
+ numba.types.uint64,
861
+ numba.types.uint64,
862
+ numba.types.Optional(numba.types.uint64)
863
+ ),
864
+ numba.types.intp(
865
+ numba.types.Any,
866
+ numba.types.Any,
867
+ numba.types.Any,
868
+ numba.types.Optional(numba.types.Any)
869
+ )
870
+ ])
871
+ bisect.bisect_left = numba.njit(sig, cache=True)(bisect.bisect_left)
872
+ bisect.bisect_right = numba.njit(sig, cache=True)(bisect.bisect_right)
873
+ builtins.np = np
874
+ builtins.T = BHA_bool(1)
875
+ builtins.F = BHA_bool(0)
876
+ builtins.BHA_Bool = BHA_Bool
877
+ builtins.BHA_List = BHA_List
878
+ builtins.FalsesArray = FalsesArray
879
+ builtins.TruesArray = TruesArray
880
+ builtins.BoolHybridArr = BoolHybridArr
881
+ builtins.BHA_Iterator = BHA_Iterator
882
+ builtins.BoolHybridArray = BoolHybridArray
883
+ builtins.BHA_Bool.T,builtins.BHA_Bool.F = BHA_bool(1),BHA_bool(0)
884
+ builtins.ResurrectMeta = ResurrectMeta
885
+ builtins.ProtectedBuiltinsDict = ProtectedBuiltinsDict
886
+ builtins.BHA_Function = BHA_Function
887
+ builtins.Ask_BHA = Ask_BHA
888
+ builtins.Create_BHA = Create_BHA
889
+ builtins.numba_opt = numba_opt
890
+ Tid,Fid = id(T),id(F)
891
+ original_id = builtins.id
892
+ def fake_id(obj):
893
+ if isinstance(obj, BHA_bool):return Tid if obj else Fid
894
+ else:return original_id(obj)
895
+ builtins.id = fake_id
896
+ original_builtins_dict = builtins.__dict__.copy()
897
+ __builtins__ = ProtectedBuiltinsDict(original_builtins_dict)
898
+ builtins = __builtins__
899
+ sys.modules['builtins'] = builtins
900
+ builtins.name = 'builtins'
901
+ try:
902
+ sys.flags.optimize = 2
903
+ except:
857
904
  pass