Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/libs/ntl/ntl_ZZ_p.pyx
4107 views
1
#*****************************************************************************
2
# Copyright (C) 2005 William Stein <[email protected]>
3
#
4
# Distributed under the terms of the GNU General Public License (GPL)
5
#
6
# This code is distributed in the hope that it will be useful,
7
# but WITHOUT ANY WARRANTY; without even the implied warranty of
8
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9
# General Public License for more details.
10
#
11
# The full text of the GPL is available at:
12
#
13
# http://www.gnu.org/licenses/
14
#*****************************************************************************
15
16
include "../../ext/interrupt.pxi"
17
include "../../ext/stdsage.pxi"
18
include "../../ext/cdefs.pxi"
19
include "../../ext/random.pxi"
20
include 'misc.pxi'
21
include 'decl.pxi'
22
23
from sage.rings.integer import Integer
24
from sage.rings.integer_ring import IntegerRing
25
from sage.rings.integer cimport Integer
26
from sage.libs.ntl.ntl_ZZ cimport ntl_ZZ
27
from sage.rings.rational cimport Rational
28
from sage.rings.integer_ring cimport IntegerRing_class
29
30
from sage.libs.ntl.ntl_ZZ import unpickle_class_args
31
32
from sage.libs.ntl.ntl_ZZ_pContext cimport ntl_ZZ_pContext_class
33
from sage.libs.ntl.ntl_ZZ_pContext import ntl_ZZ_pContext
34
35
ZZ_sage = IntegerRing()
36
37
def ntl_ZZ_p_random_element(v):
38
"""
39
Return a random number modulo p.
40
41
EXAMPLES:
42
sage: sage.libs.ntl.ntl_ZZ_p.ntl_ZZ_p_random_element(17)
43
8
44
"""
45
current_randstate().set_seed_ntl(False)
46
47
cdef ntl_ZZ_p y
48
v = ntl_ZZ_pContext(v)
49
y = ntl_ZZ_p(0,v)
50
sig_on()
51
ZZ_p_random(y.x)
52
sig_off()
53
return y
54
55
56
57
##############################################################################
58
#
59
# ZZ_p_c: integers modulo p
60
#
61
##############################################################################
62
cdef class ntl_ZZ_p:
63
r"""
64
The \class{ZZ_p} class is used to represent integers modulo $p$.
65
The modulus $p$ may be any positive integer, not necessarily prime.
66
67
Objects of the class \class{ZZ_p} are represented as a \code{ZZ} in the
68
range $0, \ldots, p-1$.
69
70
Each \class{ZZ_p} contains a pointer of a \class{ZZ_pContext} which
71
contains pre-computed data for NTL. These can be explicitly constructed
72
and passed to the constructor of a \class{ZZ_p} or the \class{ZZ_pContext}
73
method \code{ZZ_p} can be used to construct a \class{ZZ_p} element.
74
75
This class takes care of making sure that the C++ library NTL global
76
variable is set correctly before performing any arithmetic.
77
"""
78
def __init__(self, v=None, modulus=None):
79
r"""
80
Initializes an NTL integer mod p.
81
82
EXAMPLES:
83
sage: c = ntl.ZZ_pContext(11)
84
sage: ntl.ZZ_p(12r, c)
85
1
86
sage: ntl.ZZ_p(Integer(95413094), c)
87
7
88
sage: ntl.ZZ_p(long(223895239852389582988), c)
89
5
90
sage: ntl.ZZ_p('-1', c)
91
10
92
93
AUTHOR: Joel B. Mohler (2007-06-14)
94
"""
95
if modulus is None:
96
raise ValueError, "You must specify a modulus when creating a ZZ_p."
97
98
#self.c.restore_c() ## The context was restored in __new__
99
100
cdef ZZ_c temp, num, den
101
cdef long failed
102
if v is not None:
103
sig_on()
104
if PY_TYPE_CHECK(v, ntl_ZZ_p):
105
self.x = (<ntl_ZZ_p>v).x
106
elif PyInt_Check(v):
107
self.x = int_to_ZZ_p(v)
108
elif PyLong_Check(v):
109
ZZ_set_pylong(temp, v)
110
self.x = ZZ_to_ZZ_p(temp)
111
elif isinstance(v, Integer):
112
(<Integer>v)._to_ZZ(&temp)
113
self.x = ZZ_to_ZZ_p(temp)
114
elif isinstance(v, Rational):
115
(<Integer>v.numerator())._to_ZZ(&num)
116
(<Integer>v.denominator())._to_ZZ(&den)
117
ZZ_p_div(self.x, ZZ_to_ZZ_p(num), ZZ_to_ZZ_p(den))
118
else:
119
v = str(v)
120
ZZ_p_from_str(&self.x, v)
121
sig_off()
122
123
def __cinit__(self, v=None, modulus=None):
124
#################### WARNING ###################
125
## Before creating a ZZ_p, you must create a ##
126
## ZZ_pContext, and restore it. In Python, ##
127
## the error checking in __init__ will prevent##
128
## you from constructing an ntl_ZZ_p ##
129
## inappropriately. However, from Cython, you##
130
## could do r = PY_NEW(ntl_ZZ_p) without ##
131
## first restoring a ZZ_pContext, which could ##
132
## have unfortunate consequences. See _new ##
133
## defined below for an example of the right ##
134
## way to short-circuit __init__ (or just call##
135
## _new in your own code). ##
136
################################################
137
if modulus is None:
138
ZZ_p_construct(&self.x)
139
return
140
if PY_TYPE_CHECK( modulus, ntl_ZZ_pContext_class ):
141
self.c = <ntl_ZZ_pContext_class>modulus
142
self.c.restore_c()
143
ZZ_p_construct(&self.x)
144
elif modulus is not None:
145
self.c = <ntl_ZZ_pContext_class>ntl_ZZ_pContext(modulus)
146
self.c.restore_c()
147
ZZ_p_construct(&self.x)
148
149
def __dealloc__(self):
150
ZZ_p_destruct(&self.x)
151
152
cdef ntl_ZZ_p _new(self):
153
cdef ntl_ZZ_p r
154
self.c.restore_c()
155
r = PY_NEW(ntl_ZZ_p)
156
r.c = self.c
157
return r
158
159
def __reduce__(self):
160
"""
161
sage: a = ntl.ZZ_p(4,7)
162
sage: loads(dumps(a)) == a
163
True
164
"""
165
return unpickle_class_args, (ntl_ZZ_p, (self.lift(), self.modulus_context()))
166
167
def modulus_context(self):
168
"""
169
Return the modulus for self.
170
171
EXAMPLES:
172
sage: x = ntl.ZZ_p(5,17)
173
sage: c = x.modulus_context()
174
sage: y = ntl.ZZ_p(3,c)
175
sage: x+y
176
8
177
sage: c == y.modulus_context()
178
True
179
sage: c == ntl.ZZ_p(7,17).modulus_context()
180
True
181
"""
182
return self.c
183
184
def __repr__(self):
185
"""
186
Return the string representation of self.
187
188
EXAMPLES:
189
sage: ntl.ZZ_p(7,192).__repr__()
190
'7'
191
"""
192
self.c.restore_c()
193
return ZZ_p_to_PyString(&self.x)
194
195
def __richcmp__(ntl_ZZ_p self, ntl_ZZ_p other, op):
196
r"""
197
EXAMPLES:
198
sage: c = ntl.ZZ_pContext(11)
199
sage: ntl.ZZ_p(12r, c) == ntl.ZZ_p(1, c)
200
True
201
sage: ntl.ZZ_p(35r, c) == ntl.ZZ_p(1, c)
202
False
203
"""
204
self.c.restore_c()
205
if op != 2 and op != 3:
206
raise TypeError, "Integers mod p are not ordered."
207
208
cdef int t
209
# cdef ntl_ZZ_p y
210
# if not isinstance(other, ntl_ZZ_p):
211
# other = ntl_ZZ_p(other)
212
# y = other
213
sig_on()
214
t = ZZ_p_equal(self.x, other.x)
215
sig_off()
216
# t == 1 if self == other
217
if op == 2:
218
return t == 1
219
elif op == 3:
220
return t == 0
221
222
def __invert__(ntl_ZZ_p self):
223
r"""
224
EXAMPLES:
225
sage: c=ntl.ZZ_pContext(11)
226
sage: ~ntl.ZZ_p(2r,modulus=c)
227
6
228
"""
229
cdef ntl_ZZ_p r = self._new()
230
sig_on()
231
self.c.restore_c()
232
ZZ_p_inv(r.x, self.x)
233
sig_off()
234
return r
235
236
def __mul__(ntl_ZZ_p self, other):
237
"""
238
EXAMPLES:
239
sage: x = ntl.ZZ_p(5,31) ; y = ntl.ZZ_p(8,31)
240
sage: x*y ## indirect doctest
241
9
242
"""
243
cdef ntl_ZZ_p y
244
cdef ntl_ZZ_p r = self._new()
245
if not PY_TYPE_CHECK(other, ntl_ZZ_p):
246
other = ntl_ZZ_p(other,self.c)
247
elif self.c is not (<ntl_ZZ_p>other).c:
248
raise ValueError, "You can not perform arithmetic with elements of different moduli."
249
y = other
250
self.c.restore_c()
251
ZZ_p_mul(r.x, self.x, y.x)
252
return r
253
254
def __sub__(ntl_ZZ_p self, other):
255
"""
256
EXAMPLES:
257
sage: x = ntl.ZZ_p(5,31) ; y = ntl.ZZ_p(8,31)
258
sage: x-y ## indirect doctest
259
28
260
sage: y-x
261
3
262
"""
263
if not PY_TYPE_CHECK(other, ntl_ZZ_p):
264
other = ntl_ZZ_p(other,self.c)
265
elif self.c is not (<ntl_ZZ_p>other).c:
266
raise ValueError, "You can not perform arithmetic with elements of different moduli."
267
cdef ntl_ZZ_p r = self._new()
268
self.c.restore_c()
269
ZZ_p_sub(r.x, self.x, (<ntl_ZZ_p>other).x)
270
return r
271
272
def __add__(ntl_ZZ_p self, other):
273
"""
274
EXAMPLES:
275
sage: x = ntl.ZZ_p(5,31) ; y = ntl.ZZ_p(8,31)
276
sage: x+y ## indirect doctest
277
13
278
"""
279
cdef ntl_ZZ_p y
280
cdef ntl_ZZ_p r = ntl_ZZ_p(modulus=self.c)
281
if not PY_TYPE_CHECK(other, ntl_ZZ_p):
282
other = ntl_ZZ_p(other,modulus=self.c)
283
elif self.c is not (<ntl_ZZ_p>other).c:
284
raise ValueError, "You can not perform arithmetic with elements of different moduli."
285
y = other
286
sig_on()
287
self.c.restore_c()
288
ZZ_p_add(r.x, self.x, y.x)
289
sig_off()
290
return r
291
292
def __neg__(ntl_ZZ_p self):
293
"""
294
EXAMPLES:
295
sage: x = ntl.ZZ_p(5,31)
296
sage: -x ## indirect doctest
297
26
298
"""
299
cdef ntl_ZZ_p r = ntl_ZZ_p(modulus=self.c)
300
sig_on()
301
self.c.restore_c()
302
ZZ_p_negate(r.x, self.x)
303
sig_off()
304
return r
305
306
def __pow__(ntl_ZZ_p self, long e, ignored):
307
"""
308
EXAMPLES:
309
sage: x = ntl.ZZ_p(5,31)
310
sage: x**3 ## indirect doctest
311
1
312
"""
313
cdef ntl_ZZ_p r = ntl_ZZ_p(modulus=self.c)
314
sig_on()
315
self.c.restore_c()
316
ZZ_p_power(r.x, self.x, e)
317
sig_off()
318
return r
319
320
def __int__(self):
321
"""
322
Return self as an int.
323
324
EXAMPLES:
325
sage: x = ntl.ZZ_p(3,8)
326
sage: x.__int__()
327
3
328
sage: type(x.__int__())
329
<type 'int'>
330
"""
331
return self.get_as_int()
332
333
cdef int get_as_int(ntl_ZZ_p self):
334
r"""
335
Returns value as C int.
336
Return value is only valid if the result fits into an int.
337
338
AUTHOR: David Harvey (2006-08-05)
339
"""
340
self.c.restore_c()
341
return ZZ_p_to_int(self.x)
342
343
def _get_as_int_doctest(self):
344
r"""
345
This method exists solely for automated testing of get_as_int().
346
347
EXAMPLES:
348
sage: c = ntl.ZZ_pContext(20)
349
sage: x = ntl.ZZ_p(42,modulus=c)
350
sage: i = x._get_as_int_doctest()
351
sage: print i
352
2
353
sage: print type(i)
354
<type 'int'>
355
"""
356
self.c.restore_c()
357
return self.get_as_int()
358
359
cdef void set_from_int(ntl_ZZ_p self, int value):
360
r"""
361
Sets the value from a C int.
362
363
AUTHOR: David Harvey (2006-08-05)
364
"""
365
self.c.restore_c()
366
self.x = int_to_ZZ_p(value)
367
368
def _set_from_int_doctest(self, value):
369
r"""
370
This method exists solely for automated testing of set_from_int().
371
372
EXAMPLES:
373
sage: c=ntl.ZZ_pContext(ntl.ZZ(20))
374
sage: x = ntl.ZZ_p(modulus=c)
375
sage: x._set_from_int_doctest(42)
376
sage: x
377
2
378
sage: x = ntl.ZZ_p(7,81)
379
sage: x._set_from_int_doctest(int(3))
380
sage: x
381
3
382
"""
383
self.c.restore_c()
384
self.set_from_int(int(value))
385
386
def lift(self):
387
"""
388
Return a lift of self as an ntl.ZZ object.
389
390
EXAMPLES:
391
sage: x = ntl.ZZ_p(8,18)
392
sage: x.lift()
393
8
394
sage: type(x.lift())
395
<type 'sage.libs.ntl.ntl_ZZ.ntl_ZZ'>
396
"""
397
cdef ntl_ZZ r = ntl_ZZ()
398
self.c.restore_c()
399
r.x = ZZ_p_rep(self.x)
400
return r
401
402
def modulus(self):
403
r"""
404
Returns the modulus as an NTL ZZ.
405
406
EXAMPLES:
407
sage: c = ntl.ZZ_pContext(ntl.ZZ(20))
408
sage: n = ntl.ZZ_p(2983,c)
409
sage: n.modulus()
410
20
411
"""
412
cdef ntl_ZZ r = ntl_ZZ()
413
self.c.restore_c()
414
ZZ_p_modulus( &r.x, &self.x )
415
return r
416
417
def _integer_(self, ZZ=None):
418
"""
419
Return a lift of self as a Sage integer.
420
421
EXAMPLES:
422
sage: x = ntl.ZZ_p(8,188)
423
sage: x._integer_()
424
8
425
426
sage: type(x._integer_())
427
<type 'sage.rings.integer.Integer'>
428
"""
429
self.c.restore_c()
430
cdef ZZ_c rep = ZZ_p_rep(self.x)
431
return (<IntegerRing_class>ZZ_sage)._coerce_ZZ(&rep)
432
433
def _sage_(self):
434
r"""
435
Returns the value as a sage IntegerModRing.
436
437
EXAMPLES:
438
sage: c = ntl.ZZ_pContext(20)
439
sage: n = ntl.ZZ_p(2983, c)
440
sage: type(n._sage_())
441
<type 'sage.rings.finite_rings.integer_mod.IntegerMod_int'>
442
sage: n
443
3
444
445
AUTHOR: Joel B. Mohler
446
"""
447
from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
448
449
cdef ZZ_c rep
450
self.c.restore_c()
451
rep = ZZ_p_rep(self.x)
452
return IntegerModRing(self.modulus()._integer_())((<IntegerRing_class>ZZ_sage)._coerce_ZZ(&rep))
453
454
# todo: add wrapper for int_to_ZZ_p in wrap.cc?
455
456