Ejemplo n.º 1
0
def positrep_to_str(rep):
    if rep['t'] == 'z':
        return '0'
    elif rep['t'] == 'c':
        return 'cinf'

    assert rep['t'] == 'n'

    out = ''
    if rep['s'] == 1:
        out = '-'

    E = (2**rep['es'] * rep['k']) + rep['e']
    V = (1 << rep['h']) + rep['f']
    D = rep['h']

    if E >= 0:
        V <<= E
    else:
        D += -E

    mask = bitops.create_mask(D)
    fraction_bits = V & mask
    integral = V >> D

    num = 0
    den = 1
    for d in range(D):
        if fraction_bits & 0x01 == 1:
            num += den
        den *= 2
        fraction_bits >>= 1

    if num == 0:
        out += str(integral)
    else:
        if integral != 0:
            out += str(integral)
            out += '-' if rep['s'] == 1 else '+'
        g = gcd(num, den)
        num //= g
        den //= g
        out += str(num) + '/' + str(den)

    return out
Ejemplo n.º 2
0
    def run_posit_2op_exhaustive(self,
                                 op_str=None,
                                 nbits_range=None,
                                 es_range=None):
        op = None
        mpop = None
        if op_str == '+':
            op = PCPosit.__add__
            mpop = mp.mpf.__add__
        elif op_str == '-':
            op = PCPosit.__sub__
            mpop = mp.mpf.__sub__
        elif op_str == '*':
            op = PCPosit.__mul__
            mpop = mp.mpf.__mul__
        elif op_str == '/':
            op = PCPosit.__truediv__
            mpop = mp.mpf.__truediv__
        else:
            raise NotImplementedError("op={}".format(op_str))

        if nbits_range is None:
            nbits_range = self.nbits_range
        if es_range is None:
            es_range = self.es_range

        for nbits in nbits_range:
            mask = bitops.create_mask(nbits)
            cinf_bits = 1 << (nbits - 1)
            is_special = lambda bits: bits == 0 or bits == cinf_bits
            is_normal = lambda bits: not is_special(bits)
            for es in es_range:
                for abits in range(2**nbits):
                    for bbits in range(2**nbits):
                        a = PCPosit(abits, nbits=nbits, es=es, mode='bits')
                        b = PCPosit(bbits, nbits=nbits, es=es, mode='bits')
                        c = op(a, b)
                        cbits = coder.encode_posit_binary(c.rep)

                        test_info = {
                            'nbits': nbits,
                            'es': es,
                            'a': str(a),
                            'b': str(b),
                            'c': str(c),
                            'abits': abits,
                            'bbits': bbits,
                            'cbits': cbits,
                            'arep': a.rep,
                            'brep': b.rep,
                            'crep': c.rep,
                        }

                        if is_normal(abits) and is_normal(
                                bbits) and cbits == 0:
                            self.assertTrue(op_str in ['+', '-'])
                            if op_str == '+':
                                self.assertEqual(abits, -bbits & mask)
                            else:  # '-'
                                self.assertEqual(abits, bbits)

                        elif is_normal(abits) and is_normal(bbits):
                            self.assertNotEqual(cbits, 0)
                            self.assertNotEqual(cbits, cinf_bits)

                            amp = mp.mpf(
                                eval(coder.positrep_to_rational_str(a.rep)))
                            bmp = mp.mpf(
                                eval(coder.positrep_to_rational_str(b.rep)))
                            c2mp = mpop(amp, bmp)

                            c0bits = (cbits - 1) & mask
                            while c0bits == 0 or c0bits == cinf_bits:
                                c0bits = (c0bits - 1) & mask

                            c1bits = (cbits + 1) & mask
                            while c1bits == 0 or c1bits == cinf_bits:
                                c1bits = (c1bits + 1) & mask

                            c0 = PCPosit(c0bits,
                                         nbits=nbits,
                                         es=es,
                                         mode='bits')
                            c1 = PCPosit(c1bits,
                                         nbits=nbits,
                                         es=es,
                                         mode='bits')

                            test_info['c0'] = str(c0)
                            test_info['c1'] = str(c1)
                            test_info['c0bits'] = c0bits
                            test_info['c1bits'] = c1bits
                            test_info['c0rep'] = c0.rep
                            test_info['c1rep'] = c1.rep

                            rcmp = mp.mpf(
                                eval(coder.positrep_to_rational_str(c.rep)))
                            cratiodiffmp = mp.fabs(mp.log(
                                rcmp / c2mp)) if c2mp != 0 else mp.fabs(rcmp -
                                                                        c2mp)
                            cabsdiffmp = mp.fabs(rcmp - c2mp)

                            c0mp = mp.mpf(
                                eval(coder.positrep_to_rational_str(c0.rep)))
                            c0ratiodiffmp = mp.fabs(mp.log(
                                c0mp / c2mp)) if c2mp != 0 else mp.fabs(c0mp -
                                                                        c2mp)
                            c0absdiffmp = mp.fabs(c0mp - c2mp)
                            self.assertTrue(
                                cratiodiffmp <= c0ratiodiffmp
                                or cabsdiffmp <= c0absdiffmp, test_info)

                            c1mp = mp.mpf(
                                eval(coder.positrep_to_rational_str(c1.rep)))
                            c1ratiodiffmp = mp.fabs(mp.log(
                                c1mp / c2mp)) if c2mp != 0 else mp.fabs(c1mp -
                                                                        c2mp)
                            c1absdiffmp = mp.fabs(c1mp - c2mp)
                            self.assertTrue(
                                cratiodiffmp <= c1ratiodiffmp
                                or cabsdiffmp <= c1absdiffmp, test_info)

                        elif abits == cinf_bits:
                            self.assertTrue(op_str in ['+', '-', '*', '/'])
                            self.assertEqual(cbits, cinf_bits)

                        elif abits != cinf_bits and bbits == cinf_bits:
                            self.assertTrue(op_str in ['+', '-', '*', '/'])
                            if op_str == '/':
                                self.assertEqual(cbits, 0)
                            else:
                                self.assertEqual(cbits, cinf_bits)

                        elif abits == 0 and bbits == 0:
                            self.assertTrue(op_str in ['+', '-', '*', '/'])
                            if op_str == '/':
                                self.assertEqual(cbits, cinf_bits)
                            else:
                                self.assertEqual(cbits, 0)

                        elif is_normal(abits) and bbits == 0:
                            if op_str == '+' or op_str == '-':
                                self.assertEqual(cbits, abits)
                            elif op_str == '*':
                                self.assertEqual(cbits, 0)
                            elif op_str == '/':
                                self.assertEqual(cbits, cinf_bits)
                            else:
                                self.assertTrue(False)

                        elif abits == 0 and is_normal(bbits):
                            self.assertTrue(op_str in ['+', '-', '*', '/'])
                            if op_str == '+':
                                self.assertEqual(cbits, bbits)
                            elif op_str == '-':
                                self.assertEqual(cbits, -bbits & mask)
                            else:
                                self.assertEqual(cbits, 0)

                        else:
                            self.assertTrue(False)
Ejemplo n.º 3
0
def encode_posit_binary(rep):
    assert rep['nbits'] >= 2
    assert rep['es'] >= 0
    assert rep['s'] == 0 or rep['s'] == 1
    #assert rep['k'] >= -rep['nbits'] + 2 and rep['k'] <= rep['nbits'] - 2, rep
    assert rep['e'] >= 0 and rep['e'] <= 2**rep['es'] - 1
    #assert rep['h'] >= 0 and rep['h'] <= max(0, rep['nbits'] - 1 - 2 - rep['es'])
    assert rep['f'] >= 0 and rep['f'] <= 2**rep['h'] - 1
    assert rep['t'] in ['c', 'n', 'z']

    if rep['t'] == 'z':
        return 0
    elif rep['t'] == 'c':
        return 1 << (rep['nbits'] - 1)

    assert rep['t'] == 'n'

    n = rep[
        'nbits'] - 1  # Remaining number of bits after reserving 1 for sign bit.
    bits = 0
    rounded = False

    if rep['k'] >= 0:
        if n >= rep['k'] + 1:
            bits = bitops.create_mask(rep['k'] + 1)
            n -= rep['k'] + 1

            assert n >= 0

            if n > 0:
                bits <<= 1
                n -= 1
        else:
            bits = bitops.create_mask(n)
            n = 0
            rounded = True
    else:
        bits = 1
        if n < -rep['k'] + 1:
            rounded = True
        n -= min(n, -rep['k'] + 1)

    assert n >= 0

    if n >= rep['es']:
        bits <<= rep['es']
        bits |= rep['e']
        n -= rep['es']
    elif rounded == False:
        assert rep['es'] > 0

        m = rep['es'] - n  # Number of exponent bits to truncate.
        te = rep['e'] >> m
        te <<= m  # Rounded down exponent bits.

        value = rep['e'] * 2**rep['h'] + rep['f']
        represented_value = te * 2**rep['h']
        truncation = value - represented_value
        tie = 2**(m + rep['h'] - 1)

        te >>= m  # Truncated exponent bits.
        bits <<= n
        bits |= te
        n = 0

        if truncation == tie:
            if bits & 0x01 and bits + 1 < 2**(rep['nbits'] - 1):
                bits += 1
        elif truncation > tie:
            if bits + 1 < 2**(rep['nbits'] - 1):
                bits += 1

        rounded = True

    if n >= 0:
        if n > rep['h']:
            bits <<= rep['h']
            bits |= rep['f']
            n -= rep['h']

            bits <<= n
            n = 0
        elif rounded == False:
            m = rep['h'] - n  # Number of fractional bits to truncate.
            tf = rep['f'] >> m
            tf <<= m  # Rounded down fractional bits.

            value = rep['f']
            represented_value = tf
            truncation = value - represented_value
            tie = 2**(m - 1)

            tf >>= m  # Truncated fractional bits.
            bits <<= n
            bits |= tf
            n = 0

            if truncation == tie:
                if bits & 0x01 and bits + 1 < 2**(rep['nbits'] - 1):
                    bits += 1
            elif truncation > tie:
                if bits + 1 < 2**(rep['nbits'] - 1):
                    bits += 1

            rounded = True

    if rep['s'] == 1:
        bits = -bits
        mask = bitops.create_mask(rep['nbits'])
        bits &= mask

    return bits
    def run_posit_2op_exhaustive(self,
                                 op_str=None,
                                 nbits_range=None,
                                 es_range=None):
        op = None
        mpop = None
        if op_str == '+':
            op = PCPosit.__add__
            mpop = mp.mpf.__add__
        elif op_str == '-':
            op = PCPosit.__sub__
            mpop = mp.mpf.__sub__
        elif op_str == '*':
            op = PCPosit.__mul__
            mpop = mp.mpf.__mul__
        elif op_str == '/':
            op = PCPosit.__truediv__
            mpop = mp.mpf.__truediv__
        else:
            raise NotImplementedError("op={}".format(op_str))

        for nbits in nbits_range:
            mask = bitops.create_mask(nbits)
            for es in es_range:
                for abits in range(2**nbits):
                    for bbits in range(2**nbits):
                        a = PCPosit(abits, nbits=nbits, es=es, mode='bits')
                        b = PCPosit(bbits, nbits=nbits, es=es, mode='bits')
                        c = op(a, b)

                        if a.rep['t'] == 'n' and b.rep['t'] == 'n':
                            amp = mp.mpf(
                                eval(coder.positrep_to_rational_str(a.rep)))
                            bmp = mp.mpf(
                                eval(coder.positrep_to_rational_str(b.rep)))
                            c2mp = mpop(amp, bmp)
                            c0 = PCPosit((bbits - 1) & mask,
                                         nbits=nbits,
                                         es=es,
                                         mode='bits')
                            c1 = PCPosit((bbits + 1) & mask,
                                         nbits=nbits,
                                         es=es,
                                         mode='bits')

                            cbits = coder.encode_posit_binary(c.rep)
                            roundedc = coder.decode_posit_binary(cbits,
                                                                 nbits=nbits,
                                                                 es=es)

                            rcmp = mp.mpf(
                                eval(coder.positrep_to_rational_str(roundedc)))
                            cratiodiffmp = mp.fabs(mp.log(
                                rcmp / c2mp)) if c2mp != 0 else mp.fabs(rcmp -
                                                                        c2mp)
                            cabsdiffmp = mp.fabs(rcmp - c2mp)
                            if c0.rep['t'] != 'c':
                                c0mp = mp.mpf(
                                    eval(coder.positrep_to_rational_str(
                                        c0.rep)))
                                c0ratiodiffmp = mp.fabs(mp.log(
                                    c0mp /
                                    c2mp)) if c2mp != 0 else mp.fabs(c0mp -
                                                                     c2mp)
                                c0absdiffmp = mp.fabs(c0mp - c2mp)
                                self.assertTrue(cratiodiffmp <= c0ratiodiffmp
                                                or cabsdiffmp <= c0absdiffmp)
                            if c1.rep['t'] != 'c':
                                c1mp = mp.mpf(
                                    eval(coder.positrep_to_rational_str(
                                        c1.rep)))
                                c1ratiodiffmp = mp.fabs(mp.log(
                                    c1mp /
                                    c2mp)) if c2mp != 0 else mp.fabs(c1mp -
                                                                     c2mp)
                                c1absdiffmp = mp.fabs(c1mp - c2mp)
                                self.assertTrue(cratiodiffmp <= c1ratiodiffmp
                                                or cabsdiffmp <= c1absdiffmp)