def max_value(cls) -> "Integer": """ Integer 의 최대값 :return: Integer 의 최대값 (2**32 - 1) """ max_list = [Bit(True) for _ in range(cls.field_len)] sign = Bit() return Integer(max_list, sign)
def inf(cls) -> "Float": """ 무한대 값 :return: Infinite 값 """ sign = Bit() exponent = [Bit(True) for _ in range(cls.exponent_len)] fraction = [Bit() for _ in range(cls.fraction_len)] return Float(exponent, fraction, sign)
def max_value(cls) -> "Float": """ Float 의 최대값 :return: Float 의 최대값 3.40282346639e+38 """ sign = Bit() exponent = [Bit(True) for _ in range(cls.exponent_len-1)] exponent.append(Bit()) fraction = [Bit(True) for _ in range(cls.fraction_len)] return Float(exponent, fraction, sign)
def nan(cls) -> "Float": """ 알 수 없는 값 Exponent 값은 모두 1 이고 fraction이 모두 0이 아닌 값 (하나라도 1이 있음) :return: nan 값 """ sign = Bit() exponent = [Bit(True) for _ in range(cls.exponent_len)] fraction = [Bit(True) for _ in range(cls.fraction_len)] return Float(exponent, fraction, sign)
def min_value(cls) -> "Float": """ Float 의 최소값 :return: Float 의 최소값 -1.175494490952134e-38 """ sign = Bit(True) exponent = [Bit() for _ in range(cls.exponent_len-1)] exponent.append(Bit(True)) fraction = [Bit() for _ in range(cls.fraction_len-1)] fraction.append(Bit(True)) return Float(exponent, fraction, sign)
def _set(self, _int: int): """ int 값을 통해 integer 를 받기 위한 함수 int 값을 Bit를 통해 int로 어떻게 표현하는 지 로직 확인을 위한 함수 deprecated """ if _int < 0: self.sign = Bit(True) _int = -_int else: self.sign = Bit() _int = _int % self.limit for i, x in enumerate(self.frame): self.bits[i].set(bool(_int & x))
def test_float_multiplication5(): float1 = Float('0.14') float2 = Float('0.0001') res = float1 * float2 assert res.sign == Bit() exponents = map(lambda x: Bit(bool(x)), [0, 1, 1, 0, 1, 1, 1, 0]) for i, exp in enumerate(exponents): assert res.exponents[i] == exp fractions = map( lambda x: Bit(bool(x)), [1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0]) for i, exp in enumerate(fractions): assert res.fractions[i] == exp
def max_value(cls) -> "UnsignedInteger": """ UnsignedInteger 의 최대값 :return: UnsignedInteger 의 최대값 (2**33 - 1) """ max_list = [Bit(True) for _ in range(cls.field_len)] return UnsignedInteger(max_list)
def empty_bits(length: int) -> List[Bit]: """ length 길이의 비어있는 Bit List를 생성하는 함수 :param length: 원하는 Bit List의 길이 :return: 비어있는 length 길이의 Bit List """ return [Bit() for _ in range(length)]
def str_to_int(cls, val: str) -> "Integer": """ String 값을 통해 integer 값 read :param val: String 으로 표현된 정수 값 (공백이 없다는 가정) :return: Integer 의 값 """ if val[0] == '-': sign = Bit(True) val = val[1:] else: sign = Bit() bits = Arithmetic.str_to_integer(val, cls.field_len) if len(bits) > cls.field_len: sign ^= bits[-cls.field_len-1] bits = BitOperation.fit_bits(bits, cls.field_len) return Integer(bits, sign)
def fraction_bits(a: List[Bit]) -> List[Bit]: """ float 값의 fraction에 생략된 1을 추가하는 함수 :param a: 소수점의 유효숫자만 표현된 가수 값 :return: 1이 추가된 가수 값 """ frac = a[::] frac.insert(0, Bit(True)) return frac
def str_to_unsigned_int(cls, val: str) -> "UnsignedInteger": """ String 값을 통해 integer 값 read :param val: String 으로 표현된 정수 값 (공백이 없다는 가정) :return: UnsignedInteger 의 값 """ if val[0] == '-': sign = Bit(True) val = val[1:] else: sign = Bit() res = Arithmetic.str_to_integer(val, cls.field_len) res = BitOperation.fit_bits(res, cls.field_len) if sign: res, _ = Arithmetic.complement_bits(res, cls.field_len) return UnsignedInteger(res) return UnsignedInteger(res)
def raw_eq_bits(a: List[Bit], b: List[Bit]) -> bool: """ 같은 길이의 Bit List를 값이 같은 지 ( == ) 비교 :param a: equal 인지 확인하기 위한 BitList :param b: 비교 BitList :return: 값이 같은 지 여부 """ res = Bit() for i in range(len(a)): res |= (a[i] ^ b[i]) return bool(~res)
def complement_bits(a: List[Bit], length: int) -> (List[Bit], Bit): """ Bit List의 2의 보수를 계산 - 연산을 하기 위해 2의 보수 계산 :param a: 2의 보수를 계산하는 Bit List :param length: 원하는 Bit List의 길이 :return: Bit List의 2의 보수 값 """ a = BitOperation.fit_bits(a, length) a = BitOperation.invert_bits(a) return Arithmetic.add_bits(a, [Bit(True)], length)
def not_gate(a: Bit) -> Bit: """ NOT Gate 1 비트 ~ 연산을 위한 Gate 비트 값이 1일 경우 0인 비트, 비트 값이 0일 경우 1인 비트를 반환 :param a: NOT Gate의 입력 비트 :return: Not Gate의 결과 비트 """ return Bit(not a.val)
def __le__(self, other: "Integer") -> bool: """ Low Equal 연산 ( <= )을 위한 operator overloading :param other: Integer 타입 가정 :return: 새로운 Integer 객체로 return """ if self.sign != other.sign: return self.sign == Bit() if self.is_negative(): return BitOperation.le_bits(other.bits, self.bits, self.field_len) return BitOperation.le_bits(self.bits, other.bits, self.field_len)
def decomplement_bits(a: List[Bit], length: int) -> List[Bit]: """ 2의 보수 값을 되돌리는 함수 signed number 값에서 연산 후 2의 보수 값을 되돌리기 위한 함수 :param a: 2의 보수로 표현된 Bit List :param length: 원하는 Bit List의 길이 :return: 2의 보수를 되돌린 Bit List 값 """ a = BitOperation.fit_bits(a, length) a, _ = Arithmetic.add_bits(a, [Bit(True) for _ in range(len(a))], length) return BitOperation.invert_bits(a)
def and_gate(a: Bit, b: Bit) -> Bit: """ AND Gate 1 비트 & 연산을 위한 Gate a 비트의 값이 1 이면서 b 비트의 값이 1인 경우 1인 비트, 이 외의 경우에는 0인 비트를 반환 :param a: AND Gate의 입력 비트 1 :param b: AND Gate의 입력 비트 2 :return: AND Gate의 결과 비트 """ return Bit(a.val and b.val)
def or_gate(a: Bit, b: Bit) -> Bit: """ OR Gate 1 비트 | 연산을 위한 Gate a 비트의 값, b 비트의 값 둘 중 하나 이상의 비트가 1인 경우 1인 비트, 이외의 경우에는 0인 비트를 반환 :param a: OR Gate의 입력 비트 1 :param b: OR Gate의 입력 비트 2 :return: OR Gate의 결과 비트 """ return Bit(a.val or b.val)
def set(self, _float: float): """ float 값을 통해 float 를 받기 위한 함수 float 값을 Bit를 통해 float로 어떻게 표현하는 지 로직 확인을 위한 함수 deprecated """ if _float < 0: self.sign = Bit(True) _float = -_float else: self.sign = Bit() bits = [] int_val = int(_float) _float -= int_val while int_val > 0: bits.insert(0, Bit(bool(int_val % 2))) int_val //= 2 del bits[0] exp = len(bits) exp = UnsignedInteger('127') + UnsignedInteger(str(exp)) while _float > 0 and len(bits) < self.fraction_len: _float *= 2 bits.append(Bit(int(_float) == 1)) _float -= int(_float) for _ in range(self.fraction_len-len(bits)): bits.append(Bit()) bits[-1] = Bit(bool(_float)) self.exponents = exp.bits[-self.exponent_len:] self.fractions = bits[:self.fraction_len]
def __init__(self, bits: list or str or int = None, sign: Bit = Bit()): if type(bits) == str: res = self.str_to_int(bits) self.sign = res.sign self.bits = res.bits elif type(bits) == int: self.sign = sign self.bits = BitOperation.empty_bits(self.field_len) self._set(bits) elif type(bits) == list: self.sign = sign self.bits = bits else: self.sign = sign self.bits = BitOperation.empty_bits(self.field_len)
def raw_add_bits(a: List[Bit], b: List[Bit]) -> (List[Bit], Bit): """ 같은 길이의 Bit List를 더하는 ( + ) 함수 덧셈 결과 overflow 되었는지 여부를 함께 return and ( & ) 연산, xor ( ^ ) 연산과 left-shift ( << ) 연산을 통해 덧셈을 구현 :param a: 더할 Bit List :param b: 더할 Bit List :return: a + b의 값인 Bit List, overflow 된 Bit """ if BitOperation.is_empty(b): return a, Bit() carry_0 = BitOperation.raw_and_bits(a, b) remain = BitOperation.raw_xor_bits(a, b) carry = BitOperation.raw_lshift_bits(carry_0, 1) res, overflow = Arithmetic.raw_add_bits(remain, carry) return res, overflow ^ carry_0[0]
def test_unsigned_integer_max_value2(): bits = UnsignedInteger.max_value().bits for bit in bits: assert bit == Bit(True)
def __init__(self, bit_list: List[Bit] = None): if not bit_list: bit_list = [Bit() for _ in range(self.length)] self.bit_list = bit_list
def test_unsigned_integer_min_value2(): bits = UnsignedInteger.min_value().bits for bit in bits: assert bit == Bit(False)
class Float: """ Float의 메모리 구조 +--------------+--------------------------+-------------------------------------------+ | sign (1 bit) | exponent (8 bit) | fraction (23 bit) | +--------------+--------------------------+-------------------------------------------+ 32 bit로 이루어진 float 값 양수 음수를 Sign bit를 통해 구분 exponent 를 통해 소수점의 위치를 이동 (지수) fraction 을 통해 유효숫자를 표현 (가수) """ bit_len = 32 exponent_len = 8 fraction_len = 23 default_exponent_field = [Bit() for _ in range(exponent_len)] default_fraction_field = [Bit() for _ in range(fraction_len)] def __init__(self, exponents: list or float or int or str = None, fractions: list = None, sign: Bit = Bit()): if type(exponents) == str: res = self.str_to_float(exponents) self.sign = res.sign self.exponents = res.exponents self.fractions = res.fractions elif type(exponents) == float or type(exponents) == int: self.sign = sign self.exponents = self.default_exponent_field[::] self.fractions = self.default_fraction_field[::] self.set(exponents) elif type(exponents) == list: self.sign = sign self.exponents = exponents self.fractions = fractions else: self.sign = sign self.exponents = self.default_exponent_field[::] self.fractions = self.default_fraction_field[::] def is_zero(self) -> bool: """ 모든 비트가 0인지 확인하는 함수 :return: 모든 비트가 0인지 여부 """ return not self.sign and BitOperation.is_empty(self.exponents) and BitOperation.is_empty(self.fractions) def is_nan(self) -> bool: """ 값이 nan 인지 확인하는 함수 :return: exponent가 모두 1이고 fraction은 모두 0이 아닌지 여부 """ return BitOperation.is_empty(BitOperation.invert_bits(self.exponents)) and not BitOperation.is_empty(self.fractions) def is_inf(self) -> bool: """ 값이 inf 인지 확인하는 함수 :return: exponent가 모두 1이고 fraction은 모두 0인지 여부 """ return BitOperation.is_empty(BitOperation.invert_bits(self.exponents)) and BitOperation.is_empty(self.fractions) @classmethod def max_value(cls) -> "Float": """ Float 의 최대값 :return: Float 의 최대값 3.40282346639e+38 """ sign = Bit() exponent = [Bit(True) for _ in range(cls.exponent_len-1)] exponent.append(Bit()) fraction = [Bit(True) for _ in range(cls.fraction_len)] return Float(exponent, fraction, sign) @classmethod def min_value(cls) -> "Float": """ Float 의 최소값 :return: Float 의 최소값 -1.175494490952134e-38 """ sign = Bit(True) exponent = [Bit() for _ in range(cls.exponent_len-1)] exponent.append(Bit(True)) fraction = [Bit() for _ in range(cls.fraction_len-1)] fraction.append(Bit(True)) return Float(exponent, fraction, sign) @classmethod def inf(cls) -> "Float": """ 무한대 값 :return: Infinite 값 """ sign = Bit() exponent = [Bit(True) for _ in range(cls.exponent_len)] fraction = [Bit() for _ in range(cls.fraction_len)] return Float(exponent, fraction, sign) @classmethod def nan(cls) -> "Float": """ 알 수 없는 값 Exponent 값은 모두 1 이고 fraction이 모두 0이 아닌 값 (하나라도 1이 있음) :return: nan 값 """ sign = Bit() exponent = [Bit(True) for _ in range(cls.exponent_len)] fraction = [Bit(True) for _ in range(cls.fraction_len)] return Float(exponent, fraction, sign) def set(self, _float: float): """ float 값을 통해 float 를 받기 위한 함수 float 값을 Bit를 통해 float로 어떻게 표현하는 지 로직 확인을 위한 함수 deprecated """ if _float < 0: self.sign = Bit(True) _float = -_float else: self.sign = Bit() bits = [] int_val = int(_float) _float -= int_val while int_val > 0: bits.insert(0, Bit(bool(int_val % 2))) int_val //= 2 del bits[0] exp = len(bits) exp = UnsignedInteger('127') + UnsignedInteger(str(exp)) while _float > 0 and len(bits) < self.fraction_len: _float *= 2 bits.append(Bit(int(_float) == 1)) _float -= int(_float) for _ in range(self.fraction_len-len(bits)): bits.append(Bit()) bits[-1] = Bit(bool(_float)) self.exponents = exp.bits[-self.exponent_len:] self.fractions = bits[:self.fraction_len] @classmethod def str_to_float(cls, val: str) -> "Float": """ String 값을 통해 float 값 read :param val: String 으로 표현된 정수 값 (공백이 없다는 가정) :return: Float 의 값 """ if val[0] == '-': sign = Bit(True) val = val[1:] else: sign = Bit() dec, minor = cls.split_point(val) fraction, digit = Arithmetic.str_to_integer_until_overflow(dec, cls.fraction_len+1) frac, digit = Arithmetic.str_to_minor(fraction, minor, digit, cls.fraction_len+1) fraction = frac[1:] if str(digit)[0] == '-': exponent, _ = Arithmetic.sub_bits( Arithmetic.str_to_integer('127', cls.exponent_len), Arithmetic.str_to_integer(str(digit)[1:], cls.exponent_len), cls.exponent_len ) else: exponent, _ = Arithmetic.add_bits( Arithmetic.str_to_integer('127', cls.exponent_len), Arithmetic.str_to_integer(str(digit), cls.exponent_len), cls.exponent_len ) return Float(exponent, fraction, sign) @classmethod def split_point(cls, val: str) -> (str, str): """ 문자열을 . 을 기준으로 정수값과 소수값을 나눔 :param val: 실수값 문자열 :return: 정수값, 소수값 """ val = val.split('.') if len(val) < 2: return val[0], '0' return val[0], val[1] def val(self) -> float: """ bit 들로 이루어진 값을 float 값으로 읽을 수 있도록 만드는 함수 음수 확인은 signed bit를 통해 확인 테스트 및 출력을 위해 사용하는 함수 :return: float 값으로 리턴 """ if self.is_zero(): return 0 if self.is_nan(): return float('nan') if self.is_inf(): if self.sign: return -float('inf') return float('inf') res = BitOperation.binary_to_float(self.exponents, self.fractions) if self.sign: return -res return res def __str__(self) -> str: return str(self.val()) def is_negative(self) -> Bit: """ Sign 비트를 통해 음수 확인 :return: 음수인지 여부 """ return self.sign def __neg__(self) -> "Float": """ sign minus 연산( - )을 위한 operator overloading :return: 새로운 Float 객체로 return """ return Float(self.exponents[::], self.fractions[::], ~self.sign) def __add__(self, other: "Float") -> "Float": """ Binary Add 연산 ( + )을 위한 operator overloading exponent를 같은 값으로 만든 후 fraction 덧셈 연산 :param other: Float 타입 가정 :return: 새로운 Float 객체로 return """ exp, a_frac, b_frac = Arithmetic.equalize_exponent(self.exponents, self.fractions, other.exponents, other.fractions) if BitOperation.raw_ge_bits(a_frac, b_frac): sign = self.sign else: sign = other.sign if self.sign ^ other.sign: res, overflow = Arithmetic.sub_bits(a_frac, b_frac, self.fraction_len+1) if sign: res = Arithmetic.decomplement_bits(res, self.fraction_len+1) else: res, overflow = Arithmetic.add_bits(a_frac, b_frac, self.fraction_len+1) if overflow: res.insert(0, overflow) res = res[:-1] exp, _ = Arithmetic.add_bits(exp, BitOperation.num_map['1'], self.exponent_len) first = BitOperation.first_bit_index(res) if first != 0: res, _ = Arithmetic.add_bits(res, BitOperation.num_map['1'], self.fraction_len + 1) exp, _ = Arithmetic.raw_sub_bits(exp, Arithmetic.str_to_integer(str(first), self.exponent_len)) frac = BitOperation.raw_lshift_bits(res, first)[1:] return Float(exp, frac, sign) def __sub__(self, other: "Float") -> "Float": """ Binary Sub 연산 ( - )을 위한 operator overloading 음수로 변경한 후 add 연산 :param other: Float 타입 가정 :return: 새로운 Float 객체로 return """ return self + (-other) def __mul__(self, other: "Float") -> "Float": """ Binary Mul 연산 ( * )을 위한 operator overloading :param other: Float 타입 가정 :return: 새로운 Float 객체로 return """ a_frac = BitOperation.fraction_bits(self.fractions) b_frac = BitOperation.fraction_bits(other.fractions) exp, _ = Arithmetic.add_bits(self.exponents, other.exponents, self.exponent_len) bias = Arithmetic.str_to_integer('127', self.exponent_len) exp, _ = Arithmetic.raw_sub_bits(exp, bias) extra = BitOperation.empty_bits(self.fraction_len + 1) mul = a_frac over = BitOperation.empty_bits(self.fraction_len + 1) for bit in b_frac[:0:-1]: if bit: extra, overflow = Arithmetic.raw_add_bits(extra, mul) if overflow: over, _ = Arithmetic.add_bits(over, BitOperation.num_map['1'], self.fraction_len+1) mul = BitOperation.raw_lshift_bits(mul, 1) if BitOperation.is_empty(mul): break res = BitOperation.empty_bits(self.fraction_len + 1) mul = a_frac for bit in b_frac: if bit: res, overflow = Arithmetic.raw_add_bits(res, mul) if overflow: res = BitOperation.raw_rshift_bits(res, 1) res[0] = overflow exp, _ = Arithmetic.add_bits(exp, BitOperation.num_map['1'], self.exponent_len) mul = BitOperation.raw_rshift_bits(mul, 1) mul = BitOperation.raw_rshift_bits(mul, 1) if BitOperation.is_empty(mul): break res, _ = Arithmetic.raw_add_bits(res, over) res = res[1:] return Float(exp, res, self.sign ^ other.sign) def __truediv__(self, other: "Float") -> "Float": """ Binary Div 연산 ( / )을 위한 operator overloading :param other: Float 타입 가정 :return: 새로운 Float 객체로 return """ if other.is_zero(): if self.is_zero(): return self.nan() if self.sign ^ other.sign: return -self.inf() return self.inf() remain = BitOperation.fraction_bits(self.fractions) div = BitOperation.fraction_bits(other.fractions) exp, _ = Arithmetic.sub_bits(self.exponents, other.exponents, self.exponent_len) bias = Arithmetic.str_to_integer('127', self.exponent_len) exp, _ = Arithmetic.raw_add_bits(exp, bias) res = BitOperation.empty_bits(self.fraction_len+1) one = BitOperation.fit_bits(BitOperation.num_map['1'], self.fraction_len+1) for i in range(self.fraction_len, -1, -1): if BitOperation.raw_ge_bits(remain, div): remain, _ = Arithmetic.raw_sub_bits(remain, div) quotient = BitOperation.raw_lshift_bits(one, i) res = BitOperation.raw_or_bits(res, quotient) remain = BitOperation.raw_lshift_bits(remain, 1) else: div = BitOperation.raw_rshift_bits(div, 1) if BitOperation.first_bit_index(res) != 0: res = BitOperation.raw_lshift_bits(res, 1) exp, _ = Arithmetic.sub_bits(exp, BitOperation.num_map['1'], self.exponent_len) return Float(exp, res[1:], self.sign ^ other.sign) def __le__(self, other: "Float") -> bool: """ Low Equal 연산 ( <= )을 위한 operator overloading :param other: Float 타입 가정 :return: 새로운 Float 객체로 return """ pass def __eq__(self, other: "Float") -> bool: return self.sign == other.sign and BitOperation.eq_bits(self.exponents, other.exponents, self.exponent_len) and\ BitOperation.eq_bits(self.fractions, other.fractions, self.fraction_len)
class BitOperation: num_map = { '0': [], '1': [Bit(True)], '2': [Bit(True), Bit()], '3': [Bit(True), Bit(True)], '4': [Bit(True), Bit(), Bit()], '5': [Bit(True), Bit(), Bit(True)], '6': [Bit(True), Bit(True), Bit()], '7': [Bit(True), Bit(True), Bit(True)], '8': [Bit(True), Bit(), Bit(), Bit()], '9': [Bit(True), Bit(), Bit(), Bit(True)], '10': [Bit(True), Bit(), Bit(True), Bit()], } @staticmethod def equalize_bit_length(a: List[Bit], b: List[Bit], length: int) -> (List[Bit], List[Bit]): """ 입력받은 두 Bit List의 길이를 length 길이로 만듦 :param a: length 길이로 맞출 Bit List :param b: length 길이로 맞출 Bit List :param length: 원하는 Bit List의 길이 :return: length 길이의 a, b """ a = BitOperation.fit_bits(a, length) b = BitOperation.fit_bits(b, length) return a, b @staticmethod def eq_bits(a: List[Bit], b: List[Bit], length: int) -> bool: """ 두 Bit List의 길이를 length 길이로 맞춘 뒤 같은 지 ( == ) 비교 raw_eq_bits 함수를 통해 비교 :param a: equal 인지 확인하기 위한 BitList :param b: 비교 BitList :param length: 원하는 Bit List의 길이 :return: 값이 같은 지 여부 """ a, b = BitOperation.equalize_bit_length(a, b, length) return BitOperation.raw_eq_bits(a, b) @staticmethod def raw_eq_bits(a: List[Bit], b: List[Bit]) -> bool: """ 같은 길이의 Bit List를 값이 같은 지 ( == ) 비교 :param a: equal 인지 확인하기 위한 BitList :param b: 비교 BitList :return: 값이 같은 지 여부 """ res = Bit() for i in range(len(a)): res |= (a[i] ^ b[i]) return bool(~res) @staticmethod def le_bits(a: List[Bit], b: List[Bit], length: int) -> bool: """ 두 Bit List의 길이를 length 길이로 맞춘 뒤 a가 작거나 같은 지 ( <= ) 비교 raw_le_bits 함수를 통해 비교 :param a: less-equal 인지 확인하기 위한 BitList :param b: 비교 BitList :param length: 원하는 Bit List의 길이 :return: 값이 작거나 같은지 여부 """ a, b = BitOperation.equalize_bit_length(a, b, length) return BitOperation.raw_le_bits(a, b) @staticmethod def raw_le_bits(a: List[Bit], b: List[Bit]) -> bool: """ 같은 길이의 Bit List 중 a가 작거나 같은 지 ( <= ) 비교 :param a: less-equal 인지 확인하기 위한 BitList :param b: 비교 BitList :return: 값이 작거나 같은지 여부 """ for i in range(len(a)): if a[i] > b[i]: return False if b[i] > a[i]: return True return True @staticmethod def ge_bits(a: List[Bit], b: List[Bit], length: int) -> bool: """ 두 Bit List의 길이를 length 길이로 맞춘 뒤 a가 크거나 같은 지 ( >= ) 비교 raw_ge_bits 함수를 통해 비교 :param a: greater-equal 인지 확인하기 위한 BitList :param b: 비교 BitList :param length: 원하는 Bit List의 길이 :return: 값이 크거나 같은 지 여부 """ a, b = BitOperation.equalize_bit_length(a, b, length) return BitOperation.raw_ge_bits(a, b) @staticmethod def raw_ge_bits(a: List[Bit], b: List[Bit]) -> bool: """ 같은 길이의 Bit List 중 a가 크거나 같은 지 ( >= ) 비교 :param a: greater-equal 인지 확인하기 위한 BitList :param b: 비교 BitList :return: 값이 크거나 같은 지 여부 """ for i in range(len(a)): if a[i] > b[i]: return True if b[i] > a[i]: return False return True @staticmethod def and_bits(a: List[Bit], b: List[Bit], length: int) -> List[Bit]: """ Bit List의 길이를 같게 만든 후 And ( & ) 연산 raw_and_bits 함수를 통해 연산 :param a: And 연산을 수행할 Bit List :param b: And 연산을 수행할 Bit List :param length: 원하는 Bit List의 길이 :return: And 연산 결과 Bit List """ a, b = BitOperation.equalize_bit_length(a, b, length) return BitOperation.raw_and_bits(a, b) @staticmethod def raw_and_bits(a: List[Bit], b: List[Bit]) -> List[Bit]: """ Bit List 의 And ( & ) 연산 :param a: And 연산을 수행할 Bit List :param b: And 연산을 수행할 Bit List :return: And 연산 결과 Bit List """ return [a[i] & b[i] for i in range(len(a))] @staticmethod def xor_bits(a: List[Bit], b: List[Bit], length: int) -> List[Bit]: """ Bit List의 길이를 같게 만든 후 Xor ( ^ ) 연산 raw_xor_bits 함수를 통해 연산 :param a: Xor 연산을 수행할 Bit List :param b: Xor 연산을 수행할 Bit List :param length: 원하는 Bit List의 길이 :return: Xor 연산 결과 Bit List """ a, b = BitOperation.equalize_bit_length(a, b, length) return BitOperation.raw_xor_bits(a, b) @staticmethod def raw_xor_bits(a: List[Bit], b: List[Bit]) -> List[Bit]: """ Bit List 의 Xor ( ^ ) 연산 :param a: Xor 연산을 수행할 Bit List :param b: Xor 연산을 수행할 Bit List :return: Xor 연산 결과 Bit List """ return [a[i] ^ b[i] for i in range(len(a))] @staticmethod def or_bits(a: List[Bit], b: List[Bit], length: int) -> List[Bit]: """ Bit List의 길이를 같게 만든 후 Or ( | ) 연산 raw_or_bits 함수를 통해 연산 :param a: Or 연산을 수행할 Bit List :param b: Or 연산을 수행할 Bit List :param length: 원하는 Bit List의 길이 :return: Or 연산 결과 Bit List """ a, b = BitOperation.equalize_bit_length(a, b, length) return BitOperation.raw_or_bits(a, b) @staticmethod def raw_or_bits(a: List[Bit], b: List[Bit]) -> List[Bit]: """ Bit List 의 Or ( | ) 연산 :param a: Or 연산을 수행할 Bit List :param b: Or 연산을 수행할 Bit List :return: Or 연산 결과 Bit List """ return [a[i] | b[i] for i in range(len(a))] @staticmethod def lshift_bits(a: List[Bit], index: int or List[Bit], length: int) -> List[Bit]: """ Bit List의 길이를 length 길이로 만든 후 left-shift ( << ) 연산 index를 Bit List 값일 경우 shift 연산을 위해 int 값으로 변경 raw_lshift_bits 함수 이용 :param a: left-shift 연산할 Bit List :param index: left-shift 할 크기 :param length: 원하는 Bit List의 길이 :return: index 크기만큼 left-shift 한 Bit List """ if type(index) == list: index = BitOperation.binary_to_decimal(index) a = BitOperation.fit_bits(a, length) return BitOperation.raw_lshift_bits(a, index) @staticmethod def raw_lshift_bits(a: List[Bit], index: int) -> List[Bit]: """ Bit List를 left-shift ( << ) 연산 :param a: left-shift 연산할 Bit List :param index: left-shift 할 크기 :return: index 크기만큼 left-shift 한 Bit List """ bits = BitOperation.empty_bits(len(a)) bits[:len(a) - index] = a[index:] return bits @staticmethod def rshift_bits(a: List[Bit], index: int or List[Bit], length: int) -> List[Bit]: """ Bit List의 길이를 length 길이로 만든 후 right-shift ( >> ) 연산 index를 Bit List 값일 경우 shift 연산을 위해 int 값으로 변경 raw_rshift_bits 함수 이용 :param a: right-shift 연산할 Bit List :param index: right-shift 할 크기 :param length: 원하는 Bit List의 길이 :return: index 크기만큼 right-shift 한 Bit List """ if type(index) == list: index = BitOperation.binary_to_decimal(index) a = BitOperation.fit_bits(a, length) return BitOperation.raw_rshift_bits(a, index) @staticmethod def raw_rshift_bits(a: List[Bit], index: int) -> List[Bit]: """ Bit List를 right-shift ( >> )연산 :param a: right-shift 연산할 Bit List :param index: right-shift 할 크기 :return: index 크기만큼 right-shift 한 Bit List """ bits = BitOperation.empty_bits(len(a)) bits[index:] = a[:len(a) - index] return bits @staticmethod def fraction_bits(a: List[Bit]) -> List[Bit]: """ float 값의 fraction에 생략된 1을 추가하는 함수 :param a: 소수점의 유효숫자만 표현된 가수 값 :return: 1이 추가된 가수 값 """ frac = a[::] frac.insert(0, Bit(True)) return frac @staticmethod def invert_bits(a: List[Bit]) -> List[Bit]: """ Bit List에 invert ( ~ ) 연산 Bit List의 모든 Bit의 값을 반대로 뒤집음 :param a: invert 연산할 Bit List :return: invert 연산된 Bit List """ return [~bit for bit in a] @staticmethod def fit_bits(a: List[Bit], length: int) -> List[Bit]: """ Bit List를 length 길이로 만듦 length 보다 길 경우 뒤에서부터 length 길이로 자르고 length 보다 짧을 경우 0을 앞에 추가함 :param a: length 길이로 만들 Bit List :param length: 원하는 Bit List의 길이 :return: length 길이의 Bit List """ if len(a) >= length: return a[-length:] if len(a) == length: return a[::] empty = BitOperation.empty_bits(length) for i in range(1, len(a) + 1): empty[-i] = a[-i] return empty @staticmethod def is_empty(a: List[Bit]) -> bool: """ Bit List의 모든 Bit 가 0인지 확인 :param a: 모든 Bit 가 0인지 확인할 함수 :return: 모든 Bit 가 0인지 여부 """ if not a: return True return not reduce(lambda x, y: x | y, a) @staticmethod def empty_bits(length: int) -> List[Bit]: """ length 길이의 비어있는 Bit List를 생성하는 함수 :param length: 원하는 Bit List의 길이 :return: 비어있는 length 길이의 Bit List """ return [Bit() for _ in range(length)] @staticmethod def binary_to_decimal(a: List[Bit]) -> int: """ 입력받은 Bit List의 값을 읽어 int로 변환하는 함수 python 의 기능을 실행시키기 위해 int로 변환할 때 사용 ( << 연산 등 ) :param a: int 값을 확인하기 위한 Bit List :return: Bit List에 해당하는 int 값 """ res = 0 frame = 1 for bit in a[::-1]: if bit: res += frame frame <<= 1 return res @staticmethod def binary_to_float(exp: List[Bit], fraction: List[Bit]) -> float: """ 입력받은 exponent와 fraction을 읽어 float값으로 변환하는 함수 :param exp: exponent (지수) 값 :param fraction: fraction (가수) 값 :return: 가수 * 2 ^ 지수 """ res = 0 exp = BitOperation.binary_to_decimal(exp) - 127 - len(fraction) frame = 2**exp for bit in fraction[::-1]: if bit: res += frame frame *= 2 res += frame return res @staticmethod def first_bit_index(a: List[Bit]) -> int: """ Bit List에서 첫 1의 위치를 찾는 함수 없을 경우 Bit List의 길이 값을 return :param a: 첫 1의 위치를 찾을 Bit List :return: 첫 1의 위치 """ for i in range(len(a)): if a[i]: return i return len(a)
def __init__(self, exponents: list or float or int or str = None, fractions: list = None, sign: Bit = Bit()): if type(exponents) == str: res = self.str_to_float(exponents) self.sign = res.sign self.exponents = res.exponents self.fractions = res.fractions elif type(exponents) == float or type(exponents) == int: self.sign = sign self.exponents = self.default_exponent_field[::] self.fractions = self.default_fraction_field[::] self.set(exponents) elif type(exponents) == list: self.sign = sign self.exponents = exponents self.fractions = fractions else: self.sign = sign self.exponents = self.default_exponent_field[::] self.fractions = self.default_fraction_field[::]
class ControlSignal(enum.Enum): NOT = [Bit(), Bit(), Bit(), Bit()] # 0 AND = [Bit(), Bit(), Bit(), Bit(True)] # 1 NAND = [Bit(), Bit(), Bit(True), Bit()] # 2 OR = [Bit(), Bit(), Bit(True), Bit(True)] # 3 NOR = [Bit(), Bit(True), Bit(), Bit()] # 4 XOR = [Bit(), Bit(True), Bit(), Bit(True)] # 5 XNOR = [Bit(), Bit(True), Bit(True), Bit()] # 6 INC = [Bit(), Bit(True), Bit(True), Bit(True)] # 7 DEC = [Bit(True), Bit(), Bit(), Bit()] # 8 MINUS = [Bit(True), Bit(), Bit(), Bit(True)] # 9 ADD = [Bit(True), Bit(), Bit(True), Bit()] # 10 SUB = [Bit(True), Bit(), Bit(True), Bit(True)] # 11 LSHIFT = [Bit(True), Bit(True), Bit(), Bit()] # 12 RSHIFT = [Bit(True), Bit(True), Bit(), Bit(True)] # 13