#!/usr/bin/env python3 from tabulate import tabulate with open('input.txt') as f: input_string = f.read().split('\n') def twos_comp(num, length): if num == 0: return 0 return abs((num ^ ((1 << length) - 1)) + 1) def logical_shiftr(num, length, times): #print("SHIFT START___") #print(bin(num)) for t in range(times): num = (num >> 1) | ((1 << length) & num) #print(bin(num)) #print("SHIFT END___") return num def convert_if_twoscomp(num, length): if num & (1 << length - 1): return (-1 * twos_comp(num, length)) return num & (1 << length) - 1 def debug(results): headers = ['multiplicand bin', 'multiplier bin', 'multiplicand dec', 'multiplier dec', 'expected bin', 'expected dec', 'booth if correct', 'booth mod if correct'] table = [] for [multiplicand_bin, multiplier_bin, result_booth, result_booth_mod, length] in results: multiplicand = convert_if_twoscomp(multiplicand_bin, length) multiplier = convert_if_twoscomp(multiplier_bin, length) expected = multiplicand * multiplier expected_bin = (twos_comp(expected, length * 2), expected) [expected > 0] success_b = [bin(result_booth), "PASS"] [result_booth == expected_bin] success_bm = [bin(result_booth_mod), "PASS"] [result_booth_mod == expected_bin] table.append([bin(multiplicand_bin), bin(multiplier_bin), multiplicand, multiplier, bin(expected_bin), expected, success_b, success_bm]) print("\nCHECKS: \n", tabulate(table, headers), "\n") def booth(multiplier, multiplicand, length): multiplicand_twos_comp = twos_comp(multiplicand, length) result = multiplier << 1 # extended bit for i in range(length): op = result & 0b11 if op == 0b01: result += multiplicand << (length + 1) if op == 0b10: result += multiplicand_twos_comp << (length + 1) result &= (1 << (length * 2) + 1) - 1 # get rid of any overflows result = logical_shiftr(result, length * 2, 1) result = result >> 1 return result def booth_mod(multiplier, multiplicand, length): multiplicand_twos_comp = twos_comp(multiplicand, length) result = multiplier << 1 # extended bit operations = 0 for i in range(int(length / 2)): match result & 0b111: case 0b010 | 0b001: # add result += multiplicand << (length + 1) case 0b011: # add * 2 result += multiplicand << (length + 2) # extra shift is multiplying multiplicand by 2 case 0b100: # sub * 2 result += multiplicand_twos_comp << (length + 2) case 0b101 | 0b110: # sub result += multiplicand_twos_comp << (length + 1) if result & (1 << length): print("{}: overflow".format(bin(multiplicand))) result &= (1 << ((length * 2) + 1)) - 1 # get rid of any overflows result = logical_shiftr(result, length * 2, 2) result = result >> 1 return result if __name__ == "__main__": headers = ['multiplicand', 'multiplier', 'result (bin)', 'result (hex)'] table = [] debug_results = [] for operation in input_string: if operation == '' or operation[0] == '#': continue length = len(operation.split(" ")[0]) multiplicand = int(operation.split(" ")[0], 2) multiplier = int(operation.split(" ")[1], 2) result_booth = booth(multiplier, multiplicand, length) result_mod_booth = booth_mod(multiplier, multiplicand, length) table.append([bin(multiplicand), bin(multiplier), bin(result_booth), hex(result_booth)]) debug_results.append([multiplicand, multiplier, result_booth, result_mod_booth, length]) debug(debug_results) print(tabulate(table, headers)) #generate table