|
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