Compare commits
4 Commits
3338a75114
...
3598eb13f1
Author | SHA1 | Date |
---|---|---|
|
3598eb13f1 | |
|
44457b1849 | |
|
31ec6b2697 | |
|
24b62d109a |
|
@ -20,13 +20,13 @@ al = align_binary_to_left
|
||||||
|
|
||||||
|
|
||||||
def shift_left(rg, fill_bit = 0):
|
def shift_left(rg, fill_bit = 0):
|
||||||
return rg[1:] + fill_bit
|
return rg[1:] + str(fill_bit)
|
||||||
|
|
||||||
l = shift_left
|
l = shift_left
|
||||||
|
|
||||||
|
|
||||||
def shift_right(rg, fill_bit = 0):
|
def shift_right(rg, fill_bit = 0):
|
||||||
return fill_bit + rg[:-1]
|
return str(fill_bit) + rg[:-1]
|
||||||
|
|
||||||
r = shift_right
|
r = shift_right
|
||||||
|
|
||||||
|
@ -37,14 +37,20 @@ def sum_supplementary_codes(x, y, size):
|
||||||
sum = sum_supplementary_codes
|
sum = sum_supplementary_codes
|
||||||
|
|
||||||
|
|
||||||
def sum_supplementary_codes_with_overspill(x, y, size):
|
def sum_supplementary_codes_right_align(x, y, size):
|
||||||
|
return ar(bin(int("0b"+x, 2) + int("0b"+y, 2))[2:], size)
|
||||||
|
|
||||||
|
rsum = sum_supplementary_codes_right_align
|
||||||
|
|
||||||
|
|
||||||
|
def sum_supplementary_codes_with_overflow(x, y, size):
|
||||||
result = bin(int("0b"+x, 2) + int("0b"+y, 2))[2:]
|
result = bin(int("0b"+x, 2) + int("0b"+y, 2))[2:]
|
||||||
if len(result) > size:
|
if len(result) > size:
|
||||||
return al(result, size), '1'
|
return al(result, size), '1'
|
||||||
else:
|
else:
|
||||||
return al(result, size), '0'
|
return al(result, size), '0'
|
||||||
|
|
||||||
sump = sum_supplementary_codes_with_overspill
|
sump = sum_supplementary_codes_with_overflow
|
||||||
|
|
||||||
|
|
||||||
def invert_bit(b):
|
def invert_bit(b):
|
||||||
|
@ -57,3 +63,15 @@ def invert_bit(b):
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
inv = invert_bit
|
inv = invert_bit
|
||||||
|
|
||||||
|
|
||||||
|
def xor(x, y):
|
||||||
|
if len(x) == len(y):
|
||||||
|
result = ''
|
||||||
|
for i in zip(x, y):
|
||||||
|
if x != y:
|
||||||
|
result += '1'
|
||||||
|
else:
|
||||||
|
result += '0'
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
|
@ -24,4 +24,4 @@ for x in range(top_value):
|
||||||
if len(errors) == 0:
|
if len(errors) == 0:
|
||||||
print("Testing finished, no miscalculations detected.\nIt's safe to use!")
|
print("Testing finished, no miscalculations detected.\nIt's safe to use!")
|
||||||
else:
|
else:
|
||||||
print("Testing failed with {len(errors)} errors.")
|
print(f"Testing failed with {len(errors)} errors.")
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
# a wrapper for multiplication script which adds support for floating point numbers
|
||||||
|
|
||||||
|
from lib.prettytable import PrettyTable
|
||||||
|
from multiply import multiply, table_to_text
|
||||||
|
import bitutils as bu
|
||||||
|
|
||||||
|
def get_reference_register_size(*numbers):
|
||||||
|
return max(map(len, numbers))
|
||||||
|
|
||||||
|
def parse_float(number):
|
||||||
|
split_by_dot = number.split('.')
|
||||||
|
#print(number, split_by_dot)
|
||||||
|
Sn = split_by_dot[0] # sign
|
||||||
|
|
||||||
|
split_by_comma = split_by_dot[1].split(',')
|
||||||
|
Pn = len(split_by_comma[0].lstrip('0'))
|
||||||
|
Mn = ''.join(split_by_comma).lstrip('0')
|
||||||
|
#print(Sn, Pn, Mn)
|
||||||
|
return Sn, Pn, Mn
|
||||||
|
|
||||||
|
# compatibility layer for old multiply.py code
|
||||||
|
def to_int(number):
|
||||||
|
return int("0b" + number, 2)
|
||||||
|
|
||||||
|
def normalize_mantice(m, n):
|
||||||
|
M_norm = m.lstrip('0')
|
||||||
|
#print(m, M_norm)
|
||||||
|
P_delta = len(m) - len(M_norm)
|
||||||
|
#print(M_norm[:n], P_delta)
|
||||||
|
return M_norm[:n], P_delta
|
||||||
|
|
||||||
|
def round_mantice(m, n):
|
||||||
|
closest_upper = bu.sum(m[:n+1], '1', n+1)
|
||||||
|
return closest_upper[:n]
|
||||||
|
|
||||||
|
def print_classic_float(label, Sn, Pn, Mn):
|
||||||
|
pt = PrettyTable()
|
||||||
|
pt.field_names = [f"S{label}", f"P{label}", f"M{label}"]
|
||||||
|
pt.add_row([Sn, bin(Pn)[2:], Mn])
|
||||||
|
print(pt)
|
||||||
|
|
||||||
|
def multiply_float(x, y, method, n = 0, verbose = False):
|
||||||
|
Sx, Px, Mx = parse_float(x)
|
||||||
|
Sy, Py, My = parse_float(y)
|
||||||
|
|
||||||
|
print(f"Число X:\n" \
|
||||||
|
f"Знак мантиси: {Sx}\n" \
|
||||||
|
f"Порядок: {Px}\n" \
|
||||||
|
f"Мантиса: {Mx}\n")
|
||||||
|
|
||||||
|
print(f"Число Y:\n" \
|
||||||
|
f"Знак мантиси: {Sy}\n" \
|
||||||
|
f"Порядок: {Py}\n" \
|
||||||
|
f"Мантиса: {My}")
|
||||||
|
|
||||||
|
print("Запис чисел у класичному форматі:")
|
||||||
|
print_classic_float('x', Sx, Px, Mx)
|
||||||
|
print()
|
||||||
|
print_classic_float('y', Sy, Py, My)
|
||||||
|
print()
|
||||||
|
|
||||||
|
reg_size = get_reference_register_size(Mx, My)
|
||||||
|
|
||||||
|
table, result = multiply(n, to_int(bu.al(Mx, n)), to_int(bu.al(My, n)), method)
|
||||||
|
print(f"Процес множення другим методом:\n{table_to_text(table)}\n")
|
||||||
|
|
||||||
|
print("Маємо результат:")
|
||||||
|
|
||||||
|
S_result = bu.xor(Sx, Sy)
|
||||||
|
print(f"Знаковий розряд: {Sx} ^ {Sy} = {S_result}")
|
||||||
|
|
||||||
|
M_norm, P_delta = normalize_mantice(result, n+1)
|
||||||
|
print(f"Нормалізована мантиса: ,{M_norm}")
|
||||||
|
|
||||||
|
P_result = Px + Py - P_delta
|
||||||
|
print(f"Порядок: {Px} + {Py} - {P_delta} = {P_result}")
|
||||||
|
|
||||||
|
M_result = round_mantice(result, n)
|
||||||
|
print(f"Округлюємо мантису до {n} розрядів: ,{M_result}")
|
||||||
|
|
||||||
|
return S_result, P_result, M_result
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
start_x = input("X: ")
|
||||||
|
start_y = input("Y: ")
|
||||||
|
n = int(input("n: "))
|
||||||
|
method = int(input("Method: "))
|
||||||
|
|
||||||
|
S_result, P_result, M_result = multiply_float(start_x, start_y, method, n)
|
||||||
|
|
||||||
|
print(f"Запишемо результат у вигляді таблиці:")
|
||||||
|
print_classic_float('f', S_result, P_result, M_result)
|
|
@ -1,3 +1,9 @@
|
||||||
|
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):
|
def align_binary_to_right(value, size):
|
||||||
if "b" in value:
|
if "b" in value:
|
||||||
result = value.split("b")[1]
|
result = value.split("b")[1]
|
||||||
|
@ -15,19 +21,62 @@ def multiply(n, x, y, method):
|
||||||
- get just the end result of binary multiplication;
|
- get just the end result of binary multiplication;
|
||||||
|
|
||||||
it takes 4 arguments:
|
it takes 4 arguments:
|
||||||
n - (int) base register bit depth
|
n - (int) base register bit length
|
||||||
x - (int) value for X operand
|
x - (int) value for X operand
|
||||||
y - (int) value for Y operand
|
y - (int) value for Y operand
|
||||||
method - (int) which method to use to perform multiplication
|
method - (int) which method to use to perform multiplication
|
||||||
|
|
||||||
it returns 2 items:
|
it returns 2 items:
|
||||||
- (list) table with step-by-step operations and descriptions
|
- (list) table with step-by-step operations and descriptions (table format
|
||||||
- (str) binary representation of the result
|
depends on the chosen method)
|
||||||
|
- (str) binary representation of the result (method-independant)
|
||||||
|
|
||||||
Methods fully supported: №4
|
Methods fully supported:
|
||||||
|
- №2 (passed mult-test.py with 10 bits)
|
||||||
|
- №4 (passed mult-test.py with 12 bits)
|
||||||
'''
|
'''
|
||||||
|
|
||||||
if method == 4:
|
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
|
# 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]
|
data_table = [[["0", "0"*(2*n+1), "0" + al(bin(y)[2:], n) + "0"*n, al(bin(x)[2:], n), "-"]]*2]
|
||||||
|
|
||||||
|
@ -66,6 +115,19 @@ def multiply(n, x, y, method):
|
||||||
|
|
||||||
return data_table, data_table[-1][-1][1][:-1]
|
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__":
|
if __name__ == "__main__":
|
||||||
# a fully functional reference
|
# a fully functional reference
|
||||||
|
@ -86,7 +148,8 @@ if __name__ == "__main__":
|
||||||
method = int(input("Method: "))
|
method = int(input("Method: "))
|
||||||
|
|
||||||
dt, result = multiply(n, x, y, method)
|
dt, result = multiply(n, x, y, method)
|
||||||
|
|
||||||
|
'''
|
||||||
from lib.prettytable import PrettyTable
|
from lib.prettytable import PrettyTable
|
||||||
pt = PrettyTable()
|
pt = PrettyTable()
|
||||||
pt.field_names = ["Iteration", "RG1", "RG3", "RG2", "Operations"]
|
pt.field_names = ["Iteration", "RG1", "RG3", "RG2", "Operations"]
|
||||||
|
@ -99,4 +162,6 @@ if __name__ == "__main__":
|
||||||
pt.add_row(i[j])
|
pt.add_row(i[j])
|
||||||
|
|
||||||
print(pt)
|
print(pt)
|
||||||
|
'''
|
||||||
|
print(table_to_text(dt))
|
||||||
print(f"Result: {result}")
|
print(f"Result: {result}")
|
||||||
|
|
Loading…
Reference in New Issue