Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/libs/ntl/ntl_ZZ_pE.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 'misc.pxi'
20
include 'decl.pxi'
21
22
from sage.rings.integer import Integer
23
from sage.rings.integer_ring import IntegerRing
24
from sage.rings.integer cimport Integer
25
from sage.libs.ntl.ntl_ZZ cimport ntl_ZZ
26
from sage.libs.ntl.ntl_ZZ_p cimport ntl_ZZ_p
27
from sage.rings.integer cimport Integer
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
from sage.libs.ntl.ntl_ZZ_pEContext cimport ntl_ZZ_pEContext_class
36
from sage.libs.ntl.ntl_ZZ_pEContext import ntl_ZZ_pEContext
37
38
39
ZZ_sage = IntegerRing()
40
41
#def set_ZZ_pE_modulus(ntl_ZZ_pX f):
42
# f.c.restore_c()
43
# c = ntl_ZZ_pEContext_class(f)
44
# c.restore_c()
45
# return c
46
47
#def ntl_ZZ_pE_random():
48
# """
49
# Return a random number modulo p.
50
# """
51
# cdef ntl_ZZ_pE y = ntl_ZZ_pE()
52
# sig_on()
53
# y.x = *(<ntl_ZZ_pE_c>ZZ_pE_random())
54
# sig_off()
55
# return y
56
57
58
##############################################################################
59
#
60
# ZZ_pE_c: An extension of the integers modulo p
61
#
62
##############################################################################
63
cdef class ntl_ZZ_pE:
64
r"""
65
The \class{ZZ_pE} class is used to model $\Z / p\Z [x] / (f(x))$.
66
The modulus $p$ may be any positive integer, not necessarily prime,
67
and the modulus f is not required to be irreducible.
68
69
Objects of the class \class{ZZ_pE} are represented as a \code{ZZ_pX} of
70
degree less than the degree of $f$.
71
72
Each \class{ZZ_pE} contains a pointer of a \class{ZZ_pEContext} which
73
contains pre-computed data for NTL. These can be explicitly constructed
74
and passed to the constructor of a \class{ZZ_pE} or the \class{ZZ_pEContext}
75
method \code{ZZ_pE} can be used to construct a \class{ZZ_pE} element.
76
77
This class takes care of making sure that the C++ library NTL global
78
variable is set correctly before performing any arithmetic.
79
"""
80
def __init__(self, v=None, modulus=None):
81
r"""
82
Initializes an ntl ZZ_pE.
83
84
EXAMPLES:
85
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1],11))
86
sage: c.ZZ_pE([13,4,1])
87
[1 3]
88
sage: c.ZZ_pE(Integer(95413094))
89
[7]
90
sage: c.ZZ_pE(long(223895239852389582988))
91
[5]
92
sage: c.ZZ_pE('[1]')
93
[1]
94
95
AUTHOR: David Roe (2007-9-25)
96
"""
97
if PY_TYPE_CHECK( modulus, ntl_ZZ_pEContext_class ):
98
self.c = <ntl_ZZ_pEContext_class>modulus
99
elif PY_TYPE_CHECK( modulus, ntl_ZZ_pX ):
100
modulus.get_modulus_context().restore()
101
self.c = <ntl_ZZ_pEContext_class>ntl_ZZ_pEContext(<ntl_ZZ_pX>modulus)
102
elif PY_TYPE_CHECK(v, ntl_ZZ_pE):
103
self.c = (<ntl_ZZ_pE>v).c
104
elif PY_TYPE_CHECK(v, tuple) and len(v) == 2 and PY_TYPE_CHECK(v[1], ntl_ZZ_pEContext_class):
105
self.c = v[1]
106
v = v[0]
107
else:
108
raise ValueError, "You must specify a modulus when creating a ZZ_pE."
109
self.c.restore_c()
110
111
cdef ZZ_c temp
112
if v is not None:
113
sig_on()
114
if PY_TYPE_CHECK(v, ntl_ZZ_pE):
115
if (<ntl_ZZ_pE>v).c is not self.c:
116
raise ValueError, "You cannot cast between rings with different moduli"
117
self.x = (<ntl_ZZ_pE>v).x
118
elif PY_TYPE_CHECK(v, ntl_ZZ_pX):
119
if (<ntl_ZZ_pX>v).c is not self.c.pc:
120
raise ValueError, "You cannot cast between rings with different moduli"
121
self.x = ZZ_pX_to_ZZ_pE((<ntl_ZZ_pX>v).x)
122
elif PY_TYPE_CHECK(v, list) or PY_TYPE_CHECK(v, tuple):
123
self.x = ZZ_pX_to_ZZ_pE((<ntl_ZZ_pX>ntl_ZZ_pX(v, self.c.pc)).x)
124
elif PyInt_Check(v):
125
self.x = long_to_ZZ_pE(v)
126
elif PY_TYPE_CHECK(v, ntl_ZZ_p):
127
self.x = ZZ_p_to_ZZ_pE((<ntl_ZZ_p>v).x)
128
elif PyLong_Check(v):
129
ZZ_set_pylong(temp, v)
130
self.x = ZZ_to_ZZ_pE(temp)
131
elif PY_TYPE_CHECK(v, ntl_ZZ):
132
self.x = ZZ_to_ZZ_pE((<ntl_ZZ>v).x)
133
elif PY_TYPE_CHECK(v, Integer):
134
(<Integer>v)._to_ZZ(&temp)
135
self.x = ZZ_to_ZZ_pE(temp)
136
else:
137
v = str(v)
138
ZZ_pE_from_str(&self.x, PyString_AsString(v))
139
sig_off()
140
141
def __cinit__(ntl_ZZ_pE self, v=None, modulus=None):
142
#################### WARNING ###################
143
## Before creating a ZZ_pE, you must create a ##
144
## ZZ_pEContext, and restore it. In Python, ##
145
## the error checking in __init__ will prevent##
146
## you from constructing an ntl_ZZ_pE ##
147
## inappropriately. However, from Cython, you##
148
## could do r = PY_NEW(ntl_ZZ_pE) without ##
149
## first restoring a ZZ_pEContext, which could##
150
## have unfortunate consequences. See _new ##
151
## defined below for an example of the right ##
152
## way to short-circuit __init__ (or just call##
153
## _new in your own code). ##
154
################################################
155
if modulus is None:
156
ZZ_pE_construct(&self.x)
157
return
158
if PY_TYPE_CHECK( modulus, ntl_ZZ_pEContext_class ):
159
self.c = <ntl_ZZ_pEContext_class>modulus
160
self.c.restore_c()
161
ZZ_pE_construct(&self.x)
162
else:
163
self.c = <ntl_ZZ_pEContext_class>ntl_ZZ_pEContext(modulus)
164
self.c.restore_c()
165
ZZ_pE_construct(&self.x)
166
167
def __dealloc__(ntl_ZZ_pE self):
168
ZZ_pE_destruct(&self.x)
169
170
cdef ntl_ZZ_pE _new(self):
171
cdef ntl_ZZ_pE r
172
self.c.restore_c()
173
r = PY_NEW(ntl_ZZ_pE)
174
r.c = self.c
175
return r
176
177
def __reduce__(self):
178
"""
179
sage: a = ntl.ZZ_pE([4],ntl.ZZ_pX([1,1,1],ntl.ZZ(7)))
180
sage: loads(dumps(a)) == a
181
True
182
"""
183
return make_ZZ_pE, (self.get_as_ZZ_pX(), self.get_modulus_context())
184
185
def get_modulus_context(self):
186
return self.c
187
188
def __repr__(self):
189
#return self.get_as_ZZ_pX().__repr__()
190
self.c.restore_c()
191
#sig_on()
192
return ZZ_pE_to_PyString(&self.x)
193
#return string_delete(ans)
194
195
196
def __richcmp__(ntl_ZZ_pE self, ntl_ZZ_pE other, op):
197
r"""
198
EXAMPLES:
199
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1],11))
200
sage: c.ZZ_pE([13,1,1])==c.ZZ_pE(1)
201
True
202
sage: c.ZZ_pE(35r)==c.ZZ_pE(1)
203
False
204
"""
205
self.c.restore_c()
206
if op != 2 and op != 3:
207
raise TypeError, "Integers mod p are not ordered."
208
209
cdef int t
210
# cdef ntl_ZZ_p y
211
# if not isinstance(other, ntl_ZZ_p):
212
# other = ntl_ZZ_p(other)
213
# y = other
214
sig_on()
215
t = ZZ_pE_equal(self.x, other.x)
216
sig_off()
217
# t == 1 if self == other
218
if op == 2:
219
return t == 1
220
elif op == 3:
221
return t == 0
222
# And what about other op values?
223
224
def __invert__(ntl_ZZ_pE self):
225
r"""
226
EXAMPLES:
227
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([2,7,1],11))
228
sage: ~ntl.ZZ_pE([1,1],modulus=c)
229
[7 3]
230
"""
231
cdef ntl_ZZ_pE r = self._new()
232
sig_on()
233
self.c.restore_c()
234
ZZ_pE_inv(r.x, self.x)
235
sig_off()
236
return r
237
238
def __mul__(ntl_ZZ_pE self, other):
239
cdef ntl_ZZ_pE y
240
cdef ntl_ZZ_pE r = self._new()
241
if not PY_TYPE_CHECK(other, ntl_ZZ_pE):
242
other = ntl_ZZ_pE(other,self.c)
243
elif self.c is not (<ntl_ZZ_pE>other).c:
244
raise ValueError, "You can not perform arithmetic with elements of different moduli."
245
y = other
246
self.c.restore_c()
247
ZZ_pE_mul(r.x, self.x, y.x)
248
return r
249
250
def __sub__(ntl_ZZ_pE self, other):
251
if not PY_TYPE_CHECK(other, ntl_ZZ_pE):
252
other = ntl_ZZ_pE(other,self.c)
253
elif self.c is not (<ntl_ZZ_pE>other).c:
254
raise ValueError, "You can not perform arithmetic with elements of different moduli."
255
cdef ntl_ZZ_pE r = self._new()
256
self.c.restore_c()
257
ZZ_pE_sub(r.x, self.x, (<ntl_ZZ_pE>other).x)
258
return r
259
260
def __add__(ntl_ZZ_pE self, other):
261
cdef ntl_ZZ_pE y
262
cdef ntl_ZZ_pE r = self._new()
263
if not PY_TYPE_CHECK(other, ntl_ZZ_pE):
264
other = ntl_ZZ_pE(other,modulus=self.c)
265
elif self.c is not (<ntl_ZZ_pE>other).c:
266
raise ValueError, "You can not perform arithmetic with elements of different moduli."
267
y = other
268
sig_on()
269
self.c.restore_c()
270
ZZ_pE_add(r.x, self.x, y.x)
271
sig_off()
272
return r
273
274
def __neg__(ntl_ZZ_pE self):
275
cdef ntl_ZZ_pE r = self._new()
276
sig_on()
277
self.c.restore_c()
278
ZZ_pE_negate(r.x, self.x)
279
sig_off()
280
return r
281
282
def __pow__(ntl_ZZ_pE self, long e, ignored):
283
cdef ntl_ZZ_pE r = self._new()
284
sig_on()
285
self.c.restore_c()
286
ZZ_pE_power(r.x, self.x, e)
287
sig_off()
288
return r
289
290
291
cdef ntl_ZZ_pX get_as_ZZ_pX(ntl_ZZ_pE self):
292
r"""
293
Returns value as ntl_ZZ_pX.
294
"""
295
self.c.restore_c()
296
cdef ntl_ZZ_pX y = PY_NEW(ntl_ZZ_pX)
297
y.c = self.c.pc
298
sig_on()
299
y.x = ZZ_pE_to_ZZ_pX(self.x)
300
sig_off()
301
return y
302
303
def get_as_ZZ_pX_doctest(self):
304
r"""
305
This method exists solely for automated testing of get_as_ZZ_pX().
306
307
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1],11))
308
sage: x = ntl.ZZ_pE([42,1],modulus=c)
309
sage: i = x.get_as_ZZ_pX_doctest()
310
sage: print i
311
[9 1]
312
sage: print type(i)
313
<type 'sage.libs.ntl.ntl_ZZ_pX.ntl_ZZ_pX'>
314
"""
315
return self.get_as_ZZ_pX()
316
317
cdef void set_from_ZZ_pX(ntl_ZZ_pE self, ntl_ZZ_pX value):
318
r"""
319
Sets the value from a ZZ_pX.
320
"""
321
self.c.restore_c()
322
self.x = ZZ_pX_to_ZZ_pE(value.x)
323
324
def set_from_ZZ_pX_doctest(self, value):
325
r"""
326
This method exists solely for automated testing of set_from_ZZ_pX().
327
328
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1],11))
329
sage: x = ntl.ZZ_pE(modulus=c)
330
sage: x.set_from_ZZ_pX_doctest(ntl.ZZ_pX([5,2,1],11))
331
sage: x
332
[4 1]
333
"""
334
self.set_from_ZZ_pX(value)
335
336
#def lift(self):
337
# cdef ntl_ZZ r = ntl_ZZ()
338
# self.c.restore_c()
339
# r.x = rep(self.x)
340
# return r
341
342
def modulus(self):
343
r"""
344
Returns the modulus as an NTL ZZ_pX.
345
346
sage: c=ntl.ZZ_pEContext(ntl.ZZ_pX([1,1,1],11))
347
sage: n=ntl.ZZ_pE([2983,233],c)
348
sage: n.modulus()
349
[1 1 1]
350
"""
351
self.c.restore_c()
352
cdef ntl_ZZ_pX r = ntl_ZZ_pX(v = None, modulus=self.c.pc)
353
r.x = (<ntl_ZZ_pX>self.c.f).x
354
return r
355
356
def make_ZZ_pE(x, c):
357
"""
358
Here for unpickling.
359
360
EXAMPLES:
361
sage: c = ntl.ZZ_pEContext(ntl.ZZ_pX([-5,0,1],25))
362
sage: sage.libs.ntl.ntl_ZZ_pE.make_ZZ_pE([4,3], c)
363
[4 3]
364
sage: type(sage.libs.ntl.ntl_ZZ_pE.make_ZZ_pE([4,3], c))
365
<type 'sage.libs.ntl.ntl_ZZ_pE.ntl_ZZ_pE'>
366
"""
367
return ntl_ZZ_pE(x, c)
368
369