MCPcopy Index your code
hub / github.com/python/cpython / testFsum

Method testFsum

Lib/test/test_math.py:688–797  ·  view source on GitHub ↗
(self)

Source from the content-addressed store, hash-verified

686 @unittest.skipIf(HAVE_DOUBLE_ROUNDING,
687 "fsum is not exact on machines with double rounding")
688 def testFsum(self):
689 # math.fsum relies on exact rounding for correct operation.
690 # There's a known problem with IA32 floating-point that causes
691 # inexact rounding in some situations, and will cause the
692 # math.fsum tests below to fail; see issue #2937. On non IEEE
693 # 754 platforms, and on IEEE 754 platforms that exhibit the
694 # problem described in issue #2937, we simply skip the whole
695 # test.
696
697 # Python version of math.fsum, for comparison. Uses a
698 # different algorithm based on frexp, ldexp and integer
699 # arithmetic.
700 from sys import float_info
701 mant_dig = float_info.mant_dig
702 etiny = float_info.min_exp - mant_dig
703
704 def msum(iterable):
705 """Full precision summation. Compute sum(iterable) without any
706 intermediate accumulation of error. Based on the 'lsum' function
707 at https://code.activestate.com/recipes/393090-binary-floating-point-summation-accurate-to-full-p/
708
709 """
710 tmant, texp = 0, 0
711 for x in iterable:
712 mant, exp = math.frexp(x)
713 mant, exp = int(math.ldexp(mant, mant_dig)), exp - mant_dig
714 if texp > exp:
715 tmant <<= texp-exp
716 texp = exp
717 else:
718 mant <<= exp-texp
719 tmant += mant
720 # Round tmant * 2**texp to a float. The original recipe
721 # used float(str(tmant)) * 2.0**texp for this, but that's
722 # a little unsafe because str -> float conversion can't be
723 # relied upon to do correct rounding on all platforms.
724 tail = max(len(bin(abs(tmant)))-2 - mant_dig, etiny - texp)
725 if tail > 0:
726 h = 1 << (tail-1)
727 tmant = tmant // (2*h) + bool(tmant & h and tmant & 3*h-1)
728 texp += tail
729 return math.ldexp(tmant, texp)
730
731 test_values = [
732 ([], 0.0),
733 ([0.0], 0.0),
734 ([1e100, 1.0, -1e100, 1e-100, 1e50, -1.0, -1e50], 1e-100),
735 ([1e100, 1.0, -1e100, 1e-100, 1e50, -1, -1e50], 1e-100),
736 ([2.0**53, -0.5, -2.0**-54], 2.0**53-1.0),
737 ([2.0**53, 1.0, 2.0**-100], 2.0**53+2.0),
738 ([2.0**53+10.0, 1.0, 2.0**-100], 2.0**53+12.0),
739 ([2.0**53-4.0, 0.5, 2.0**-54], 2.0**53-3.0),
740 ([1./n for n in range(1, 1001)],
741 float.fromhex('0x1.df11f45f4e61ap+2')),
742 ([(-1.)**n/n for n in range(1, 1001)],
743 float.fromhex('-0x1.62a2af1bd3624p-1')),
744 ([1e16, 1., 1e-16], 10000000000000002.0),
745 ([1e16-2., 1.-2.**-53, -(1e16-2.), -(1.-2.**-53)], 0.0),

Callers

nothing calls this directly

Calls 7

enumerateFunction · 0.85
assertTrueMethod · 0.80
FloatLikeClass · 0.70
appendMethod · 0.45
failMethod · 0.45
assertEqualMethod · 0.45
assertRaisesMethod · 0.45

Tested by

no test coverage detected