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

Method test_sumprod_extended_precision_accuracy

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

Source from the content-addressed store, hash-verified

1501 @support.cpython_only # Other implementations may choose a different algorithm
1502 @support.requires_resource('cpu')
1503 def test_sumprod_extended_precision_accuracy(self):
1504 import operator
1505 from fractions import Fraction
1506 from itertools import starmap
1507 from collections import namedtuple
1508 from math import log2, exp2, fabs
1509 from random import choices, uniform, shuffle
1510 from statistics import median
1511
1512 DotExample = namedtuple('DotExample', ('x', 'y', 'target_sumprod', 'condition'))
1513
1514 def DotExact(x, y):
1515 vec1 = map(Fraction, x)
1516 vec2 = map(Fraction, y)
1517 return sum(starmap(operator.mul, zip(vec1, vec2, strict=True)))
1518
1519 def Condition(x, y):
1520 return 2.0 * DotExact(map(abs, x), map(abs, y)) / abs(DotExact(x, y))
1521
1522 def linspace(lo, hi, n):
1523 width = (hi - lo) / (n - 1)
1524 return [lo + width * i for i in range(n)]
1525
1526 def GenDot(n, c):
1527 """ Algorithm 6.1 (GenDot) works as follows. The condition number (5.7) of
1528 the dot product xT y is proportional to the degree of cancellation. In
1529 order to achieve a prescribed cancellation, we generate the first half of
1530 the vectors x and y randomly within a large exponent range. This range is
1531 chosen according to the anticipated condition number. The second half of x
1532 and y is then constructed choosing xi randomly with decreasing exponent,
1533 and calculating yi such that some cancellation occurs. Finally, we permute
1534 the vectors x, y randomly and calculate the achieved condition number.
1535 """
1536
1537 assert n >= 6
1538 n2 = n // 2
1539 x = [0.0] * n
1540 y = [0.0] * n
1541 b = log2(c)
1542
1543 # First half with exponents from 0 to |_b/2_| and random ints in between
1544 e = choices(range(int(b/2)), k=n2)
1545 e[0] = int(b / 2) + 1
1546 e[-1] = 0.0
1547
1548 x[:n2] = [uniform(-1.0, 1.0) * exp2(p) for p in e]
1549 y[:n2] = [uniform(-1.0, 1.0) * exp2(p) for p in e]
1550
1551 # Second half
1552 e = list(map(round, linspace(b/2, 0.0 , n-n2)))
1553 for i in range(n2, n):
1554 x[i] = uniform(-1.0, 1.0) * exp2(e[i - n2])
1555 y[i] = (uniform(-1.0, 1.0) * exp2(e[i - n2]) - DotExact(x, y)) / x[i]
1556
1557 # Shuffle
1558 pairs = list(zip(x, y))
1559 shuffle(pairs)
1560 x, y = zip(*pairs)

Callers

nothing calls this directly

Calls 3

namedtupleFunction · 0.90
medianFunction · 0.90
assertLessMethod · 0.45

Tested by

no test coverage detected