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}")