MCPcopy Create free account
hub / github.com/RustPython/RustPython / testFsum

Method testFsum

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

Source from the content-addressed store, hash-verified

645 @unittest.skipIf(HAVE_DOUBLE_ROUNDING,
646 "fsum is not exact on machines with double rounding")
647 def testFsum(self):
648 # math.fsum relies on exact rounding for correct operation.
649 # There's a known problem with IA32 floating-point that causes
650 # inexact rounding in some situations, and will cause the
651 # math.fsum tests below to fail; see issue #2937. On non IEEE
652 # 754 platforms, and on IEEE 754 platforms that exhibit the
653 # problem described in issue #2937, we simply skip the whole
654 # test.
655
656 # Python version of math.fsum, for comparison. Uses a
657 # different algorithm based on frexp, ldexp and integer
658 # arithmetic.
659 from sys import float_info
660 mant_dig = float_info.mant_dig
661 etiny = float_info.min_exp - mant_dig
662
663 def msum(iterable):
664 """Full precision summation. Compute sum(iterable) without any
665 intermediate accumulation of error. Based on the 'lsum' function
666 at https://code.activestate.com/recipes/393090-binary-floating-point-summation-accurate-to-full-p/
667
668 """
669 tmant, texp = 0, 0
670 for x in iterable:
671 mant, exp = math.frexp(x)
672 mant, exp = int(math.ldexp(mant, mant_dig)), exp - mant_dig
673 if texp > exp:
674 tmant <<= texp-exp
675 texp = exp
676 else:
677 mant <<= exp-texp
678 tmant += mant
679 # Round tmant * 2**texp to a float. The original recipe
680 # used float(str(tmant)) * 2.0**texp for this, but that's
681 # a little unsafe because str -> float conversion can't be
682 # relied upon to do correct rounding on all platforms.
683 tail = max(len(bin(abs(tmant)))-2 - mant_dig, etiny - texp)
684 if tail > 0:
685 h = 1 << (tail-1)
686 tmant = tmant // (2*h) + bool(tmant & h and tmant & 3*h-1)
687 texp += tail
688 return math.ldexp(tmant, texp)
689
690 test_values = [
691 ([], 0.0),
692 ([0.0], 0.0),
693 ([1e100, 1.0, -1e100, 1e-100, 1e50, -1.0, -1e50], 1e-100),
694 ([1e100, 1.0, -1e100, 1e-100, 1e50, -1, -1e50], 1e-100),
695 ([2.0**53, -0.5, -2.0**-54], 2.0**53-1.0),
696 ([2.0**53, 1.0, 2.0**-100], 2.0**53+2.0),
697 ([2.0**53+10.0, 1.0, 2.0**-100], 2.0**53+12.0),
698 ([2.0**53-4.0, 0.5, 2.0**-54], 2.0**53-3.0),
699 ([1./n for n in range(1, 1001)],
700 float.fromhex('0x1.df11f45f4e61ap+2')),
701 ([(-1.)**n/n for n in range(1, 1001)],
702 float.fromhex('-0x1.62a2af1bd3624p-1')),
703 ([1e16, 1., 1e-16], 10000000000000002.0),
704 ([1e16-2., 1.-2.**-53, -(1e16-2.), -(1.-2.**-53)], 0.0),

Callers

nothing calls this directly

Calls 8

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

Tested by

no test coverage detected