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
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)
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)