mirror of
https://github.com/pocketpy/pocketpy
synced 2025-11-09 21:20:17 +00:00
modified ulong_divmod to make it tremendously faster
This commit is contained in:
parent
642810d3b5
commit
2200b859d0
129
python/_long.py
129
python/_long.py
@ -99,12 +99,129 @@ def ulong_divmodi(a: list, b: int):
|
|||||||
ulong_unpad_(res)
|
ulong_unpad_(res)
|
||||||
return res, carry
|
return res, carry
|
||||||
|
|
||||||
def ulong_divmod(a: list, b: list):
|
def ulong_divmod(a: list, b: list) -> tuple:
|
||||||
q = [0]
|
# defined a new data structure binary list for fast division
|
||||||
while ulong_cmp(a, b) >= 0:
|
# binary list is just a list of binary representation of a number
|
||||||
ulong_inc_(q)
|
def bl_fromint(number) -> list:
|
||||||
a = ulong_sub(a, b)
|
binary_string = bin(number)[2:]
|
||||||
return q, a
|
binary_list = (PyLong_SHIFT - len(binary_string)) * [0] + [
|
||||||
|
int(bit) for bit in binary_string
|
||||||
|
]
|
||||||
|
return binary_list
|
||||||
|
|
||||||
|
def bl_add(a: list, b: list) -> list:
|
||||||
|
len_a = len(a)
|
||||||
|
len_b = len(b)
|
||||||
|
max_len = max(len_a, len_b)
|
||||||
|
a = (max_len - len_a) * [0] + a
|
||||||
|
b = (max_len - len_b) * [0] + b
|
||||||
|
res = [0] * max_len
|
||||||
|
carry = 0
|
||||||
|
for i in range(max_len - 1, -1, -1):
|
||||||
|
carry = a[i] + b[i] + carry
|
||||||
|
res[i] = carry & 1
|
||||||
|
carry = carry >> 1
|
||||||
|
if carry:
|
||||||
|
res.insert(0, 1)
|
||||||
|
return res
|
||||||
|
|
||||||
|
def bl_subtract(a: list, b: list) -> tuple:
|
||||||
|
max_len = max(len(a), len(b))
|
||||||
|
a = (max_len - len(a)) * [0] + a
|
||||||
|
b = (max_len - len(b)) * [0] + b
|
||||||
|
sign = 0
|
||||||
|
for i in range(len(b)):
|
||||||
|
b[i] = 1 - b[i]
|
||||||
|
res = bl_add(a, b)
|
||||||
|
if len(res) > max_len:
|
||||||
|
sign = 1
|
||||||
|
res.pop(0)
|
||||||
|
res = bl_add(res, [1])
|
||||||
|
else:
|
||||||
|
sign = -1
|
||||||
|
for i in range(len(res)):
|
||||||
|
res[i] = 1 - res[i]
|
||||||
|
|
||||||
|
return sign, res
|
||||||
|
|
||||||
|
def bl_compare(a: list, b: list) -> int:
|
||||||
|
if len(a) != len(b):
|
||||||
|
return 1 if len(a) > len(b) else -1
|
||||||
|
max_len = max(len(a), len(b))
|
||||||
|
for i in range(max_len):
|
||||||
|
if a[i] != b[i]:
|
||||||
|
return 1 if a[i] > b[i] else -1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def bl_unpad(a: list) -> list:
|
||||||
|
while len(a) > 0 and a[0] == 0:
|
||||||
|
a.pop(0)
|
||||||
|
if len(a) == 0:
|
||||||
|
a = []
|
||||||
|
return a
|
||||||
|
|
||||||
|
def print_bl(a: list):
|
||||||
|
for elem in a:
|
||||||
|
print(elem, end="")
|
||||||
|
print()
|
||||||
|
|
||||||
|
def bl_divide(a: list, b: list) -> tuple: # returns quotient, remainder
|
||||||
|
if len(b) == 1 and b[0] == 0:
|
||||||
|
return ZeroDivisionError
|
||||||
|
elif len(b) == 1 and b[0] == 1:
|
||||||
|
return a, 0
|
||||||
|
flag = bl_compare(a, b)
|
||||||
|
if flag == -1:
|
||||||
|
return 0, b
|
||||||
|
elif flag == 0:
|
||||||
|
return 1, 0
|
||||||
|
r = []
|
||||||
|
q = []
|
||||||
|
for i in range(0, len(b) - 1):
|
||||||
|
r.append(a[i])
|
||||||
|
for i in range(len(b) - 1, len(a)):
|
||||||
|
if len(r) == 1 and r[0] == 0 and a[i] == 0:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
r.append(a[i])
|
||||||
|
if bl_compare(r, b) >= 0:
|
||||||
|
r = bl_subtract(r, b)[1]
|
||||||
|
r = bl_unpad(r)
|
||||||
|
q.append(1)
|
||||||
|
else:
|
||||||
|
q.append(0)
|
||||||
|
q = bl_unpad(q)
|
||||||
|
r = bl_unpad(r)
|
||||||
|
if r == []:
|
||||||
|
r = [0]
|
||||||
|
return q, r
|
||||||
|
|
||||||
|
def bl_from_ulong(a: list):
|
||||||
|
a = a[::-1]
|
||||||
|
res = []
|
||||||
|
for i in a:
|
||||||
|
res.extend(bl_fromint(i))
|
||||||
|
bl_unpad(res)
|
||||||
|
return res
|
||||||
|
|
||||||
|
def ulong_frombl(a: list) -> tuple:
|
||||||
|
length = len(a)
|
||||||
|
# print(length)
|
||||||
|
res = []
|
||||||
|
t = 0
|
||||||
|
while length > 0:
|
||||||
|
for i in range(min(length, PyLong_SHIFT)):
|
||||||
|
t = t << 1
|
||||||
|
t += a[length - min(length, PyLong_SHIFT) + i]
|
||||||
|
res.append(t) # t is the decimal representation of last min(29, length) digits
|
||||||
|
length -= PyLong_SHIFT
|
||||||
|
t = 0
|
||||||
|
return res, 1
|
||||||
|
|
||||||
|
li_a = bl_from_ulong(a)
|
||||||
|
li_b = bl_from_ulong(b)
|
||||||
|
q, r = bl_divide(li_a, li_b)
|
||||||
|
return ulong_frombl(q), ulong_frombl(r)
|
||||||
|
|
||||||
def ulong_floordivi(a: list, b: int):
|
def ulong_floordivi(a: list, b: int):
|
||||||
# b > 0
|
# b > 0
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user