Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/tests/book_stein_ent.py
4069 views
1
"""
2
This file contains all the example code from the published book
3
'Elementary Number Theory: Primes, Congruences, and Secrets' by
4
William Stein, Springer-Verlag, 2009.
5
"""
6
7
8
"""
9
sage: prime_range(10,50)
10
[11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
11
sage: [n for n in range(10,30) if not is_prime(n)]
12
[10, 12, 14, 15, 16, 18, 20, 21, 22, 24, 25, 26, 27, 28]
13
sage: gcd(97,100)
14
1
15
sage: gcd(97 * 10^15, 19^20 * 97^2)
16
97
17
sage: factor(1275)
18
3 * 5^2 * 17
19
sage: factor(2007)
20
3^2 * 223
21
sage: factor(31415926535898)
22
2 * 3 * 53 * 73 * 2531 * 534697
23
sage: n = 7403756347956171282804679609742957314259318888\
24
...9231289084936232638972765034028266276891996419625117\
25
...8439958943305021275853701189680982867331732731089309\
26
...0055250511687706329907239638078671008609696253793465\
27
...0563796359
28
sage: len(n.str(2))
29
704
30
sage: len(n.str(10))
31
212
32
sage: n.is_prime() # this is instant
33
False
34
sage: p = 2^32582657 - 1
35
sage: p.ndigits()
36
9808358
37
sage: s = p.str(10) # this takes a long time
38
sage: len(s) # s is a very long string (long time)
39
9808358
40
sage: s[:20] # the first 20 digits of p (long time)
41
'12457502601536945540'
42
sage: s[-20:] # the last 20 digits (long time)
43
'11752880154053967871'
44
sage: prime_pi(6)
45
3
46
sage: prime_pi(100)
47
25
48
sage: prime_pi(3000000)
49
216816
50
sage: plot(prime_pi, 1,1000, rgbcolor=(0,0,1))
51
sage: P = plot(Li, 2,10000, rgbcolor='purple')
52
sage: Q = plot(prime_pi, 2,10000, rgbcolor='black')
53
sage: R = plot(sqrt(x)*log(x),2,10000,rgbcolor='red')
54
sage: show(P+Q+R,xmin=0, figsize=[8,3])
55
sage: R = Integers(3)
56
sage: list(R)
57
[0, 1, 2]
58
sage: R = Integers(10)
59
sage: a = R(3) # create an element of Z/10Z
60
sage: a.multiplicative_order()
61
4
62
sage: [a^i for i in range(15)]
63
[1, 3, 9, 7, 1, 3, 9, 7, 1, 3, 9, 7, 1, 3, 9]
64
sage: euler_phi(2007)
65
1332
66
sage: n = 20
67
sage: k = euler_phi(n); k
68
8
69
sage: [Mod(x,n)^k for x in range(n) if gcd(x,n) == 1]
70
[1, 1, 1, 1, 1, 1, 1, 1]
71
sage: for n in range(1,10):
72
... print n, factorial(n-1) % n, -1 % n
73
1 0 0
74
2 1 1
75
3 2 2
76
4 2 3
77
5 4 4
78
6 0 5
79
7 6 6
80
8 0 7
81
9 0 8
82
sage: CRT(2,3, 3, 5)
83
8
84
sage: CRT_list([2,3,2], [3,5,7])
85
23
86
sage: xgcd(5,7)
87
(1, 3, -2)
88
sage: xgcd(130,61)
89
(1, 23, -49)
90
sage: a = Mod(17, 61)
91
sage: a^(-1)
92
18
93
sage: 100.str(2)
94
'1100100'
95
sage: 0*2^0 + 0*2^1 + 1*2^2 + 0*2^3 + 0*2^4 + 1*2^5 + 1*2^6
96
100
97
sage: Mod(7,100)^91
98
43
99
sage: 7^91
100
80153343160247310515380886994816022539378033762994852007501964604841680190743
101
sage: n = 95468093486093450983409583409850934850938459083
102
sage: Mod(2,n)^(n-1)
103
34173444139265553870830266378598407069248687241
104
sage: factor(n) # takes up to a few seconds.
105
1610302526747 * 59285812386415488446397191791023889
106
sage: n = 95468093486093450983409583409850934850938459083
107
sage: is_prime(n)
108
False
109
sage: for p in primes(100):
110
... if is_prime(2^p - 1):
111
... print p, 2^p - 1
112
2 3
113
3 7
114
5 31
115
7 127
116
13 8191
117
17 131071
118
19 524287
119
31 2147483647
120
61 2305843009213693951
121
89 618970019642690137449562111
122
sage: def is_prime_lucas_lehmer(p):
123
... s = Mod(4, 2^p - 1)
124
... for i in range(3, p+1):
125
... s = s^2 - 2
126
... return s == 0
127
sage: # Check primality of 2^9941 - 1
128
sage: is_prime_lucas_lehmer(9941)
129
True
130
sage: # Check primality of 2^next_prime(1000)-1
131
sage: is_prime_lucas_lehmer(next_prime(1000))
132
False
133
sage: for p in primes(20):
134
... print p, primitive_root(p)
135
2 1
136
3 2
137
5 2
138
7 3
139
11 2
140
13 2
141
17 3
142
19 2
143
sage: R.<x> = PolynomialRing(Integers(13))
144
sage: f = x^15 + 1
145
sage: f.roots()
146
[(12, 1), (10, 1), (4, 1)]
147
sage: f(12)
148
0
149
sage: R.<x> = PolynomialRing(Integers(13))
150
sage: f = x^6 + 1
151
sage: f.roots()
152
[(11, 1), (8, 1), (7, 1), (6, 1), (5, 1), (2, 1)]
153
sage: log(19683.0)
154
9.88751059801299
155
sage: log(3.0)
156
1.09861228866811
157
sage: log(19683.0) / log(3.0)
158
9.00000000000000
159
sage: plot(log, 0.1,10, rgbcolor=(0,0,1))
160
sage: p = 53
161
sage: R = Integers(p)
162
sage: a = R.multiplicative_generator()
163
sage: v = sorted([(a^n, n) for n in range(p-1)])
164
sage: G = plot(point(v,pointsize=50,rgbcolor=(0,0,1)))
165
sage: H = plot(line(v,rgbcolor=(0.5,0.5,0.5)))
166
sage: G + H
167
sage: q = 93450983094850938450983409623
168
sage: q.is_prime()
169
True
170
sage: is_prime((q-1)//2)
171
True
172
sage: g = Mod(-2, q)
173
sage: g.multiplicative_order()
174
93450983094850938450983409622
175
sage: n = 18319922375531859171613379181
176
sage: m = 82335836243866695680141440300
177
sage: g^n
178
45416776270485369791375944998
179
sage: g^m
180
15048074151770884271824225393
181
sage: (g^n)^m
182
85771409470770521212346739540
183
sage: (g^m)^n
184
85771409470770521212346739540
185
sage: def rsa(bits):
186
... # only prove correctness up to 1024 bits
187
... proof = (bits <= 1024)
188
... p = next_prime(ZZ.random_element(2**(bits//2 +1)),
189
... proof=proof)
190
... q = next_prime(ZZ.random_element(2**(bits//2 +1)),
191
... proof=proof)
192
... n = p * q
193
... phi_n = (p-1) * (q-1)
194
... while True:
195
... e = ZZ.random_element(1,phi_n)
196
... if gcd(e,phi_n) == 1: break
197
... d = lift(Mod(e,phi_n)^(-1))
198
... return e, d, n
199
...
200
sage: def encrypt(m,e,n):
201
... return lift(Mod(m,n)^e)
202
...
203
sage: def decrypt(c,d,n):
204
... return lift(Mod(c,n)^d)
205
...
206
sage: e,d,n = rsa(20)
207
sage: c = encrypt(123, e, n)
208
sage: decrypt(c, d, n)
209
123
210
sage: def encode(s):
211
... s = str(s) # make input a string
212
... return sum(ord(s[i])*256^i for i in range(len(s)))
213
sage: def decode(n):
214
... n = Integer(n) # make input an integer
215
... v = []
216
... while n != 0:
217
... v.append(chr(n % 256))
218
... n //= 256 # this replaces n by floor(n/256).
219
... return ''.join(v)
220
sage: m = encode('Run Nikita!'); m
221
40354769014714649421968722
222
sage: decode(m)
223
'Run Nikita!'
224
sage: def crack_rsa(n, phi_n):
225
... R.<x> = PolynomialRing(QQ)
226
... f = x^2 - (n+1 -phi_n)*x + n
227
... return [b for b, _ in f.roots()]
228
sage: crack_rsa(31615577110997599711, 31615577098574867424)
229
[8850588049, 3572144239]
230
sage: def crack_when_pq_close(n):
231
... t = Integer(ceil(sqrt(n)))
232
... while True:
233
... k = t^2 - n
234
... if k > 0:
235
... s = Integer(int(round(sqrt(t^2 - n))))
236
... if s^2 + n == t^2:
237
... return t+s, t-s
238
...
239
... t += 1
240
...
241
sage: crack_when_pq_close(23360947609)
242
(153649, 152041)
243
sage: p = next_prime(2^128); p
244
340282366920938463463374607431768211507
245
sage: q = next_prime(p)
246
sage: crack_when_pq_close(p*q)
247
(340282366920938463463374607431768211537,
248
340282366920938463463374607431768211507)
249
sage: def crack_given_decrypt(n, m):
250
... n = Integer(n); m = Integer(m); # some type checking
251
... # Step 1: divide out powers of 2
252
... while True:
253
... if is_odd(m): break
254
... divide_out = True
255
... for i in range(5):
256
... a = randrange(1,n)
257
... if gcd(a,n) == 1:
258
... if Mod(a,n)^(m//2) != 1:
259
... divide_out = False
260
... break
261
... if divide_out:
262
... m = m//2
263
... else:
264
... break
265
... # Step 2: Compute GCD
266
... while True:
267
... a = randrange(1,n)
268
... g = gcd(lift(Mod(a, n)^(m//2)) - 1, n)
269
... if g != 1 and g != n:
270
... return g
271
...
272
sage: n=32295194023343; e=29468811804857; d=11127763319273
273
sage: crack_given_decrypt(n, e*d - 1)
274
737531
275
sage: factor(n)
276
737531 * 43788253
277
sage: e = 22601762315966221465875845336488389513
278
sage: d = 31940292321834506197902778067109010093
279
sage: n = 268494924039590992469444675130990465673
280
sage: p = crack_given_decrypt(n, e*d - 1)
281
sage: p # random output (could be other prime divisor)
282
13432418150982799907
283
sage: n % p
284
0
285
sage: set_random_seed(0)
286
sage: p = next_prime(randrange(2^96))
287
sage: q = next_prime(randrange(2^97))
288
sage: n = p * q
289
sage: qsieve(n) # long time (8s on sage.math, 2011)
290
([6340271405786663791648052309,
291
46102313108592180286398757159], '')
292
sage: legendre_symbol(2,3)
293
-1
294
sage: legendre_symbol(1,3)
295
1
296
sage: legendre_symbol(3,5)
297
-1
298
sage: legendre_symbol(Mod(3,5), 5)
299
-1
300
sage: legendre_symbol(69,389)
301
1
302
sage: def kr(a, p):
303
... if Mod(a,p)^((p-1)//2) == 1:
304
... return 1
305
... else:
306
... return -1
307
sage: for a in range(1,5):
308
... print a, kr(a,5)
309
1 1
310
2 -1
311
3 -1
312
4 1
313
sage: p = 726377359
314
sage: Mod(3, p)^((p-1)//2)
315
726377358
316
sage: def gauss(a, p):
317
... # make the list of numbers reduced modulo p
318
... v = [(n*a)%p for n in range(1, (p-1)//2 + 1)]
319
... # normalize them to be in the range -p/2 to p/2
320
... v = [(x if (x < p/2) else x - p) for x in v]
321
... # sort and print the resulting numbers
322
... v.sort()
323
... print v
324
... # count the number that are negative
325
... num_neg = len([x for x in v if x < 0])
326
... return (-1)^num_neg
327
sage: gauss(2, 13)
328
[-5, -3, -1, 2, 4, 6]
329
-1
330
sage: legendre_symbol(2,13)
331
-1
332
sage: gauss(4, 13)
333
[-6, -5, -2, -1, 3, 4]
334
1
335
sage: legendre_symbol(4,13)
336
1
337
sage: gauss(2,31)
338
[-15, -13, -11, -9, -7, -5, -3, -1, 2, 4, 6, 8, 10, 12, 14]
339
1
340
sage: legendre_symbol(2,31)
341
1
342
sage: K.<zeta> = CyclotomicField(5)
343
sage: zeta^5
344
1
345
sage: 1/zeta
346
-zeta^3 - zeta^2 - zeta - 1
347
sage: def gauss_sum(a,p):
348
... K.<zeta> = CyclotomicField(p)
349
... return sum(legendre_symbol(n,p) * zeta^(a*n) for n in range(1,p))
350
sage: g2 = gauss_sum(2,5); g2
351
2*zeta^3 + 2*zeta^2 + 1
352
sage: g2.complex_embedding()
353
-2.236067977... + ...e-16*I
354
sage: g2^2
355
5
356
sage: [gauss_sum(a, 7)^2 for a in range(1,7)]
357
[-7, -7, -7, -7, -7, -7]
358
sage: [gauss_sum(a, 13)^2 for a in range(1,13)]
359
[13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13]
360
sage: S.<x> = PolynomialRing(GF(13))
361
sage: R.<alpha> = S.quotient(x^2 - 3)
362
sage: (2+3*alpha)*(1+2*alpha)
363
7*alpha + 7
364
sage: def find_sqrt(a, p):
365
... assert (p-1)%4 == 0
366
... assert legendre_symbol(a,p) == 1
367
... S.<x> = PolynomialRing(GF(p))
368
... R.<alpha> = S.quotient(x^2 - a)
369
... while True:
370
... z = GF(p).random_element()
371
... w = (1 + z*alpha)^((p-1)//2)
372
... (u, v) = (w[0], w[1])
373
... if v != 0: break
374
... if (-u/v)^2 == a: return -u/v
375
... if ((1-u)/v)^2 == a: return (1-u)/v
376
... if ((-1-u)/v)^2 == a: return (-1-u)/v
377
...
378
sage: b = find_sqrt(3,13)
379
sage: b # random: either 9 or 3
380
9
381
sage: b^2
382
3
383
sage: b = find_sqrt(3,13)
384
sage: b # see, it's random
385
4
386
sage: find_sqrt(5,389) # random: either 303 or 86
387
303
388
sage: find_sqrt(5,389) # see, it's random
389
86
390
391
# Several of the examples below had to be changed due to improved
392
# behavior of the continued_fraction function #8017.
393
394
sage: continued_fraction(17/23)
395
[0, 1, 2, 1, 5]
396
sage: reset('e')
397
sage: continued_fraction(e)
398
[2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8, 1, 1, 10, 1, 1, 12, 1, 1]
399
sage: continued_fraction(e, bits=21)
400
[2, 1, 2, 1, 1, 4, 1, 1, 6]
401
sage: continued_fraction(e, bits=30)
402
[2, 1, 2, 1, 1, 4, 1, 1, 6, 1, 1, 8]
403
sage: a = continued_fraction(17/23); a
404
[0, 1, 2, 1, 5]
405
sage: a.value()
406
17/23
407
sage: b = continued_fraction(6/23); b
408
[0, 3, 1, 5]
409
sage: a + b
410
[1]
411
sage: c = continued_fraction(pi,bits=35); c
412
[3, 7, 15, 1, 292, 1]
413
sage: c.convergents()
414
[3, 22/7, 333/106, 355/113, 103993/33102, 104348/33215]
415
sage: c = continued_fraction(pi); c
416
[3, 7, 15, 1, 292, 1, 1, 1, 2, 1, 3, 1, 14]
417
sage: for n in range(-1, len(c)):
418
... print c.pn(n)*c.qn(n-1) - c.qn(n)*c.pn(n-1),
419
1 -1 1 -1 1 -1 1 -1 1 -1 1 -1 1 -1
420
sage: for n in range(len(c)):
421
... print c.pn(n)*c.qn(n-2) - c.qn(n)*c.pn(n-2),
422
3 -7 15 -1 292 -1 1 -1 2 -1 3 -1 14
423
sage: c = continued_fraction([1,2,3,4,5])
424
sage: c.convergents()
425
[1, 3/2, 10/7, 43/30, 225/157]
426
sage: [c.pn(n) for n in range(len(c))]
427
[1, 3, 10, 43, 225]
428
sage: [c.qn(n) for n in range(len(c))]
429
[1, 2, 7, 30, 157]
430
sage: c = continued_fraction([1,1,1,1,1,1,1,1])
431
sage: v = [(i, c.pn(i)/c.qn(i)) for i in range(len(c))]
432
sage: P = point(v, rgbcolor=(0,0,1), pointsize=40)
433
sage: L = line(v, rgbcolor=(0.5,0.5,0.5))
434
sage: L2 = line([(0,c.value()),(len(c)-1,c.value())], \
435
... thickness=0.5, rgbcolor=(0.7,0,0))
436
sage: (L+L2+P).show(xmin=0,ymin=1)
437
sage: def cf(bits):
438
... x = (1 + sqrt(RealField(bits)(5))) / 2
439
... return continued_fraction(x)
440
sage: cf(10)
441
[1, 1, 1, 1, 1, 1, 1]
442
sage: cf(30)
443
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
444
sage: cf(50)
445
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
446
sage: def cf_sqrt_d(d, bits):
447
... x = sqrt(RealField(bits)(d))
448
... return continued_fraction(x)
449
sage: cf_sqrt_d(389,50)
450
[19, 1, 2, 1, 1, 1, 1, 2, 1, 38, 1, 2, 1, 1, 1, 1, 2, 1, 38, 2]
451
sage: cf_sqrt_d(389,100)
452
[19, 1, 2, 1, 1, 1, 1, 2, 1, 38, 1, 2, 1, 1, 1, 1, 2, 1, 38, 1, 2, 1, 1, 1, 1, 2, 1, 38, 1, 2, 1, 1, 1, 1, 2, 1, 38, 1, 2, 1, 1]
453
sage: def newton_root(f, iterates=2, x0=0, prec=53):
454
... x = RealField(prec)(x0)
455
... R = PolynomialRing(ZZ,'x')
456
... f = R(f)
457
... g = f.derivative()
458
... for i in range(iterates):
459
... x = x - f(x)/g(x)
460
... return x
461
sage: reset('x')
462
sage: a = newton_root(3847*x^2 - 14808904*x + 36527265); a
463
2.46815700480740
464
sage: cf = continued_fraction(a); cf
465
[2, 2, 7, 2, 1, 5, 1, 1, 1, 1, 1, 1, 103, 8, 1, 2, 3]
466
sage: c = cf[:12]; c
467
[2, 2, 7, 2, 1, 5, 1, 1, 1, 1, 1, 1]
468
sage: c.value()
469
9495/3847
470
sage: def sum_of_two_squares_naive(n):
471
... for i in range(int(sqrt(n))):
472
... if is_square(n - i^2):
473
... return i, (Integer(n-i^2)).sqrt()
474
... return "%s is not a sum of two squares"%n
475
sage: sum_of_two_squares_naive(23)
476
'23 is not a sum of two squares'
477
sage: sum_of_two_squares_naive(389)
478
(10, 17)
479
sage: sum_of_two_squares_naive(2007)
480
'2007 is not a sum of two squares'
481
sage: sum_of_two_squares_naive(2008)
482
'2008 is not a sum of two squares'
483
sage: sum_of_two_squares_naive(2009)
484
(28, 35)
485
sage: 28^2 + 35^2
486
2009
487
sage: sum_of_two_squares_naive(2*3^4*5*7^2*13)
488
(189, 693)
489
sage: def sum_of_two_squares(p):
490
... p = Integer(p)
491
... assert p%4 == 1, "p must be 1 modulo 4"
492
... r = Mod(-1,p).sqrt().lift()
493
... v = continued_fraction(-r/p)
494
... n = floor(sqrt(p))
495
... for x in v.convergents():
496
... c = r*x.denominator() + p*x.numerator()
497
... if -n <= c and c <= n:
498
... return (abs(x.denominator()),abs(c))
499
sage: p = next_prime(next_prime(10^10))
500
sage: sum_of_two_squares(p)
501
(55913, 82908)
502
sage: sum_of_two_squares_naive(p)
503
(55913, 82908)
504
sage: E = EllipticCurve([-5, 4])
505
sage: E
506
Elliptic Curve defined by y^2 = x^3 - 5*x + 4
507
over Rational Field
508
sage: P = E.plot(thickness=4,rgbcolor=(0.1,0.7,0.1))
509
sage: P.show(figsize=[4,6])
510
sage: E = EllipticCurve(GF(37), [1,0])
511
sage: E
512
Elliptic Curve defined by y^2 = x^3 + x over
513
Finite Field of size 37
514
sage: E.plot(pointsize=45)
515
sage: E = EllipticCurve([-5,4])
516
sage: P = E([1,0]); Q = E([0,2])
517
sage: P + Q
518
(3 : 4 : 1)
519
sage: P + P
520
(0 : 1 : 0)
521
sage: P + Q + Q + Q + Q
522
(350497/351649 : 16920528/208527857 : 1)
523
sage: R.<x1,y1,x2,y2,x3,y3,a,b> = QQ[]
524
sage: rels = [y1^2 - (x1^3 + a*x1 + b),
525
... y2^2 - (x2^3 + a*x2 + b),
526
... y3^2 - (x3^3 + a*x3 + b)]
527
...
528
sage: Q = R.quotient(rels)
529
sage: def op(P1,P2):
530
... x1,y1 = P1; x2,y2 = P2
531
... lam = (y1 - y2)/(x1 - x2); nu = y1 - lam*x1
532
... x3 = lam^2 - x1 - x2; y3 = -lam*x3 - nu
533
... return (x3, y3)
534
sage: P1 = (x1,y1); P2 = (x2,y2); P3 = (x3,y3)
535
sage: Z = op(P1, op(P2,P3)); W = op(op(P1,P2),P3)
536
sage: (Q(Z[0].numerator()*W[0].denominator() -
537
... Z[0].denominator()*W[0].numerator())) == 0
538
True
539
sage: (Q(Z[1].numerator()*W[1].denominator() -
540
... Z[1].denominator()*W[1].numerator())) == 0
541
True
542
sage: def lcm_upto(B):
543
... return prod([p^int(math.log(B)/math.log(p))
544
... for p in prime_range(B+1)])
545
sage: lcm_upto(10^2)
546
69720375229712477164533808935312303556800
547
sage: LCM([1..10^2])
548
69720375229712477164533808935312303556800
549
sage: def pollard(N, B=10^5, stop=10):
550
... m = prod([p^int(math.log(B)/math.log(p))
551
... for p in prime_range(B+1)])
552
... for a in [2..stop]:
553
... x = (Mod(a,N)^m - 1).lift()
554
... if x == 0: continue
555
... g = gcd(x, N)
556
... if g != 1 or g != N: return g
557
... return 1
558
sage: pollard(5917,5)
559
61
560
sage: pollard(779167,5)
561
1
562
sage: pollard(779167,15)
563
2003
564
sage: pollard(4331,7)
565
1
566
sage: pollard(4331,5)
567
61
568
sage: pollard(187, 15, 2)
569
1
570
sage: pollard(187, 15)
571
11
572
sage: def ecm(N, B=10^3, trials=10):
573
... m = prod([p^int(math.log(B)/math.log(p))
574
... for p in prime_range(B+1)])
575
... R = Integers(N)
576
... # Make Sage think that R is a field:
577
... R.is_field = lambda : True
578
... for _ in range(trials):
579
... while True:
580
... a = R.random_element()
581
... if gcd(4*a.lift()^3 + 27, N) == 1: break
582
... try:
583
... m * EllipticCurve([a, 1])([0,1])
584
... except ZeroDivisionError, msg:
585
... # msg: "Inverse of <int> does not exist"
586
... return gcd(Integer(str(msg).split()[2]), N)
587
... return 1
588
sage: set_random_seed(2)
589
sage: ecm(5959, B=20)
590
101
591
sage: ecm(next_prime(10^20)*next_prime(10^7), B=10^3)
592
10000019
593
sage: p = 785963102379428822376694789446897396207498568951
594
sage: E = EllipticCurve(GF(p), \
595
... [317689081251325503476317476413827693272746955927,
596
... 79052896607878758718120572025718535432100651934])
597
sage: E.cardinality()
598
785963102379428822376693024881714957612686157429
599
sage: E.cardinality().is_prime()
600
True
601
sage: B = E([
602
... 771507216262649826170648268565579889907769254176,
603
... 390157510246556628525279459266514995562533196655])
604
sage: n=670805031139910513517527207693060456300217054473
605
sage: r=70674630913457179596452846564371866229568459543
606
sage: P = E([14489646124220757767,
607
... 669337780373284096274895136618194604469696830074])
608
sage: encrypt = (r*B, P + r*(n*B))
609
sage: encrypt[1] - n*encrypt[0] == P # decrypting works
610
True
611
sage: T = lambda v: EllipticCurve(v
612
... ).torsion_subgroup().invariants()
613
sage: T([-5,4])
614
(2,)
615
sage: T([-43,166])
616
(7,)
617
sage: T([-4,0])
618
(2, 2)
619
sage: T([-1386747, 368636886])
620
(2, 8)
621
sage: r = lambda v: EllipticCurve(v).rank()
622
sage: r([-5,4])
623
1
624
sage: r([0,1])
625
0
626
sage: r([-3024, 46224])
627
2
628
sage: r([-112, 400])
629
3
630
sage: r([-102627, 12560670])
631
4
632
sage: def cong(n):
633
... G = EllipticCurve([-n^2,0]).gens()
634
... if len(G) == 0: return False
635
... x,y,_ = G[0]
636
... return ((n^2-x^2)/y,-2*x*n/y,(n^2+x^2)/y)
637
sage: cong(6)
638
(3, 4, 5)
639
sage: cong(5)
640
(3/2, 20/3, 41/6)
641
sage: cong(1)
642
False
643
sage: cong(13)
644
(323/30, 780/323, 106921/9690)
645
sage: (323/30 * 780/323)/2
646
13
647
sage: (323/30)^2 + (780/323)^2 == (106921/9690)^2
648
True
649
"""
650
651