Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2b7411d

Browse files
committed
Merged revisions 63542-63544,63546,63553,63563-63564,63567,63569,63576 via svnmerge from
svn+ssh://[email protected]/python/trunk ........ r63542 | mark.dickinson | 2008-05-22 20:35:30 -0500 (Thu, 22 May 2008) | 5 lines Issue #2819: Add math.sum, a function that sums a sequence of floats efficiently but with no intermediate loss of precision. Based on Raymond Hettinger's ASPN recipe. Thanks Jean Brouwers for the patch. ........ r63543 | mark.dickinson | 2008-05-22 21:36:48 -0500 (Thu, 22 May 2008) | 2 lines Add tests for math.sum (Issue #2819) ........ r63544 | mark.dickinson | 2008-05-22 22:30:01 -0500 (Thu, 22 May 2008) | 2 lines Better error reporting in test_math.py ........ r63546 | raymond.hettinger | 2008-05-22 23:32:43 -0500 (Thu, 22 May 2008) | 1 line Tweak the comments and formatting. ........ r63553 | mark.dickinson | 2008-05-23 07:07:36 -0500 (Fri, 23 May 2008) | 3 lines Skip math.sum tests on non IEEE 754 platforms, and on IEEE 754 platforms that exhibit the problem described in issue #2937. ........ r63563 | martin.v.loewis | 2008-05-23 10:18:28 -0500 (Fri, 23 May 2008) | 3 lines Issue #1390: Raise ValueError in toxml when an invalid comment would otherwise be produced. ........ r63564 | raymond.hettinger | 2008-05-23 12:21:44 -0500 (Fri, 23 May 2008) | 1 line Issue 2909: show how to name unpacked fields. ........ r63567 | raymond.hettinger | 2008-05-23 12:34:34 -0500 (Fri, 23 May 2008) | 1 line Fix typo ........ r63569 | martin.v.loewis | 2008-05-23 14:33:13 -0500 (Fri, 23 May 2008) | 3 lines Mention that the leaking of variables from list comprehensions is fixed in 3.0. ........ r63576 | martin.v.loewis | 2008-05-24 04:36:45 -0500 (Sat, 24 May 2008) | 3 lines Don't try to get the window size if it was never set before. Fixes the test failure on Solaris. ........
1 parent 1b466f2 commit 2b7411d

7 files changed

Lines changed: 368 additions & 4 deletions

File tree

Doc/library/collections.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ Notes on using :class:`Set` and :class:`MutableSet` as a mixin:
113113
Since some set operations create new sets, the default mixin methods need
114114
a way to create new instances from an iterable. The class constructor is
115115
assumed to have a signature in the form ``ClassName(iterable)``.
116-
That assumption is factored-out to a single internal classmethod called
116+
That assumption is factored-out to an internal classmethod called
117117
:meth:`_from_iterable` which calls ``cls(iterable)`` to produce a new set.
118118
If the :class:`Set` mixin is being used in a class with a different
119119
constructor signature, you will need to override :meth:`from_iterable`

Doc/library/struct.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,16 @@ end, assuming longs are aligned on 4-byte boundaries. This only works when
216216
native size and alignment are in effect; standard size and alignment does not
217217
enforce any alignment.
218218

219+
Unpacked fields can be named by assigning them to variables or by wrapping
220+
the result in a named tuple::
221+
222+
>>> record = 'raymond \x32\x12\x08\x01\x08'
223+
>>> name, serialnum, school, gradelevel = unpack('<10sHHb', record)
224+
225+
>>> from collections import namedtuple
226+
>>> Student = namedtuple('Student', 'name serialnum school gradelevel')
227+
>>> Student._make(unpack('<10sHHb', s))
228+
Student(name='raymond ', serialnum=4658, school=264, gradelevel=8)
219229

220230
.. seealso::
221231

Lib/test/test_ioctl.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,10 @@ def test_ioctl_signed_unsigned_code_param(self):
5252
set_winsz_opcode_maybe_neg, = struct.unpack("i",
5353
struct.pack("I", termios.TIOCSWINSZ))
5454

55-
# We're just testing that these calls do not raise exceptions.
56-
saved_winsz = fcntl.ioctl(mfd, termios.TIOCGWINSZ, "\0"*8)
5755
our_winsz = struct.pack("HHHH",80,25,0,0)
5856
# test both with a positive and potentially negative ioctl code
5957
new_winsz = fcntl.ioctl(mfd, set_winsz_opcode_pos, our_winsz)
6058
new_winsz = fcntl.ioctl(mfd, set_winsz_opcode_maybe_neg, our_winsz)
61-
fcntl.ioctl(mfd, set_winsz_opcode_maybe_neg, saved_winsz)
6259
finally:
6360
os.close(mfd)
6461
os.close(sfd)

Lib/test/test_math.py

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,158 @@ def testSqrt(self):
626626
self.assertRaises(ValueError, math.sqrt, NINF)
627627
self.assert_(math.isnan(math.sqrt(NAN)))
628628

629+
def testSum(self):
630+
# math.sum relies on exact rounding for correct operation.
631+
# There's a known problem with IA32 floating-point that causes
632+
# inexact rounding in some situations, and will cause the
633+
# math.sum tests below to fail; see issue #2937. On non IEEE
634+
# 754 platforms, and on IEEE 754 platforms that exhibit the
635+
# problem described in issue #2937, we simply skip the whole
636+
# test.
637+
638+
if not float.__getformat__("double").startswith("IEEE"):
639+
return
640+
641+
# on IEEE 754 compliant machines, both of the expressions
642+
# below should round to 10000000000000002.0.
643+
if 1e16+2.999 != 1e16+2.9999:
644+
return
645+
646+
# Python version of math.sum algorithm, for comparison
647+
def msum(iterable):
648+
"""Full precision sum of values in iterable. Returns the value of
649+
the sum, rounded to the nearest representable floating-point number
650+
using the round-half-to-even rule.
651+
652+
"""
653+
# Stage 1: accumulate partials
654+
partials = []
655+
for x in iterable:
656+
i = 0
657+
for y in partials:
658+
if abs(x) < abs(y):
659+
x, y = y, x
660+
hi = x + y
661+
lo = y - (hi - x)
662+
if lo:
663+
partials[i] = lo
664+
i += 1
665+
x = hi
666+
partials[i:] = [x] if x else []
667+
668+
# Stage 2: sum partials
669+
if not partials:
670+
return 0.0
671+
672+
# sum from the top, stopping as soon as the sum is inexact.
673+
total = partials.pop()
674+
while partials:
675+
x = partials.pop()
676+
old_total, total = total, total + x
677+
error = x - (total - old_total)
678+
if error != 0.0:
679+
# adjust for correct rounding if necessary
680+
if partials and (partials[-1] > 0.0) == (error > 0.0) and \
681+
total + 2*error - total == 2*error:
682+
total += 2*error
683+
break
684+
return total
685+
686+
from sys import float_info
687+
maxfloat = float_info.max
688+
twopow = 2.**(float_info.max_exp - 1)
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+
([1e308, 1e308, -1e308], OverflowError),
695+
([-1e308, 1e308, 1e308], 1e308),
696+
([1e308, -1e308, 1e308], 1e308),
697+
([2.0**1023, 2.0**1023, -2.0**1000], OverflowError),
698+
([twopow, twopow, twopow, twopow, -twopow, -twopow, -twopow],
699+
OverflowError),
700+
([2.0**53, -0.5, -2.0**-54], 2.0**53-1.0),
701+
([2.0**53, 1.0, 2.0**-100], 2.0**53+2.0),
702+
([2.0**53+10.0, 1.0, 2.0**-100], 2.0**53+12.0),
703+
704+
([2.0**53-4.0, 0.5, 2.0**-54], 2.0**53-3.0),
705+
([2.0**1023-2.0**970, -1.0, 2.0**1023], OverflowError),
706+
([maxfloat, maxfloat*2.**-54], maxfloat),
707+
([maxfloat, maxfloat*2.**-53], OverflowError),
708+
([1./n for n in range(1, 1001)], 7.4854708605503451),
709+
([(-1.)**n/n for n in range(1, 1001)], -0.69264743055982025),
710+
([1.7**(i+1)-1.7**i for i in range(1000)] + [-1.7**1000], -1.0),
711+
([INF, -INF, NAN], ValueError),
712+
([NAN, INF, -INF], ValueError),
713+
([INF, NAN, INF], ValueError),
714+
715+
([INF, INF], OverflowError),
716+
([INF, -INF], ValueError),
717+
([-INF, 1e308, 1e308, -INF], OverflowError),
718+
([2.0**1023-2.0**970, 0.0, 2.0**1023], OverflowError),
719+
([2.0**1023-2.0**970, 1.0, 2.0**1023], OverflowError),
720+
([2.0**1023, 2.0**1023], OverflowError),
721+
([2.0**1023, 2.0**1023, -1.0], OverflowError),
722+
([twopow, twopow, twopow, twopow, -twopow, -twopow],
723+
OverflowError),
724+
([twopow, twopow, twopow, twopow, -twopow, twopow], OverflowError),
725+
([-twopow, -twopow, -twopow, -twopow], OverflowError),
726+
727+
([2.**1023, 2.**1023, -2.**971], OverflowError),
728+
([2.**1023, 2.**1023, -2.**970], OverflowError),
729+
([-2.**970, 2.**1023, 2.**1023, -2.**-1074], OverflowError),
730+
([ 2.**1023, 2.**1023, -2.**970, 2.**-1074], OverflowError),
731+
([-2.**1023, 2.**971, -2.**1023], -maxfloat),
732+
([-2.**1023, -2.**1023, 2.**970], OverflowError),
733+
([-2.**1023, -2.**1023, 2.**970, 2.**-1074], OverflowError),
734+
([-2.**-1074, -2.**1023, -2.**1023, 2.**970], OverflowError),
735+
([2.**930, -2.**980, 2.**1023, 2.**1023, twopow, -twopow],
736+
OverflowError),
737+
([2.**1023, 2.**1023, -1e307], OverflowError),
738+
([1e16, 1., 1e-16], 10000000000000002.0),
739+
([1e16-2., 1.-2.**53, -(1e16-2.), -(1.-2.**53)], 0.0),
740+
]
741+
742+
for i, (vals, s) in enumerate(test_values):
743+
if isinstance(s, type) and issubclass(s, Exception):
744+
try:
745+
m = math.sum(vals)
746+
except s:
747+
pass
748+
else:
749+
self.fail("test %d failed: got %r, expected %r "
750+
"for math.sum(%.100r)" %
751+
(i, m, s.__name__, vals))
752+
else:
753+
try:
754+
self.assertEqual(math.sum(vals), s)
755+
except OverflowError:
756+
self.fail("test %d failed: got OverflowError, expected %r "
757+
"for math.sum(%.100r)" % (i, s, vals))
758+
except ValueError:
759+
self.fail("test %d failed: got ValueError, expected %r "
760+
"for math.sum(%.100r)" % (i, s, vals))
761+
762+
# compare with output of msum above, but only when
763+
# result isn't an IEEE special or an exception
764+
if not math.isinf(s) and not math.isnan(s):
765+
self.assertEqual(msum(vals), s)
766+
767+
from random import random, gauss, shuffle
768+
for j in range(1000):
769+
vals = [7, 1e100, -7, -1e100, -9e-20, 8e-20] * 10
770+
s = 0
771+
for i in range(200):
772+
v = gauss(0, random()) ** 7 - s
773+
s += v
774+
vals.append(v)
775+
shuffle(vals)
776+
777+
s = msum(vals)
778+
self.assertEqual(msum(vals), math.sum(vals))
779+
780+
629781
def testTan(self):
630782
self.assertRaises(TypeError, math.tan)
631783
self.ftest('tan(0)', math.tan(0), 0)
@@ -763,6 +915,10 @@ def test_testfile(self):
763915
message = (("Unexpected ValueError: %s\n " +
764916
"in test %s:%s(%r)\n") % (exc.args[0], id, fn, ar))
765917
self.fail(message)
918+
except OverflowError:
919+
message = ("Unexpected OverflowError in " +
920+
"test %s:%s(%r)\n" % (id, fn, ar))
921+
self.fail(message)
766922
self.ftest("%s:%s(%r)" % (id, fn, ar), result, er)
767923

768924
def test_main():

Lib/test/test_minidom.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,6 +1314,11 @@ def testPickledDocument(self):
13141314
for i in range(len(n1.childNodes)):
13151315
stack.append((n1.childNodes[i], n2.childNodes[i]))
13161316

1317+
def testSerializeCommentNodeWithDoubleHyphen(self):
1318+
doc = create_doc_without_doctype()
1319+
doc.appendChild(doc.createComment("foo--bar"))
1320+
self.assertRaises(ValueError, doc.toxml)
1321+
13171322
def test_main():
13181323
run_unittest(MinidomTest)
13191324

Lib/xml/dom/minidom.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1132,6 +1132,8 @@ def __init__(self, data):
11321132
self.data = self.nodeValue = data
11331133

11341134
def writexml(self, writer, indent="", addindent="", newl=""):
1135+
if "--" in self.data:
1136+
raise ValueError("'--' is not allowed in a comment node")
11351137
writer.write("%s<!--%s-->%s" % (indent, self.data, newl))
11361138

11371139

0 commit comments

Comments
 (0)