]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.2/Demo/classes/bitvec.py
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Demo / classes / bitvec.py
CommitLineData
4710c53d 1#\r
2# this is a rather strict implementation of a bit vector class\r
3# it is accessed the same way as an array of python-ints, except\r
4# the value must be 0 or 1\r
5#\r
6\r
7import sys; rprt = sys.stderr.write #for debugging\r
8\r
9class error(Exception):\r
10 pass\r
11\r
12\r
13def _check_value(value):\r
14 if type(value) != type(0) or not 0 <= value < 2:\r
15 raise error, 'bitvec() items must have int value 0 or 1'\r
16\r
17\r
18import math\r
19\r
20def _compute_len(param):\r
21 mant, l = math.frexp(float(param))\r
22 bitmask = 1L << l\r
23 if bitmask <= param:\r
24 raise RuntimeError('(param, l) = %r' % ((param, l),))\r
25 while l:\r
26 bitmask = bitmask >> 1\r
27 if param & bitmask:\r
28 break\r
29 l = l - 1\r
30 return l\r
31\r
32\r
33def _check_key(len, key):\r
34 if type(key) != type(0):\r
35 raise TypeError, 'sequence subscript not int'\r
36 if key < 0:\r
37 key = key + len\r
38 if not 0 <= key < len:\r
39 raise IndexError, 'list index out of range'\r
40 return key\r
41\r
42def _check_slice(len, i, j):\r
43 #the type is ok, Python already checked that\r
44 i, j = max(i, 0), min(len, j)\r
45 if i > j:\r
46 i = j\r
47 return i, j\r
48\r
49\r
50class BitVec:\r
51\r
52 def __init__(self, *params):\r
53 self._data = 0L\r
54 self._len = 0\r
55 if not len(params):\r
56 pass\r
57 elif len(params) == 1:\r
58 param, = params\r
59 if type(param) == type([]):\r
60 value = 0L\r
61 bit_mask = 1L\r
62 for item in param:\r
63 # strict check\r
64 #_check_value(item)\r
65 if item:\r
66 value = value | bit_mask\r
67 bit_mask = bit_mask << 1\r
68 self._data = value\r
69 self._len = len(param)\r
70 elif type(param) == type(0L):\r
71 if param < 0:\r
72 raise error, 'bitvec() can\'t handle negative longs'\r
73 self._data = param\r
74 self._len = _compute_len(param)\r
75 else:\r
76 raise error, 'bitvec() requires array or long parameter'\r
77 elif len(params) == 2:\r
78 param, length = params\r
79 if type(param) == type(0L):\r
80 if param < 0:\r
81 raise error, \\r
82 'can\'t handle negative longs'\r
83 self._data = param\r
84 if type(length) != type(0):\r
85 raise error, 'bitvec()\'s 2nd parameter must be int'\r
86 computed_length = _compute_len(param)\r
87 if computed_length > length:\r
88 print 'warning: bitvec() value is longer than the length indicates, truncating value'\r
89 self._data = self._data & \\r
90 ((1L << length) - 1)\r
91 self._len = length\r
92 else:\r
93 raise error, 'bitvec() requires array or long parameter'\r
94 else:\r
95 raise error, 'bitvec() requires 0 -- 2 parameter(s)'\r
96\r
97\r
98 def append(self, item):\r
99 #_check_value(item)\r
100 #self[self._len:self._len] = [item]\r
101 self[self._len:self._len] = \\r
102 BitVec(long(not not item), 1)\r
103\r
104\r
105 def count(self, value):\r
106 #_check_value(value)\r
107 if value:\r
108 data = self._data\r
109 else:\r
110 data = (~self)._data\r
111 count = 0\r
112 while data:\r
113 data, count = data >> 1, count + (data & 1 != 0)\r
114 return count\r
115\r
116\r
117 def index(self, value):\r
118 #_check_value(value):\r
119 if value:\r
120 data = self._data\r
121 else:\r
122 data = (~self)._data\r
123 index = 0\r
124 if not data:\r
125 raise ValueError, 'list.index(x): x not in list'\r
126 while not (data & 1):\r
127 data, index = data >> 1, index + 1\r
128 return index\r
129\r
130\r
131 def insert(self, index, item):\r
132 #_check_value(item)\r
133 #self[index:index] = [item]\r
134 self[index:index] = BitVec(long(not not item), 1)\r
135\r
136\r
137 def remove(self, value):\r
138 del self[self.index(value)]\r
139\r
140\r
141 def reverse(self):\r
142 #ouch, this one is expensive!\r
143 #for i in self._len>>1: self[i], self[l-i] = self[l-i], self[i]\r
144 data, result = self._data, 0L\r
145 for i in range(self._len):\r
146 if not data:\r
147 result = result << (self._len - i)\r
148 break\r
149 result, data = (result << 1) | (data & 1), data >> 1\r
150 self._data = result\r
151\r
152\r
153 def sort(self):\r
154 c = self.count(1)\r
155 self._data = ((1L << c) - 1) << (self._len - c)\r
156\r
157\r
158 def copy(self):\r
159 return BitVec(self._data, self._len)\r
160\r
161\r
162 def seq(self):\r
163 result = []\r
164 for i in self:\r
165 result.append(i)\r
166 return result\r
167\r
168\r
169 def __repr__(self):\r
170 ##rprt('<bitvec class instance object>.' + '__repr__()\n')\r
171 return 'bitvec(%r, %r)' % (self._data, self._len)\r
172\r
173 def __cmp__(self, other, *rest):\r
174 #rprt('%r.__cmp__%r\n' % (self, (other,) + rest))\r
175 if type(other) != type(self):\r
176 other = apply(bitvec, (other, ) + rest)\r
177 #expensive solution... recursive binary, with slicing\r
178 length = self._len\r
179 if length == 0 or other._len == 0:\r
180 return cmp(length, other._len)\r
181 if length != other._len:\r
182 min_length = min(length, other._len)\r
183 return cmp(self[:min_length], other[:min_length]) or \\r
184 cmp(self[min_length:], other[min_length:])\r
185 #the lengths are the same now...\r
186 if self._data == other._data:\r
187 return 0\r
188 if length == 1:\r
189 return cmp(self[0], other[0])\r
190 else:\r
191 length = length >> 1\r
192 return cmp(self[:length], other[:length]) or \\r
193 cmp(self[length:], other[length:])\r
194\r
195\r
196 def __len__(self):\r
197 #rprt('%r.__len__()\n' % (self,))\r
198 return self._len\r
199\r
200 def __getitem__(self, key):\r
201 #rprt('%r.__getitem__(%r)\n' % (self, key))\r
202 key = _check_key(self._len, key)\r
203 return self._data & (1L << key) != 0\r
204\r
205 def __setitem__(self, key, value):\r
206 #rprt('%r.__setitem__(%r, %r)\n' % (self, key, value))\r
207 key = _check_key(self._len, key)\r
208 #_check_value(value)\r
209 if value:\r
210 self._data = self._data | (1L << key)\r
211 else:\r
212 self._data = self._data & ~(1L << key)\r
213\r
214 def __delitem__(self, key):\r
215 #rprt('%r.__delitem__(%r)\n' % (self, key))\r
216 key = _check_key(self._len, key)\r
217 #el cheapo solution...\r
218 self._data = self[:key]._data | self[key+1:]._data >> key\r
219 self._len = self._len - 1\r
220\r
221 def __getslice__(self, i, j):\r
222 #rprt('%r.__getslice__(%r, %r)\n' % (self, i, j))\r
223 i, j = _check_slice(self._len, i, j)\r
224 if i >= j:\r
225 return BitVec(0L, 0)\r
226 if i:\r
227 ndata = self._data >> i\r
228 else:\r
229 ndata = self._data\r
230 nlength = j - i\r
231 if j != self._len:\r
232 #we'll have to invent faster variants here\r
233 #e.g. mod_2exp\r
234 ndata = ndata & ((1L << nlength) - 1)\r
235 return BitVec(ndata, nlength)\r
236\r
237 def __setslice__(self, i, j, sequence, *rest):\r
238 #rprt('%s.__setslice__%r\n' % (self, (i, j, sequence) + rest))\r
239 i, j = _check_slice(self._len, i, j)\r
240 if type(sequence) != type(self):\r
241 sequence = apply(bitvec, (sequence, ) + rest)\r
242 #sequence is now of our own type\r
243 ls_part = self[:i]\r
244 ms_part = self[j:]\r
245 self._data = ls_part._data | \\r
246 ((sequence._data | \\r
247 (ms_part._data << sequence._len)) << ls_part._len)\r
248 self._len = self._len - j + i + sequence._len\r
249\r
250 def __delslice__(self, i, j):\r
251 #rprt('%r.__delslice__(%r, %r)\n' % (self, i, j))\r
252 i, j = _check_slice(self._len, i, j)\r
253 if i == 0 and j == self._len:\r
254 self._data, self._len = 0L, 0\r
255 elif i < j:\r
256 self._data = self[:i]._data | (self[j:]._data >> i)\r
257 self._len = self._len - j + i\r
258\r
259 def __add__(self, other):\r
260 #rprt('%r.__add__(%r)\n' % (self, other))\r
261 retval = self.copy()\r
262 retval[self._len:self._len] = other\r
263 return retval\r
264\r
265 def __mul__(self, multiplier):\r
266 #rprt('%r.__mul__(%r)\n' % (self, multiplier))\r
267 if type(multiplier) != type(0):\r
268 raise TypeError, 'sequence subscript not int'\r
269 if multiplier <= 0:\r
270 return BitVec(0L, 0)\r
271 elif multiplier == 1:\r
272 return self.copy()\r
273 #handle special cases all 0 or all 1...\r
274 if self._data == 0L:\r
275 return BitVec(0L, self._len * multiplier)\r
276 elif (~self)._data == 0L:\r
277 return ~BitVec(0L, self._len * multiplier)\r
278 #otherwise el cheapo again...\r
279 retval = BitVec(0L, 0)\r
280 while multiplier:\r
281 retval, multiplier = retval + self, multiplier - 1\r
282 return retval\r
283\r
284 def __and__(self, otherseq, *rest):\r
285 #rprt('%r.__and__%r\n' % (self, (otherseq,) + rest))\r
286 if type(otherseq) != type(self):\r
287 otherseq = apply(bitvec, (otherseq, ) + rest)\r
288 #sequence is now of our own type\r
289 return BitVec(self._data & otherseq._data, \\r
290 min(self._len, otherseq._len))\r
291\r
292\r
293 def __xor__(self, otherseq, *rest):\r
294 #rprt('%r.__xor__%r\n' % (self, (otherseq,) + rest))\r
295 if type(otherseq) != type(self):\r
296 otherseq = apply(bitvec, (otherseq, ) + rest)\r
297 #sequence is now of our own type\r
298 return BitVec(self._data ^ otherseq._data, \\r
299 max(self._len, otherseq._len))\r
300\r
301\r
302 def __or__(self, otherseq, *rest):\r
303 #rprt('%r.__or__%r\n' % (self, (otherseq,) + rest))\r
304 if type(otherseq) != type(self):\r
305 otherseq = apply(bitvec, (otherseq, ) + rest)\r
306 #sequence is now of our own type\r
307 return BitVec(self._data | otherseq._data, \\r
308 max(self._len, otherseq._len))\r
309\r
310\r
311 def __invert__(self):\r
312 #rprt('%r.__invert__()\n' % (self,))\r
313 return BitVec(~self._data & ((1L << self._len) - 1), \\r
314 self._len)\r
315\r
316 def __coerce__(self, otherseq, *rest):\r
317 #needed for *some* of the arithmetic operations\r
318 #rprt('%r.__coerce__%r\n' % (self, (otherseq,) + rest))\r
319 if type(otherseq) != type(self):\r
320 otherseq = apply(bitvec, (otherseq, ) + rest)\r
321 return self, otherseq\r
322\r
323 def __int__(self):\r
324 return int(self._data)\r
325\r
326 def __long__(self):\r
327 return long(self._data)\r
328\r
329 def __float__(self):\r
330 return float(self._data)\r
331\r
332\r
333bitvec = BitVec\r