关于掩码
什么是标志flag
在掩码的语境下,标志flag,是只有1位的掩码,取值范围range(flag)满足:
range(flag)={0,1}
。
flag可以是一个单纯的取值范围为{0,1}的二值的状态量,也可以是相对于另一个取值范围是{s1,s2}的二值的状态量state,所建立一一映射
flag:{s1,s2}↔{0,1}
。
Note 更一般而且常见的,标志flag是一个离散的状态量,取值范围是自然数集N的子集。它可以是单纯的状态量,也可以是:设存在一个状态量state,它的取值范围range(state)是离散的,flag是range(state)到自然数集N的映射
flag:range(state)→N
。也即,使用不同的自然数来分别枚举和指代状态量state的各个状态值。
什么是掩码mask
掩码mask,是一个二进制的位模式,取值范围range(mask)满足:
range(mask)={0,1}n,n∈N
。
mask是一个状态量,或者状态映射:给定状态向量state,是一组二值的状态量{statei∣∣0<i≤n,n∈N}的序列,分别有取值范围range(statei)={si,1,si,2},mask是相对于state,所建立一一映射
mask:i=1×n{si,1,si,2}↔{0,1}n
。
Note 标志flag的值域是标量scalar,掩码mask的值域是向量vector,两者都是状态量或者状态映射。
可以认为,mask是建立在{0,1}n,n∈N上的线性空间,给定它的一组基{ui∈{0,1}n∣∣0<i≤n;∀0<i,j≤n,ui[j]=1⟺i=j},也即分别有ui对应于mask的第i位。令标志flagi对应于mask的第i位的值,即有flagi=mask[i]且有线性组合
mask=i=1∑nflagi⋅ui
。总而言之,mask的每一位分别对应一个flag,mask是多个占据不同位的flag的线性组合,因此mask是一个状态向量或者组合状态映射。
实现:标志Flag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class Flag:
def __init__(self): self._value = 0
@property def flag(self) -> int: return self._value
def set(self): 'set the flag to 1' self._value = 1
def clear(self): 'set the flag to 0' self._value = 0
def reverse(self): 'reverse/invert the flag, 0 to 1, 1 to 0' self._value ^= 1
def isset(self) -> bool: 'Is flag = 1?' return self._value is 1
|
实现:掩码Mask
Note 因为在Python中,int是不可变类型,操作的结果往往会产生新的int对象,这是低效的。建议使用C扩展或者某些可改动内存的结构,至少保证位操作可以复用原来的内存区域。
mask.py1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
| from typing import TypeVar, Generic, Union
T = TypeVar('T')
class MaskOpMixin(Generic[T]):
def __eq__(self, o: Union[int, T]) -> bool: if isinstance(o, type(self)): o = o._value return self._value == o
def __invert__(self): return type(self)(~self._value)
def __and__(self, o: Union[int, T]) -> T: cls = type(self) if isinstance(o, cls): o = o._value return cls(self._value & o)
def __or__(self, o: Union[int, T]) -> T: cls = type(self) if isinstance(o, cls): o = o._value return cls(self._value | o)
def __xor__(self, o: Union[int, T]) -> T: cls = type(self) if isinstance(o, cls): o = o._value return cls(self._value ^ o)
__rand__ = __and__ __ror__ = __or__ __rxor__ = __xor__
def __iand__(self, o: Union[int, T]) -> T: if isinstance(o, type(self)): o = o._value self._value &= o return self
def __ior__(self, o: Union[int, T]) -> T: if isinstance(o, type(self)): o = o._value self._value |= o return self
def __ixor__(self, o: Union[int, T]) -> T: if isinstance(o, type(self)): o = o._value self._value ^= o return self
def __sub__(self, o: Union[int, T]) -> T: cls = type(self) if isinstance(o, cls): o = o._value return cls(self._value & ~o)
def __isub__(self, o: Union[int, T]) -> T: if isinstance(o, type(self)): o = o._value self._value &= ~o return self
class MaskBase:
def __init__(self, mask: int = 0) -> None: self._value = mask
@property def mask(self) -> int: return self._value
@property def binmask(self) -> str: return bin(self._value)
def __repr__(self) -> str: return f'{type(self).__name__}({bin(self._value)})'
def set(self, m: int) -> None: 'set mask by offset m' self._value |= 1 << m
def clear(self, m: int) -> None: 'clear mask by offset m' self._value &= ~(1 << m)
def reverse(self, m: Union[int, MaskBase]) -> None: 'reverse/invert mask by offset m' self._value ^= 1 << m
def test(self, m: int) -> bool: 'test mask by offset m' return bool(self._value & 1 << m)
class Mask(MaskBase, MaskOpMixin[MaskBase]):
def set(self, m: Union[int, MaskBase]) -> None: 'set mask by mask m' self |= m
def clear(self, m: Union[int, MaskBase]) -> None: 'clear mask by mask m' self -= m
def reverse(self, m: Union[int, MaskBase]) -> None: 'reverse/invert mask by mask m' self ^= m
def test(self, m: Union[int, MaskBase]) -> bool: 'clear mask by mask m' return self & m == m
|
测试结果如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| >>> from mask import * >>> EVENT0 = 1 << 0 >>> EVENT1 = 1 << 1 >>> EVENT2 = 1 << 2 >>> EVENT3 = 1 << 3 >>> m = Mask(EVENT1) >>> m.set(EVENT0 | EVENT3) >>> m Mask(0b1011) >>> m.test(EVENT0 | EVENT1) True >>> m.clear(EVENT0 | EVENT1) >>> m Mask(0b1000) >>> m.reverse((1 << 4) - 1) >>> m Mask(0b111)
|