Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/libs/ntl/ntl_lzz_p.pyx
4107 views
1
"""
2
ntl_lzz_p.pyx
3
4
Wraps NTL's zz_p type for SAGE
5
6
NOTE: This file is essentially useless. While we provide
7
this wrapper for consistency, this should never be used in
8
*production* code, i.e. anything intended to be fast. The
9
reason for this is simple: this is a wrapper for a Python
10
interface to the zz_p type, which is just a long! Any speed
11
gains you get from working with longs will be TOTALLY
12
destroyed by the overhead of having a wrapper.
13
14
AUTHORS:
15
- Craig Citro
16
"""
17
18
#*****************************************************************************
19
# Copyright (C) 2005 William Stein <[email protected]>
20
#
21
# Distributed under the terms of the GNU General Public License (GPL)
22
#
23
# This code is distributed in the hope that it will be useful,
24
# but WITHOUT ANY WARRANTY; without even the implied warranty of
25
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
26
# General Public License for more details.
27
#
28
# The full text of the GPL is available at:
29
#
30
# http://www.gnu.org/licenses/
31
#*****************************************************************************
32
33
include "../../ext/interrupt.pxi"
34
include "../../ext/stdsage.pxi"
35
include "../../ext/cdefs.pxi"
36
include 'misc.pxi'
37
include 'decl.pxi'
38
39
from sage.rings.integer import Integer
40
from sage.rings.integer_ring import IntegerRing
41
from sage.rings.integer cimport Integer
42
from sage.rings.integer_ring cimport IntegerRing_class
43
44
from sage.rings.finite_rings.integer_mod cimport IntegerMod_gmp, IntegerMod_int, IntegerMod_int64
45
46
from sage.libs.ntl.ntl_lzz_pContext import ntl_zz_pContext
47
from sage.libs.ntl.ntl_lzz_pContext cimport ntl_zz_pContext_class
48
49
ZZ_sage = IntegerRing()
50
51
##############################################################################
52
#
53
# zz_pX -- polynomials over the integers modulo p, p small
54
#
55
##############################################################################
56
57
cdef class ntl_zz_p:
58
r"""
59
The class \class{zz_p} implements arithmetic modulo $p$,
60
for p smaller than a machine word.
61
62
NOTE: This type is provided mostly for completeness, and
63
shouldn't be used in any production code.
64
"""
65
# See ntl_zz_p.pxd for definition of data members
66
def __init__(self, a=0, modulus=None):
67
"""
68
EXAMPLES:
69
sage: f = ntl.zz_p(5,7)
70
sage: f
71
5
72
sage: g = ntl.zz_p(2,7) ; g
73
2
74
"""
75
if modulus is None:
76
raise ValueError, "You must specify a modulus."
77
78
cdef long temp
79
if PY_TYPE_CHECK(modulus, Integer):
80
p_sage = modulus
81
else:
82
p_sage = Integer(self.c.p)
83
84
85
#self.c.restore_c() ## This was done in __new__
86
87
if PY_TYPE_CHECK(a, IntegerMod_int):
88
if (self.c.p == (<IntegerMod_int>a).__modulus.int32): ## this is slow
89
zz_p_set_from_long(self.x, (<IntegerMod_int>a).ivalue)
90
else:
91
raise ValueError, \
92
"Mismatched modulus for converting to zz_p."
93
94
elif PY_TYPE_CHECK(a, IntegerMod_int64):
95
if (self.c.p == (<IntegerMod_int64>a).__modulus.int64): ## this is slow
96
zz_p_set_from_long(self.x, (<IntegerMod_int64>a).ivalue)
97
else:
98
raise ValueError, \
99
"Mismatched modulus for converting to zz_p."
100
101
elif PY_TYPE_CHECK(a, IntegerMod_gmp):
102
if (p_sage == (<IntegerMod_gmp>a).__modulus.sageInteger): ## this is slow
103
zz_p_set_from_long(self.x, mpz_get_si((<IntegerMod_gmp>a).value))
104
else:
105
raise ValueError, \
106
"Mismatched modulus for converting to zz_p."
107
108
elif PY_TYPE_CHECK(a, Integer):
109
zz_p_set_from_long(self.x, mpz_get_si((<Integer>a).value)%self.c.p)
110
111
elif PY_TYPE_CHECK(a, int):
112
## we're lucky that python int is no larger than long
113
temp = a
114
zz_p_set_from_long(self.x, temp%self.c.p)
115
else:
116
a = Integer(a)
117
zz_p_set_from_long(self.x, mpz_get_si((<Integer>a).value)%self.c.p)
118
119
return
120
121
def __cinit__(self, v=None, modulus=None):
122
#################### WARNING ###################
123
## Before creating a zz_p, you must create a ##
124
## zz_pContext, and restore it. In Python, ##
125
## the error checking in __init__ will prevent##
126
## you from constructing a zz_p ##
127
## inappropriately. However, from Cython, you##
128
## could do r = PY_NEW(ntl_zz_p) without ##
129
## first restoring a zz_pContext, which could ##
130
## have unfortunate consequences. See _new ##
131
## defined below for an example of the right ##
132
## way to short-circuit __init__ (or just call##
133
## _new in your own code). ##
134
################################################
135
if modulus is None:
136
zz_p_construct(&self.x)
137
return
138
if PY_TYPE_CHECK( modulus, ntl_zz_pContext_class ):
139
self.c = <ntl_zz_pContext_class>modulus
140
elif PY_TYPE_CHECK( modulus, Integer ):
141
self.c = <ntl_zz_pContext_class>ntl_zz_pContext(modulus)
142
elif PY_TYPE_CHECK( modulus, long ):
143
self.c = <ntl_zz_pContext_class>ntl_zz_pContext(modulus)
144
else:
145
try:
146
modulus = int(modulus)
147
except:
148
raise ValueError, "%s is not a valid modulus."%modulus
149
self.c = <ntl_zz_pContext_class>ntl_zz_pContext(modulus)
150
151
## now that we've determined the modulus, set that modulus.
152
self.c.restore_c()
153
zz_p_construct(&self.x)
154
155
def __dealloc__(self):
156
zz_p_destruct(&self.x)
157
158
cdef ntl_zz_p _new(self):
159
"""
160
Quick and dirty zz_p object creation.
161
162
EXAMPLES:
163
sage: x = ntl.zz_p(23,75)
164
sage: y = x*x ## indirect doctest
165
"""
166
cdef ntl_zz_p y
167
self.c.restore_c()
168
y = PY_NEW(ntl_zz_p)
169
y.c = self.c
170
return y
171
172
def __reduce__(self):
173
"""
174
For pickling.
175
176
TESTS:
177
sage: f = ntl.zz_p(16,244)
178
sage: loads(dumps(f)) == f
179
True
180
"""
181
return make_zz_p, (zz_p_rep(self.x), self.c)
182
183
def __repr__(self):
184
"""
185
Return the string representation of self.
186
187
EXAMPLES:
188
sage: ntl.zz_p(3,79).__repr__()
189
'3'
190
"""
191
return Integer(zz_p_rep(self.x)).__repr__()
192
193
def __add__(ntl_zz_p self, other):
194
"""
195
EXAMPLES:
196
sage: ntl.zz_p(5,23) + ntl.zz_p(6,23)
197
11
198
"""
199
cdef ntl_zz_p y
200
if not PY_TYPE_CHECK(other, ntl_zz_p):
201
other = ntl_zz_p(other, modulus=self.c)
202
elif self.c is not (<ntl_zz_p>other).c:
203
raise ValueError, "arithmetic operands must have the same modulus."
204
self.c.restore_c()
205
y = self._new()
206
zz_p_add(y.x, self.x, (<ntl_zz_p>other).x)
207
return y
208
209
def __sub__(ntl_zz_p self, other):
210
"""
211
EXAMPLES:
212
sage: ntl.zz_p(5,23) - ntl.zz_p(6,23)
213
22
214
"""
215
cdef ntl_zz_p y
216
if not PY_TYPE_CHECK(other, ntl_zz_p):
217
other = ntl_zz_p(other, modulus=self.c)
218
elif self.c is not (<ntl_zz_p>other).c:
219
raise ValueError, "arithmetic operands must have the same modulus."
220
self.c.restore_c()
221
y = self._new()
222
zz_p_sub(y.x, self.x, (<ntl_zz_p>other).x)
223
return y
224
225
def __mul__(ntl_zz_p self, other):
226
"""
227
EXAMPLES:
228
sage: ntl.zz_p(5,23) * ntl.zz_p(6,23)
229
7
230
"""
231
cdef ntl_zz_p y
232
if not PY_TYPE_CHECK(other, ntl_zz_p):
233
other = ntl_zz_p(other, modulus=self.c)
234
elif self.c is not (<ntl_zz_p>other).c:
235
raise ValueError, "arithmetic operands must have the same modulus."
236
y = self._new()
237
self.c.restore_c()
238
zz_p_mul(y.x, self.x, (<ntl_zz_p>other).x)
239
return y
240
241
def __div__(ntl_zz_p self, other):
242
"""
243
EXAMPLES:
244
sage: ntl.zz_p(5,23) / ntl.zz_p(2,23)
245
14
246
"""
247
cdef ntl_zz_p q
248
if not PY_TYPE_CHECK(other, ntl_zz_p):
249
other = ntl_zz_p(other, modulus=self.c)
250
elif self.c is not (<ntl_zz_p>other).c:
251
raise ValueError, "arithmetic operands must have the same modulus."
252
q = self._new()
253
self.c.restore_c()
254
sig_on()
255
zz_p_div(q.x, self.x, (<ntl_zz_p>other).x)
256
sig_off()
257
return q
258
259
def __pow__(ntl_zz_p self, long n, ignored):
260
"""
261
Return the n-th nonnegative power of self.
262
263
EXAMPLES:
264
sage: g = ntl.zz_p(5,13)
265
sage: g**10
266
12
267
sage: g**(-1)
268
8
269
sage: g**(-5)
270
8
271
"""
272
cdef ntl_zz_p y
273
if self.is_zero():
274
if n == 0:
275
raise ArithmeticError, "0^0 is undefined."
276
elif n < 0:
277
raise ZeroDivisionError
278
else:
279
return self
280
else:
281
from sage.groups.generic import power
282
283
self.c.restore_c()
284
285
if n == 0:
286
return self
287
elif n < 0:
288
y = PY_NEW(ntl_zz_p)
289
y.c = self.c
290
zz_p_inv(y.x, self.x)
291
return power(y, -n, ntl_zz_p(1,self.c))
292
else:
293
return power(self, n, ntl_zz_p(1,self.c))
294
295
def __neg__(self):
296
"""
297
Return the negative of self.
298
299
EXAMPLES:
300
sage: f = ntl.zz_p(5,234)
301
sage: -f ## indirect doctest
302
229
303
"""
304
cdef ntl_zz_p y
305
y = self._new()
306
self.c.restore_c()
307
zz_p_negate(y.x, self.x)
308
return y
309
310
def __cmp__(ntl_zz_p self, other):
311
"""
312
Decide whether or not self and other are equal.
313
314
EXAMPLES:
315
sage: f = ntl.zz_p(3,20)
316
sage: g = ntl.zz_p(2,20)
317
sage: f == g
318
False
319
sage: f == f
320
True
321
sage: g = ntl.zz_p(3,60)
322
sage: f == g
323
False
324
"""
325
if not PY_TYPE_CHECK(other, ntl_zz_p):
326
return cmp(ntl_zz_p, other.parent())
327
if not (self.c is (<ntl_zz_p>other).c):
328
return cmp(self.c.p, (<ntl_zz_p>other).c.p)
329
330
self.c.restore_c()
331
if not PY_TYPE_CHECK(other, ntl_zz_p):
332
return -1
333
if (NTL_zz_p_DOUBLE_EQUALS(self.x, (<ntl_zz_p>other).x)):
334
return 0
335
else:
336
return -1
337
338
def __int__(self):
339
"""
340
Return self as an int.
341
342
EXAMPLES:
343
sage: ntl.zz_p(3,next_prime(100)).__int__()
344
3
345
sage: int(ntl.zz_p(3,next_prime(100)))
346
3
347
sage: type(int(ntl.zz_p(3,next_prime(100))))
348
<type 'int'>
349
"""
350
return zz_p_rep(self.x)
351
352
def square(self):
353
"""
354
Return f*f.
355
356
EXAMPLES:
357
sage: f = ntl.zz_p(15,23)
358
sage: f*f
359
18
360
"""
361
cdef ntl_zz_p y
362
y = self._new()
363
self.c.restore_c()
364
zz_p_sqr(y.x, self.x)
365
return y
366
367
def is_zero(self):
368
"""
369
Return True exactly if this element is 0.
370
371
EXAMPLES:
372
sage: f = ntl.zz_p(0,20)
373
sage: f.is_zero()
374
True
375
sage: f = ntl.zz_p(1,20)
376
sage: f.is_zero()
377
False
378
"""
379
self.c.restore_c()
380
return zz_p_rep(self.x) == 0
381
382
def is_one(self):
383
"""
384
Return True exactly if this element is 1.
385
386
EXAMPLES:
387
sage: f = ntl.zz_p(1,11)
388
sage: f.is_one()
389
True
390
sage: f = ntl.zz_p(5,11)
391
sage: f.is_one()
392
False
393
"""
394
self.c.restore_c()
395
return zz_p_rep(self.x) == 1
396
397
def clear(self):
398
"""
399
Reset this element to 0.
400
401
EXAMPLES:
402
sage: x = ntl.zz_p(5,102) ; x
403
5
404
sage: x.clear() ; x
405
0
406
"""
407
self.c.restore_c()
408
zz_p_clear(self.x)
409
410
def make_zz_p(val, context):
411
"""
412
For unpickling.
413
414
TEST:
415
sage: f = ntl.zz_p(1, 12)
416
sage: loads(dumps(f)) == f
417
True
418
"""
419
return ntl_zz_p(val, context)
420
421