Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/wapython
Path: blob/main/python/bench/src/cython/nt.pyx
1068 views
1
# mypy
2
# A little pure python number theory library, which is useful
3
# as a foundation for some microbenchmarks
4
5
from math import sqrt
6
from typing import Tuple
7
8
9
cpdef int gcd(int a, int b):
10
cdef int c
11
while b:
12
c = a % b
13
a = b
14
b = c
15
return a
16
17
18
cdef int xgcd_c(int a, int b, int* cx, int* cy):
19
cdef int prevx, prevy, x, y, q, r
20
prevx, x = 1, 0
21
prevy, y = 0, 1
22
while b:
23
q = a // b
24
r = a % b
25
x, prevx = prevx - q * x, x
26
y, prevy = prevy - q * y, y
27
a, b = b, r
28
cx[0] = prevx
29
cy[0] = prevy
30
return a
31
32
def xgcd(int a, int b) -> Tuple[int, int, int]:
33
cdef int cx, cy, g
34
g = xgcd_c(a,b,&cx,&cy)
35
return [g,cx,cy]
36
37
38
cpdef int inverse_mod(int a, int N):
39
"""
40
Compute multiplicative inverse of a modulo N.
41
"""
42
if a == 1 or N <= 1: # common special cases
43
return a % N
44
cdef int g, s, cy
45
g = xgcd_c(a, N, &s, &cy)
46
if g != 1:
47
raise ZeroDivisionError
48
cdef b = s % N
49
if b < 0:
50
b += N
51
return b
52
53
54
def trial_division(N: int, bound: int = 0, start: int = 2) -> int:
55
if N <= 1:
56
return N
57
m = 7
58
i = 1
59
dif = [6, 4, 2, 4, 2, 4, 6, 2]
60
if start > 7:
61
m = start % 30
62
if m <= 1:
63
i = 0
64
m = start + (1 - m)
65
elif m <= 7:
66
i = 1
67
m = start + (7 - m)
68
elif m <= 11:
69
i = 2
70
m = start + (11 - m)
71
elif m <= 13:
72
i = 3
73
m = start + (13 - m)
74
elif m <= 17:
75
i = 4
76
m = start + (17 - m)
77
elif m <= 19:
78
i = 5
79
m = start + (19 - m)
80
elif m <= 23:
81
i = 6
82
m = start + (23 - m)
83
elif m <= 29:
84
i = 7
85
m = start + (29 - m)
86
if start <= 2 and N % 2 == 0:
87
return 2
88
if start <= 3 and N % 3 == 0:
89
return 3
90
if start <= 5 and N % 5 == 0:
91
return 5
92
limit = round(sqrt(N))
93
if bound != 0 and bound < limit:
94
limit = bound
95
while m <= limit:
96
if N % m == 0:
97
return m
98
m += dif[i % 8]
99
i += 1
100
101
return N
102
103
104
def is_prime(N: int) -> bool:
105
return N > 1 and trial_division(N) == N
106
107
108
def pi(n: int = 100000) -> int:
109
s = 0
110
for i in range(1, n + 1):
111
if is_prime(i):
112
s += 1
113
return s
114
115