1#
2# Copyright (C) 2001-2012 Python Software Foundation. All Rights Reserved.
3# Modified and extended by Stefan Krah.
4#
5
6# Usage: ../../../python bench.py
7
8
9import time
10try:
11    from test.support import import_fresh_module
12except ImportError:
13    from test.test_support import import_fresh_module
14
15C = import_fresh_module('decimal', fresh=['_decimal'])
16P = import_fresh_module('decimal', blocked=['_decimal'])
17
18#
19# NOTE: This is the pi function from the decimal documentation, modified
20# for benchmarking purposes. Since floats do not have a context, the higher
21# intermediate precision from the original is NOT used, so the modified
22# algorithm only gives an approximation to the correctly rounded result.
23# For serious use, refer to the documentation or the appropriate literature.
24#
25def pi_float():
26    """native float"""
27    lasts, t, s, n, na, d, da = 0, 3.0, 3, 1, 0, 0, 24
28    while s != lasts:
29        lasts = s
30        n, na = n+na, na+8
31        d, da = d+da, da+32
32        t = (t * n) / d
33        s += t
34    return s
35
36def pi_cdecimal():
37    """cdecimal"""
38    D = C.Decimal
39    lasts, t, s, n, na, d, da = D(0), D(3), D(3), D(1), D(0), D(0), D(24)
40    while s != lasts:
41        lasts = s
42        n, na = n+na, na+8
43        d, da = d+da, da+32
44        t = (t * n) / d
45        s += t
46    return s
47
48def pi_decimal():
49    """decimal"""
50    D = P.Decimal
51    lasts, t, s, n, na, d, da = D(0), D(3), D(3), D(1), D(0), D(0), D(24)
52    while s != lasts:
53        lasts = s
54        n, na = n+na, na+8
55        d, da = d+da, da+32
56        t = (t * n) / d
57        s += t
58    return s
59
60def factorial(n, m):
61    if (n > m):
62        return factorial(m, n)
63    elif m == 0:
64        return 1
65    elif n == m:
66        return n
67    else:
68        return factorial(n, (n+m)//2) * factorial((n+m)//2 + 1, m)
69
70
71print("\n# ======================================================================")
72print("#                   Calculating pi, 10000 iterations")
73print("# ======================================================================\n")
74
75to_benchmark = [pi_float, pi_decimal]
76if C is not None:
77    to_benchmark.insert(1, pi_cdecimal)
78
79for prec in [9, 19]:
80    print("\nPrecision: %d decimal digits\n" % prec)
81    for func in to_benchmark:
82        start = time.time()
83        if C is not None:
84            C.getcontext().prec = prec
85        P.getcontext().prec = prec
86        for i in range(10000):
87            x = func()
88        print("%s:" % func.__name__.replace("pi_", ""))
89        print("result: %s" % str(x))
90        print("time: %fs\n" % (time.time()-start))
91
92
93print("\n# ======================================================================")
94print("#                               Factorial")
95print("# ======================================================================\n")
96
97if C is not None:
98    c = C.getcontext()
99    c.prec = C.MAX_PREC
100    c.Emax = C.MAX_EMAX
101    c.Emin = C.MIN_EMIN
102
103for n in [100000, 1000000]:
104
105    print("n = %d\n" % n)
106
107    if C is not None:
108        # C version of decimal
109        start_calc = time.time()
110        x = factorial(C.Decimal(n), 0)
111        end_calc = time.time()
112        start_conv = time.time()
113        sx = str(x)
114        end_conv = time.time()
115        print("cdecimal:")
116        print("calculation time: %fs" % (end_calc-start_calc))
117        print("conversion time: %fs\n" % (end_conv-start_conv))
118
119    # Python integers
120    start_calc = time.time()
121    y = factorial(n, 0)
122    end_calc = time.time()
123    start_conv = time.time()
124    sy = str(y)
125    end_conv =  time.time()
126
127    print("int:")
128    print("calculation time: %fs" % (end_calc-start_calc))
129    print("conversion time: %fs\n\n" % (end_conv-start_conv))
130
131    if C is not None:
132        assert(sx == sy)
133