def _PyLong_FromByteArray(space, bytes, n, little_endian, signed): little_endian = rffi.cast(lltype.Signed, little_endian) signed = rffi.cast(lltype.Signed, signed) result = rbigint() negative = False for i in range(0, n): if little_endian: c = intmask(bytes[i]) else: c = intmask(bytes[n - i - 1]) if i == 0 and signed and c & 0x80: negative = True if negative: c = c ^ 0xFF digit = rbigint.fromint(c) result = result.lshift(8) result = result.add(digit) if negative: result = result.neg() return space.newlong_from_rbigint(result)
def _rbigint_rshift(value, shamt): if not value.sign or not shamt.sign: return value if shamt.numdigits() > 1: return NULLRBIGINT shamt = shamt.digit(0) wordshift = shamt / SHIFT newsize = value.numdigits() - wordshift if newsize <= 0: return NULLRBIGINT loshift = shamt - wordshift * SHIFT hishift = SHIFT - loshift ret = rbigint([NULLDIGIT] * newsize, 1, newsize) i = 0 lastidx = newsize - 1 curword = value.digit(wordshift) while i < lastidx: newdigit = curword >> loshift wordshift = wordshift + 1 curword = value.digit(wordshift) ret.setdigit(i, newdigit | (curword << hishift)) i += 1 # last digit ret.setdigit(i, curword >> loshift) ret._normalize() return ret
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 __init__(self, itemlist): self.value = {} self.keys = [] i = 0 while i < len(itemlist): self.value[itemlist[i].str()] = itemlist[i + 1] self.keys.append(itemlist[i]) i += 2 a = rbigint() self.length = SodaInt(a.fromint(len(self.value)))
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 expression_normalizedarray(s): sourcepos = s[0].getsourcepos() package = fetcher.packages[sourcepos.idx] line = str(sourcepos.lineno) col = str(sourcepos.colno) lst = s[1].get() enumlist = [] a = rbigint() for i in range(0, len(lst)): enumlist.append(ast.Integer(a.fromint(i), package, line, col)) enumlist.append(lst[i]) enumlist.reverse() return ast.Array(enumlist, package, line, col)
def create_arrays(self, text): self.textarrays = [] chars, words, lines = [], [], [] wordbuffer, linebuffer = [], [] i, j, k = 0, 0, 0 a = rbigint() text, trash = str_decode_utf_8(text, len(text), "strict", True) for char in text: if char == " " and wordbuffer != []: word = u"".join(wordbuffer) words.append(SodaInt(a.fromint(j))) words.append(SodaString(word)) wordbuffer = [] j += 1 chars.append(SodaInt(a.fromint(i))) chars.append(SodaString(char)) linebuffer.append(char) i += 1 elif char == "\n" and linebuffer != []: line = u"".join(linebuffer) lines.append(SodaInt(a.fromint(k))) lines.append(SodaString(line)) linebuffer = [] k += 1 if not wordbuffer == []: word = u"".join(wordbuffer) words.append(SodaInt(a.fromint(j))) words.append(SodaString(word)) wordbuffer = [] j += 1 chars.append(SodaInt(a.fromint(i))) chars.append(SodaString(char)) i += 1 else: chars.append(SodaInt(a.fromint(i))) chars.append(SodaString(char)) wordbuffer.append(char) linebuffer.append(char) i += 1 if not wordbuffer == []: word = u"".join(wordbuffer) words.append(SodaInt(a.fromint(j))) words.append(SodaString(word)) if not linebuffer == []: line = u"".join(linebuffer) lines.append(SodaInt(a.fromint(k))) lines.append(SodaString(line)) self.textarrays.append(SodaArray(chars)) self.textarrays.append(SodaArray(words)) self.textarrays.append(SodaArray(lines))
def number_number(s): sourcepos = s[0].getsourcepos() package = fetcher.packages[sourcepos.idx] line = str(sourcepos.lineno) col = str(sourcepos.colno) try: a = rbigint() return ast.Integer(a.fromstr(s[0].getstr()), package, line, col) except Exception: package = fetcher.packages[s[0].getsourcepos().idx] line = str(s[0].getsourcepos().lineno) col = str(s[0].getsourcepos().colno) msg = "error in number %s" % s[0].getstr() sodaError(package, line, col, msg)
def evaluate_args(self, argstack): argstack.reverse() if self.isvariadic: a = rbigint() enumlist = [] nargstack = [] j = 0 for i in range(self.arity - 1, len(argstack)): enumlist.append(SodaInt(a.fromint(j))) enumlist.append(argstack[i]) j += 1 for k in range(0, self.arity - 1): nargstack.append(argstack[k]) argstack = nargstack argstack.append(SodaArray(enumlist)) for i in range(0, len(self.compiler.constants)): self.constbuffer.append(self.compiler.constants[i]) if isinstance(self.compiler.constants[i], SodaDummy): self.compiler.constants[i] = argstack.pop()
def _rbigint_maskoff_high(value, masklen): if not value.sign: return value # assert value.sign > 0 lastword = (masklen - 1) / SHIFT masksize = lastword + 1 if masksize > value.numdigits(): return value assert masksize > 0 # tell the dumb translator # From now on 0 < masksize <= value.numdigits(), so lastword exists ret = rbigint(value._digits[:masksize], 1, masksize) # Here, if masklen % SHIFT == 0, then we don't need to mask the last # word because wordpos = masklen / SHIFT = masksize in this case maskbit = masklen % SHIFT if maskbit != 0: lastdigit = ret.digit(lastword) mask = get_int_mask(maskbit) if lastdigit >= mask: ret.setdigit(lastword, lastdigit & mask) ret._normalize() return ret
def _rbigint_rshift_maskoff(value, shamt, masklen): if not value.sign: return value # shamt must be > 0, value.sign must > 0 if shamt == 0: return _rbigint_maskoff_high(value, masklen) wordshift = shamt / SHIFT oldsize = value.numdigits() if oldsize <= wordshift: return NULLRBIGINT newsize = oldsize - wordshift masksize = (masklen - 1) / SHIFT + 1 retsize = min(newsize, masksize) loshift = shamt - wordshift * SHIFT hishift = SHIFT - loshift ret = rbigint([NULLDIGIT] * retsize, 1, retsize) i = 0 while i < retsize: newdigit = (value.digit(wordshift) >> loshift) if i + 1 < newsize: newdigit |= (value.digit(wordshift + 1) << hishift) ret.setdigit(i, newdigit) i += 1 wordshift += 1 if masksize <= retsize: maskbit = masklen % SHIFT if maskbit != 0: lastword = i - 1 lastdigit = ret.digit(lastword) mask = get_int_mask(maskbit) if lastdigit >= mask: ret.setdigit(lastword, lastdigit & mask) ret._normalize() return ret
def bigint(lst, sign): for digit in lst: assert digit & MASK == digit # wrongly written test! return rbigint(map(_store_digit, map(_mask_digit, lst)), sign)
def fromdecimalstr(s): return rbigint(s)
def fromint(i): return rbigint(i)
def __init__(self, value): assert isinstance(value, unicode) self.value = value a = rbigint() self.length = SodaInt(a.fromint(len(self.value)))
def toint(self): a = rbigint() number = a.fromstr(str(self.value.build())) return SodaInt(number)
def _rbigint_lshift_maskoff(value, shamt, masklen): if not value.sign or not shamt: return value if shamt >= masklen: return NULLRBIGINT assert shamt > 0 # shamt must > 0, value.sign must >= 0 wordshift = shamt // SHIFT remshift = shamt - wordshift * SHIFT oldsize = value.numdigits() maskbit = masklen % SHIFT masksize = (masklen - 1) / SHIFT + 1 if not remshift: retsize = min(oldsize + wordshift, masksize) ret = rbigint([NULLDIGIT] * retsize, 1, retsize) j = 0 while j < oldsize and wordshift < retsize: ret.setdigit(wordshift, value.digit(j)) wordshift += 1 j += 1 if wordshift == masksize and maskbit != 0: lastword = retsize - 1 ret.setdigit(lastword, ret.digit(lastword) & get_int_mask(maskbit)) ret._normalize() return ret newsize = oldsize + wordshift + 1 if masksize < newsize: retsize = masksize ret = rbigint([NULLDIGIT] * retsize, 1, retsize) accum = _widen_digit(0) j = 0 while j < oldsize and wordshift < retsize: accum += value.widedigit(j) << remshift ret.setdigit(wordshift, accum) accum >>= SHIFT wordshift += 1 j += 1 # no accum if maskbit != 0: lastword = retsize - 1 lastdigit = ret.digit(lastword) mask = get_int_mask(maskbit) if lastdigit >= mask: ret.setdigit(lastword, lastdigit & mask) ret._normalize() return ret # masksize >= newsize retsize = newsize ret = rbigint([NULLDIGIT] * retsize, 1, retsize) accum = _widen_digit(0) j = 0 while j < oldsize and wordshift < retsize: accum += value.widedigit(j) << remshift ret.setdigit(wordshift, accum) accum >>= SHIFT wordshift += 1 j += 1 if masksize == newsize and maskbit != 0: accum &= get_int_mask(maskbit) ret.setdigit(wordshift, accum) ret._normalize() return ret
def setval(self, idx, value): self.value[idx.str()] = value self.keys.append(idx) a = rbigint() self.length = SodaInt(a.fromint(len(self.value)))
# Date : March 10, 2020 from rpython.rlib import jit from rpython.rlib.rbigint import rbigint, SHIFT, NULLDIGIT, ONERBIGINT, \ NULLRBIGINT, _store_digit, _x_int_sub, \ _widen_digit, BASE16 BASE2 = '01' # NOTE that we should keep self.value positive after any computation: # - The sign of the rbigint field should always be one # - Always AND integer value with mask, never store any negative int # * Performing rbigint.and_/rbigint.int_and_ will turn sign back to 1 # - rbigint._normalize() can only be called in @jit.elidable funcs mask = rbigint([NULLDIGIT], 1, 1) LONG_MASKS = [mask] for i in xrange(1024): mask = mask.int_mul(2).int_add(1) LONG_MASKS.append(mask) def get_long_mask(i): return LONG_MASKS[i] get_long_mask._always_inline_ = True def get_long_lower(i): return LONG_MASKS[i - 1].int_add(1).neg()
def gcd(u, v): from rpython.rlib.rbigint import _v_isub, _v_rshift, SHIFT # binary gcd from https://en.wikipedia.org/wiki/Binary_GCD_algorithm if not u.tobool(): return v.abs() if not v.tobool(): return u.abs() # The result is negative iff both inputs have a common -1 factor if v.sign == -1 and u.sign == -1: sign = -1 else: sign = 1 if u.size == 1 and v.size == 1: result = gcd1(u.digit(0), v.digit(0)) return rbigint([result], sign, 1) # Compute the factors of 2 for u and v and record the number of # common 2 factors in shift. shiftu = count_trailing_zeros(u) shiftv = count_trailing_zeros(v) shift = min(shiftu, shiftv) # Perform shift on each number, but guarantee that we will end up with a new # digit array for each rbigint. They will be mutated if shiftu: u = u.rshift(shiftu, dont_invert=True) if u.sign == -1: u.sign = 1 else: u = rbigint(u._digits[:], 1, u.numdigits()) if shiftv: v = v.rshift(shiftv, dont_invert=True) if v.sign == -1: v.sign = 1 else: v = rbigint(v._digits[:], 1, v.numdigits()) # From here on, u is always odd. while True: if u.size == 1 and v.size == 1: digit = gcd1(u.digit(0), v.digit(0)) u = rbigint([digit], 1, 1) break # Now u and v are both odd. Swap if necessary so u <= v, # then set v = v - u (which is even). if u.gt(v): u, v, = v, u assert _v_isub(v, 0, v.numdigits(), u, u.numdigits()) == 0 v._normalize() if not v.tobool(): break # remove all factors of 2 in v -- they are not common # note: v is not zero, so while will terminate # XXX: Better to perform multiple inplace shifts, or one # shift which allocates a new array? rshift = count_trailing_zeros(v) while rshift >= SHIFT: assert _v_rshift(v, v, v.numdigits(), SHIFT - 1) == 0 rshift -= SHIFT - 1 assert _v_rshift(v, v, v.numdigits(), rshift) == 0 v._normalize() # restore common factors of 2 and sign result = u.lshift(shift) result.sign = sign return result
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
def setitem_long_long_helper(value, other, start, stop): if other.numdigits() <= 1: return setitem_long_int_helper(value, other.digit(0), start, stop) if other.sign < 0: other = other.and_(get_long_mask(stop - start)) if other.numdigits() == 1: return setitem_long_int_helper(value, other.digit(0), start, stop) vsize = value.numdigits() other = other.lshift(start) # lshift first to align two rbigints osize = other.numdigits() # After the two above checks, we have made sure other has more than one digit # assert osize >= 2 # assert wordstart < wordstop # Also, the caller must have already checked if bitwidth exceeds the slice # assert wordstart <= osize - 1 <= wordstop wordstart = start / SHIFT # 1. vsize <= wordstart < wordstop, concatenate if vsize <= wordstart: return rbigint(value._digits[:vsize] + other._digits[vsize:], 1, osize) bitstart = start - wordstart * SHIFT wordstop = stop / SHIFT # 2. wordstart < vsize <= wordstop, merge wordstart and concatenate if vsize <= wordstop: assert wordstart >= 0 ret = rbigint( value._digits[:wordstart] + \ other._digits[wordstart:osize], 1, osize ) # union start, there is no value in lower bits of other.digit(wordstart) if bitstart: value_lo = value.digit(wordstart) & get_int_mask(bitstart) # lo ret.setdigit(wordstart, value_lo | ret.digit(wordstart)) # lo | hi return ret # 3. wordstart < wordstop < vsize, handle both sides ret = rbigint(value._digits[:], 1, vsize) # union start, there is no value in lower bits of other.digit(wordstart) value_lo = ret.digit(wordstart) & get_int_mask(bitstart) # lo ret.setdigit(wordstart, value_lo | other.digit(wordstart)) # lo | hi # put other into i = wordstart + 1 inv_maskstop = ~get_int_mask(stop - wordstop * SHIFT) # wordstop == osize - 1 means other's last word is wordstop if wordstop == osize - 1: while i < wordstop: ret.setdigit(i, other.digit(i)) i += 1 # union stop value_hi = ret.digit(wordstop) & inv_maskstop # hi ret.setdigit(wordstop, other.digit(wordstop) | value_hi) # lo|hi # wordstop > osize - 1, other is shorter else: while i < osize: ret.setdigit(i, other.digit(i)) i += 1 while i < wordstop: ret._digits[i] = NULLDIGIT i += 1 # clear stop ret.setdigit(wordstop, ret.digit(wordstop) & inv_maskstop) ret._normalize() return ret