def descr_int(self, space): # TODO index = self.nbits - 1 bigval = self.bigval wordpos = index / SHIFT if wordpos > bigval.numdigits( ): # msb must be zero, number is positive return self.descr_uint(space) bitpos = index - wordpos * SHIFT word = bigval.digit(wordpos) msb = (word >> bitpos) & 1 if not msb: return newlong(space, bigval) # calculate self.nbits's index bitpos += 1 if bitpos == SHIFT: wordpos += 1 bitpos = 0 # manually assemble (1 << (index+1)) shift = rbigint([NULLDIGIT] * wordpos + [_store_digit(1 << bitpos)], 1, wordpos + 1) res = bigval.sub(shift) return newlong(space, res)
def test__kmul_split(self): split = 5 diglo = [0] * split dighi = [lobj.MASK] * split f1 = bigint(diglo + dighi, 1) hi, lo = lobj._kmul_split(f1, split) assert lo._digits == [_store_digit(0)] assert hi._digits == map(_store_digit, dighi)
def _rbigint_setidx(value, index, other): size = value.numdigits() wordpos = index / SHIFT if wordpos >= size: if not other: return value bitpos = index - wordpos * SHIFT shift = 1 << bitpos return rbigint( value._digits[:size] + \ [NULLDIGIT]*(wordpos-size) + \ [_store_digit(shift)], 1, wordpos + 1 ) # wordpos < size digit = value.digit(wordpos) bitpos = index - wordpos * SHIFT shift = 1 << bitpos if other == 1: if digit & shift: # already 1 return value # the value is changed ret = rbigint(value._digits[:size], 1, size) ret.setdigit(wordpos, digit | shift) return ret # other == 0 if not (digit & shift): # already 0 return value # the value is changed digit ^= shift if digit == 0 and wordpos == size - 1: assert wordpos >= 0 return rbigint(value._digits[:wordpos] + [NULLDIGIT], 1, wordpos) ret = rbigint(value._digits[:size], 1, size) ret.setdigit(wordpos, digit) return ret
def read_bytearray_bits_impl(space, w_arr, w_addr, w_nbytes): # We directly manipulate bytearray here assert isinstance(w_arr, W_BytearrayObject) ba_data = w_arr._data ba_len = len(ba_data) ba_offset = w_arr._offset nbytes = 0 if isinstance(w_nbytes, W_SmallBits): nbytes = w_nbytes.intval elif type(w_nbytes) is W_IntObject: nbytes = w_nbytes.intval elif isinstance(w_nbytes, W_BigBits): tmp = w_nbytes.bigval if tmp.numdigits() > 1: raise oefmt(space.w_ValueError, "nbytes [%s] too big for bytearray read Bits%d", rbigint.str(tmp), w_nbytes.nbits) nbytes = tmp.digit(0) elif type(w_nbytes) is W_LongObject: nbytes = w_nbytes.num.toint() else: raise oefmt(space.w_TypeError, "Please pass in int/Bits") addr = 0 if isinstance(w_addr, W_SmallBits): addr = w_addr.intval elif type(w_addr) is W_IntObject: addr = w_addr.intval elif isinstance(w_addr, W_BigBits): tmp = w_addr.bigval if tmp.numdigits() > 1: raise oefmt(space.w_ValueError, "Index [%s] too big for bytearray read Bits%d", rbigint.str(tmp), w_addr.nbits) addr = tmp.digit(0) elif type(w_addr) is W_LongObject: addr = w_addr.num.toint() else: raise oefmt(space.w_TypeError, "Please pass in int/Bits") if addr < 0: raise oefmt(space.w_ValueError, "read_bytearray_bits only accept positive addr.") begin = addr + ba_offset end = begin + nbytes if end > ba_len: raise OperationError(space.w_IndexError, space.newtext("bytearray index out of range")) if nbytes < 8: intval = 0 while end > begin: end -= 1 intval = (intval << 8) + ord(ba_data[end]) return W_SmallBits(nbytes << 3, intval) else: digits = [] current_word = 0 bitstart = 0 while begin < end: item = ord(ba_data[begin]) bitend = bitstart + 8 if bitend <= SHIFT: # we are good current_word |= item << bitstart bitstart = bitend else: bitend -= SHIFT this_nbits = 8 - bitend current_word |= (item & get_int_mask(this_nbits)) << bitstart digits.append(_store_digit(current_word)) current_word = item >> this_nbits bitstart = 8 - this_nbits begin += 1 digits.append(_store_digit(current_word)) bigval = rbigint(digits[:], sign=1) # 1 is positive!!! bigval._normalize() return W_BigBits(nbytes << 3, bigval)
def setitem_long_int_helper(value, other, start, stop): vsize = value.numdigits() if other < 0: slice_nbits = stop - start if slice_nbits < SHIFT: other &= get_int_mask(slice_nbits) else: tmp = get_long_mask(slice_nbits).int_and_(other) return setitem_long_long_helper(value, tmp, start, stop) # wordstart must < wordstop wordstart = start / SHIFT bitstart = start - wordstart * SHIFT # vsize <= wordstart < wordstop, concatenate if wordstart >= vsize: if not other: return value # if other is zero, do nothing if not bitstart: # aha, not chopped into two parts return rbigint( value._digits[:vsize] + \ [NULLDIGIT]*(wordstart-vsize) + \ [_store_digit(other)], 1, wordstart+1 ) # split into two parts lo = SHIFT - bitstart val1 = other & get_int_mask(lo) if val1 == other: # aha, the higher part is zero return rbigint( value._digits[:vsize] + \ [NULLDIGIT]*(wordstart-vsize) + \ [_store_digit(val1 << bitstart)], 1, wordstart+1 ) return rbigint( value._digits[:vsize] + \ [NULLDIGIT]*(wordstart-vsize) + \ [_store_digit(val1 << bitstart)] + \ [_store_digit(other >> lo)], 1, wordstart+2 ) wordstop = stop / SHIFT bitstop = stop - wordstop * SHIFT # (wordstart <=) wordstop < vsize if wordstop < vsize: ret = rbigint(value._digits[:vsize], 1, vsize) maskstop = get_int_mask(bitstop) valstop = ret.digit(wordstop) if wordstop == wordstart: # valstop is ret.digit(wordstart) valuemask = ~(maskstop - get_int_mask(bitstart)) ret.setdigit(wordstop, (valstop & valuemask) | (other << bitstart)) # span multiple words # wordstart < wordstop else: # do start if not bitstart: ret.setdigit(wordstart, other) i = wordstart + 1 while i < wordstop: ret._digits[i] = NULLDIGIT i += 1 ret.setdigit(wordstop, valstop & ~maskstop) else: lo = SHIFT - bitstart val1 = other & get_int_mask(lo) word = (ret.digit(wordstart) & get_int_mask(bitstart)) | (val1 << bitstart) ret.setdigit(wordstart, word) val2 = other >> lo i = wordstart + 1 if i == wordstop: ret.setdigit(i, val2 | (valstop & ~maskstop)) else: # i < wordstop ret.setdigit(i, val2) i += 1 while i < wordstop: ret._digits[i] = NULLDIGIT i += 1 ret.setdigit(wordstop, valstop & ~maskstop) ret._normalize() return ret # wordstart < vsize <= wordstop, highest bits will be cleared newsize = wordstart + 2 # assert wordstart >= 0 ret = rbigint( value._digits[:wordstart] + \ [NULLDIGIT, NULLDIGIT], 1, newsize ) bitstart = start - wordstart * SHIFT if not bitstart: ret.setdigit(wordstart, other) else: lo = SHIFT - bitstart val1 = other & get_int_mask(lo) word = (value.digit(wordstart) & get_int_mask(bitstart)) | (val1 << bitstart) ret.setdigit(wordstart, word) if val1 != other: ret.setdigit(wordstart + 1, other >> lo) ret._normalize() return ret