prepare multiply.py for release and add script for automatic calculation testing
This commit is contained in:
		
							parent
							
								
									6cda8bcfa0
								
							
						
					
					
						commit
						1ab5b67c77
					
				
							
								
								
									
										27
									
								
								src/mult-test.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/mult-test.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
			
		||||
import multiply as mlt
 | 
			
		||||
 | 
			
		||||
top_value = int("0b" + input("Top value (in binary): "), 2)
 | 
			
		||||
m = int(input("Method: "))
 | 
			
		||||
 | 
			
		||||
total_iterations = (top_value + 1) ** 2
 | 
			
		||||
print(f"Total test amount: {top_value + 1}^2 = {total_iterations}")
 | 
			
		||||
 | 
			
		||||
errors = []
 | 
			
		||||
 | 
			
		||||
for x in range(top_value):
 | 
			
		||||
    for y in range(top_value):
 | 
			
		||||
        n = max([len(bin(i)[2:]) for i in (x, y)])
 | 
			
		||||
        expected_result = mlt.al(bin(x*y)[2:], 2*n)
 | 
			
		||||
 | 
			
		||||
        _, r = mlt.multiply(n, x, y, m)
 | 
			
		||||
 | 
			
		||||
        if r == expected_result:
 | 
			
		||||
            print(f"{str(x*top_value+y).rjust(len(str(total_iterations)))}/{total_iterations}", end = "\r")
 | 
			
		||||
        else:
 | 
			
		||||
            errors.append([x, y, expected_result, r])
 | 
			
		||||
            print(f"Failed at {x}*{y}; expected {expected_result} but got {r}!")
 | 
			
		||||
 | 
			
		||||
if len(errors) == 0:
 | 
			
		||||
    print("Testing finished, no miscalculations detected.\nIt's safe to use!")
 | 
			
		||||
else:
 | 
			
		||||
    print("Testing failed with {len(errors)} errors.")
 | 
			
		||||
@ -8,52 +8,90 @@ def align_binary_to_right(value, size):
 | 
			
		||||
 | 
			
		||||
al = align_binary_to_right
 | 
			
		||||
 | 
			
		||||
def multiply(x, y, method):
 | 
			
		||||
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 depth
 | 
			
		||||
    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
 | 
			
		||||
    - (str)  binary representation of the result
 | 
			
		||||
 | 
			
		||||
    Methods fully supported: №4
 | 
			
		||||
    '''
 | 
			
		||||
 | 
			
		||||
    if method == 4:
 | 
			
		||||
        n = len(bin(x)[2:]) # base registry bit length, usually written as n
 | 
			
		||||
 | 
			
		||||
        # every table line has registers like so: RG1, RG3, RG2
 | 
			
		||||
        data_table = [[["0"*(2*n+1), "0" + bin(y)[2:] + "0"*n, bin(x)[2:], "-"]]*2]
 | 
			
		||||
        data_table = [[["0", "0"*(2*n+1), "0" + al(bin(y)[2:], n) + "0"*n, al(bin(x)[2:], n), "-"]]*2]
 | 
			
		||||
 | 
			
		||||
        while int('0b' + data_table[-1][-1][2], 2) != 0:
 | 
			
		||||
        # iteration number
 | 
			
		||||
        i = 0
 | 
			
		||||
 | 
			
		||||
        while int('0b' + data_table[-1][-1][3], 2) != 0:
 | 
			
		||||
            data_table.append([])
 | 
			
		||||
            i += 1
 | 
			
		||||
 | 
			
		||||
            if data_table[-2][-1][2][0] == "1":
 | 
			
		||||
            if data_table[-2][-1][3][0] == "1":
 | 
			
		||||
                data_table[-1].append([
 | 
			
		||||
                    al(bin(int("0b"+data_table[-2][-1][0], 2) + int("0b"+data_table[-2][-1][1], 2))[-(2*n+1):], 2*n+1), # RG1 + RG3
 | 
			
		||||
                    data_table[-2][-1][1],
 | 
			
		||||
                    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([
 | 
			
		||||
                    data_table[-1][-1][0],
 | 
			
		||||
                    '0' + data_table[-1][-1][1][:-1], # 0.r(RG3)
 | 
			
		||||
                    data_table[-1][-1][2][1:] + '0', # l(RG2).0
 | 
			
		||||
                    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([
 | 
			
		||||
                    data_table[-2][-1][0],
 | 
			
		||||
                    '0' + data_table[-2][-1][1][:-1], # 0.r(RG3)
 | 
			
		||||
                    data_table[-2][-1][2][1:] + '0', # l(RG2).0
 | 
			
		||||
                    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
 | 
			
		||||
        return data_table, data_table[-1][-1][1][:-1]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    x = int("0b" + input("X: "), 2)
 | 
			
		||||
    y = int("0b" + input("Y: "), 2)
 | 
			
		||||
    # 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 = multiply(x, y, method)
 | 
			
		||||
 | 
			
		||||
    dt, result = multiply(n, x, y, method)
 | 
			
		||||
 | 
			
		||||
    from lib.prettytable import PrettyTable
 | 
			
		||||
    pt = PrettyTable()
 | 
			
		||||
    pt.field_names = ["RG1", "RG3", "RG2", "Operations"]
 | 
			
		||||
    pt.field_names = ["Iteration", "RG1", "RG3", "RG2", "Operations"]
 | 
			
		||||
 | 
			
		||||
    for i in dt[1:]:
 | 
			
		||||
    for i in dt:
 | 
			
		||||
        for j in range(len(i)):
 | 
			
		||||
            if j+1 == len(i):
 | 
			
		||||
                pt.add_row(i[j], divider = True)
 | 
			
		||||
@ -61,3 +99,4 @@ if __name__ == "__main__":
 | 
			
		||||
                pt.add_row(i[j])
 | 
			
		||||
 | 
			
		||||
    print(pt)
 | 
			
		||||
    print(f"Result: {result}")
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user