mirror of
https://github.com/pocketpy/pocketpy
synced 2025-11-10 05:30:16 +00:00
adoping a more efficient division algorithm for bigint.
This commit is contained in:
parent
79cafcf32c
commit
60aee30548
@ -99,12 +99,78 @@ def ulong_divmodi(a: list, b: int):
|
|||||||
ulong_unpad_(res)
|
ulong_unpad_(res)
|
||||||
return res, carry
|
return res, carry
|
||||||
|
|
||||||
|
def ulong_lshift_(a: list, shift: int):
|
||||||
|
if shift == 0:
|
||||||
|
return
|
||||||
|
bits = shift % PyLong_SHIFT
|
||||||
|
carry = 0
|
||||||
|
for i in range(len(a) - 1, -1, -1):
|
||||||
|
new_carry = (a[i] >> (PyLong_SHIFT - bits)) & PyLong_MASK
|
||||||
|
a[i] = (a[i] << bits) & PyLong_MASK | carry
|
||||||
|
carry = new_carry
|
||||||
|
if carry != 0:
|
||||||
|
a.insert(0, carry)
|
||||||
|
|
||||||
|
def ulong_rshift_(a: list, shift: int):
|
||||||
|
if shift == 0:
|
||||||
|
return
|
||||||
|
bits = shift % PyLong_SHIFT
|
||||||
|
carry = 0
|
||||||
|
for i in range(len(a)):
|
||||||
|
new_carry = (a[i] << (PyLong_SHIFT - bits)) & PyLong_MASK
|
||||||
|
a[i] = (a[i] >> bits) | carry
|
||||||
|
carry = new_carry
|
||||||
|
if carry != 0:
|
||||||
|
a.pop(0)
|
||||||
|
|
||||||
def ulong_divmod(a: list, b: list):
|
def ulong_divmod(a: list, b: list):
|
||||||
q = [0]
|
|
||||||
while ulong_cmp(a, b) >= 0:
|
if ulong_cmp(a, b) < 0:
|
||||||
ulong_inc_(q)
|
return [0], a
|
||||||
a = ulong_sub(a, b)
|
|
||||||
return q, a
|
if len(b) == 1:
|
||||||
|
quotient = [0] * len(a)
|
||||||
|
remainder = 0
|
||||||
|
for i in range(len(a)-1, -1, -1):
|
||||||
|
temp = (remainder << PyLong_SHIFT) + a[i]
|
||||||
|
quotient[i] = temp // b[0]
|
||||||
|
remainder = temp % b[0]
|
||||||
|
return quotient, [remainder]
|
||||||
|
|
||||||
|
shift = PyLong_SHIFT - (b[-1].bit_length() - 1)
|
||||||
|
a = a.copy()
|
||||||
|
b = b.copy()
|
||||||
|
ulong_lshift_(a, shift)
|
||||||
|
ulong_lshift_(b, shift)
|
||||||
|
|
||||||
|
quotient = [0] * (len(a) - len(b) + 1)
|
||||||
|
|
||||||
|
for j in range(len(a)-len(b), -1, -1):
|
||||||
|
temp = ((a[j+len(b)] << PyLong_SHIFT) + a[j+len(b)-1]) // b[-1]
|
||||||
|
temp = min(temp, PyLong_MASK)
|
||||||
|
while temp*b[-1] > ((a[j+len(b)] << PyLong_SHIFT) + a[j+len(b)-1] - temp*a[j+len(b)-2] + (b[-2] if len(b) > 1 else 0)):
|
||||||
|
temp -= 1
|
||||||
|
|
||||||
|
carry = 0
|
||||||
|
for i in range(len(b)):
|
||||||
|
carry += a[i+j] - temp*b[i]
|
||||||
|
a[i+j] = carry & PyLong_MASK
|
||||||
|
carry >>= PyLong_SHIFT
|
||||||
|
a[j+len(b)] += carry
|
||||||
|
|
||||||
|
if a[j+len(b)] < 0:
|
||||||
|
carry = 0
|
||||||
|
for i in range(len(b)):
|
||||||
|
carry += a[i+j] + b[i]
|
||||||
|
a[i+j] = carry & PyLong_MASK
|
||||||
|
carry >>= PyLong_SHIFT
|
||||||
|
a[j+len(b)] += carry
|
||||||
|
else:
|
||||||
|
quotient[j] = temp
|
||||||
|
|
||||||
|
ulong_unpad_(a)
|
||||||
|
ulong_rshift_(a, shift)
|
||||||
|
return quotient, a
|
||||||
|
|
||||||
def ulong_floordivi(a: list, b: int):
|
def ulong_floordivi(a: list, b: int):
|
||||||
# b > 0
|
# b > 0
|
||||||
|
|||||||
@ -14,7 +14,7 @@ assert -a == -2
|
|||||||
assert 1 + a == 3L
|
assert 1 + a == 3L
|
||||||
assert 1 - a == -1L
|
assert 1 - a == -1L
|
||||||
assert 2 * a == 4L
|
assert 2 * a == 4L
|
||||||
|
assert 2L**500 // 3333L
|
||||||
|
|
||||||
# __lshift__ and __rshift__
|
# __lshift__ and __rshift__
|
||||||
for i in range(29):
|
for i in range(29):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user