cl-tools/src/multiply.py

168 lines
5.1 KiB
Python

import bitutils as bu
# this needs to be replaced at some point, because:
# - it uses old notation for align operation, which contradicts with
# modern instruction sets, thus making it easily confusable with
# the bu.al() operation which aligns bits to the left
def align_binary_to_right(value, size):
if "b" in value:
result = value.split("b")[1]
else:
result = str(value)
return result.rjust(size, "0")
al = align_binary_to_right
def multiply(n, x, y, method):
'''
this method can be used to:
- get step-by-step binary multiplication data using different methods;
- get just the end result of binary multiplication;
it takes 4 arguments:
n - (int) base register bit length
x - (int) value for X operand
y - (int) value for Y operand
method - (int) which method to use to perform multiplication
it returns 2 items:
- (list) table with step-by-step operations and descriptions (table format
depends on the chosen method)
- (str) binary representation of the result (method-independant)
Methods fully supported:
- №2 (passed mult-test.py with 10 bits)
- №4 (passed mult-test.py with 12 bits)
'''
if method == 2:
# every table line has registers like so: RG1, RG3, RG2
data_table = [[["0", "0"*(2*n), "0"*n + bu.ar(bin(y)[2:], n), bu.ar(bin(x)[2:], n), "-"]]*2]
# iteration number
i = 0
while int('0b' + data_table[-1][-1][3], 2) != 0:
data_table.append([])
i += 1
if data_table[-2][-1][3][-1] == "1":
data_table[-1].append([
i,
#al(bin(int("0b"+data_table[-2][-1][1], 2) + int("0b"+data_table[-2][-1][2], 2))[-(2*n+1):], 2*n+1), # RG1 + RG3
bu.rsum(data_table[-2][-1][1], data_table[-2][-1][2], 2*n),
data_table[-2][-1][2],
data_table[-2][-1][3],
"RG1+RG3"
])
data_table[-1].append([
i,
data_table[-1][-1][1],
bu.l(data_table[-1][-1][2]), # l(RG3).0
bu.r(data_table[-1][-1][3]), # 0.r(RG2)
"0.r(RG2), l(RG3).0"
])
else:
data_table[-1].append([
i,
data_table[-2][-1][1],
bu.l(data_table[-2][-1][2]), # l(RG3).0
bu.r(data_table[-2][-1][3]), # 0.r(RG2)
"0.r(RG2), l(RG3).0"
])
return data_table, data_table[-1][-1][1]
elif method == 4:
# every table line has registers like so: RG1, RG3, RG2
data_table = [[["0", "0"*(2*n+1), "0" + al(bin(y)[2:], n) + "0"*n, al(bin(x)[2:], n), "-"]]*2]
# iteration number
i = 0
while int('0b' + data_table[-1][-1][3], 2) != 0:
data_table.append([])
i += 1
if data_table[-2][-1][3][0] == "1":
data_table[-1].append([
i,
al(bin(int("0b"+data_table[-2][-1][1], 2) + int("0b"+data_table[-2][-1][2], 2))[-(2*n+1):], 2*n+1), # RG1 + RG3
data_table[-2][-1][2],
data_table[-2][-1][3],
"RG1+RG3"
])
data_table[-1].append([
i,
data_table[-1][-1][1],
'0' + data_table[-1][-1][2][:-1], # 0.r(RG3)
data_table[-1][-1][3][1:] + '0', # l(RG2).0
"0.r(RG3), l(RG2).0"
])
else:
data_table[-1].append([
i,
data_table[-2][-1][1],
'0' + data_table[-2][-1][2][:-1], # 0.r(RG3)
data_table[-2][-1][3][1:] + '0', # l(RG2).0
"0.r(RG3), l(RG2).0"
])
return data_table, data_table[-1][-1][1][:-1]
def table_to_text(dt):
from lib.prettytable import PrettyTable
pt = PrettyTable()
pt.field_names = ["Iteration", "RG1", "RG3", "RG2", "Operations"]
for i in dt:
for j in range(len(i)):
if j+1 == len(i):
pt.add_row(i[j], divider = True)
else:
pt.add_row(i[j])
return pt.get_string()
if __name__ == "__main__":
# a fully functional reference
# implementation for this library
# is provided below
raw_x = input("X: ")
raw_y = input("Y: ")
if len(raw_x) == len(raw_y):
n = len(raw_x)
else:
n = int(input("n: "))
x = int("0b" + raw_x, 2)
y = int("0b" + raw_y, 2)
method = int(input("Method: "))
dt, result = multiply(n, x, y, method)
'''
from lib.prettytable import PrettyTable
pt = PrettyTable()
pt.field_names = ["Iteration", "RG1", "RG3", "RG2", "Operations"]
for i in dt:
for j in range(len(i)):
if j+1 == len(i):
pt.add_row(i[j], divider = True)
else:
pt.add_row(i[j])
print(pt)
'''
print(table_to_text(dt))
print(f"Result: {result}")