def msum(iterable): """Full precision summation. Compute sum(iterable) without any intermediate accumulation of error. Based on the 'lsum' function at http://code.activestate.com/recipes/393090/ """ tmant, texp = 0, 0 for x in iterable: mant, exp = math.frexp(x) mant, exp = int(math.ldexp(mant, mant_dig)), exp - mant_dig if texp > exp: tmant <<= texp-exp texp = exp else: mant <<= exp-texp tmant += mant # Round tmant * 2**texp to a float. The original recipe # used float(str(tmant)) * 2.0**texp for this, but that's # a little unsafe because str -> float conversion can't be # relied upon to do correct rounding on all platforms. tail = max(len(bin(abs(tmant)))-2 - mant_dig, etiny - texp) if tail > 0: h = 1 << (tail-1) tmant = tmant // (2*h) + bool(tmant & h and tmant & 3*h-1) texp += tail return math.ldexp(tmant, texp)
def testLdexp(self): self.assertRaises(TypeError, math.ldexp) self.ftest('ldexp(0,1)', math.ldexp(0,1), 0) self.ftest('ldexp(1,1)', math.ldexp(1,1), 2) self.ftest('ldexp(1,-1)', math.ldexp(1,-1), 0.5) self.ftest('ldexp(-1,1)', math.ldexp(-1,1), -2) ###self.assertRaises(OverflowError, math.ldexp, 1., 1000000) ###self.assertRaises(OverflowError, math.ldexp, -1., 1000000) ###self.assertEqual(math.ldexp(1., -1000000), 0.) ###self.assertEqual(math.ldexp(-1., -1000000), -0.) self.assertEqual(math.ldexp(INF, 30), INF) self.assertEqual(math.ldexp(NINF, -213), NINF) self.assertTrue(math.isnan(math.ldexp(NAN, 0))) # large second argument for n in [10**5, 10L**5, 10**10, 10L**10, 10**20, 10**40]: self.assertEqual(math.ldexp(INF, -n), INF) self.assertEqual(math.ldexp(NINF, -n), NINF) ###self.assertEqual(math.ldexp(1., -n), 0.) ###self.assertEqual(math.ldexp(-1., -n), -0.) self.assertEqual(math.ldexp(0., -n), 0.) self.assertEqual(math.ldexp(-0., -n), -0.) self.assertTrue(math.isnan(math.ldexp(NAN, -n))) ###self.assertRaises(OverflowError, math.ldexp, 1., n) ###self.assertRaises(OverflowError, math.ldexp, -1., n) self.assertEqual(math.ldexp(0., n), 0.) self.assertEqual(math.ldexp(-0., n), -0.) self.assertEqual(math.ldexp(INF, n), INF) self.assertEqual(math.ldexp(NINF, n), NINF) self.assertTrue(math.isnan(math.ldexp(NAN, n)))
def testLdexp(self): self.assertRaises(TypeError, math.ldexp) self.ftest('ldexp(0,1)', math.ldexp(0,1), 0) self.ftest('ldexp(1,1)', math.ldexp(1,1), 2) self.ftest('ldexp(1,-1)', math.ldexp(1,-1), 0.5) self.ftest('ldexp(-1,1)', math.ldexp(-1,1), -2) #self.assertRaises(OverflowError, math.ldexp, 1., 1000000) #self.assertRaises(OverflowError, math.ldexp, -1., 1000000) self.assertTrue(math.ldexp(1.0,100000)>0) self.assertTrue(math.ldexp(-1.0,100000)<0) #cf don't return +-0 for big numbers in ldexp function #self.assertEquals(math.ldexp(1., -1000000), 0.) #self.assertEquals(math.ldexp(-1., -1000000), -0.) self.assertEquals(math.ldexp(INF, 30), INF) self.assertEquals(math.ldexp(NINF, -213), NINF) self.assert_(math.isnan(math.ldexp(NAN, 0))) # large second argument for n in [10**5, 10L**5, 10**10, 10L**10, 10**20, 10**40]: self.assertEquals(math.ldexp(INF, -n), INF) self.assertEquals(math.ldexp(NINF, -n), NINF) #cf doesn't return 0/-0 #self.assertEquals(math.ldexp(1., -n), 0.) #self.assertEquals(math.ldexp(-1., -n), -0.) self.assertEquals(math.ldexp(0., -n), 0.) self.assertEquals(math.ldexp(-0., -n), -0.) self.assert_(math.isnan(math.ldexp(NAN, -n))) #cf doesn't raise exceptions #self.assertRaises(OverflowError, math.ldexp, 1., n) #self.assertRaises(OverflowError, math.ldexp, -1., n) self.assertEquals(math.ldexp(0., n), 0.) self.assertEquals(math.ldexp(-0., n), -0.) self.assertEquals(math.ldexp(INF, n), INF) self.assertEquals(math.ldexp(NINF, n), NINF) self.assert_(math.isnan(math.ldexp(NAN, n)))
def testLdexp(self): self.assertRaises(TypeError, math.ldexp) self.ftest('ldexp(0,1)', math.ldexp(0,1), 0) self.ftest('ldexp(1,1)', math.ldexp(1,1), 2) self.ftest('ldexp(1,-1)', math.ldexp(1,-1), 0.5) self.ftest('ldexp(-1,1)', math.ldexp(-1,1), -2) #self.assertRaises(OverflowError, math.ldexp, 1., 1000000) #self.assertRaises(OverflowError, math.ldexp, -1., 1000000) #self.assertEqual(math.ldexp(1., -1000000), 0.) #self.assertEqual(math.ldexp(-1., -1000000), -0.) self.assertEqual(math.ldexp(INF, 30), INF) self.assertEqual(math.ldexp(NINF, -213), NINF) self.assertTrue(math.isnan(math.ldexp(NAN, 0))) # large second argument for n in [10**5, 10L**5, 10**10, 10L**10, 10**20, 10**40]: self.assertEqual(math.ldexp(INF, -n), INF) self.assertEqual(math.ldexp(NINF, -n), NINF) #self.assertEqual(math.ldexp(1., -n), 0.) #self.assertEqual(math.ldexp(-1., -n), -0.) self.assertEqual(math.ldexp(0., -n), 0.) self.assertEqual(math.ldexp(-0., -n), -0.) self.assertTrue(math.isnan(math.ldexp(NAN, -n))) #self.assertRaises(OverflowError, math.ldexp, 1., n) #self.assertRaises(OverflowError, math.ldexp, -1., n) self.assertEqual(math.ldexp(0., n), 0.) self.assertEqual(math.ldexp(-0., n), -0.) self.assertEqual(math.ldexp(INF, n), INF) self.assertEqual(math.ldexp(NINF, n), NINF) self.assertTrue(math.isnan(math.ldexp(NAN, n)))
def testLdexp(self): self.assertRaises(TypeError, math.ldexp) self.ftest('ldexp(0,1)', math.ldexp(0, 1), 0) self.ftest('ldexp(1,1)', math.ldexp(1, 1), 2) self.ftest('ldexp(1,-1)', math.ldexp(1, -1), 0.5) self.ftest('ldexp(-1,1)', math.ldexp(-1, 1), -2) #self.assertRaises(OverflowError, math.ldexp, 1., 1000000) #self.assertRaises(OverflowError, math.ldexp, -1., 1000000) self.assertTrue(math.ldexp(1.0, 100000) > 0) self.assertTrue(math.ldexp(-1.0, 100000) < 0) #cf don't return +-0 for big numbers in ldexp function #self.assertEquals(math.ldexp(1., -1000000), 0.) #self.assertEquals(math.ldexp(-1., -1000000), -0.) self.assertEquals(math.ldexp(INF, 30), INF) self.assertEquals(math.ldexp(NINF, -213), NINF) self.assert_(math.isnan(math.ldexp(NAN, 0))) # large second argument for n in [10**5, 10L**5, 10**10, 10L**10, 10**20, 10**40]: self.assertEquals(math.ldexp(INF, -n), INF) self.assertEquals(math.ldexp(NINF, -n), NINF) #cf doesn't return 0/-0 #self.assertEquals(math.ldexp(1., -n), 0.) #self.assertEquals(math.ldexp(-1., -n), -0.) self.assertEquals(math.ldexp(0., -n), 0.) self.assertEquals(math.ldexp(-0., -n), -0.) self.assert_(math.isnan(math.ldexp(NAN, -n))) #cf doesn't raise exceptions #self.assertRaises(OverflowError, math.ldexp, 1., n) #self.assertRaises(OverflowError, math.ldexp, -1., n) self.assertEquals(math.ldexp(0., n), 0.) self.assertEquals(math.ldexp(-0., n), -0.) self.assertEquals(math.ldexp(INF, n), INF) self.assertEquals(math.ldexp(NINF, n), NINF) self.assert_(math.isnan(math.ldexp(NAN, n)))