Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/rings/finite_rings/element_ext_pari.py
8820 views
1
"""
2
Elements of Finite Fields
3
4
EXAMPLES::
5
6
sage: K = FiniteField(2)
7
sage: V = VectorSpace(K,3)
8
sage: w = V([0,1,2])
9
sage: K(1)*w
10
(0, 1, 0)
11
12
We do some arithmetic involving a bigger field and a Conway
13
polynomial, i.e., we verify compatibility condition.
14
15
::
16
17
sage: f = conway_polynomial(2,63)
18
sage: K.<a> = GF(2**63, name='a', modulus=f, impl='pari_mod')
19
sage: n = f.degree()
20
sage: m = 3;
21
sage: e = (2^n - 1) / (2^m - 1)
22
sage: c = a^e
23
sage: conway = conway_polynomial(2,m)
24
sage: conway(c) == 0
25
True
26
"""
27
28
29
import operator
30
31
import sage.structure.element as element
32
import sage.rings.arith as arith
33
import sage.rings.integer_ring as integer_ring
34
from sage.rings.integer import Integer
35
import sage.rings.rational as rational
36
from sage.libs.pari.all import pari, pari_gen
37
from sage.rings.finite_rings.element_base import FinitePolyExtElement
38
import sage.rings.field_element as field_element
39
import sage.rings.finite_rings.integer_mod as integer_mod
40
from element_base import is_FiniteFieldElement
41
from sage.modules.free_module_element import FreeModuleElement
42
from sage.structure.dynamic_class import dynamic_class
43
from sage.categories.finite_fields import FiniteFields
44
45
class FiniteField_ext_pariElement(FinitePolyExtElement):
46
"""
47
An element of a finite field.
48
49
Create elements by first defining the finite field ``F``, then use the
50
notation ``F(n)``, for ``n`` an integer, or let ``a = F.gen()`` and
51
write the element in terms of ``a``.
52
53
EXAMPLES::
54
55
sage: K = FiniteField(10007^10, 'a', impl='pari_mod')
56
sage: a = K.gen(); a
57
a
58
sage: loads(a.dumps()) == a
59
True
60
sage: K = GF(10007)
61
sage: a = K(938); a
62
938
63
sage: loads(a.dumps()) == a
64
True
65
66
TESTS::
67
68
sage: K.<a> = GF(2^16, impl='pari_mod')
69
sage: K(0).is_zero()
70
True
71
sage: (a - a).is_zero()
72
True
73
sage: a - a
74
0
75
sage: a == a
76
True
77
sage: a - a == 0
78
True
79
sage: a - a == K(0)
80
True
81
sage: TestSuite(a).run()
82
"""
83
def __init__(self, parent, value, value_from_pari=False):
84
"""
85
Create element of a finite field.
86
87
INPUT:
88
89
- ``parent`` -- A finite field, the parent of this element.
90
91
- ``value`` -- Anything that can be converted into the PARI
92
interface and can be interpreted as an element of ``parent``.
93
94
- ``value_from_pari`` -- optional bool, default ``False``. If it
95
evaluates as ``True``, then ``value`` *must* be an element of the
96
PARI interface, and there will be no conversion.
97
98
.. NOTE::
99
100
If the given value is a list or an element of the vector space
101
associated with the given parent, then it is interpreted as
102
the list of coefficients of a polynomial over the prime subfield,
103
and that polynomial is interpreted as an element of the given
104
parent. The empty list results in zero.
105
106
If ``value_from_pari`` is ``True`` then it is assumed that the
107
given value is a suitable representation of the element in PARI,
108
and there is no conversion. Hence, it is very fast, but must be
109
used with care.
110
111
EXAMPLES::
112
113
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
114
sage: k = FiniteField_ext_pari(9,'a')
115
sage: a = k(11); a
116
2
117
sage: a.parent()
118
Finite Field in a of size 3^2
119
sage: V = k.vector_space(); v = V((1,2))
120
sage: k(v)
121
2*a + 1
122
123
We create elements using a list and verify that :trac:`10486` has
124
been fixed::
125
126
sage: k = FiniteField_ext_pari(3^11, 't')
127
sage: x = k([1,0,2,1]); x
128
t^3 + 2*t^2 + 1
129
sage: x + x + x
130
0
131
sage: pari(x)
132
Mod(Mod(1, 3)*a^3 + Mod(2, 3)*a^2 + Mod(1, 3), Mod(1, 3)*a^11 + Mod(2, 3)*a^2 + Mod(1, 3))
133
134
If the list is longer than the degree, we just get the result
135
modulo the modulus::
136
137
sage: R.<a> = PolynomialRing(GF(5))
138
sage: k = FiniteField_ext_pari(5^2, 't', modulus=a^2-2)
139
sage: x = k([0,0,0,1]); x
140
2*t
141
sage: pari(x)
142
Mod(Mod(2, 5)*a, Mod(1, 5)*a^2 + Mod(3, 5))
143
144
When initializing from a list, the elements are first coerced
145
to the prime field (:trac:`11685`)::
146
147
sage: k = FiniteField_ext_pari(3^11, 't')
148
sage: k([ 0, 1/2 ])
149
2*t
150
sage: k([ k(0), k(1) ])
151
t
152
sage: k([ GF(3)(2), GF(3^5,'u')(1) ])
153
t + 2
154
sage: R.<x> = PolynomialRing(k)
155
sage: k([ R(-1), x/x ])
156
t + 2
157
158
We demonstrate the creation of an element via polynomials::
159
160
sage: k.polynomial()
161
t^11 + 2*t^2 + 1
162
sage: P = k.polynomial_ring()
163
sage: k(P.0^11)
164
t^2 + 2
165
166
We demonstrate the creation of an element via a vector::
167
168
sage: V = k.vector_space()
169
sage: V
170
Vector space of dimension 11 over Finite Field of size 3
171
sage: v = V([0,1,2,0,1,2,0,1,2,0,1])
172
sage: k(v)
173
t^10 + 2*t^8 + t^7 + 2*t^5 + t^4 + 2*t^2 + t
174
175
TESTS:
176
177
Check that zeros are created correctly (:trac:`11685`)::
178
179
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
180
sage: K = FiniteField_ext_pari(3^11, 't'); a = K.0
181
sage: v = 0; pari(K(v)).lift()
182
Mod(0, 3)
183
sage: v = Mod(0,3); pari(K(v)).lift()
184
Mod(0, 3)
185
sage: v = pari(0); pari(K(v)).lift()
186
Mod(0, 3)
187
sage: v = pari("Mod(0,3)"); pari(K(v)).lift()
188
Mod(0, 3)
189
sage: v = []; pari(K(v)).lift()
190
Mod(0, 3)
191
sage: v = [0]; pari(K(v)).lift()
192
Mod(0, 3)
193
sage: v = [0,0]; pari(K(v)).lift()
194
Mod(0, 3)
195
sage: v = pari("Pol(0)"); pari(K(v)).lift()
196
Mod(0, 3)
197
sage: v = pari("Mod(0, %s)"%K._pari_modulus()); pari(K(v)).lift()
198
Mod(0, 3)
199
sage: v = pari("Mod(Pol(0), %s)"%K._pari_modulus()); pari(K(v)).lift()
200
Mod(0, 3)
201
sage: v = K(1) - K(1); pari(K(v)).lift()
202
Mod(0, 3)
203
sage: v = K([1]) - K([1]); pari(K(v)).lift()
204
Mod(0, 3)
205
sage: v = a - a; pari(K(v)).lift()
206
Mod(0, 3)
207
sage: v = K(1)*0; pari(K(v)).lift()
208
Mod(0, 3)
209
sage: v = K([1])*K([0]); pari(K(v)).lift()
210
Mod(0, 3)
211
sage: v = a*0; pari(K(v)).lift()
212
Mod(0, 3)
213
214
The following test documents the optional argument ``value_from_pari``.
215
It is for internal use only and greatly improves the speed in
216
arithmetic operations. However, the example shows why it must only be
217
used carefully::
218
219
sage: from sage.rings.finite_rings.element_ext_pari import FiniteField_ext_pariElement
220
sage: a = FiniteField_ext_pariElement(K,pari(0),value_from_pari=True)
221
sage: a
222
0
223
sage: a == K(0)
224
False
225
226
The reason is that the pari elements representing ``a`` and ``K(0)``
227
are different::
228
229
sage: pari(a).lift()
230
0
231
sage: pari(K(0)).lift()
232
Mod(0, 3)
233
234
"""
235
field_element.FieldElement.__init__(self, parent)
236
self.__class__ = dynamic_FiniteField_ext_pariElement
237
238
# If value_from_pari is True, directly set self.__value to value.
239
# This assumes that value is a POLMOD with the correct modulus
240
# whose lift is either an INTMOD or a POL with INTMOD
241
# coefficients. In practice, this means that value comes from a
242
# PARI calculation with other elements of this finite field.
243
# This assumption is not checked.
244
if value_from_pari:
245
self.__value = value
246
return
247
248
try:
249
if isinstance(value, pari_gen):
250
try:
251
# In some cases we get two different versions of
252
# the 0 element of a finite field. This has to do
253
# with how PARI's Mod() function works -- it treats
254
# polynomials different from integers.
255
# Also, we need to fix things like ``1/Mod(3,5)`` when
256
# we want ``Mod(2,5)``.
257
# These issues are solved by first simplifying the
258
# given value.
259
value = value.simplify()
260
if value.type() != "t_POLMOD":
261
value = value.Mod(parent._pari_modulus())
262
self.__value = value * parent._pari_one()
263
except RuntimeError:
264
raise TypeError, "no possible coercion implemented"
265
elif isinstance(value, FiniteField_ext_pariElement):
266
if parent != value.parent():
267
raise TypeError, "no coercion implemented"
268
else:
269
self.__value = value.__value
270
elif isinstance(value, FreeModuleElement):
271
if parent.vector_space() != value.parent():
272
raise TypeError, "e.parent must match self.vector_space"
273
self.__value = pari(0).Mod(parent._pari_modulus())*parent._pari_one()
274
for i in range(len(value)):
275
self.__value = self.__value + pari(int(value[i])).Mod(parent._pari_modulus())*pari("a^%s"%i)
276
elif isinstance(value, list):
277
# AUTHOR: Jeroen Demeyer
278
# See Trac #10486 and #11685 for comments about this
279
# implementation
280
281
# We need a special case for the empty list because
282
# PARI's ``Pol([])`` returns an exact 0 while we want
283
# ``Mod(0,3)``.
284
if not value:
285
value = [0]
286
try:
287
# First, try the conversion directly in PARI. This
288
# should cover the most common cases, like converting
289
# from integers or intmods.
290
# Convert the list to PARI, then mod out the
291
# characteristic (PARI can do this directly for lists),
292
# convert to a polynomial with variable "a" and finally
293
# mod out the field modulus.
294
self.__value = pari(value).Mod(parent.characteristic()).Polrev("a").Mod(parent._pari_modulus())
295
except RuntimeError:
296
# That didn't work, do it in a more general but also
297
# slower way: first convert all list elements to the
298
# prime field.
299
GFp = parent.prime_subfield()
300
self.__value = pari([GFp(c) for c in value]).Polrev("a").Mod(parent._pari_modulus())
301
elif isinstance(value, str):
302
raise TypeError, "value must not be a string"
303
else:
304
try:
305
self.__value = pari(value).Mod(parent._pari_modulus())*parent._pari_one()
306
except RuntimeError:
307
raise TypeError, "no coercion implemented"
308
309
except (AttributeError, TypeError):
310
raise TypeError, "unable to coerce"
311
312
def __hash__(self):
313
"""
314
The hash of this element is the hash of the underlying polynomial.
315
316
EXAMPLES::
317
318
sage: k.<a> = GF(3^15, impl='pari_mod')
319
sage: R = GF(3)['a']; aa = R.gen()
320
sage: hash(a^2 + 1) == hash(aa^2 + 1)
321
True
322
"""
323
return hash(self.polynomial())
324
325
def polynomial(self):
326
"""
327
Elements of a finite field are represented as a polynomial modulo a
328
modulus. This function returns the representing polynomial as an
329
element of the polynomial ring over the prime finite field, with
330
the same variable as the finite field.
331
332
EXAMPLES:
333
334
The default variable is ``a``::
335
336
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
337
sage: k = FiniteField_ext_pari(3**2,'a')
338
sage: k.gen().polynomial()
339
a
340
341
The variable can be any string::
342
343
sage: k = FiniteField(3**4, "alpha", impl='pari_mod')
344
sage: a = k.gen()
345
sage: a.polynomial()
346
alpha
347
sage: (a**2 + 1).polynomial()
348
alpha^2 + 1
349
sage: (a**2 + 1).polynomial().parent()
350
Univariate Polynomial Ring in alpha over Finite Field of size 3
351
"""
352
return self.parent().polynomial_ring()(self.__value.lift())
353
354
def is_square(self):
355
"""
356
Returns ``True`` if and only if this element is a perfect square.
357
358
EXAMPLES::
359
360
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
361
sage: k = FiniteField_ext_pari(3**2, 'a')
362
sage: a = k.gen()
363
sage: a.is_square()
364
False
365
sage: (a**2).is_square()
366
True
367
sage: k = FiniteField_ext_pari(2**2,'a')
368
sage: a = k.gen()
369
sage: (a**2).is_square()
370
True
371
sage: k = FiniteField_ext_pari(17**5,'a'); a = k.gen()
372
sage: (a**2).is_square()
373
True
374
sage: a.is_square()
375
False
376
377
::
378
379
sage: k(0).is_square()
380
True
381
"""
382
K = self.parent()
383
if K.characteristic() == 2:
384
return True
385
n = K.order() - 1
386
a = self**(n // 2)
387
return a == 1 or a == 0
388
389
def square_root(self, extend=False, all=False):
390
"""
391
The square root function.
392
393
INPUT:
394
395
396
- ``extend`` -- bool (default: ``True``); if ``True``, return a
397
square root in an extension ring, if necessary. Otherwise, raise a
398
ValueError if the root is not in the base ring.
399
400
.. WARNING::
401
402
This option is not implemented!
403
404
- ``all`` - bool (default: ``False``); if ``True``, return all
405
square roots of ``self``, instead of just one.
406
407
.. WARNING::
408
409
The ``'extend'`` option is not implemented (yet).
410
411
EXAMPLES::
412
413
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
414
sage: F = FiniteField_ext_pari(7^2, 'a')
415
sage: F(2).square_root()
416
4
417
sage: F(3).square_root()
418
5*a + 1
419
sage: F(3).square_root()**2
420
3
421
sage: F(4).square_root()
422
5
423
sage: K = FiniteField_ext_pari(7^3, 'alpha')
424
sage: K(3).square_root()
425
Traceback (most recent call last):
426
...
427
ValueError: must be a perfect square.
428
"""
429
if extend:
430
raise NotImplementedError
431
R = self.parent()['x']
432
f = R([-self, 0, 1])
433
g = f.factor()
434
if len(g) == 2 or g[0][1] == 2:
435
if all:
436
return [-g[0][0][0], g[0][0][0]]
437
else:
438
return -g[0][0][0]
439
if all:
440
return []
441
else:
442
raise ValueError, "must be a perfect square."
443
444
def sqrt(self, extend=False, all = False):
445
"""
446
See :meth:square_root().
447
448
EXAMPLES::
449
450
sage: k.<a> = GF(3^17, impl='pari_mod')
451
sage: (a^3 - a - 1).sqrt()
452
2*a^16 + a^15 + 2*a^13 + a^12 + 2*a^10 + a^9 + a^8 + 2*a^7 + 2*a^6 + a^5 + 2*a^4 + a^2 + a + 1
453
"""
454
return self.square_root(extend=extend, all=all)
455
456
def rational_reconstruction(self):
457
"""
458
If the parent field is a prime field, uses rational reconstruction
459
to try to find a lift of this element to the rational numbers.
460
461
EXAMPLES::
462
463
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
464
sage: k = GF(97)
465
sage: a = k(RationalField()('2/3'))
466
sage: a
467
33
468
sage: a.rational_reconstruction()
469
2/3
470
"""
471
if self.parent().degree() != 1:
472
raise ArithmeticError, "finite field must be prime"
473
t = arith.rational_reconstruction(int(self), self.parent().characteristic())
474
if t == None or t[1] == 0:
475
raise ZeroDivisionError, "unable to compute rational reconstruction"
476
return rational.Rational((t[0],t[1]))
477
478
def multiplicative_order(self):
479
r"""
480
Returns the *multiplicative* order of this element, which must be
481
nonzero.
482
483
EXAMPLES::
484
485
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
486
sage: a = FiniteField_ext_pari(5**3, 'a').0
487
sage: a.multiplicative_order()
488
124
489
sage: a**124
490
1
491
"""
492
try:
493
return self.__multiplicative_order
494
except AttributeError:
495
if self.is_zero():
496
raise ArithmeticError("Multiplicative order of 0 not defined.")
497
n = self.parent().order() - 1
498
order = 1
499
for p, e in arith.factor(n):
500
# Determine the power of p that divides the order.
501
a = self**(n//(p**e))
502
while a != 1:
503
order *= p
504
a = a**p
505
self.__multiplicative_order = order
506
return order
507
508
def __copy__(self):
509
"""
510
Return a copy of this element.
511
512
EXAMPLES::
513
514
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
515
sage: k = FiniteField_ext_pari(3**3,'a')
516
sage: a = k(5)
517
sage: a
518
2
519
sage: copy(a)
520
2
521
sage: b = copy(a)
522
sage: a == b
523
True
524
sage: a is b
525
False
526
sage: a is a
527
True
528
"""
529
return FiniteField_ext_pariElement(self.parent(), self.__value, value_from_pari=True)
530
531
def _pari_(self, var=None):
532
"""
533
Return PARI object corresponding to this finite field element.
534
535
EXAMPLES::
536
537
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
538
sage: k = FiniteField_ext_pari(3**3, 'a')
539
sage: a = k.gen()
540
sage: b = a**2 + 2*a + 1
541
sage: b._pari_()
542
Mod(Mod(1, 3)*a^2 + Mod(2, 3)*a + Mod(1, 3), Mod(1, 3)*a^3 + Mod(2, 3)*a + Mod(1, 3))
543
544
Looking at the PARI representation of a finite field element, it's
545
no wonder people find PARI difficult to work with directly. Compare
546
our representation::
547
548
sage: b
549
a^2 + 2*a + 1
550
sage: b.parent()
551
Finite Field in a of size 3^3
552
"""
553
if var is None:
554
var = self.parent().variable_name()
555
if var == 'a':
556
return self.__value
557
else:
558
return self.__value.subst('a', var)
559
560
def _pari_init_(self):
561
"""
562
The string producing this finite field element in PARI.
563
564
EXAMPLES::
565
566
sage: k.<a> = GF(3^17, impl='pari_mod')
567
sage: a._pari_init_()
568
'Mod(Mod(1, 3)*a, Mod(1, 3)*a^17 + Mod(2, 3)*a + Mod(1, 3))'
569
"""
570
return str(self.__value)
571
572
def _magma_init_(self, magma):
573
"""
574
Return a string representation of self that Magma can understand.
575
576
EXAMPLES::
577
578
sage: GF(7)(3)._magma_init_(magma) # optional - magma
579
'GF(7)!3'
580
"""
581
km = magma(self.parent())
582
vn = km.gen(1).name()
583
return ("%s"%(self.__value.lift().lift())).replace('a',vn)
584
585
def _gap_init_(self):
586
r"""
587
Supports returning corresponding GAP object. This can be slow since
588
non-prime GAP finite field elements are represented as powers of a
589
generator for the multiplicative group, so the discrete log problem
590
must be solved.
591
592
.. NOTE::
593
594
The order of the parent field must be `\leq 65536`.
595
596
EXAMPLES::
597
598
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
599
sage: F = FiniteField_ext_pari(8,'a')
600
sage: a = F.multiplicative_generator()
601
sage: gap(a) # indirect doctest
602
Z(2^3)
603
sage: b = F.multiplicative_generator()
604
sage: a = b^3
605
sage: gap(a)
606
Z(2^3)^3
607
sage: gap(a^3)
608
Z(2^3)^2
609
610
You can specify the instance of the Gap interpreter that is used::
611
612
sage: F = FiniteField_ext_pari(next_prime(200)^2, 'a')
613
sage: a = F.multiplicative_generator ()
614
sage: a._gap_ (gap)
615
Z(211^2)
616
sage: (a^20)._gap_(gap)
617
Z(211^2)^20
618
619
Gap only supports relatively small finite fields.
620
621
::
622
623
sage: F = FiniteField_ext_pari(next_prime(1000)^2, 'a')
624
sage: a = F.multiplicative_generator ()
625
sage: gap._coerce_(a)
626
Traceback (most recent call last):
627
...
628
TypeError: order must be at most 65536
629
"""
630
F = self.parent()
631
if F.order() > 65536:
632
raise TypeError, "order must be at most 65536"
633
634
if self == 0:
635
return '0*Z(%s)'%F.order()
636
assert F.degree() > 1
637
g = F.multiplicative_generator()
638
n = self.log(g)
639
return 'Z(%s)^%s'%(F.order(), n)
640
641
def _repr_(self):
642
"""
643
String representation of this element.
644
645
EXAMPLES::
646
647
sage: k.<c> = GF(3^17, impl='pari_mod')
648
sage: c^20 # indirect doctest
649
c^4 + 2*c^3
650
"""
651
return ("%s"%(self.__value.lift().lift())).replace('a',self.parent().variable_name())
652
653
def _add_(self, right):
654
"""
655
Addition.
656
657
EXAMPLES::
658
659
sage: k.<a> = GF(3^17, impl='pari_mod')
660
sage: a + a^2 # indirect doctest
661
a^2 + a
662
"""
663
return FiniteField_ext_pariElement(self.parent(), self.__value + right.__value, value_from_pari=True)
664
665
def _sub_(self, right):
666
"""
667
Subtraction.
668
669
EXAMPLES::
670
671
sage: k.<a> = GF(3^17, impl='pari_mod')
672
sage: a - a # indirect doctest
673
0
674
"""
675
return FiniteField_ext_pariElement(self.parent(), self.__value - right.__value, value_from_pari=True)
676
677
def _mul_(self, right):
678
"""
679
Multiplication.
680
681
EXAMPLES::
682
683
sage: k.<a> = GF(3^17, impl='pari_mod')
684
sage: (a^12 + 1)*(a^15 - 1) # indirect doctest
685
a^15 + 2*a^12 + a^11 + 2*a^10 + 2
686
"""
687
return FiniteField_ext_pariElement(self.parent(), self.__value * right.__value, value_from_pari=True)
688
689
def _div_(self, right):
690
"""
691
Division.
692
693
EXAMPLES::
694
695
sage: k.<a> = GF(3^17, impl='pari_mod')
696
sage: (a - 1) / (a + 1) # indirect doctest
697
2*a^16 + a^15 + 2*a^14 + a^13 + 2*a^12 + a^11 + 2*a^10 + a^9 + 2*a^8 + a^7 + 2*a^6 + a^5 + 2*a^4 + a^3 + 2*a^2 + a + 1
698
"""
699
if right.__value == 0:
700
raise ZeroDivisionError
701
return FiniteField_ext_pariElement(self.parent(), self.__value / right.__value, value_from_pari=True)
702
703
def __int__(self):
704
"""
705
Lifting to a python int, if possible.
706
707
EXAMPLES::
708
709
sage: k.<a> = GF(3^17, impl='pari_mod'); b = k(2)
710
sage: int(b)
711
2
712
sage: int(a)
713
Traceback (most recent call last):
714
...
715
TypeError: Unable to coerce PARI a to an Integer
716
"""
717
try:
718
return int(self.__value.lift().lift())
719
except ValueError:
720
raise TypeError, "cannot coerce to int"
721
722
def _integer_(self, ZZ=None):
723
"""
724
Lifting to a sage integer if possible.
725
726
EXAMPLES::
727
728
sage: k.<a> = GF(3^17, impl='pari_mod'); b = k(2)
729
sage: b._integer_()
730
2
731
sage: a._integer_()
732
Traceback (most recent call last):
733
...
734
TypeError: Unable to coerce PARI a to an Integer
735
"""
736
return self.lift()
737
738
def __long__(self):
739
"""
740
Lifting to a python long, if possible.
741
742
EXAMPLES::
743
744
sage: k.<a> = GF(3^17, impl='pari_mod'); b = k(2)
745
sage: long(b)
746
2L
747
"""
748
try:
749
return long(self.__value.lift().lift())
750
except ValueError:
751
raise TypeError, "cannot coerce to long"
752
753
def __float__(self):
754
"""
755
Lifting to a python float, if possible.
756
757
EXAMPLES::
758
759
sage: k.<a> = GF(3^17, impl='pari_mod'); b = k(2)
760
sage: float(b)
761
2.0
762
"""
763
try:
764
return float(self.__value.lift().lift())
765
except ValueError:
766
raise TypeError, "cannot coerce to float"
767
768
def __pow__(self, _right):
769
"""
770
TESTS::
771
772
sage: K.<a> = GF(5^10, impl='pari_mod')
773
sage: n = (2*a)/a
774
775
Naively compute `n^{-15}` in PARI, note that the result is `1/3`.
776
This is mathematically correct (modulo 5), but not what we want.
777
In particular, comparisons will fail::
778
779
sage: pari(n)^-15
780
Mod(1/Mod(3, 5), Mod(1, 5)*a^10 + Mod(3, 5)*a^5 + Mod(3, 5)*a^4 + Mod(2, 5)*a^3 + Mod(4, 5)*a^2 + Mod(1, 5)*a + Mod(2, 5))
781
782
We need to :meth:`simplify()` the result (which is done in the
783
:class:`FiniteField_ext_pariElement` constructor::
784
785
sage: n^-15
786
2
787
788
Large exponents are not a problem::
789
790
sage: e = 3^10000
791
sage: a^e
792
2*a^9 + a^5 + 4*a^4 + 4*a^3 + a^2 + 3*a
793
sage: a^(e % (5^10 - 1))
794
2*a^9 + a^5 + 4*a^4 + 4*a^3 + a^2 + 3*a
795
"""
796
right = int(_right)
797
if right != _right:
798
raise ValueError
799
# It is important to set value_from_pari=False, see doctest above!
800
return FiniteField_ext_pariElement(self.parent(), self.__value**right, value_from_pari=False)
801
802
def __neg__(self):
803
"""
804
Negation.
805
806
EXAMPLES::
807
808
sage: k.<a> = GF(3^17, impl='pari_mod')
809
sage: -a
810
2*a
811
"""
812
return FiniteField_ext_pariElement(self.parent(), -self.__value, value_from_pari=True)
813
814
def __pos__(self):
815
"""
816
Unitary positive operator...
817
818
EXAMPLES::
819
820
sage: k.<a> = GF(3^17, impl='pari_mod')
821
sage: +a
822
a
823
"""
824
return self
825
826
def __abs__(self):
827
"""
828
Absolute value, which is not defined.
829
830
EXAMPLES::
831
832
sage: k.<a> = GF(3^17, impl='pari_mod')
833
sage: abs(a)
834
Traceback (most recent call last):
835
...
836
ArithmeticError: absolute value not defined
837
"""
838
raise ArithmeticError, "absolute value not defined"
839
840
def __invert__(self):
841
"""
842
EXAMPLES::
843
844
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
845
sage: a = FiniteField_ext_pari(9, 'a').gen()
846
sage: ~a
847
a + 2
848
sage: (a+1)*a
849
2*a + 1
850
sage: ~((2*a)/a)
851
2
852
"""
853
854
if self.__value == 0:
855
raise ZeroDivisionError, "Cannot invert 0"
856
return FiniteField_ext_pariElement(self.parent(), ~self.__value, value_from_pari=True)
857
858
def lift(self):
859
"""
860
If this element lies in a prime finite field, return a lift of this
861
element to an integer.
862
863
EXAMPLES::
864
865
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
866
sage: k = GF(next_prime(10**10))
867
sage: a = k(17)/k(19)
868
sage: b = a.lift(); b
869
7894736858
870
sage: b.parent()
871
Integer Ring
872
"""
873
return integer_ring.IntegerRing()(self.__value.lift().lift())
874
875
876
def __cmp__(self, other):
877
"""
878
Compare an element of a finite field with other. If other is not an
879
element of a finite field, an attempt is made to coerce it so it is
880
one.
881
882
EXAMPLES::
883
884
sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
885
sage: a = FiniteField_ext_pari(3**3, 'a').gen()
886
sage: a == 1
887
False
888
sage: a**0 == 1
889
True
890
sage: a == a
891
True
892
sage: a < a**2
893
True
894
sage: a > a**2
895
False
896
"""
897
return cmp(self.__value, other.__value)
898
899
def log(self, base):
900
"""
901
Return `x` such that `b^x = a`, where `x`
902
is `a` and `b` is the base.
903
904
INPUT:
905
906
- ``b`` -- finite field element that generates the
907
multiplicative group.
908
909
OUTPUT:
910
911
Integer `x` such that `a^x = b`, if it exists. Raises a
912
``ValueError`` exception if no such `x` exists.
913
914
EXAMPLES::
915
916
sage: F = GF(17)
917
sage: F(3^11).log(F(3))
918
11
919
sage: F = GF(113)
920
sage: F(3^19).log(F(3))
921
19
922
sage: F = GF(next_prime(10000))
923
sage: F(23^997).log(F(23))
924
997
925
926
::
927
928
sage: F = FiniteField(2^10, 'a', impl='pari_mod')
929
sage: g = F.gen()
930
sage: b = g; a = g^37
931
sage: a.log(b)
932
37
933
sage: b^37; a
934
a^8 + a^7 + a^4 + a + 1
935
a^8 + a^7 + a^4 + a + 1
936
937
AUTHORS:
938
939
- David Joyner and William Stein (2005-11)
940
"""
941
from sage.groups.generic import discrete_log
942
943
b = self.parent()(base)
944
# TODO: This function is TERRIBLE!
945
return discrete_log(self, b)
946
947
dynamic_FiniteField_ext_pariElement = None
948
def _late_import():
949
"""
950
Used to reset the class of PARI finite field elements in their initialization.
951
952
EXAMPLES::
953
954
sage: from sage.rings.finite_rings.element_ext_pari import FiniteField_ext_pariElement
955
sage: k.<a> = GF(3^17, impl='pari_mod')
956
sage: a.__class__ is FiniteField_ext_pariElement # indirect doctest
957
False
958
"""
959
global dynamic_FiniteField_ext_pariElement
960
dynamic_FiniteField_ext_pariElement = dynamic_class("%s_with_category"%FiniteField_ext_pariElement.__name__, (FiniteField_ext_pariElement, FiniteFields().element_class), doccls=FiniteField_ext_pariElement)
961
962
from sage.structure.sage_object import register_unpickle_override
963
register_unpickle_override('sage.rings.finite_field_element', 'FiniteField_ext_pariElement', FiniteField_ext_pariElement)
964
965