掩码(Python实现)

掩码(Python实现)

关于掩码

什么是标志flag

在掩码的语境下,标志flag,是只有1位的掩码,取值范围range(flag)range(\mathrm{flag})满足:

range(flag)={0,1}range(\mathrm{flag}) = \{0, 1\}

flag可以是一个单纯的取值范围为{0,1}\{0,1\}的二值的状态量,也可以是相对于另一个取值范围是{s1,s2}\{s_1, s_2\}的二值的状态量state,所建立一一映射

flag:{s1,s2}{0,1}\mathrm{flag}: \{s_1, s_2\} \leftrightarrow \{0,1\}

Note 更一般而且常见的,标志flag是一个离散的状态量,取值范围是自然数集N\N的子集。它可以是单纯的状态量,也可以是:设存在一个状态量state,它的取值范围range(state)range(\mathrm{state})是离散的,flagrange(state)range(\mathrm{state})到自然数集N\N的映射

flag:range(state)N\mathrm{flag}: range(\mathrm{state}) \to \N

。也即,使用不同的自然数来分别枚举和指代状态量state的各个状态值。

什么是掩码mask

掩码mask,是一个二进制的位模式,取值范围range(mask)range(\mathrm{mask})满足:

range(mask)={0,1}n,nNrange(\mathrm{mask}) = \{0, 1\}^n, n \in \N

mask是一个状态量,或者状态映射:给定状态向量state,是一组二值的状态量{statei0<in,nN}\{\mathrm{state}_i \big| 0 < i \le n, n \in \N\}的序列,分别有取值范围range(statei)={si,1,si,2}range(\mathrm{state}_i)=\{s_{i, 1}, s_{i, 2}\}mask是相对于state,所建立一一映射

mask:×ni=1{si,1,si,2}{0,1}n\mathrm{mask}: \underset{i=1}{\overset{n}{\times}}\{s_{i, 1}, s_{i, 2}\} \leftrightarrow \{0,1\}^n

Note 标志flag的值域是标量scalar,掩码mask的值域是向量vector,两者都是状态量或者状态映射。
可以认为,mask是建立在{0,1}n,nN\{0,1\}^n,n \in \N上的线性空间,给定它的一组基{ui{0,1}n0<in;0<i,jn,ui[j]=1    i=j}\{\bold{u}_i \in \{0,1\}^n \big| 0 < i \le n;\forall 0 < i, j \le n,\bold{u}_i[j] = 1 \iff i = j\},也即分别有ui\bold{u}_i对应于mask的第ii位。令标志flagi\mathrm{flag}_i对应于mask\mathrm{mask}的第ii位的值,即有flagi=mask[i]\mathrm{flag}_i = \mathrm{mask}[i]且有线性组合

mask=i=1nflagiui\mathrm{mask} = \sum_{i=1}^n \mathrm{flag}_i \cdot \bold{u}_i

。总而言之,mask的每一位分别对应一个flagmask是多个占据不同位的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.py
1
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
# 🤔 l & ~r == (l | r) ^ r
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)
# Python

评论

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×