示例#1
0
def mul(a, b):
    """
    Return the unsigned product
    of a-arg and b-arg unsigned binary strings.

    Remark: the product is of the same bit number
    as the bigger argument so this method is to be used
    with small numbers to avoid overflows.
    """
    p = '0'
    a, b = _align(a, b)

    for bit in reversed(a):
        if bit == '1':
            p = basic.sum(p, b)
        b = basic.shift_left(b)

    return p
示例#2
0
def idiv(a, b, rus_output=False):
    """
    Return tuple of quotient and remainder of a-arg / b-arg
    as well as boolean indicating whether an error has occured.

    Remark: a-arg and b-arg are 2s-complement binary strings.

    Another remark:
    (here I am using python int variables and binary string variables
    interchangeably since any one of the former type corresponds to
    the one of the latter)

    Let's say q, r = idiv(a, b).

    Well, while a is indeed equal to q*b + r,
    q is not necessary a // b and r is not necessary a % b.
    """
    if rus_output:
        print('Поделим следующие числа в дополнительном коде:')
        print('a = {0}(2) = {1}(10)'.format(
            a, bsio.twos_comp_binary_string_to_int(a)))
        print('b = {0}(2) = {1}(10)\n'.format(
            b, bsio.twos_comp_binary_string_to_int(b)))

    if bsio.twos_comp_binary_string_to_int(b) == 0:
        print('Ошибка: деление на ноль.')
        raise ZeroDivisionError

    a, b = _align(a, b)
    M = b
    AQ = basic.expand_to_len(a, len(a) * 2)
    A, Q = AQ[:len(a)], AQ[-len(a):]

    if rus_output:
        print('Установим значения регистров A, Q и M:')
        print('A: {0}'.format(A))
        print('Q: {0}'.format(Q))
        print('M: {0}\n'.format(M))

        print('A:' + ' ' * (len(A) - 2) + ' Q:\n')

    for _ in range(len(a)):
        AQ = basic.shift_left(A + Q)
        A, Q = AQ[:len(a)], AQ[-len(a):]

        old_A = A
        if M[0] == A[0]:
            A = dif(A, M)[0]
        else:
            A = basic.sum(A, M)[0]

        if old_A[0] == A[0] or A == Q == basic.expand_to_len('0', len(A)):
            Q = Q[:-1] + '1'
        else:
            Q = Q[:-1] + '0'
            A = old_A

        if rus_output:
            print('{0} {1}'.format(A, Q))

    r = A
    q = Q if a[0] == b[0] else basic.neg(Q)[0]

    if rus_output:
        print('')
    error_bool = False
    if basic.neg(Q)[1]:
        error_bool = True
        if rus_output:
            print('Произошло переполнение.')

    if rus_output:
        print('Результат деления:\n' + 'q = {0}(2) = {1}(10)\n'.format(
            q, bsio.twos_comp_binary_string_to_int(q)) +
              'r = {0}(2) = {1}(10)'.format(
                  r, bsio.twos_comp_binary_string_to_int(r)))

    return q, r, error_bool
    def __mul__(self, other):
        """
        Return product of two Floats.

        (a draft; seems to be working with 1 bit error)
        """

        # step 1: account for special cases.
        # i.e. nans present -> nan
        #      zeros present -> zeros
        #      infs present -> signed inf
        #
        #     but also (this overrides what's above):
        #       inf * zero -> nan

        # TODO: step 1.

        # interstep: setup.

        sign_one = self.sign_bit
        exponent_one = self.exponent
        mantissa_one = self.mantissa

        sign_two = other.sign_bit
        exponent_two = other.exponent
        mantissa_two = other.mantissa

        prod_sign = '0' if sign_one == sign_two else '1'

        # step 2: get exponents' sum.
        # 2a: get it:

        exponent_sum = basic.sum(exponent_one, exponent_two)
        exponent_sum = ('0' + ('1' if exponent_sum[1] else '0') +
                        exponent_sum[0])
        exponent_sum = basic.sum(exponent_sum, '01')[0]
        exponent_sum = arth.dif(exponent_sum,
                                '0' + '1' * (EXPONENT_BIT_COUNT - 1))[0]

        # 2b: check the overflow or the underflow or whatever.
        #     (just whether exponents' sum fits in 8 bits)

        if set(exponent_sum[:2]) != set('0'):
            return (self.pos_infinity() if
                    (prod_sign == '0') else self.neg_infinity())

        prod_exponent = exponent_sum[2:]

        # step 3: get mantissas' 48-bit product.

        # the following line is a bit crappy but it works as it should.
        prod_mantissa = arth.imul('0' + mantissa_one, '0' + mantissa_two)[2:]

        # step 4: normalize the result.
        # (if during normalization exponent goes zero, break the loop)

        while (prod_mantissa[0] == '0'
               and prod_exponent != '0' * EXPONENT_BIT_COUNT):
            prod_mantissa = basic.shift_left(prod_mantissa)
            # decrementing exponent:
            prod_exponent = basic.sum(prod_exponent, '11')[0]

        prod_mantissa = prod_mantissa[:(MANTISSA_BIT_COUNT + 1)]

        # finally return the result.
        prod_binary = prod_sign + prod_exponent + prod_mantissa[1:]
        prod = deepcopy(self)
        prod.binary = prod_binary

        return prod
    def __truediv__(self, other):
        """
        Return quotient of two Floats.

        (a draft; seems to be working with 2 bit error)

        NOTE: denormal numbers are processed as zeros for now.
              this could be changed but meh.
        """

        # step 1: account for special cases.
        # (zero implies zero or denormal rn)
        # i.e. divisor is zero -> error
        #      nans present -> nan
        #      inf / inf -> nan
        #      num / inf = signed zero

        # TODO: implement step 1.

        # interstep: setup.

        sign_one = self.sign_bit
        exponent_one = self.exponent
        mantissa_one = self.mantissa

        sign_two = other.sign_bit
        exponent_two = other.exponent
        mantissa_two = other.mantissa

        q_sign = '0' if sign_one == sign_two else '1'

        # step 2: calculating the difference of exponents.
        # 2a: get it.

        exponent_dif = arth.dif('0' + exponent_one, '0' + exponent_two)[0]
        exponent_dif = arth.sum(exponent_dif,
                                '0' + '1' * (EXPONENT_BIT_COUNT - 1))[0]

        # 2b: validate quotient's exponent.
        # NOTE: I hope this works.

        if exponent_dif[0] == '1':
            if binstrings.first_is_bigger(exponent_one, exponent_two):
                return (self.pos_infinity()
                        if q_sign == '0' else self.neg_infinity())
            else:
                return (self.pos_zero() if q_sign == '0' else self.neg_zero())

        q_exponent = exponent_dif[1:]

        # step 3: divide mantissas.

        mantissa_one_double = mantissa_one + '0' * MANTISSA_BIT_COUNT
        q_mantissa = arth.idiv('0' + mantissa_one_double,
                               '0' + mantissa_two)[0][-24:]

        # step 4: normalize the result.

        while q_mantissa[0] == '0' and q_exponent != '0' * EXPONENT_BIT_COUNT:
            q_mantissa = basic.shift_left(q_mantissa)
            # decrementing exponent:
            q_exponent = basic.sum(q_exponent, '11')[0]

        # finally return the result.
        q_binary = q_sign + q_exponent + q_mantissa[1:]
        q = deepcopy(self)
        q.binary = q_binary

        return q
    def __add__(self, other):
        """
        Return sum of two Floats.

        (works for random big and small pos and neg floats;
         to be tested w/ special cases;
         1 bit error sometimes - dunno why)
        """
        # step 1 (account for special cases):

        # a. NaNs:
        if self.is_nan() or other.is_nan():
            return Float(float('nan'))

        # b. two infinities:
        if self.is_infinity() and other.is_infinity():
            if self.sign_bit != other.sign_bit:
                return self.nan
            else:
                return deepcopy(self)

        # c. one infinity:
        if self.is_infinity():
            return deepcopy(self)
        elif other.is_infinity():
            return deepcopy(other)

        # d. one or two zeros:
        if self.is_zero():
            return deepcopy(other)
        elif other.is_zero():
            return deepcopy(self)

        # at this point any of the two arguments is
        # either normal or denormal
        # step 2: deconstructing arguments' binaries:

        bigger, smaller = (self,
                           other) if (self.abs() >= other.abs()) else (other,
                                                                       self)

        biggers_sign = bigger.sign_bit
        smallers_sign = smaller.sign_bit

        biggers_exponent = bigger.exponent
        smallers_exponent = smaller.exponent

        biggers_mantissa = bigger.mantissa
        smallers_mantissa = smaller.mantissa

        # step 3: aligning the exponents:

        while biggers_exponent != smallers_exponent:
            # incrementing exponent of the smaller number and shifting
            # its mantissa to the right.
            smallers_exponent = basic.sum(smallers_exponent, '01')[0]
            smallers_mantissa = basic.logical_shift_right(smallers_mantissa)

            # if mantissa of the smaller one goes zero, return
            # the bigger operand copy.
            if binstrings.is_zero(smallers_mantissa):
                return deepcopy(bigger)

        # step 4: getting mantissas' sum and setting up
        # sum's sign, exponent and mantissa:

        sum_sign = biggers_sign
        sum_exponent = biggers_exponent
        sum_mantissa = (basic.sum(biggers_mantissa, smallers_mantissa)
                        if biggers_sign == smallers_sign else basic.oc_sum(
                            biggers_mantissa,
                            basic.invert_bits(smallers_mantissa)))

        if (biggers_sign != smallers_sign
                and sum_mantissa == '1' * (MANTISSA_BIT_COUNT + 1)):
            sum_mantissa = '0' * MANTISSA_BIT_COUNT

        # shifting mantissa to fit if neccesary:
        if type(sum_mantissa) is tuple:
            if sum_mantissa[1]:
                sum_mantissa = '1' + sum_mantissa[0][:-1]
                sum_exponent = basic.sum(sum_exponent, '01')[0]

                # if exponent overflows, return infinity:
                if sum_exponent == '1' * EXPONENT_BIT_COUNT:
                    return (Float(float('inf')) if sum_sign == '0' else Float(
                        float('-inf')))
            else:
                sum_mantissa = sum_mantissa[0]

        # in case sum's mantissa is zero return zero Float.
        if (binstrings.is_zero(sum_mantissa)):
            return Float(0.)

        # step 5: normalize the number if possible.
        while sum_mantissa[0] == '0':
            sum_mantissa = basic.shift_left(sum_mantissa)
            # decrementing exponent:
            sum_exponent = basic.sum(sum_exponent, '11')[0]

            if sum_exponent == '0' * EXPONENT_BIT_COUNT:
                break

        # TODO: do this the normal way.
        sum_binary = sum_sign + sum_exponent + sum_mantissa[1:]
        sum_float = deepcopy(self)
        sum_float.binary = sum_binary
        return sum_float