def test_endian(self): for endian in 'big', 'little': a = zeros(1, endian) self.assertEqual(a, bitarray('0')) self.assertEqual(a.endian(), endian) a = zeros(1, endian=endian) self.assertEqual(a, bitarray('0')) self.assertEqual(a.endian(), endian)
def is_global(white_constraint, black_constraint, white_degree, black_degree): #V.a, V.b if(white_constraint[0] == 1 and white_constraint[white_degree] == 1 and white_constraint[1:white_degree] == util.zeros(white_degree-1) and\ black_degree == 2 and black_constraint == bitarray('010')): return True #VI.a VI.b if (white_constraint[:white_degree - 1] == util.zeros(white_degree - 1) and white_constraint[white_degree - 1] == 1 and black_constraint[1] == 1 and black_constraint[2:] == util.zeros(black_degree - 1)): return True return False
def test_zeros(self): for n in range(10): for mode in 'left', 'right', 'both': a = zeros(n) c = strip(a, mode) self.assertIsType(c, 'bitarray') self.assertEqual(c, bitarray()) self.assertEqual(a, zeros(n)) b = frozenbitarray(a) c = strip(b, mode) self.assertIsType(c, 'frozenbitarray') self.assertEqual(c, bitarray())
def constraints_to_bitvector_tuple(white_constraint, black_constraint, alphabet, white_degree, black_degree): if not len(alphabet) < 3: print("Error, the constraints have more than 2 labels") return white = util.zeros(white_degree + 1) black = util.zeros(black_degree + 1) label = list(alphabet)[0] for configuration in white_constraint: white[configuration[label]] = 1 for configuration in black_constraint: black[configuration[label]] = 1 return (white, black)
def __mergedata(cls, n, c, side): """Merge the data of two nodes, ``n`` and ``c``. Args: n (`BitstreamSegmentTree._Node`): Node that remains after the merge c (`BitstreamSegmentTree._Node`): Node to be merged side (``0`` or ``1``): ``0`` for left, ``1`` for right """ if side == cls._Node.L: n.data = c.data + zeros(n.low - c.high, endian='little') + n.data else: n.data = n.data + zeros(c.low - n.high, endian='little') + c.data n.interval[side] = c.interval[side]
def test_bitwise_inplace(self): for a in self.randombitarrays(start=1): b = urandom(len(a), a.endian()) bb = b.copy() i = ba2int(a) j = ba2int(b) c = a.copy() c &= b self.assertEqual(ba2int(c), i & j) c = a.copy() c |= b self.assertEqual(ba2int(c), i | j) c = a.copy() c ^= b self.assertEqual(ba2int(c), i ^ j) self.assertEQUAL(b, bb) n = randint(0, len(a)) if a.endian() == 'big': c = a.copy() c >>= n self.assertEqual(ba2int(c), i >> n) c = zeros(len(a)) + a c <<= n self.assertEqual(ba2int(c), i << n)
def uint_to_bitarray(number, size): a = util.int2ba(number, signed=False) add = size - len(a) z = util.zeros(add) for x in a: z.append(x) return z
def test_1(self): for default_endian in 'big', 'little': _set_default_endian(default_endian) a = zeros(0) self.assertEqual(a, bitarray()) self.assertEqual(a.endian(), default_endian) b = zeros(0, endian=None) self.assertEqual(b.endian(), default_endian) for n in range(100): a = zeros(n) self.assertEqual(a, bitarray(n * '0')) for endian in 'big', 'little': a = zeros(3, endian) self.assertEqual(a, bitarray('000')) self.assertEqual(a.endian(), endian)
def SimpleSegSiev(n, Delta, M): S = zeros(Delta + 1) S.setall(True) if n <= 2: S[0:2 - n] = False # Set 0 1 to false if present Primes = SimpleSiev(M) # Get list of primes up to M for p in Primes.itersearch(bitarray('1')): S[max(-(n // -p), 2) * p - n::p] = False # Set multiples of p to false return S
def SimpleSiev(N): P = zeros(N + 1) # Create bitarray of zeros representing numbers 0 to N P[2] = True # Set 2 to True P[3::2] = True # Set odd numbers >1 to True for num in range(3, int(sqrt(N)) + 1, 2): if P[num]: P[num * num::2 * num] = False return P
def test_zeros_and_ones(self): for endian in 'little', 'big': for n in range(100): a = zeros(n, endian) s = serialize(a) self.assertEqual(s[1:], b'\0' * bits2bytes(n)) self.assertEQUAL(a, deserialize(s)) a.setall(1) self.assertEQUAL(a, deserialize(serialize(a)))
def test_init(self): a = zeros(0) self.assertEqual(a, bitarray('')) self.assertEqual(a.endian(), 'big') self.assertRaises(TypeError, zeros, 1.0) for n in range(100): a = zeros(n) self.assertEqual(a, bitarray(n * '0')) self.assertRaises(TypeError, zeros) # no argument # wrong arguments self.assertRaises(TypeError, zeros, '') self.assertRaises(TypeError, zeros, bitarray()) self.assertRaises(TypeError, zeros, []) self.assertRaises(ValueError, zeros, -1) self.assertRaises(TypeError, zeros, 0, 1) # endian not string self.assertRaises(ValueError, zeros, 0, 'foo') # endian wrong string
def check_round_trip(self, i): for endian in 'big', 'little': a = int2ba(i, endian=endian) self.assertEqual(a.endian(), endian) self.assertTrue(len(a) > 0) # ensure we have no leading zeros if a.endian == 'big': self.assertTrue(len(a) == 1 or a.index(1) == 0) self.assertEqual(ba2int(a), i) if i > 0 and sys.version_info[:2] >= (2, 7): self.assertEqual(i.bit_length(), len(a)) # add a few / trailing leading zeros to bitarray if endian == 'big': a = zeros(randint(0, 3), endian) + a else: a = a + zeros(randint(0, 3), endian) self.assertEqual(a.endian(), endian) self.assertEqual(ba2int(a), i)
def SimpleSegSiev(n, Delta, M): S = zeros(Delta + 1) S.setall(True) if n <= 1: S[0:2 - n] = False # Set 0 1 to false if present Primes = SimpleSiev(M) # Get list of primes up to M for p in range(2, M + 1): # Iterate through primes up to M if Primes[p]: S[max(-(n // -p), 2) * p - n::p] = False # Set multiples of p to false return S
def SimpleSiev(N): P = zeros(N + 1) # Create bitarray of zeros representing numbers 0 to N P[2] = True # Set 2 to True P[3::2] = True # Set odd numbers >1 to True num = 3 # Start at 3 mult = 9 # Start with (multiple of num) = num^2 while mult <= N: if P[num]: # If number is prime P[mult::2 * num] = False # Set its odd multiples to False num = num + 2 # Go to next odd number mult = num * num # This seems to be faster than num**2 return P
def test_basic(self): for default_endian in 'big', 'little': _set_default_endian(default_endian) a = zeros(0) self.assertEqual(a, bitarray()) self.assertEqual(a.endian(), default_endian) a = zeros(0, endian=None) self.assertEqual(len(a), 0) self.assertEqual(a.endian(), default_endian) for n in range(100): a = zeros(n) self.assertEqual(len(a), n) self.assertFalse(a.any()) self.assertEqual(a.count(1), 0) self.assertEqual(a, bitarray(n * '0')) for endian in 'big', 'little': a = zeros(3, endian) self.assertEqual(a, bitarray('000')) self.assertEqual(a.endian(), endian)
def SegSieveList(n, Delta): M = int(sqrt(n + Delta)) S = zeros(Delta + 1) S.setall(True) if n <= 2: S[0:2 - n] = False D_s = int(sqrt(M)) L = readInPrimes("primes1BILL", M + 1) for M_s in range(1, M + 1, D_s + 1): for p in L[M_s:M_s + D_s].itersearch(bitarray('1')): p = p + M_s S[max(-(n // -p), 2) * p - n::p] = False return S
def SubSegSiev(n, Delta, M): S = zeros(Delta + 1) S.setall(True) S[0:2 - n] = False # Set numbers 0 and 1 to false if present D_s = int(sqrt(M)) # Size of each segment (-1) for M_s in range(1, M + 1, D_s + 1): # Iterate through segments Primes = SimpleSegSiev(M_s, D_s, int(sqrt(M_s + D_s))) # Get primes in segment # Primes = SimpleSegSiev(M_s, min(M-M_s, D_s), int(sqrt((M_s+D_s)) # Get primes in segment for p in Primes.itersearch(bitarray('1')): p = p + M_s S[max(-(n // -p), 2) * p - n::p] = False return S
def test_invalid_bytes(self): self.assertRaises(ValueError, deserialize, b'') for i in range(256): b = bytes(bytearray([i])) if i == 0 or i == 16: self.assertEqual(deserialize(b), bitarray()) else: self.assertRaises(ValueError, deserialize, b) b += b'\0' if i < 32 and i % 16 < 8: self.assertEqual(deserialize(b), zeros(8 - i % 8)) else: self.assertRaises(ValueError, deserialize, b)
def SubSegSiev(n, Delta, M): S = zeros(Delta + 1) S.setall(True) if n <= 1: S[0:2 - n] = False # Set numbers 0 and 1 to false if present D_s = floor(sqrt(M)) # Size of each segment (-1) M = floor(M) # Needed since range only takes ints for M_s in range(1, M + 1, D_s + 1): # Iterate through segments Primes = SimpleSegSiev(M_s, D_s, floor(sqrt(M_s + D_s))) # Get primes in segment for p in range(M_s, min(M, M_s + D_s) + 1): # Iterate through segment if Primes[p - M_s]: # if p-M_s is prime S[max(-(n // -p), 2) * p - n::p] = False # Set multiples of p to false return S
def is_unsolvable(white_constraint, black_constraint, white_degree, black_degree): #I.a, I.c if (white_constraint[0] == 1 and not white_constraint[1:].any() and black_constraint[0] == 0): return True #I.b, I.d expected_white_constraint = util.zeros(white_degree + 1) expected_white_constraint[white_degree] = 1 if (white_constraint == expected_white_constraint and black_constraint[black_degree] == 0): return True #II.a, II.b if (not white_constraint.any()): return True return False
def test_bitwise(self): for a in self.randombitarrays(start=1): b = urandom(len(a), a.endian()) aa = a.copy() bb = b.copy() i = ba2int(a) j = ba2int(b) self.assertEqual(ba2int(a & b), i & j) self.assertEqual(ba2int(a | b), i | j) self.assertEqual(ba2int(a ^ b), i ^ j) n = randint(0, len(a)) if a.endian() == 'big': self.assertEqual(ba2int(a >> n), i >> n) c = zeros(len(a)) + a self.assertEqual(ba2int(c << n), i << n) self.assertEQUAL(a, aa) self.assertEQUAL(b, bb)
def __init__(self, width: int = 64, height: int = 32, wrap: bool = False): """ Create a VideoRam instance. If wrap is true, any pixels drawn off the edge of the screen will get wrapped to the start of the screen. :param width: video display size in pixels :param height: video display size in pixels :param wrap: whether to wrap out-of-bounds drawing to the other side """ if width < 1 or height < 1: raise ValueError("Video memory dimensions must be at least 1px") self.width = width self.height = height self.wrap = wrap # Note that the endian argument here is *bit* endianness specifying # bit order, not the byte endianess you normally see. See the bitarray # documentation for more details. self.pixels = ba_util.zeros(width * height, endian='big')
def all_perm(n, k, endian=None): """all_perm(n, k, endian=None) -> iterator Return an iterator over all bitarrays of length `n` with `k` bits set to 1 in lexicographical order. """ n = int(n) if n < 0: raise ValueError("length must be >= 0") k = int(k) if k < 0 or k > n: raise ValueError("number of set bits must be in range(0, n + 1)") if k == 0: yield zeros(n, endian) return v = (1 << k) - 1 for _ in range(binomial(n, k)): yield int2ba(v, length=n, endian=get_default_endian() if endian is None else endian) t = (v | (v - 1)) + 1 v = t | ((((t & -t) // (v & -v)) >> 1) - 1)
def QUADRANT_0(ba): if ba == zeros(16): # illegal instructions are all 0s return RVInstruction(rv_name="illegal", rv_size=16) f3 = fp.getCFunct3(ba) if f3 == bitarray("000"): # C.ADDI4SPN data = fp.parseCIW(ba) imm = data["imm"] return RVInstruction( rv_format="CIW", rv_src_registers=["x2"], rv_dest_registers=[data["rd_pop"]], rv_immediates=[ fp.immToInt(imm[2:6] + imm[:2] + bitarray([imm[-1]]) + bitarray([imm[-2]])) * 4 ], rv_name="c.addi4spn", rv_size=16, rv_binary=ba, ) elif f3 == bitarray("001"): # C.FLD, not implemented pass elif f3 == bitarray("010"): # C.LW data = fp.parseCL(ba) imm3 = data["imm3"] imm2 = data["imm2"] return RVInstruction( rv_format="CL", rv_src_registers=[data["rs1_pop"]], rv_dest_registers=[data["rd_pop"]], rv_immediates=[ fp.immToInt( bitarray([imm2[1]]) + imm3 + bitarray([imm2[0]])) * 4 ], rv_name="c.lw", rv_size=16, rv_binary=ba, ) elif f3 == bitarray("011"): # C.FLW, not implemented pass elif f3 == bitarray("100"): return RVInstruction(rv_name="reserved", rv_size=16) elif f3 == bitarray("101"): # C.FSD, not implemented pass elif f3 == bitarray("110"): # C.SW data = fp.parseCS(ba) imm3 = data["imm3"] imm2 = data["imm2"] return RVInstruction( rv_format="CS", rv_src_registers=[data["rs1_pop"], data["rs2_pop"]], rv_immediates=[ fp.immToInt( bitarray([imm2[1]]) + imm3 + bitarray([imm2[0]])) * 4 ], rv_name="c.sw", rv_size=16, rv_binary=ba, ) elif f3 == bitarray("111"): # C.FSW, not implemented pass
def QUADRANT_2(ba): f3 = fp.getCFunct3(ba) if f3 == bitarray("000"): # C.SLLI data = fp.parseCI(ba) imm = data["imm1"] + data["imm5"] return RVInstruction( rv_format="CI", rv_src_registers=[data["register"]], rv_dest_registers=[data["register"]], rv_immediates=[fp.immToInt(imm)], rv_name="c.slli", rv_size=16, rv_binary=ba, ) elif f3 == bitarray("001"): # C.FLDSP, not implemented here pass elif f3 == bitarray("010"): # C.LWSP data = fp.parseCI(ba) imm1 = data["imm1"] imm5 = data["imm5"] imm = imm5[3:] + imm1 + imm5[:3] + zeros(2) return RVInstruction( rv_format="CI", rv_src_registers=["x2"], rv_dest_registers=[data["register"]], rv_immediates=[fp.immToInt(imm)], rv_name="c.lwsp", rv_size=16, rv_binary=ba, ) elif f3 == bitarray("011"): # C.FLWSP, not implemented here pass elif f3 == bitarray("100"): # C.JR, C.MV, C.EBREAK, C.JALR, and C.ADD bit12 = bitarray([ba[-13]]) data = fp.parseCR(ba) # all of these are CR format if bit12 == bitarray("0"): # C.JR or C.MV if data["rs2"] == "x0": # C.JR return RVInstruction( rv_format="CR", rv_src_registers=[data["register"]], rv_name="c.jr", rv_size=16, rv_binary=ba, ) else: # C.MV return RVInstruction( rv_format="CR", rv_src_registers=[data["rs2"]], rv_dest_registers=[data["register"]], rv_name="c.mv", rv_size=16, rv_binary=ba, ) else: # C.EBREAK, C.JALR, and C.ADD if data["rs2"] == "x0" and data["register"] == "x0": # C.EBREAK return RVInstruction( rv_format="CR", rv_name="c.ebreak", rv_size=16, rv_binary=ba, ) elif data["rs2"] == "x0": # C.JALR return RVInstruction( rv_format="CR", rv_src_registers=[data["register"]], rv_dest_registers=["x1"], rv_name="c.jalr", rv_size=16, rv_binary=ba, ) else: # C.ADD return RVInstruction( rv_format="CR", rv_src_registers=[data["register"], data["rs2"]], rv_dest_registers=[data["register"]], rv_name="c.add", rv_size=16, rv_binary=ba, ) elif f3 == bitarray("101"): # C.FSDSP, not implemented here pass elif f3 == bitarray("110"): # C.SWSP data = fp.parseCSS(ba) imm = data["imm"] offset = fp.immToInt(imm[4:] + imm[:4] + zeros(2)) return RVInstruction( rv_format="CR", rv_src_registers=[data["rs2"]], rv_immediates=[offset], rv_name="c.swsp", rv_size=16, rv_binary=ba, ) elif f3 == bitarray("111"): # C.FSWSP, not implemented here pass
def QUADRANT_1(ba): f3 = fp.getCFunct3(ba) if f3 == bitarray("000"): # C.NOP or C.ADDI data = fp.parseCI(ba) imm = data["imm1"] + data["imm5"] if data["register"] == zeros(5): # C.NOP return RVInstruction( rv_format="CI", rv_immediates=[fp.immToInt(imm)], rv_name="c.nop", rv_size=16, rv_binary=ba, ) else: # C.ADDI return RVInstruction( rv_format="CI", # rv_src_registers=[data["register"]], # does not show up in output rv_dest_registers=[data["register"]], rv_immediates=[fp.immToInt(imm)], rv_name="c.addi", rv_size=16, rv_binary=ba, ) elif f3 == bitarray("001"): # C.JAL data = fp.parseCJ(ba) jump_t = data["jump_target"] imm = ( bitarray([jump_t[0]]) # 11 + bitarray([jump_t[4]]) # 10 + jump_t[2:4] # 9:8 + bitarray([jump_t[6]]) # 7 + bitarray([jump_t[5]]) # 6 + bitarray([jump_t[10]]) # 5 + bitarray([jump_t[1]]) # 4 + jump_t[7:10] # 3:1 + bitarray("0") # 0, as it is left shifted 2 ) return RVInstruction( rv_format="CJ", rv_dest_registers=["x1"], rv_immediates=[fp.immToInt(imm)], rv_name="c.jal", rv_size=16, rv_binary=ba, ) elif f3 == bitarray("010"): # C.LI data = fp.parseCI(ba) imm = data["imm1"] + data["imm5"] if data["register"] == "x0": # TODO something with HINT? pass return RVInstruction( rv_format="CI", rv_dest_registers=[data["register"]], rv_immediates=[fp.immToInt(imm)], rv_name="c.li", rv_size=16, rv_binary=ba, ) elif f3 == bitarray("011"): # C.ADDI16SP or C.LUI data = fp.parseCI(ba) imm1 = data["imm1"] imm5 = data["imm5"] if data["register"] == "x2": # C.ADDI16SP nzimm = (imm1 + imm5[2:4] + bitarray([imm5[1]]) + bitarray([imm5[4]]) + bitarray([imm5[0]])) return RVInstruction( rv_format="CI", rv_src_registers=["x2"], rv_dest_registers=[data["register"]], rv_immediates=[fp.immToInt(nzimm) * 16 ], # left shift by 4 (multiplying by 16) rv_name="c.addi16sp", rv_size=16, rv_binary=ba, ) else: # C.LUI nzimm = imm1 + imm5 + zeros(12) imm = fp.immToInt(nzimm) if data["register"] == "x0": raise Exception( "C.LUI cannot have a destination register of x0") if imm == 0: return RVInstruction(rv_name="reserved", rv_size=16) return RVInstruction( rv_format="CI", rv_dest_registers=[data["register"]], rv_immediates=[imm], rv_name="c.lui", rv_size=16, rv_binary=ba, ) elif f3 == bitarray("100"): # C.SRLI, C.SRAI, C.ANDI, C.SUB, C.XOR, C.OR, C.AND f2 = ba[-12:-10] if f2 == bitarray("00"): # C.SRLI data = fp.parseCB(ba) if data["offset3"][0] == "1": # TODO? reserved for custom instructions return RVInstruction(rv_name="reserved", rv_size=16) shamt = bitarray([data["offset3"][0]]) + data["offset5"] return RVInstruction( rv_format="CB", rv_src_registers=[data["rs1_pop"]], rv_dest_registers=[data["rs1_pop"]], rv_immediates=[fp.immToInt(shamt)], rv_name="c.srli", rv_size=16, rv_binary=ba, ) elif f2 == bitarray("01"): # C.SRAI data = fp.parseCB(ba) if data["offset3"][0] == "1": # TODO? reserved for custom instructions return RVInstruction(rv_name="reserved", rv_size=16) shamt = bitarray([data["offset3"][0]]) + data["offset5"] return RVInstruction( rv_format="CB", rv_src_registers=[data["rs1_pop"]], rv_dest_registers=[data["rs1_pop"]], rv_immediates=[fp.immToInt(shamt)], rv_name="c.srai", rv_size=16, rv_binary=ba, ) elif f2 == bitarray("10"): # C.ANDI data = fp.parseCB(ba) imm = bitarray([data["offset3"][0]]) + data["offset5"] return RVInstruction( rv_format="CB", rv_src_registers=[data["rs1_pop"]], rv_dest_registers=[data["rs1_pop"]], rv_immediates=[fp.immToInt(imm)], rv_name="c.andi", rv_size=16, rv_binary=ba, ) elif f2 == bitarray("11"): # C.SUB, C.XOR, C.OR, and C.AND data = fp.parseCA(ba) funct2 = fp.getCFunct2(ba) name = "" if funct2 == bitarray("00"): # C.SUB name = "c.sub" elif funct2 == bitarray("01"): # C.XOR name = "c.xor" elif funct2 == bitarray("10"): # C.OR name = "c.or" elif funct2 == bitarray("11"): # C.AND name = "c.and" return RVInstruction( rv_format="CA", rv_src_registers=[data["register_pop"], data["rs2_pop"]], rv_dest_registers=[data["register_pop"]], rv_name=name, rv_size=16, rv_binary=ba, ) elif f3 == bitarray("101"): # C.J data = fp.parseCJ(ba) jump_t = data["jump_target"] # same format as C.JAL imm = ( bitarray([jump_t[0]]) # 11 + bitarray([jump_t[4]]) # 10 + jump_t[2:4] # 9:8 + bitarray([jump_t[6]]) # 7 + bitarray([jump_t[5]]) # 6 + bitarray([jump_t[10]]) # 5 + bitarray([jump_t[1]]) # 4 + jump_t[7:10] # 3:1 + bitarray("0") # 0, as it is left shifted 2 ) return RVInstruction( rv_format="CJ", rv_dest_registers=["x0"], rv_immediates=[fp.immToInt(imm)], rv_name="c.j", rv_size=16, rv_binary=ba, ) elif f3 == bitarray("110"): # C.BEQZ data = fp.parseCB(ba) offset3 = data["offset3"] offset5 = data["offset5"] offset = (bitarray([offset3[0]]) + offset5[:2] + bitarray([offset5[4]]) + offset3[1:] + offset5[2:4] + bitarray("0")) return RVInstruction( rv_format="CB", rv_src_registers=[data["rs1_pop"]], rv_immediates=[fp.immToInt(offset)], rv_name="c.beqz", rv_size=16, rv_binary=ba, ) elif f3 == bitarray("111"): # C.BNEZ data = fp.parseCB(ba) offset3 = data["offset3"] offset5 = data["offset5"] offset = (bitarray([offset3[0]]) + offset5[:2] + bitarray([offset5[4]]) + offset3[1:] + offset5[2:4] + bitarray("0")) return RVInstruction( rv_format="CB", rv_src_registers=[data["rs1_pop"]], rv_immediates=[fp.immToInt(offset)], rv_name="c.bnez", rv_size=16, rv_binary=ba, )
def set_data(self, low, high, data): """Set ``data`` to the specified interval. Args: low (:obj:`int`): high (:obj:`int`): data (`bitarray`_): Little-endian, ``high - low`` -bits bitarray. .. _bitarray: https://pypi.org/project/bitarray/ """ if self.root is None: self.root = self._Node(low, high, data) return # Adding interval might cause merges, and the post-removal fixes might change tree structure, so we have to do # it in a loop while True: r, p, side = self.root, None, None while r: if high + self._min_gap < r.low: r, p, side = r.left, r, self._Node.L elif r.high + self._min_gap < low: r, p, side = r.right, r, self._Node.R else: break if r is None: self.__insert(self._Node(low, high, data), p, side) return # ``r`` is out temporary root now, possibly need to merge subtree # for quickly get out of the nested loop, use try-except try: for d in (self._Node.L, self._Node.R): c, p = r.children[d], r while c: if ((d == self._Node.L and c.high + self._min_gap < low) or (d == self._Node.R and c.low - self._min_gap > high)): c, p = c.children[1 - d], c else: # merge the subtree of c self.__merge(c, 1 - d) # update r self.__mergedata(r, c, d) # connect c.child (at most one remaining) to c.parent (p) side = c.side l = p.children[side] = c.children[d] if l is not None: l.parent = p # fix color if c.is_red: # removing a red node is always harmless pass elif l is not None and l.is_red: # promote ``l` from red to black, compensating the loss of ``c`` l.is_black = True elif self.__postremoval_fix(p, side, r): # ``r`` is moved after the fix. we need to restart the search from root raise StopIteration # jump out of the for-while nested loops # terminate if we've covered the interval if ((d == self._Node.L and r.low + self._min_gap <= low) or (d == self._Node.R and r.high - self._min_gap >= high)): break # continue the while loop c, p = l, p except StopIteration: continue # done merging # set data lower, upper = min(r.low, low), max(r.high, high) newdata = zeros(upper - lower, endian='little') newdata[r.low - lower:r.high - lower] = r.data newdata[low - lower:high - lower] = data r.data = newdata r.interval = [lower, upper] return
def crossbar(cls, N, M, connectivity, *, n_util=None): """Generate ``(n, m)`` pairs so that each ``m`` is paired with ``connectivity`` ``n`` s. The goal is that each ``n`` is paired with about the same number of ``m`` s \(fairness\), while each ``m`` is paired with a different composition of ``n`` s \(diversity\). Args: N (:obj:`int`): M (:obj:`int`): connectivity (:obj:`int`): Keyword Args: n_util (:obj:`Sequence` [:obj:`int` ]): carry-over state Yields: :obj:`tuple` [:obj:`int`, :obj:`int` ]: """ # special cases if connectivity == 0: return elif connectivity >= N: for p in product(range(N), range(M)): yield p return # general cases period_step = 1 / float(connectivity) # utilization of elements in N n_util = n_util or [0 for _ in range(N)] # period & phase combo search iterator ppit = cycle(product(reversed(range(N - connectivity + 1)), range(N))) # for each element in M for m in range(M): unassigned_left = sum(1 if util == 0 else 0 for util in n_util) # if the number of unused tracks happens to be equal to the tracks needed, we don't need to search # ATTENTION: this might affect our period-phase search.e.g. when N = 4, connectivity = 2, we would # expect the pattern to be alternating between 1010 and 0101. But if this short path is enabled, we # would get 1010, 0101, 0101, 1010, 1010 instead # if unassigned_left == connectivity: # # apply pattern # for n in range(len(n_util)): # if n_util[n] > 0: # n_util[n] -= 1 # else: # yield n, m # continue # search the best phase & period combo that maximizes the utilization of previously unused elements in N pat, max_unassigned = None, 0 unassigned_left = min(unassigned_left, connectivity) for period, phase in islice(ppit, (N - connectivity + 1) * N): pat_tmp = zeros(N) period_f = 1 + period * period_step fails = 0 for i in count(phase): idx = round(i * period_f) % N if pat_tmp[idx]: fails += 1 if fails == N: break else: pat_tmp[idx] = True if pat_tmp.count() == connectivity: break unassigned = sum(1 if n_util[i] == 0 and pat_tmp[i] else 0 for i in range(N)) if unassigned > max_unassigned: pat, max_unassigned = pat_tmp, unassigned if max_unassigned == unassigned_left: break # apply pattern for n, flag in enumerate(pat): if flag: yield n, m n_util[n] += 1 # update n_util while all(n_util): for n in range(len(n_util)): n_util[n] -= 1