|
7 | 7 |
|
8 | 8 |
|
9 | 9 | import time
|
| 10 | +import sys |
| 11 | +from functools import wraps |
10 | 12 | from test.support.import_helper import import_fresh_module
|
11 | 13 |
|
12 | 14 | C = import_fresh_module('decimal', fresh=['_decimal'])
|
@@ -64,66 +66,85 @@ def factorial(n, m):
|
64 | 66 | else:
|
65 | 67 | return factorial(n, (n+m)//2) * factorial((n+m)//2 + 1, m)
|
66 | 68 |
|
| 69 | +# Fix failed test cases caused by CVE-2020-10735 patch. |
| 70 | +# See gh-95778 for details. |
| 71 | +def increase_int_max_str_digits(maxdigits): |
| 72 | + def _increase_int_max_str_digits(func, maxdigits=maxdigits): |
| 73 | + @wraps(func) |
| 74 | + def wrapper(*args, **kwargs): |
| 75 | + previous_int_limit = sys.get_int_max_str_digits() |
| 76 | + sys.set_int_max_str_digits(maxdigits) |
| 77 | + ans = func(*args, **kwargs) |
| 78 | + sys.set_int_max_str_digits(previous_int_limit) |
| 79 | + return ans |
| 80 | + return wrapper |
| 81 | + return _increase_int_max_str_digits |
| 82 | + |
| 83 | +def test_calc_pi(): |
| 84 | + print("\n# ======================================================================") |
| 85 | + print("# Calculating pi, 10000 iterations") |
| 86 | + print("# ======================================================================\n") |
| 87 | + |
| 88 | + to_benchmark = [pi_float, pi_decimal] |
| 89 | + if C is not None: |
| 90 | + to_benchmark.insert(1, pi_cdecimal) |
| 91 | + |
| 92 | + for prec in [9, 19]: |
| 93 | + print("\nPrecision: %d decimal digits\n" % prec) |
| 94 | + for func in to_benchmark: |
| 95 | + start = time.time() |
| 96 | + if C is not None: |
| 97 | + C.getcontext().prec = prec |
| 98 | + P.getcontext().prec = prec |
| 99 | + for i in range(10000): |
| 100 | + x = func() |
| 101 | + print("%s:" % func.__name__.replace("pi_", "")) |
| 102 | + print("result: %s" % str(x)) |
| 103 | + print("time: %fs\n" % (time.time()-start)) |
| 104 | + |
| 105 | +@increase_int_max_str_digits(maxdigits=10000000) |
| 106 | +def test_factorial(): |
| 107 | + print("\n# ======================================================================") |
| 108 | + print("# Factorial") |
| 109 | + print("# ======================================================================\n") |
67 | 110 |
|
68 |
| -print("\n# ======================================================================") |
69 |
| -print("# Calculating pi, 10000 iterations") |
70 |
| -print("# ======================================================================\n") |
71 |
| - |
72 |
| -to_benchmark = [pi_float, pi_decimal] |
73 |
| -if C is not None: |
74 |
| - to_benchmark.insert(1, pi_cdecimal) |
75 |
| - |
76 |
| -for prec in [9, 19]: |
77 |
| - print("\nPrecision: %d decimal digits\n" % prec) |
78 |
| - for func in to_benchmark: |
79 |
| - start = time.time() |
80 |
| - if C is not None: |
81 |
| - C.getcontext().prec = prec |
82 |
| - P.getcontext().prec = prec |
83 |
| - for i in range(10000): |
84 |
| - x = func() |
85 |
| - print("%s:" % func.__name__.replace("pi_", "")) |
86 |
| - print("result: %s" % str(x)) |
87 |
| - print("time: %fs\n" % (time.time()-start)) |
88 |
| - |
89 |
| - |
90 |
| -print("\n# ======================================================================") |
91 |
| -print("# Factorial") |
92 |
| -print("# ======================================================================\n") |
93 |
| - |
94 |
| -if C is not None: |
95 |
| - c = C.getcontext() |
96 |
| - c.prec = C.MAX_PREC |
97 |
| - c.Emax = C.MAX_EMAX |
98 |
| - c.Emin = C.MIN_EMIN |
| 111 | + if C is not None: |
| 112 | + c = C.getcontext() |
| 113 | + c.prec = C.MAX_PREC |
| 114 | + c.Emax = C.MAX_EMAX |
| 115 | + c.Emin = C.MIN_EMIN |
99 | 116 |
|
100 |
| -for n in [100000, 1000000]: |
| 117 | + for n in [100000, 1000000]: |
101 | 118 |
|
102 |
| - print("n = %d\n" % n) |
| 119 | + print("n = %d\n" % n) |
103 | 120 |
|
104 |
| - if C is not None: |
105 |
| - # C version of decimal |
| 121 | + if C is not None: |
| 122 | + # C version of decimal |
| 123 | + start_calc = time.time() |
| 124 | + x = factorial(C.Decimal(n), 0) |
| 125 | + end_calc = time.time() |
| 126 | + start_conv = time.time() |
| 127 | + sx = str(x) |
| 128 | + end_conv = time.time() |
| 129 | + print("cdecimal:") |
| 130 | + print("calculation time: %fs" % (end_calc-start_calc)) |
| 131 | + print("conversion time: %fs\n" % (end_conv-start_conv)) |
| 132 | + |
| 133 | + # Python integers |
106 | 134 | start_calc = time.time()
|
107 |
| - x = factorial(C.Decimal(n), 0) |
| 135 | + y = factorial(n, 0) |
108 | 136 | end_calc = time.time()
|
109 | 137 | start_conv = time.time()
|
110 |
| - sx = str(x) |
111 |
| - end_conv = time.time() |
112 |
| - print("cdecimal:") |
113 |
| - print("calculation time: %fs" % (end_calc-start_calc)) |
114 |
| - print("conversion time: %fs\n" % (end_conv-start_conv)) |
| 138 | + sy = str(y) |
| 139 | + end_conv = time.time() |
115 | 140 |
|
116 |
| - # Python integers |
117 |
| - start_calc = time.time() |
118 |
| - y = factorial(n, 0) |
119 |
| - end_calc = time.time() |
120 |
| - start_conv = time.time() |
121 |
| - sy = str(y) |
122 |
| - end_conv = time.time() |
| 141 | + print("int:") |
| 142 | + print("calculation time: %fs" % (end_calc-start_calc)) |
| 143 | + print("conversion time: %fs\n\n" % (end_conv-start_conv)) |
123 | 144 |
|
124 |
| - print("int:") |
125 |
| - print("calculation time: %fs" % (end_calc-start_calc)) |
126 |
| - print("conversion time: %fs\n\n" % (end_conv-start_conv)) |
| 145 | + if C is not None: |
| 146 | + assert(sx == sy) |
127 | 147 |
|
128 |
| - if C is not None: |
129 |
| - assert(sx == sy) |
| 148 | +if __name__ == "__main__": |
| 149 | + test_calc_pi() |
| 150 | + test_factorial() |
0 commit comments