def run_posit_op(self, abits=None, op_str=None, bbits=None, ref_cbits=None, nbits=None, es=None): a = PCPosit(abits, nbits=nbits, es=es, mode='bits') b = PCPosit(bbits, nbits=nbits, es=es, mode='bits') c = None if op_str == '+': c = a + b elif op_str == '-': c = a - b elif op_str == '*': c = a * b elif op_str == '/': c = a / b elif op_str == 'u-': c = -a else: raise NotImplementedError("op={}".format(op_str)) cbits = coder.encode_posit_binary(c.rep) self.assertEqual(cbits, ref_cbits)
def __truediv__(self, other): if self.rep['t'] == 'c' or other.rep['t'] == 'z': p = PCPosit() # FIXME: Use constructor to directly initialized to posit zero. p.rep = coder.create_cinf_positrep(nbits=self.rep['nbits'], es=self.rep['es']) return p elif self.rep['t'] == 'z' or other.rep['t'] == 'c': p = PCPosit() # FIXME p.rep = coder.create_zero_positrep(nbits=self.rep['nbits'], es=self.rep['es']) return p assert self.rep['t'] == 'n' and other.rep['t'] == 'n' xa = ( -1)**self.rep['s'] * ( 2**self.rep['h'] + self.rep['f']) xb = (-1)**other.rep['s'] * (2**other.rep['h'] + other.rep['f']) ma = 2**self.rep['es'] * self.rep['k'] + self.rep['e'] - self.rep['h'] mb = 2**other.rep['es'] * other.rep['k'] + other.rep['e'] - other.rep['h'] pc = PCPosit() # FIXME pc.rep = coder.create_zero_positrep(nbits=self.rep['nbits'], es=self.rep['es']) pc.rep['t'] = 'n' if (xa < 0) ^ (xb < 0): pc.rep['s'] = 1 if xa < 0: xa = -xa if xb < 0: xb = -xb g = ma - mb + (2**pc.rep['es'])*(pc.rep['nbits']-2) + pc.rep['nbits'] - 1 g = max(0, g) xc = (xa * 2**g) // xb mc = ma - mb - g if xc != 0: while xc != 0 and xc % 2 == 0: xc >>= 1 mc += 1 g = 0 x = xc while x >= 2: x >>= 1 g -= 1 assert x >= 1 and x < 2, "x={}".format(x) pc.rep['e'] = (mc - g) % 2**pc.rep['es'] pc.rep['k'] = (mc - g) // 2**pc.rep['es'] pc.rep['h'] = -g pc.rep['f'] = xc - 2**pc.rep['h'] else: pc.rep = coder.create_zero_positrep(nbits=self.rep['nbits'], es=self.rep['es']) bits = coder.encode_posit_binary(pc.rep) pc.rep = coder.decode_posit_binary(bits, nbits=pc.rep['nbits'], es=pc.rep['es']) return pc
def __add__(self, other): if self.rep['t'] == 'z': return PCPosit(other) elif other.rep['t'] == 'z': return PCPosit(self) elif self.rep['t'] == 'c' or other.rep['t'] == 'c': ret = PCPosit(2**(self.rep['nbits']-1), mode='bits', nbits=self.rep['nbits'], es=self.rep['es']) return ret assert self.rep['t'] == 'n' and other.rep['t'] == 'n' xa = ( -1)**self.rep['s'] * ( 2**self.rep['h'] + self.rep['f']) xb = (-1)**other.rep['s'] * (2**other.rep['h'] + other.rep['f']) ma = 2**self.rep['es'] * self.rep['k'] + self.rep['e'] - self.rep['h'] mb = 2**other.rep['es'] * other.rep['k'] + other.rep['e'] - other.rep['h'] m = max(ma, mb) xc = xa*2**(m-mb) + xb*2**(m-ma) mc = ma + mb - m pc = PCPosit(self, nbits=self.rep['nbits'], es=self.rep['es']) pc.rep = coder.create_positrep(nbits=self.rep['nbits'], es=self.rep['es']) if xc == 0: pc.rep['t'] = 'z' return pc elif xc < 0: xc = -xc pc.rep['s'] = 1 while xc != 0 and xc % 2 == 0: xc >>= 1 mc += 1 g = 0 x = xc while x >= 2: x >>= 1 g -= 1 assert x >= 1 and x < 2, "x={}".format(x) pc.rep['e'] = (mc - g) % 2**pc.rep['es'] pc.rep['k'] = (mc - g) // 2**pc.rep['es'] pc.rep['h'] = -g pc.rep['f'] = xc - 2**pc.rep['h'] bits = coder.encode_posit_binary(pc.rep) pc.rep = coder.decode_posit_binary(bits, nbits=pc.rep['nbits'], es=pc.rep['es']) return pc
def __mul__(self, other): if self.rep['t'] == 'c' or other.rep['t'] == 'c': p = PCPosit() # FIXME: Use constructor to directly initialized to posit zero. p.rep = coder.create_cinf_positrep(nbits=self.rep['nbits'], es=self.rep['es']) return p elif self.rep['t'] == 'z' or other.rep['t'] == 'z': p = PCPosit() # FIXME p.rep = coder.create_zero_positrep(nbits=self.rep['nbits'], es=self.rep['es']) return p assert self.rep['t'] == 'n' and other.rep['t'] == 'n' xa = ( -1)**self.rep['s'] * ( 2**self.rep['h'] + self.rep['f']) xb = (-1)**other.rep['s'] * (2**other.rep['h'] + other.rep['f']) ma = 2**self.rep['es'] * self.rep['k'] + self.rep['e'] - self.rep['h'] mb = 2**other.rep['es'] * other.rep['k'] + other.rep['e'] - other.rep['h'] xc = xa * xb mc = ma + mb pc = PCPosit() # FIXME pc.rep = coder.create_zero_positrep(nbits=self.rep['nbits'], es=self.rep['es']) pc.rep['t'] = 'n' if xc < 0: xc = -xc pc.rep['s'] = 1 while xc != 0 and xc % 2 == 0: xc >>= 1 mc += 1 g = 0 x = xc while x >= 2: x >>= 1 g -= 1 assert x >= 1 and x < 2, "x={}".format(x) pc.rep['e'] = (mc - g) % 2**pc.rep['es'] pc.rep['k'] = (mc - g) // 2**pc.rep['es'] pc.rep['h'] = -g pc.rep['f'] = xc - 2**pc.rep['h'] bits = coder.encode_posit_binary(pc.rep) pc.rep = coder.decode_posit_binary(bits, nbits=pc.rep['nbits'], es=pc.rep['es']) return pc
def _fixedpoint_to_posit(cls, x, m, nbits=None, es=None): assert nbits is not None assert es is not None if x == 0: return PCPosit('0', nbits=nbits, es=es) p = PCPosit(nbits=nbits, es=es) p.rep['t'] = 'n' p.rep['s'] = 0 if x < 0: x = -x p.rep['s'] = 1 assert x != 0 while x != 0 and x % 2 == 0: x >>= 1 m += 1 g = 0 y = x while y >= 2: y >>= 1 g -= 1 assert y >= 1 and y < 2, "y={}".format(y) p.rep['e'] = (m - g) % 2**es p.rep['k'] = (m - g) // 2**es p.rep['h'] = -g p.rep['f'] = x - 2**p.rep['h'] bits = coder.encode_posit_binary(p.rep) p.rep = coder.decode_posit_binary(bits, nbits=nbits, es=es) return p
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 __repr__(self): nbits, es = self.rep['nbits'], self.rep['es'] bits = coder.encode_posit_binary(self.rep) template = "PCPosit({}, mode='bits', nbits={}, es={})" return template.format(hex(bits), nbits, es)
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)