Changeset 8432:eee6353af42a
- Timestamp:
- 11/11/07 14:27:50 (6 years ago)
- Branch:
- default
- Location:
- sage/rings/padics
- Files:
-
- 4 edited
-
pow_computer.pxd (modified) (2 diffs)
-
pow_computer.pyx (modified) (8 diffs)
-
pow_computer_ext.pxd (modified) (1 diff)
-
pow_computer_ext.pyx (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
sage/rings/padics/pow_computer.pxd
r7016 r8432 1 1 include "../../ext/cdefs.pxi" 2 include "../../libs/ntl/decl.pxi"3 2 4 cimport sage.structure.sage_object5 3 from sage.structure.sage_object cimport SageObject 6 cimport sage.rings.integer7 4 from sage.rings.integer cimport Integer 8 5 … … 15 12 cdef unsigned long prec_cap 16 13 14 cdef mpz_t temp_m 15 17 16 cdef Integer pow_Integer(self, unsigned long n) 18 cdef mpz_t* pow_mpz_top(self) 19 cdef mpz_t* pow_mpz_t(self, unsigned long n) 17 cdef mpz_t* pow_mpz_t_top(self) 20 18 cdef mpz_t* pow_mpz_t_tmp(self, unsigned long n) 21 cdef ZZ_c pow_ZZ(self, unsigned long n)22 19 23 20 cdef class PowComputer_base(PowComputer_class): 24 21 cdef mpz_t* small_powers 25 22 cdef mpz_t top_power 26 cdef mpz_t temp27 23 cdef object __weakref__ -
sage/rings/padics/pow_computer.pyx
r7016 r8432 43 43 self._initialized = 1 44 44 45 def __cmp__(self, other): 46 """ 47 Compares self to other 48 49 EXAMPLES: 50 sage: P = PowComputer(3, 4, 9) 51 sage: P == 7 52 False 53 sage: Q = PowComputer(3, 6, 9) 54 sage: P == Q 55 False 56 sage: Q = PowComputer(3, 4, 9) 57 sage: P == Q 58 True 59 sage: P is Q 60 True 61 """ 62 a = cmp(type(self), type(other)) 63 cdef PowComputer_class o 64 if a == 0: 65 o = <PowComputer_class>other 66 if self.prime < o.prime: 67 return -1 68 elif self.prime > o.prime: 69 return 1 70 elif self.prec_cap < o.prec_cap: 71 return -1 72 elif self.prec_cap > o.prec_cap: 73 return 1 74 elif self.cache_limit < o.cache_limit: 75 return -1 76 elif self.cache_limit > o.cache_limit: 77 return 1 78 elif self.in_field < o.in_field: 79 return -1 80 elif self.in_field > o.in_field: 81 return 1 82 else: 83 return 0 84 else: 85 return cmp(type(self), type(other)) 86 45 87 cdef Integer pow_Integer(self, unsigned long n): 88 """ 89 Returns self.prime^n 90 """ 46 91 cdef Integer ans = PY_NEW(Integer) 47 _sig_on 48 mpz_pow_ui(ans.value, self.prime.value, n) 49 _sig_off 50 return ans 51 52 cdef mpz_t* pow_mpz_t(self, unsigned long n): 92 mpz_set(ans.value, self.pow_mpz_t_tmp(n)[0]) 93 return ans 94 95 def pow_Integer_Integer(self, n): 96 """ 97 Tests the pow_Integer function. 98 99 EXAMPLES: 100 sage: PC = PowComputer(3, 5, 10) 101 sage: PC.pow_Integer_Integer(4) 102 81 103 sage: PC.pow_Integer_Integer(6) 104 729 105 sage: PC.pow_Integer_Integer(0) 106 1 107 sage: PC.pow_Integer_Integer(10) 108 59049 109 sage: PC = PowComputer_ext_maker(3, 5, 10, False, ntl.ZZ_pX([-9,0,1], 3^10), "big") 110 sage: PC.pow_Integer_Integer(4) 111 81 112 sage: PC.pow_Integer_Integer(6) 113 729 114 sage: PC.pow_Integer_Integer(0) 115 1 116 sage: PC.pow_Integer_Integer(10) 117 59049 118 """ 119 cdef Integer _n = Integer(n) 120 cdef Integer ans 121 if _n < 0: 122 if mpz_fits_ulong_p((<Integer>-_n).value) == 0: 123 raise ValueError, "result too big" 124 return ~self.pow_Integer(mpz_get_ui((<Integer>-_n).value)) 125 else: 126 if mpz_fits_ulong_p(_n.value) == 0: 127 raise ValueError, "result too big" 128 return self.pow_Integer(mpz_get_ui(_n.value)) 129 130 cdef mpz_t* pow_mpz_t_tmp(self, unsigned long n): 131 """ 132 Provides fast access to an mpz_t* pointing to self.prime^n. 133 134 The location pointed to depends on the underlying representation. 135 In no circumstances should you mpz_clear the result. 136 The value pointed to may be an internal temporary variable for the class. 137 In particular, you should not try to refer to the results of two 138 pow_mpz_t_tmp calls at the same time, because the second 139 call may overwrite the memory pointed to by the first. 140 141 See pow_mpz_t_tmp_demo for an example of this phenomenon. 142 """ 143 ## READ THE DOCSTRING 53 144 raise NotImplementedError 54 145 55 cdef mpz_t* pow_mpz_t_tmp(self, unsigned long n): 146 def pow_mpz_t_tmp_demo(self, m, n): 147 """ 148 This function demonstrates a danger in using pow_mpz_t_tmp. 149 150 EXAMPLES: 151 sage: PC = PowComputer(5, 5, 10) 152 153 When you cal pow_mpz_t_tmp with an input that is not stored 154 (ie n > self.cache_limit and n != self.prec_cap), 155 it stores the result in self.temp_m and returns a pointer 156 to that mpz_t. So if you try to use the results of two 157 calls at once, things will break. 158 sage: PC.pow_mpz_t_tmp_demo(6, 8) 159 244140625 160 sage: 5^6*5^8 161 6103515625 162 sage: 5^6*5^6 163 244140625 164 165 Note that this does not occur if you try a stored value, 166 because the result of one of the calls points to that 167 stored value. 168 sage: PC.pow_mpz_t_tmp_demo(6, 10) 169 152587890625 170 sage: 5^6*5^10 171 152587890625 172 """ 173 m = Integer(m) 174 n = Integer(n) 175 if m < 0 or n < 0: 176 raise ValueError, "m, n must be non-negative" 177 cdef Integer ans = PY_NEW(Integer) 178 mpz_mul(ans.value, self.pow_mpz_t_tmp(mpz_get_ui((<Integer>m).value))[0], self.pow_mpz_t_tmp(mpz_get_ui((<Integer>n).value))[0]) 179 return ans 180 181 def pow_mpz_t_tmp_test(self, n): 182 """ 183 Tests the pow_Integer function. 184 185 EXAMPLES: 186 sage: PC = PowComputer(3, 5, 10) 187 sage: PC.pow_mpz_t_tmp_test(4) 188 81 189 sage: PC.pow_mpz_t_tmp_test(6) 190 729 191 sage: PC.pow_mpz_t_tmp_test(0) 192 1 193 sage: PC.pow_mpz_t_tmp_test(10) 194 59049 195 sage: PC = PowComputer_ext_maker(3, 5, 10, False, ntl.ZZ_pX([-9,0,1], 3^10), "big") 196 sage: PC.pow_mpz_t_tmp_test(4) 197 81 198 sage: PC.pow_mpz_t_tmp_test(6) 199 729 200 sage: PC.pow_mpz_t_tmp_test(0) 201 1 202 sage: PC.pow_mpz_t_tmp_test(10) 203 59049 204 """ 205 cdef Integer _n = Integer(n) 206 cdef Integer ans = PY_NEW(Integer) 207 mpz_set(ans.value, self.pow_mpz_t_tmp(mpz_get_ui(_n.value))[0]) 208 return ans 209 210 cdef mpz_t* pow_mpz_t_top(self): 56 211 raise NotImplementedError 57 212 58 cdef ZZ_c pow_ZZ(self, unsigned long n): 59 raise NotImplementedError 60 61 cdef mpz_t* pow_mpz_top(self): 62 raise NotImplementedError 213 def pow_mpz_t_top_test(self): 214 """ 215 Tests the pow_mpz_t_top function. 216 217 EXAMPLES: 218 sage: PC = PowComputer(3, 5, 10) 219 sage: PC.pow_mpz_t_top_test() 220 59049 221 sage: PC = PowComputer_ext_maker(3, 5, 10, False, ntl.ZZ_pX([-9,0,1], 3^10), "big") 222 sage: PC.pow_mpz_t_top_test() 223 59049 224 """ 225 cdef Integer ans = PY_NEW(Integer) 226 mpz_set(ans.value, self.pow_mpz_t_top()[0]) 227 return ans 228 229 def __repr__(self): 230 """ 231 Returns a string representation of self. 232 233 EXAMPLES: 234 sage: PC = PowComputer(3, 5, 10); PC 235 PowComputer for 3 236 """ 237 return "PowComputer for %s"%(self.prime) 63 238 64 239 def _prime(self): … … 75 250 def _in_field(self): 76 251 """ 77 For use by p-adic rings and fields. Feel free to ignore if you're using a PowComputer otherwise. 252 Returns whether or not self is attached to a field. 253 254 EXAMPLES: 255 sage: P = PowComputer(3, 5, 10) 256 sage: P._in_field() 257 False 78 258 """ 79 259 return self.in_field 80 260 261 def _cache_limit(self): 262 """ 263 Returns the limit to which powers of prime are computed. 264 265 EXAMPLES: 266 sage: P = PowComputer(3, 5, 10) 267 sage: P._cache_limit() 268 5 269 """ 270 cdef Integer ans 271 ans = PY_NEW(Integer) 272 mpz_set_ui(ans.value, self.cache_limit) 273 return ans 274 275 def _prec_cap(self): 276 """ 277 Returns prec_cap, a single value that for which self._prime()^prec_cap is stored 278 279 EXAMPLES: 280 sage: P = PowComputer(3, 5, 10) 281 sage: P._prec_cap() 282 10 283 """ 284 cdef Integer ans 285 ans = PY_NEW(Integer) 286 mpz_set_ui(ans.value, self.prec_cap) 287 return ans 288 289 def _top_power(self): 290 """ 291 Returns self._prime()^self._prec_cap() 292 293 EXAMPLES: 294 sage: P = PowComputer(3, 4, 6) 295 sage: P._top_power() 296 729 297 """ 298 cdef Integer ans 299 ans = PY_NEW(Integer) 300 mpz_set(ans.value, self.pow_mpz_t_top()[0]) 301 return ans 302 81 303 def __call__(self, n): 304 """ 305 Returns self.prime^n. 306 307 EXAMPLES: 308 sage: P = PowComputer(3, 4, 6) 309 sage: P(3) 310 27 311 sage: P(6) 312 729 313 sage: P(5) 314 243 315 sage: P(7) 316 2187 317 sage: P(0) 318 1 319 sage: P(-2) 320 1/9 321 """ 82 322 cdef Integer z, _n 83 323 cdef mpz_t tmp … … 88 328 else: 89 329 _n = <Integer>n 90 if mpz_cmp_ui(_n.value, 0) >= 0: 91 return self.pow_Integer(mpz_get_ui(_n.value)) 92 else: 330 if _n < 0: 93 331 return self.prime.__pow__(_n) 332 if mpz_fits_ulong_p(_n.value) == 0: 333 raise ValueError, "n too big" 334 return self.pow_Integer(mpz_get_ui(_n.value)) 94 335 95 336 cdef class PowComputer_base(PowComputer_class): … … 102 343 raise MemoryError, "out of memory allocating power storing" 103 344 mpz_init(self.top_power) 104 mpz_init(self.temp )345 mpz_init(self.temp_m) 105 346 106 347 def __init__(self, Integer prime, unsigned long cache_limit, unsigned long prec_cap, bint in_field): … … 121 362 122 363 def __dealloc__(self): 364 """ 365 sage: P = PowComputer(5, 7, 10) 366 sage: del P 367 sage: PowComputer(5, 7, 10) 368 PowComputer for 5 369 """ 123 370 cdef Py_ssize_t i 124 371 if (<PowComputer_class>self)._initialized: … … 127 374 sage_free(self.small_powers) 128 375 mpz_clear(self.top_power) 129 mpz_clear(self.temp )376 mpz_clear(self.temp_m) 130 377 131 def __cmp__(self, other):132 if isinstance(other, PowComputer_base):133 if self.prime < (<PowComputer_class>other).prime:134 return -1135 elif self.prime > (<PowComputer_class>other).prime:136 return 1137 elif self.prec_cap < (<PowComputer_base>other).prec_cap:138 return -1139 elif self.prec_cap > (<PowComputer_base>other).prec_cap:140 return 1141 elif self.cache_limit < (<PowComputer_base>other).cache_limit:142 return -1143 elif self.cache_limit > (<PowComputer_base>other).cache_limit:144 return 1145 elif self.in_field < (<PowComputer_class>other).in_field:146 return -1147 elif self.in_field > (<PowComputer_class>other).in_field:148 return 1149 else:150 return 0151 else:152 return cmp(type(self), type(other))153 378 154 379 def __reduce__(self): … … 161 386 return PowComputer, (self.prime, self.cache_limit, self.prec_cap, self.in_field) 162 387 163 def _cache_limit(self): 164 """ 165 Returns the limit to which powers of prime are computed. 166 """ 167 cdef Integer ans 168 ans = PY_NEW(Integer) 169 mpz_set_ui(ans.value, self.cache_limit) 170 return ans 171 172 def _top_power(self): 173 """ 174 Returns self._prime()^self._prec_cap() 175 """ 176 cdef Integer ans 177 ans = PY_NEW(Integer) 178 mpz_set(ans.value, self.top_power) 179 return ans 180 181 def _prec_cap(self): 182 """ 183 Returns prec_cap, a single value that for which self._prime()^prec_cap is stored 184 """ 185 cdef Integer ans 186 ans = PY_NEW(Integer) 187 mpz_set_ui(ans.value, self.prec_cap) 188 return ans 189 190 cdef Integer pow_Integer(self, unsigned long n): 191 cdef Integer ans = PY_NEW(Integer) 192 if n <= self.cache_limit: 193 mpz_set(ans.value, self.small_powers[n]) 194 elif n == self.prec_cap: 195 mpz_set(ans.value, self.top_power) 196 else: 197 mpz_pow_ui(ans.value, self.prime.value, n) 198 return ans 199 200 cdef mpz_t* pow_mpz_top(self): 388 cdef mpz_t* pow_mpz_t_top(self): 201 389 return &self.top_power 202 390 203 cdef mpz_t* pow_mpz_t(self, unsigned long n): 204 #################### WARNING ###################### 205 ## If you use this function, you MAY need to ## 206 ## call mpz_clear on the returned value after ## 207 ## you are finished with it. You need to do ## 208 ## so if and only if (n > self.cache_limit and ## 209 ## n != self.prec_cap). So your code should ## 210 ## look something like the following: ## 211 ## ## 212 ## cdef PowComputer_base ppow ## 213 ## ppow = PowComputer(5, 10, 1000) ## 214 ## cdef unsigned long n = get_long_somehow() ## 215 ## cdef mpz_t foo = ppow.pow_mpz_t(n)[0] ## 216 ## # Do stuff with foo ## 217 ## # Now done with foo ## 218 ## if n > ppow.cache_limit and n != ppow.prec_cap## 219 ## mpz_clear(foo) ## 220 ################################################### 391 cdef mpz_t* pow_mpz_t_tmp(self, unsigned long n): 221 392 if n <= self.cache_limit: 222 393 return &(self.small_powers[n]) 223 394 if n == self.prec_cap: 224 395 return &(self.top_power) 225 cdef mpz_t ans 226 mpz_init(ans) 227 mpz_pow_ui(ans, self.prime.value, n) 228 return &ans 229 230 cdef mpz_t* pow_mpz_t_tmp(self, unsigned long n): 231 ## Solves the problem noted in the above warning by storing the returned mpz_t in a temporary variable 232 ## Each call to this function overwrites that temporary variable. 233 if n <= self.cache_limit: 234 return &(self.small_powers[n]) 235 if n == self.prec_cap: 236 return &(self.top_power) 237 mpz_pow_ui(self.temp, self.prime.value, n) 238 return &(self.temp) 396 mpz_pow_ui(self.temp_m, self.prime.value, n) 397 return &(self.temp_m) 239 398 240 241 cdef ZZ_c pow_ZZ(self, unsigned long n):242 ## You always need to call ZZ_destruct on the return value of this function243 cdef ZZ_c ans244 cdef mpz_t temp245 ZZ_construct(&ans)246 if n <= self.cache_limit:247 mpz_to_ZZ(&ans, &(self.small_powers[n]))248 elif n == self.prec_cap:249 mpz_to_ZZ(&ans, &self.top_power)250 else:251 mpz_init(temp)252 mpz_pow_ui(temp, self.prime.value, n)253 mpz_to_ZZ(&ans, &temp)254 mpz_clear(temp)255 return ans256 257 258 399 pow_comp_cache = {} 259 400 cdef PowComputer_base PowComputer_c(Integer m, Integer cache_limit, Integer prec_cap, in_field): … … 286 427 EXAMPLES: 287 428 sage: PC = PowComputer(3, 5, 10) 429 sage: PC 430 PowComputer for 3 288 431 sage: PC(4) 289 432 81 -
sage/rings/padics/pow_computer_ext.pxd
r7014 r8432 1 include "../../libs/ntl/decl.pxi"" 1 include "../../ext/cdefs.pxi" 2 include "../../libs/ntl/decl.pxi" 2 3 3 4 from sage.rings.padics.pow_computer cimport PowComputer_class 5 from sage.libs.ntl.ntl_ZZ_pContext cimport ntl_ZZ_pContext_class 4 6 5 7 cdef class PowComputer_ext(PowComputer_class): 6 8 cdef ZZ_c* small_powers 7 cdef unsigned long cache_limit8 9 cdef ZZ_c top_power 9 cdef unsigned long prec_cap 10 cdef ZZ_c temp_z 11 12 # the following three should be set by the subclasses 13 cdef long ram_prec_cap # = prec_cap * e 14 cdef long deg 15 cdef long e 16 cdef long f 17 18 cdef ZZ_c* pow_ZZ_tmp(self, unsigned long n) 19 cdef ZZ_c* pow_ZZ_top(self) 20 21 cdef void cleanup_ext(self) 10 22 11 23 cdef class PowComputer_ZZ_pX(PowComputer_ext): 12 cdef ntl_ZZ_pContext get_context(self, unsigned long n)13 cdef ntl_ZZ_pContext get_top_context(self)14 cdef voidrestore_context(self, unsigned long n)24 cdef ntl_ZZ_pContext_class get_context(self, unsigned long n) 25 cdef ntl_ZZ_pContext_class get_top_context(self) 26 cdef restore_context(self, unsigned long n) 15 27 cdef void restore_top_context(self) 16 cdef ZZ_pX_Modulus_c get_modulus(self, unsigned long n)17 cdef ZZ_pX_Modulus_c get_top_modulus(self)28 cdef ZZ_pX_Modulus_c* get_modulus(self, unsigned long n) 29 cdef ZZ_pX_Modulus_c* get_top_modulus(self) 18 30 19 31 cdef class PowComputer_ZZ_pX_FM(PowComputer_ZZ_pX): 20 cdef ZZ_pX_c poly21 cdef ntl_ZZ_pContext c32 #cdef ZZ_pX_c poly 33 cdef ntl_ZZ_pContext_class c 22 34 cdef ZZ_pX_Modulus_c mod 23 35 36 cdef void cleanup_ZZ_pX_FM(self) 37 24 38 cdef class PowComputer_ZZ_pX_FM_Eis(PowComputer_ZZ_pX_FM): 39 cdef int low_length 40 cdef int high_length 41 cdef ZZ_pX_Multiplier_c* low_shifter 42 cdef ZZ_pX_Multiplier_c* high_shifter 43 44 cdef void cleanup_ZZ_pX_FM_Eis(self) 45 46 cdef class PowComputer_ZZ_pX_small(PowComputer_ZZ_pX): 47 cdef object c # using a python list so that we can store ntl_ZZ_pContext_class objects 48 cdef ZZ_pX_Modulus_c *mod 49 50 cdef void cleanup_ZZ_pX_small(self) 51 52 cdef class PowComputer_ZZ_pX_small_Eis(PowComputer_ZZ_pX_small): 25 53 pass 26 54 27 #cdef class PowComputer_ZZ_pX_small(PowComputer_ZZ_pX): 28 # cdef ZZ_pX_c *poly 29 # cdef ntl_ZZ_pContext *c 30 # cdef ZZ_pX_Modulus_c *mod 31 # 32 #cdef class PowComputer_ZZ_pX_small_Eis(PowComputer_ZZ_pX_small): 33 # pass 34 # 35 #cdef class PowComputer_ZZ_pX_big(PowComputer_ZZ_pX): 36 # cdef ZZX_c poly 37 # cdef context_dict #currently using a dict, optimize for speed later 38 # cdef modulus_dict #currently using a dict, optimize for speed later 39 # 40 #cdef class PowComputer_ZZ_pX_big_Eis(PowComputer_ZZ_pX_big): 41 # pass 42 # 55 cdef class PowComputer_ZZ_pX_big(PowComputer_ZZ_pX): 56 cdef object context_list # using a python list so that we can store ntl_ZZ_pContext_class objects 57 cdef ZZ_pX_Modulus_c *modulus_list 58 59 cdef ntl_ZZ_pContext_class top_context 60 cdef ZZ_pX_Modulus_c top_mod 61 62 cdef object context_dict #currently using a dict, optimize for speed later 63 cdef object modulus_dict #currently using a dict, optimize for speed later 64 65 cdef void cleanup_ZZ_pX_big(self) 66 67 cdef class PowComputer_ZZ_pX_big_Eis(PowComputer_ZZ_pX_big): 68 pass 69 43 70 #cdef class PowComputer_ZZ_pEX(PowComputer_ext): 44 71 # cdef ntl_ZZ_pEContext get_context(self, unsigned long n) -
sage/rings/padics/pow_computer_ext.pyx
r7017 r8432 1 from sage.rings.integer cimport Integer2 3 1 """ 4 2 AUTHOR: … … 15 13 #***************************************************************************** 16 14 17 18 19 import weakref20 from sage.rings.infinity import infinity21 from sage.libs.ntl.ntl_ZZ_pContext import ntl_ZZ_pContext, ntl_ZZ_pContext_class22 from sage.libs.ntl.ntl_ZZ import ntl_ZZ23 24 #from sage.rings.integer import Integer25 26 15 include "../../ext/gmp.pxi" 27 16 include "../../ext/interrupt.pxi" 28 17 include "../../ext/stdsage.pxi" 18 include "../../ext/python_list.pxi" 19 include "../../ext/python_dict.pxi" 20 21 import weakref 22 from sage.misc.misc import cputime 23 from sage.rings.infinity import infinity 24 from sage.libs.ntl.ntl_ZZ_pContext cimport ntl_ZZ_pContext_factory 25 from sage.libs.ntl.ntl_ZZ_pContext import ZZ_pContext_factory 26 from sage.libs.ntl.ntl_ZZ cimport ntl_ZZ 27 from sage.libs.ntl.ntl_ZZ_pX cimport ntl_ZZ_pX, ntl_ZZ_pX_Modulus 28 from sage.rings.integer cimport Integer 29 29 30 30 cdef class PowComputer_ext(PowComputer_class): 31 31 def __new__(self, Integer prime, unsigned long cache_limit, unsigned long prec_cap, bint in_field, poly): 32 (<PowComputer_class>self)._initialized = 0 32 """ 33 Constructs the storage for powers of prime as ZZ_c's. 34 35 EXAMPLES: 36 sage: PC = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5, 0, 1], 5^10), "small") #indirect doctest 37 """ 38 self._initialized = 0 33 39 _sig_on 34 40 self.small_powers = <ZZ_c *>sage_malloc(sizeof(ZZ_c) * (cache_limit + 1)) … … 41 47 cdef Integer x 42 48 43 self.cache_limit = cache_limit44 self.prec_cap = prec_cap45 46 49 ZZ_construct(self.small_powers) 47 ZZ_conv_ int(self.small_powers[0], 1)50 ZZ_conv_from_int(self.small_powers[0], 1) 48 51 49 52 if cache_limit > 0: … … 54 57 for i from 2 <= i <= cache_limit: 55 58 ZZ_construct(&(self.small_powers[i])) 56 mul_ZZ(self.small_powers[i], self.small_powers[i-1], self.small_powers[1])59 ZZ_mul(self.small_powers[i], self.small_powers[i-1], self.small_powers[1]) 57 60 mpz_to_ZZ(&self.top_power, &prime.value) 58 power_ZZ(self.top_power, self.top_power, prec_cap)61 ZZ_power(self.top_power, self.top_power, prec_cap) 59 62 _sig_off 60 63 mpz_init(self.temp_m) 64 ZZ_construct(&self.temp_z) 61 65 62 66 def __init__(self, Integer prime, unsigned long cache_limit, unsigned long prec_cap, bint in_field, poly): 63 PowComputer_class.__init__(self, prime, in_field) 67 """ 68 Initializes prime, cache_limit, prec_cap, in_field. 69 70 EXAMPLES: 71 sage: PC = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5, 0, 1], 5^10), "small") #indirect doctest 72 """ 73 PowComputer_class.__init__(self, prime, cache_limit, prec_cap, in_field) 64 74 65 75 def __dealloc__(self): 76 """ 77 Frees allocated memory. 78 79 EXAMPLES: 80 sage: PC = PowComputer_ext_maker(5, 5, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "FM") 81 sage: del PC # indirect doctest 82 """ 83 if (<PowComputer_class>self)._initialized: 84 self.cleanup_ext() 85 86 def __repr__(self): 87 """ 88 Returns a string representation of self. 89 90 EXAMPLES: 91 sage: PC = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5, 0, 1], 5^10), "small") 92 sage: PC # indirect doctest 93 PowComputer_ext for 5, with polynomial [9765620 0 1] 94 """ 95 return "PowComputer_ext for %s, with polynomial %s"%(self.prime, self.polynomial()) 96 97 cdef void cleanup_ext(self): 98 """ 99 Frees memory allocated in PowComputer_ext. 100 101 EXAMPLES: 102 sage: PC = PowComputer_ext_maker(5, 5, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "FM") 103 sage: del PC # indirect doctest 104 """ 66 105 cdef Py_ssize_t i 67 if (<PowComputer_class>self)._initialized: 68 for i from 0 <= i <= self.cache_limit: 69 ZZ_destruct(&(self.small_powers[i])) 70 sage_free(self.small_powers) 71 ZZ_destruct(&self.top_power) 106 for i from 0 <= i <= self.cache_limit: 107 ZZ_destruct(&(self.small_powers[i])) 108 sage_free(self.small_powers) 109 ZZ_destruct(&self.top_power) 110 mpz_clear(self.temp_m) 111 ZZ_destruct(&self.temp_z) 72 112 73 def _cache_limit(self): 74 """ 75 Returns the limit to which powers of prime are computed. 76 """ 77 cdef Integer ans 78 ans = PY_NEW(Integer) 79 mpz_set_ui(ans.value, self.cache_limit) 113 cdef mpz_t* pow_mpz_t_tmp(self, unsigned long n): 114 """ 115 Provides fast access to an mpz_t* pointing to self.prime^n. 116 117 The location pointed to depends on the underlying representation. 118 In no circumstances should you mpz_clear the result. 119 The value pointed to may be an internal temporary variable for the class. 120 In particular, you should not try to refer to the results of two 121 pow_mpz_t_tmp calls at the same time, because the second 122 call may overwrite the memory pointed to by the first. 123 124 In the case of PowComputer_exts, the mpz_t pointed to will always 125 be a temporary variable. 126 127 See pow_mpz_t_tmp_demo for an example of this phenomenon. 128 129 EXAMPLES: 130 sage: PC = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5, 0, 1], 5^10), "small") 131 sage: PC.pow_mpz_t_tmp_test(4) #indirect doctest 132 625 133 """ 134 # READ THE DOCSTRING 135 if n <= self.cache_limit: 136 ZZ_to_mpz(&self.temp_m, &(self.small_powers[n])) 137 elif n == self.prec_cap: 138 ZZ_to_mpz(&self.temp_m, &self.top_power) 139 else: 140 mpz_pow_ui(self.temp_m, self.prime.value, n) 141 return &self.temp_m 142 143 cdef ZZ_c* pow_ZZ_tmp(self, unsigned long n): 144 """ 145 Provides fast access to a ZZ_c* pointing to self.prime^n. 146 147 The location pointed to depends on the underlying representation. 148 In no circumstances should you ZZ_destruct the result. 149 The value pointed to may be an internal temporary variable for the class. 150 In particular, you should not try to refer to the results of two 151 pow_ZZ_tmp calls at the same time, because the second 152 call may overwrite the memory pointed to by the first. 153 154 See pow_ZZ_tmp_demo for an example of this phenomenon. 155 156 EXAMPLES: 157 sage: PC = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5, 0, 1], 5^10), "small") 158 sage: PC.pow_mpz_t_tmp_test(4) #indirect doctest 159 625 160 """ 161 if n <= self.cache_limit: 162 return &(self.small_powers[n]) 163 if n == self.prec_cap: 164 return &self.top_power 165 ZZ_power(self.temp_z, self.small_powers[1], n) 166 return &self.temp_z 167 168 def pow_ZZ_tmp_test(self, n): 169 """ 170 Tests the pow_ZZ_tmp function 171 172 EXAMPLES: 173 sage: PC = PowComputer_ext_maker(5, 6, 6, False, ntl.ZZ_pX([-5,0,1],5^6),"small") 174 sage: PC.pow_ZZ_tmp_test(4) 175 625 176 sage: PC.pow_ZZ_tmp_test(7) 177 78125 178 """ 179 cdef Integer _n = Integer(n) 180 if _n < 0: raise ValueError 181 cdef ntl_ZZ ans = PY_NEW(ntl_ZZ) 182 ans.x = self.pow_ZZ_tmp(mpz_get_ui(_n.value))[0] 80 183 return ans 81 184 82 def _top_power(self): 83 """ 84 Returns self._prime()^self._prec_cap() 85 """ 86 cdef Integer ans 87 ans = PY_NEW(Integer) 88 mpz_set(ans.value, self.top_power) 185 def pow_ZZ_tmp_demo(self, m, n): 186 """ 187 This function demonstrates a danger in using pow_ZZ_tmp. 188 189 EXAMPLES: 190 sage: PC = PowComputer_ext_maker(5, 5, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "big") 191 192 When you cal pow_ZZ_tmp with an input that is not stored 193 (ie n > self.cache_limit and n != self.prec_cap), 194 it stores the result in self.temp_z and returns a pointer 195 to that ZZ_c. So if you try to use the results of two 196 calls at once, things will break. 197 sage: PC.pow_ZZ_tmp_demo(6, 8) 198 244140625 199 sage: 5^6*5^8 200 6103515625 201 sage: 5^6*5^6 202 244140625 203 204 Note that this does not occur if you try a stored value, 205 because the result of one of the calls points to that 206 stored value. 207 sage: PC.pow_ZZ_tmp_demo(6, 10) 208 152587890625 209 sage: 5^6*5^10 210 152587890625 211 """ 212 m = Integer(m) 213 n = Integer(n) 214 if m < 0 or n < 0: 215 raise ValueError, "m, n must be non-negative" 216 cdef ntl_ZZ ans = PY_NEW(ntl_ZZ) 217 ZZ_mul(ans.x, self.pow_ZZ_tmp(mpz_get_ui((<Integer>m).value))[0], self.pow_ZZ_tmp(mpz_get_ui((<Integer>n).value))[0]) 89 218 return ans 90 219 91 def _prec_cap(self): 92 """ 93 Returns prec_cap, a single value that for which self._prime()^prec_cap is stored 94 """ 95 cdef Integer ans 96 ans = PY_NEW(Integer) 97 mpz_set_ui(ans.value, self.prec_cap) 220 221 cdef mpz_t* pow_mpz_t_top(self): 222 """ 223 Returns self.prime^self.prec_cap as an mpz_t*. 224 225 EXAMPLES: 226 sage: PC = PowComputer_ext_maker(5, 6, 6, False, ntl.ZZ_pX([-5,0,1],5^6),"small") 227 sage: PC.pow_mpz_t_top_test() #indirect doctest 228 15625 229 """ 230 ZZ_to_mpz(&self.temp_m, &self.top_power) 231 return &self.temp_m 232 233 cdef ZZ_c* pow_ZZ_top(self): 234 """ 235 Returns self.prime^self.prec_cap as a ZZ_c. 236 237 EXAMPLES: 238 sage: PC = PowComputer_ext_maker(5, 6, 6, False, ntl.ZZ_pX([-5,0,1],5^6),"small") 239 sage: PC.pow_ZZ_top_test() #indirect doctest 240 15625 241 """ 242 return &self.top_power 243 244 def pow_ZZ_top_test(self): 245 """ 246 Tests the pow_ZZ_top function. 247 248 EXAMPLES: 249 sage: PC = PowComputer_ext_maker(5, 6, 6, False, ntl.ZZ_pX([-5,0,1],5^6),"small") 250 sage: PC.pow_ZZ_top_test() 251 15625 252 """ 253 cdef ntl_ZZ ans = PY_NEW(ntl_ZZ) 254 ans.x = self.pow_ZZ_top()[0] 98 255 return ans 99 256 100 cdef Integer pow_Integer(self, unsigned long n): 101 cdef Integer ans = PY_NEW(Integer) 102 if n <= self.cache_limit: 103 ZZ_to_mpz(&ans.value, &(self.small_powers[n])) 104 elif n == self.prec_cap: 105 ZZ_to_mpz(&ans.value, &self.top_power) 106 else: 107 mpz_pow_ui(ans.value, self.prime.value, n) 257 cdef class PowComputer_ZZ_pX(PowComputer_ext): 258 def __new__(self, Integer prime, unsigned long cache_limit, unsigned long prec_cap, bint in_field, poly): 259 if not PY_TYPE_CHECK(poly, ntl_ZZ_pX): 260 raise TypeError 261 self.deg = ZZ_pX_deg((<ntl_ZZ_pX>poly).x) 262 PowComputer_ext.__init__(self, prime, cache_limit, prec_cap, in_field, poly) 263 264 def polynomial(self): 265 """ 266 Returns the polynomial (with coefficient precision prec_cap) associated to this PowComputer. 267 268 The polynomial is output as an ntl_ZZ_pX. 269 270 EXAMPLES: 271 sage: PC = PowComputer_ext_maker(5, 5, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "FM") 272 sage: PC.polynomial() 273 [9765620 0 1] 274 """ 275 self.restore_top_context() 276 cdef ntl_ZZ_pX r = PY_NEW(ntl_ZZ_pX) 277 r.c = self.get_top_context() 278 r.x = (self.get_top_modulus()[0]).val() 279 return r 280 281 cdef ntl_ZZ_pContext_class get_context(self, unsigned long n): 282 """ 283 Returns a ZZ_pContext for self.prime^n. 284 285 EXAMPLES: 286 sage: PC = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5, 0, 1], 5^10), "FM") 287 sage: PC.get_context_test(15) #indirect doctest 288 NTL modulus 30517578125 289 """ 290 cdef ntl_ZZ pn = PY_NEW(ntl_ZZ) 291 pn.x = self.pow_ZZ_tmp(n)[0] 292 cdef ntl_ZZ_pContext_class context = (<ntl_ZZ_pContext_factory>ZZ_pContext_factory).make_c(pn) 293 return context 294 295 def get_context_test(self, n): 296 """ 297 Returns a ZZ_pContext for self.prime^n. 298 299 EXAMPLES: 300 sage: PC = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5, 0, 1], 5^10), "FM") 301 sage: PC.get_context_test(15) 302 NTL modulus 30517578125 303 """ 304 cdef Integer _n = Integer(n) 305 if _n < 1: raise ValueError 306 return self.get_context(mpz_get_ui(_n.value)) 307 308 def speed_test(self, n, runs): 309 """ 310 Runs a speed test. 311 312 INPUT: 313 n -- input to a function to be tested (the function needs to be set in the source code). 314 runs -- The number of runs of that function 315 OUTPUT: 316 The time in seconds that it takes to call the function on n, runs times. 317 318 sage: PC = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5, 0, 1], 5^10), "small") 319 sage: PC.speed_test(10, 10^6) # random 320 0.0090679999999991878 321 """ 322 cdef Py_ssize_t i, end, _n 323 end = mpz_get_ui((<Integer>Integer(runs)).value) 324 _n = mpz_get_ui((<Integer>Integer(n)).value) 325 t = cputime() 326 for i from 0 <= i < end: 327 # Put the function you want speed tested here. 328 self.get_modulus(_n) 329 return cputime(t) 330 331 cdef ntl_ZZ_pContext_class get_top_context(self): 332 """ 333 Returns a ZZ_pContext for self.prime^self.prec_cap 334 335 sage: PC = PowComputer_ext_maker(5, 5, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "FM") 336 sage: PC.get_top_context_test() #indirect doctest 337 NTL modulus 9765625 338 """ 339 return self.get_context(self.prec_cap) 340 341 def get_top_context_test(self): 342 """ 343 Returns a ZZ_pContext for self.prime^self.prec_cap 344 345 sage: PC = PowComputer_ext_maker(5, 5, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "FM") 346 sage: PC.get_top_context_test() 347 NTL modulus 9765625 348 """ 349 return self.get_top_context() 350 351 cdef restore_context(self, unsigned long n): 352 """ 353 Restores the contest corresponding to self.prime^n 354 355 EXAMPLES: 356 sage: PC = PowComputer_ext_maker(5, 5, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "FM") 357 sage: PC.restore_context_test(4) #indirect doctest 358 """ 359 self.get_context(n).restore_c() 360 361 def restore_context_test(self, n): 362 """ 363 Restores the contest corresponding to self.prime^n 364 365 EXAMPLES: 366 sage: PC = PowComputer_ext_maker(5, 5, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "FM") 367 sage: PC.restore_context_test(4) 368 """ 369 cdef Integer _n = Integer(n) 370 if _n < 0: raise ValueError 371 self.restore_context(mpz_get_ui(_n.value)) 372 373 cdef void restore_top_context(self): 374 """ 375 Restores the context corresponding to self.prime^self.prec_cap 376 377 EXAMPLES: 378 sage: PC = PowComputer_ext_maker(5, 5, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "FM") 379 sage: PC.restore_top_context_test() 380 """ 381 (<ntl_ZZ_pContext_class>self.get_top_context()).restore_c() 382 383 def restore_top_context_test(self): 384 """ 385 Restores the context corresponding to self.prime^self.prec_cap 386 387 EXAMPLES: 388 sage: PC = PowComputer_ext_maker(5, 5, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "FM") 389 sage: PC.restore_top_context_test() 390 """ 391 self.restore_top_context() 392 393 cdef ZZ_pX_Modulus_c* get_modulus(self, unsigned long n): 394 """ 395 Returns the modulus corresponding to self.polynomial() (mod self.prime^n) 396 397 EXAMPLES: 398 sage: A = PowComputer_ext_maker(5, 10, 1000, False, ntl.ZZ_pX([-5,0,1],5^1000), "big") 399 sage: a = ntl.ZZ_pX([4,2],5^2) 400 sage: b = ntl.ZZ_pX([6,3],5^2) 401 sage: A.get_modulus_test(a, b, 2) # indirect doctest 402 [4 24] 403 """ 404 raise NotImplementedError 405 406 def get_modulus_test(self, ntl_ZZ_pX a, ntl_ZZ_pX b, Integer n): 407 """ 408 Multiplies a and b modulo the modulus corresponding to self.polynomial() (mod self.prime^n). 409 410 EXAMPLES: 411 sage: A = PowComputer_ext_maker(5, 10, 1000, False, ntl.ZZ_pX([-5,0,1],5^1000), "big") 412 sage: a = ntl.ZZ_pX([4,2],5^2) 413 sage: b = ntl.ZZ_pX([6,3],5^2) 414 sage: A.get_modulus_test(a, b, 2) 415 [4 24] 416 sage: a * b 417 [24 24 6] 418 sage: mod(6 * 5 + 24, 25) 419 4 420 """ 421 cdef ntl_ZZ_pX r = (<ntl_ZZ_pX>a)._new() 422 ZZ_pX_MulMod_pre(r.x, a.x, b.x, self.get_modulus(mpz_get_ui(n.value))[0]) 423 return r 424 425 cdef ZZ_pX_Modulus_c* get_top_modulus(self): 426 """ 427 Returns the modulus corresponding to self.polynomial() (mod self.prime^self.prec_cap) 428 429 EXAMPLES: 430 sage: A = PowComputer_ext_maker(5, 3, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "FM") 431 sage: a = ntl.ZZ_pX([129223,1231],5^10) 432 sage: b = ntl.ZZ_pX([289741,323],5^10) 433 sage: A.get_top_modulus_test(a, b) #indirect doctest 434 [1783058 7785200] 435 """ 436 raise NotImplementedError 437 438 def get_top_modulus_test(self, ntl_ZZ_pX a, ntl_ZZ_pX b): 439 """ 440 Multiplies a and b modulo the modulus corresponding to self.polynomial() (mod self.prime^self.prec_cap) 441 442 EXAMPLES: 443 sage: A = PowComputer_ext_maker(5, 3, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "FM") 444 sage: a = ntl.ZZ_pX([129223,1231],5^10) 445 sage: b = ntl.ZZ_pX([289741,323],5^10) 446 sage: A.get_top_modulus_test(a, b) 447 [1783058 7785200] 448 sage: a*b 449 [9560618 7785200 397613] 450 sage: mod(397613 * 5 + 9560618, 5^10) 451 1783058 452 """ 453 cdef ntl_ZZ_pX ans = a._new() 454 ZZ_pX_MulMod_pre(ans.x, a.x, b.x, self.get_top_modulus()[0]) 108 455 return ans 109 456 110 cdef mpz_t pow_mpz_t(self, unsigned long n):111 ## You always need to call mpz_clear on the return value of this function112 cdef mpz_t ans113 mpz_init(ans)114 if n <= self.cache_limit:115 ZZ_to_mpz(&ans, &(self.small_powers[n]))116 elif n == self.prec_cap:117 ZZ_to_mpz(&ans, &self.top_power)118 else:119 mpz_pow_ui(ans, self.prime.value, n)120 return ans121 122 cdef ZZ_c pow_ZZ(self, unsigned long n):123 #################### WARNING ######################124 ## If you use this function, you MAY need to ##125 ## call ZZ_destruct on the returned value after ##126 ## you are finished with it. You need to do ##127 ## so if and only if (n > self.cache_limit and ##128 ## n != self.prec_cap). So your code should ##129 ## look something like the following: ##130 ## ##131 ## cdef PowComputer_ext ppow ##132 ## ppow = PowComputer(5, 10, 1000, poly) ##133 ## cdef unsigned long n = get_long_somehow() ##134 ## cdef ZZ_c foo = ppow.pow_ZZ(n) ##135 ## # Do stuff with foo ##136 ## # Now done with foo ##137 ## if n > ppow.cache_limit and n != ppow.prec_cap##138 ## ZZ_destruct(foo) ##139 ###################################################140 if n <= self.cache_limit:141 return self.small_powers[n]142 if n == self.prec_cap:143 return self.top_power144 cdef ZZ_c ans145 ZZ_construct(&ans)146 power_ZZ(ans, self.small_powers[1], n)147 return ans148 149 cdef class PowComputer_ZZ_pX(PowComputer_ext):150 cdef ntl_ZZ_pContext get_context(self, unsigned long n):151 cdef ZZ_c pn = self.pow_ZZ(n)152 cdef ntl_ZZ_pContext_class context = <ntl_ZZ_pContext_class> ntl_ZZ_pContext(pn)153 if n > self.cache_limit and n != self.prec_cap:154 ZZ_destruct(pn)155 return context156 157 cdef ntl_ZZ_pContext get_top_context(self):158 return ntl_ZZ_pContext(self.top_power)159 160 cdef void restore_context(self, unsigned long n):161 self.get_context(n).restore_c()162 163 cdef void restore_top_context(self):164 self.get_top_context().restore_c()165 166 cdef ZZ_pX_Modulus_c get_modulus(self, unsigned long n):167 raise NotImplementedError168 169 cdef ZZ_pX_Modulus_c get_top_modulus(self):170 raise NotImplementedError171 172 457 cdef class PowComputer_ZZ_pX_FM(PowComputer_ZZ_pX): 458 """ 459 This class only caches a context and modulus for p^prec_cap. 460 Designed for use with fixed modulus p-adic rings, in Eisenstein and unramified extensions of $\mathbb{Z}_p$. 461 """ 462 173 463 def __new__(self, Integer prime, unsigned long cache_limit, unsigned long prec_cap, bint in_field, poly): 464 """ 465 Caches a context and modulus for prime^prec_cap 466 467 EXAMPLES: 468 sage: A = PowComputer_ext_maker(5, 3, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "FM") #indirect doctest 469 sage: A 470 PowComputer_ext for 5, with polynomial [9765620 0 1] 471 """ 472 174 473 # The __new__ method for PowComputer_ext has already run, so we have access to small_powers, top_power. 175 474 176 475 # We use ntl_ZZ_pContexts so that contexts are cached centrally. 177 self.c = ntl_ZZ_pContext(self.top_power) 476 477 self.c = self.get_context(prec_cap) 178 478 self.c.restore_c() 179 180 479 # For now, we don't do anything complicated with poly 181 480 if PY_TYPE_CHECK(poly, ntl_ZZ_pX) and (<ntl_ZZ_pX>poly).c is self.c: 182 self.poly = (<ntl_ZZ_pX>poly).x 481 ZZ_pX_Modulus_construct(&self.mod) 482 ZZ_pX_Modulus_build(self.mod, (<ntl_ZZ_pX>poly).x) 483 # These will be reset if we're actually eisenstein 484 self.e = 1 485 self.f = ZZ_pX_deg((<ntl_ZZ_pX>poly).x) 486 self.ram_prec_cap = self.prec_cap 183 487 else: 488 print "NOT IMPLEMENTED IN PowComputer_ZZ_pX_FM" 184 489 raise NotImplementedError 185 ZZ_pX_Modulus_construct(&self.mod)186 ZZ_pX_Modulus_build(self.mod, self.poly)187 490 188 491 def __init__(self, Integer prime, unsigned long cache_limit, unsigned long prec_cap, bint in_field, poly): 492 """ 493 Caches a context and modulus for prime^prec_cap 494 495 EXAMPLES: 496 sage: A = PowComputer_ext_maker(5, 3, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "FM") #indirect doctest 497 sage: A 498 PowComputer_ext for 5, with polynomial [9765620 0 1] 499 """ 189 500 PowComputer_ZZ_pX.__init__(self, prime, cache_limit, prec_cap, in_field, poly) 190 501 191 cdef ntl_ZZ_pContext get_top_context(self): 502 def __dealloc__(self): 503 """ 504 Cleans up the memory for self.mod 505 506 EXAMPLES: 507 sage: A = PowComputer_ext_maker(5, 3, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "FM") #indirect doctest 508 sage: del A # indirect doctest 509 """ 510 if self._initialized: 511 self.cleanup_ZZ_pX_FM() 512 513 cdef void cleanup_ZZ_pX_FM(self): 514 """ 515 Cleans up the memory for self.mod 516 517 EXAMPLES: 518 sage: A = PowComputer_ext_maker(5, 3, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "FM") #indirect doctest 519 sage: del A # indirect doctest 520 """ 521 ZZ_pX_Modulus_destruct(&self.mod) 522 523 cdef ntl_ZZ_pContext_class get_top_context(self): 524 """ 525 Returns a ZZ_pContext for self.prime^self.prec_cap 526 527 sage: PC = PowComputer_ext_maker(5, 5, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "FM") 528 sage: PC.get_top_context_test() # indirect doctest 529 NTL modulus 9765625 530 """ 192 531 return self.c 193 532 194 533 cdef void restore_top_context(self): 534 """ 535 Restores the context corresponding to self.prime^self.prec_cap 536 537 EXAMPLES: 538 sage: PC = PowComputer_ext_maker(5, 5, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "FM") 539 sage: PC.restore_top_context_test() #indirect doctest 540 """ 195 541 self.c.restore_c() 196 542 197 cdef ZZ_pX_Modulus_c get_modulus(self, unsigned long n): 198 ## You always need to call ZZ_pX_Modulus_destruct on the return value of this function once you're done. 199 cdef ZZX_c temp 200 cdef ZZ_pX_c tempZZ_pX 201 self.c.restore_c() 202 ZZX_construct(&temp) 203 ZZ_pX_to_ZZX(temp, self.poly) 204 self.restore_context(n) 205 ZZ_pX_construct(&tempZZ_pX) 206 ZZX_to_ZZ_pX(tempZZ_pX, temp) 207 cdef ZZ_pX_Modulus ans 208 ZZ_pX_Modulus_construct(&ans) 209 ZZ_pX_Modulus_build(ans, tempZZ_pX) 210 ZZX_destruct(&temp) 211 ZZ_pX_destruct(&tempZZ_pX) 212 return ans 213 214 cdef ZZ_pX_Modulus_c get_top_modulus(self): 215 ## Never call ZZ_pX_Modulus_destruct on the return value of this function 216 return self.mod 217 218 543 cdef ZZ_pX_Modulus_c* get_top_modulus(self): 544 """ 545 Returns the modulus corresponding to self.polynomial() (mod self.prime^self.prec_cap) 546 547 EXAMPLES: 548 sage: A = PowComputer_ext_maker(5, 3, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "FM") 549 sage: a = ntl.ZZ_pX([129223,1231],5^10) 550 sage: b = ntl.ZZ_pX([289741,323],5^10) 551 sage: A.get_top_modulus_test(a, b) #indirect doctest 552 [1783058 7785200] 553 """ 554 return &self.mod 555 556 cdef class PowComputer_ZZ_pX_FM_Eis(PowComputer_ZZ_pX_FM): 557 """ 558 This class computes and stores eis_shifter, which aids in right shifting elements. 559 """ 560 561 def __new__(self, Integer prime, unsigned long cache_limit, unsigned long prec_cap, bint in_field, poly): 562 # The __new__ method for PowComputer_ZZ_pX_FM has already run, so we have access to self.mod 563 564 # self.low_shifter stores multipliers for p/x^(2^i) 565 # If self.deg is one more than a power of 2, we need to store p/x, p/x^2, up to p/x^(2^n) where 2^n is that power of 2. 566 #print "here" 567 #cdef ntl_ZZ_pX printer = ntl_ZZ_pX([], self.c) 568 self.e = ZZ_pX_deg((<ntl_ZZ_pX>poly).x) 569 self.f = 1 570 self.ram_prec_cap = self.prec_cap * self.e 571 if self.deg <= 1: 572 raise ValueError 573 574 def _low_shifter(self, i): 575 cdef long _i = i 576 cdef ntl_ZZ_pX ans 577 if _i >= 0 and _i < self.low_length: 578 ans = ntl_ZZ_pX([], self.get_top_context()) 579 ans.x = self.low_shifter[i].val() 580 return ans 581 else: 582 raise IndexError 583 584 def _high_shifter(self, i): 585 cdef long _i = i 586 cdef ntl_ZZ_pX ans 587 if _i >= 0 and _i < self.high_length: 588 ans = ntl_ZZ_pX([], self.get_top_context()) 589 ans.x = self.high_shifter[i].val() 590 return ans 591 else: 592 raise IndexError 593 594 595 596 597 def __dealloc__(self): 598 if self._initialized: 599 self.cleanup_ZZ_pX_FM_Eis() 600 601 cdef void cleanup_ZZ_pX_FM_Eis(self): 602 pass 603 # I may or may not need to deallocate these: 604 # 605 #cdef int i # yes, an int is good enough 606 #for i from 0 <= i < self.low_length: 607 # ZZ_pX_Multiplier_destruct(self.low_shifter[i]) 608 #sage_free(self.low_shifter) 609 #for i from 0 <= i < self.high_length: 610 # ZZ_pX_Multiplier_destruct(self.high_shifter[i]) 611 #sage_free(self.high_shifter) 612 613 614 cdef class PowComputer_ZZ_pX_small(PowComputer_ZZ_pX): 615 """ 616 This class caches contexts and moduli densely between 1 and cache_limit. It requires cache_limit == prec_cap. 617 618 It is intended for use with capped relative and capped absolute rings and fields, in Eisenstein and unramified 619 extensions of the base p-adic fields. 620 """ 621 622 def __new__(self, Integer prime, unsigned long cache_limit, unsigned long prec_cap, bint in_field, poly): 623 """ 624 Caches contexts and moduli densely between 1 and cache_limit. 625 626 EXAMPLES: 627 sage: A = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "small") # indirect doctest 628 sage: A 629 PowComputer_ext for 5, with polynomial [9765620 0 1] 630 """ 631 # The __new__ method for PowComputer_ext has already run, so we have access to small_powers, top_power. 632 633 # We use ntl_ZZ_pContexts so that contexts are cached centrally. 634 635 if not PY_TYPE_CHECK(poly, ntl_ZZ_pX): 636 self.cleanup_ext() 637 self.cleanup_ZZ_pX() 638 raise TypeError 639 640 if cache_limit != prec_cap: 641 self.cleanup_ext() 642 self.cleanup_ZZ_pX() 643 raise ValueError, "prec_cap and cache_limit must be equal in the small case" 644 645 self.c = [] 646 #if self.c == NULL: 647 # self.cleanup_ext() 648 # self.cleanup_ZZ_pX() 649 # raise MemoryError, "out of memory allocating contexts" 650 _sig_on 651 self.mod = <ZZ_pX_Modulus_c *>sage_malloc(sizeof(ZZ_pX_Modulus_c) * (cache_limit + 1)) 652 _sig_off 653 if self.mod == NULL: 654 self.cleanup_ext() 655 self.cleanup_ZZ_pX() 656 raise MemoryError, "out of memory allocating moduli" 657 658 cdef Py_ssize_t i 659 cdef ZZ_pX_c tmp, pol 660 ZZ_pX_construct(&tmp) 661 ZZ_pX_construct(&pol) 662 pol = (<ntl_ZZ_pX>poly).x 663 self.c.append(None) 664 for i from 1 <= i <= cache_limit: 665 self.c.append(PowComputer_ZZ_pX.get_context(self,i)) 666 ZZ_pX_Modulus_construct(&(self.mod[i])) 667 ZZ_pX_conv_modulus(tmp, pol, (<ntl_ZZ_pContext_class>self.c[i]).x) 668 ZZ_pX_Modulus_build(self.mod[i], tmp) 669 ## I get malloc errors if I leave the following in: I don't know why. 670 #ZZ_pX_destruct(&tmp) 671 #ZZ_pX_destruct(&pol) 672 673 def __init__(self, Integer prime, unsigned long cache_limit, unsigned long prec_cap, bint in_field, poly): 674 """ 675 Initializes prime, cache_limit, prec_cap, in_field. 676 677 EXAMPLES: 678 sage: A = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "small") # indirect doctest 679 sage: A 680 PowComputer_ext for 5, with polynomial [9765620 0 1] 681 """ 682 PowComputer_ZZ_pX.__init__(self, prime, cache_limit, prec_cap, in_field, poly) 683 684 def __dealloc__(self): 685 """ 686 Deallocates cache of contexts, moduli. 687 688 EXAMPLES: 689 sage: A = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "small") 690 sage: del A # indirect doctest 691 """ 692 if self._initialized: 693 self.cleanup_ZZ_pX_small() 694 695 cdef void cleanup_ZZ_pX_small(self): 696 """ 697 Deallocates cache of contexts, moduli. 698 699 EXAMPLES: 700 sage: A = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "small") 701 sage: del A # indirect doctest 702 """ 703 pass 704 ## These cause segfaults: I don't know why. 705 #cdef Py_ssize_t i 706 #for i from 0 <= i <= self.cache_limit: 707 # ZZ_pX_Modulus_destruct(&(self.mod[i])) 708 #sage_free(self.mod) 709 710 cdef ntl_ZZ_pContext_class get_context(self, unsigned long n): 711 """ 712 Returns the context for p^n. 713 714 Note that this function will raise an Index error if n > self.cache_limit. 715 Also, it will return None on input 0 716 717 INPUT: 718 n -- A long between 1 and self.cache_limit, inclusive 719 OUTPUT: 720 A context for p^n 721 722 EXAMPLES: 723 sage: A = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "small") 724 sage: A.get_context_test(4) #indirect doctest 725 NTL modulus 625 726 """ 727 return self.c[n] 728 729 cdef restore_context(self, unsigned long n): 730 """ 731 Restores the context for p^n. 732 733 INPUT: 734 n -- A long between 1 and self.cache_limit, inclusive 735 736 EXAMPLES: 737 sage: A = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "small") 738 sage: A.restore_context_test(4) #indirect doctest 739 """ 740 _sig_on 741 (<ntl_ZZ_pContext_class>self.c[n]).restore_c() 742 _sig_off 743 744 cdef ntl_ZZ_pContext_class get_top_context(self): 745 """ 746 Returns a ZZ_pContext for self.prime^self.prec_cap 747 748 sage: PC = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "small") 749 sage: PC.get_top_context_test() # indirect doctest 750 NTL modulus 9765625 751 """ 752 return self.c[self.prec_cap] 753 754 cdef void restore_top_context(self): 755 """ 756 Restores the context corresponding to self.prime^self.prec_cap 757 758 EXAMPLES: 759 sage: PC = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "small") 760 sage: PC.restore_top_context_test() #indirect doctest 761 """ 762 (<ntl_ZZ_pContext_class>self.c[self.prec_cap]).restore_c() 763 764 cdef ZZ_pX_Modulus_c* get_modulus(self, unsigned long n): 765 """ 766 Returns the modulus corresponding to self.polynomial() (mod self.prime^n). 767 768 INPUT: 769 n -- A long between 1 and self.cache_limit, inclusive 770 771 EXAMPLES: 772 sage: A = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "small") 773 sage: a = ntl.ZZ_pX([4,2],5^2) 774 sage: b = ntl.ZZ_pX([6,3],5^2) 775 sage: A.get_modulus_test(a, b, 2) 776 [4 24] 777 """ 778 return &(self.mod[n]) 779 780 cdef ZZ_pX_Modulus_c* get_top_modulus(self): 781 """ 782 Returns the modulus corresponding to self.polynomial() (mod self.prime^self.prec_cap) 783 784 EXAMPLES: 785 sage: A = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "small") 786 sage: a = ntl.ZZ_pX([129223,1231],5^10) 787 sage: b = ntl.ZZ_pX([289741,323],5^10) 788 sage: A.get_top_modulus_test(a, b) #indirect doctest 789 [1783058 7785200] 790 """ 791 return &(self.mod[self.prec_cap]) 792 793 cdef class PowComputer_ZZ_pX_small_Eis(PowComputer_ZZ_pX_small): 794 """ 795 This class computes and stores eis_shifter, which aids in right shifting elements. 796 eis_shifter is only stored at maximal precision: in order to get lower precision versions just reduce mod p. 797 """ 798 def _low_shifter(self, i): 799 cdef long _i = i 800 cdef ntl_ZZ_pX ans 801 if _i >= 0 and _i < self.low_length: 802 ans = ntl_ZZ_pX([], self.get_top_context()) 803 ans.x = self.low_shifter[i].val() 804 return ans 805 else: 806 raise IndexError 807 808 def _high_shifter(self, i): 809 cdef long _i = i 810 cdef ntl_ZZ_pX ans 811 if _i >= 0 and _i < self.high_length: 812 ans = ntl_ZZ_pX([], self.get_top_context()) 813 ans.x = self.high_shifter[i].val() 814 return ans 815 else: 816 raise IndexError 817 818 819 820 821 def __dealloc__(self): 822 if self._initialized: 823 self.cleanup_ZZ_pX_FM_Eis() 824 825 cdef void cleanup_ZZ_pX_FM_Eis(self): 826 pass 827 # I may or may not need to deallocate these: 828 # 829 #cdef int i # yes, an int is good enough 830 #for i from 0 <= i < self.low_length: 831 # ZZ_pX_Multiplier_destruct(self.low_shifter[i]) 832 #sage_free(self.low_shifter) 833 #for i from 0 <= i < self.high_length: 834 # ZZ_pX_Multiplier_destruct(self.high_shifter[i]) 835 #sage_free(self.high_shifter) 836 837 cdef class PowComputer_ZZ_pX_big(PowComputer_ZZ_pX): 838 """ 839 This class caches all contexts and moduli between 1 and cache_limit, and also caches for prec_cap. In addition, it stores 840 a dictionary of contexts and moduli of 841 """ 842 843 def __new__(self, Integer prime, unsigned long cache_limit, unsigned long prec_cap, bint in_field, poly): 844 """ 845 Caches contexts and moduli densely between 1 and cache_limit. Caches a context and modulus for prec_cap. 846 Also creates the dictionaries. 847 848 EXAMPLES: 849 sage: A = PowComputer_ext_maker(5, 6, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "big") # indirect doctest 850 sage: A 851 PowComputer_ext for 5, with polynomial [9765620 0 1] 852 """ 853 # The __new__ method for PowComputer_ext has already run, so we have access to small_powers, top_power. 854 855 # We use ntl_ZZ_pContexts so that contexts are cached centrally. 856 857 if not PY_TYPE_CHECK(poly, ntl_ZZ_pX): 858 self.cleanup_ext() 859 self.cleanup_ZZ_pX() 860 raise TypeError 861 862 self.context_list = [] 863 #if self.c == NULL: 864 # self.cleanup_ext() 865 # self.cleanup_ZZ_pX() 866 # raise MemoryError, "out of memory allocating contexts" 867 _sig_on 868 self.modulus_list = <ZZ_pX_Modulus_c *>sage_malloc(sizeof(ZZ_pX_Modulus_c) * (cache_limit + 1)) 869 _sig_off 870 if self.modulus_list == NULL: 871 self.cleanup_ext() 872 self.cleanup_ZZ_pX() 873 raise MemoryError, "out of memory allocating moduli" 874 875 cdef Py_ssize_t i 876 cdef ZZ_pX_c tmp, pol 877 ZZ_pX_construct(&tmp) 878 ZZ_pX_construct(&pol) 879 pol = (<ntl_ZZ_pX>poly).x 880 self.context_list.append(None) 881 for i from 1 <= i <= cache_limit: 882 self.context_list.append(PowComputer_ZZ_pX.get_context(self,i)) 883 ZZ_pX_Modulus_construct(&(self.modulus_list[i])) 884 ZZ_pX_conv_modulus(tmp, pol, (<ntl_ZZ_pContext_class>self.context_list[i]).x) 885 ZZ_pX_Modulus_build(self.modulus_list[i], tmp) 886 self.top_context = PowComputer_ZZ_pX.get_context(self, prec_cap) 887 ZZ_pX_Modulus_construct(&(self.top_mod)) 888 ZZ_pX_conv_modulus(tmp, pol, self.top_context.x) 889 ZZ_pX_Modulus_build(self.top_mod, tmp) 890 ## I get malloc errors if I leave the following in: I don't know why. 891 #ZZ_pX_destruct(&tmp) 892 #ZZ_pX_destruct(&pol) 893 self.context_dict = {} 894 self.modulus_dict = {} 895 896 def __init__(self, Integer prime, unsigned long cache_limit, unsigned long prec_cap, bint in_field, poly): 897 """ 898 Initializes prime, cache_limit, prec_cap, in_field. 899 900 EXAMPLES: 901 sage: A = PowComputer_ext_maker(5, 6, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "big") # indirect doctest 902 sage: A 903 PowComputer_ext for 5, with polynomial [9765620 0 1] 904 """ 905 PowComputer_ZZ_pX.__init__(self, prime, cache_limit, prec_cap, in_field, poly) 906 907 def __dealloc__(self): 908 """ 909 Deallocates the stored moduli and contexts. 910 911 EXAMPLES: 912 sage: A = PowComputer_ext_maker(5, 6, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "big") 913 sage: del A # indirect doctest 914 """ 915 if self._initialized: 916 self.cleanup_ZZ_pX_big() 917 918 cdef void cleanup_ZZ_pX_big(self): 919 """ 920 Deallocates the stored moduli and contexts. 921 922 EXAMPLES: 923 sage: A = PowComputer_ext_maker(5, 6, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "big") 924 sage: del A # indirect doctest 925 """ 926 pass 927 ## These cause a segfault. I don't know why. 928 #cdef Py_ssize_t i 929 #for i from 0 <= i <= self.cache_limit: 930 # ZZ_pX_Modulus_destruct(&(self.modulus_list[i])) 931 #sage_free(self.modulus_list) 932 #ZZ_pX_Modulus_destruct(&self.top_mod) 933 934 def reset_dictionaries(self): 935 """ 936 Resets the dictionaries. Note that if there are elements lying around that need access to these dictionaries, calling this function and then doing arithmetic with those elements could cause trouble (if the context object gets garbage collected for example. The bugs introduced could be very subtle, because NTL will generate a new context object and use it, but there's the potential for the object to be incompatible with the different context object). 937 938 EXAMPLES: 939 sage: A = PowComputer_ext_maker(5, 6, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "big") 940 sage: P = A.get_context_test(8) 941 sage: A._context_dict() 942 {8L: NTL modulus 390625} 943 sage: A.reset_dictionaries() 944 """ 945 self.context_dict = {} 946 self.modulus_dict = {} 947 948 def _context_dict(self): 949 """ 950 Returns the context dictionary. 951 952 EXAMPLES: 953 sage: A = PowComputer_ext_maker(5, 6, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "big") 954 sage: P = A.get_context_test(8) 955 sage: A._context_dict() 956 {8L: NTL modulus 390625} 957 """ 958 return self.context_dict 959 960 def _modulus_dict(self): 961 """ 962 Returns the context dictionary. 963 964 EXAMPLES: 965 sage: A = PowComputer_ext_maker(5, 6, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "big") 966 sage: P = A.get_context_test(8) 967 sage: A._modulus_dict() 968 {} 969 sage: a = ntl.ZZ_pX([4,2],5^8) 970 sage: b = ntl.ZZ_pX([6,3],5^8) 971 sage: A.get_modulus_test(a, b, 8) 972 [54 24] 973 sage: A._modulus_dict() 974 {8L: NTL ZZ_pXModulus [390620 0 1] (mod 390625)} 975 """ 976 return self.modulus_dict 977 978 cdef ntl_ZZ_pContext_class get_context(self, unsigned long n): 979 """ 980 Returns the context for p^n. 981 982 Note that this function will raise an Index error if n > self.cache_limit. 983 Also, it will return None on input 0 984 985 INPUT: 986 n -- A long between 1 and self.cache_limit, inclusive 987 OUTPUT: 988 A context for p^n 989 990 EXAMPLES: 991 sage: A = PowComputer_ext_maker(5, 6, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "big") 992 sage: A.get_context_test(4) #indirect doctest 993 NTL modulus 625 994 sage: A.get_context_test(8) #indirect doctest 995 NTL modulus 390625 996 """ 997 if n == 0: 998 raise ValueError, "n must be positive" 999 if n <= self.cache_limit: 1000 return self.context_list[n] 1001 elif n == self.prec_cap: 1002 return self.top_context 1003 else: 1004 try: 1005 return self.context_dict[n] 1006 except KeyError: 1007 self.context_dict[n] = PowComputer_ZZ_pX.get_context(self, n) 1008 return self.context_dict[n] 1009 1010 cdef ntl_ZZ_pContext_class get_top_context(self): 1011 """ 1012 Returns a ZZ_pContext for self.prime^self.prec_cap 1013 1014 sage: PC = PowComputer_ext_maker(5, 5, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "big") 1015 sage: PC.get_top_context_test() # indirect doctest 1016 NTL modulus 9765625 1017 """ 1018 return self.top_context 1019 1020 cdef void restore_top_context(self): 1021 """ 1022 Restores the context corresponding to self.prime^self.prec_cap 1023 1024 EXAMPLES: 1025 sage: PC = PowComputer_ext_maker(5, 5, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "big") 1026 sage: PC.restore_top_context_test() #indirect doctest 1027 """ 1028 self.top_context.restore_c() 1029 1030 cdef ZZ_pX_Modulus_c* get_modulus(self, unsigned long n): 1031 """ 1032 Returns the modulus corresponding to self.polynomial() (mod self.prime^n). 1033 1034 INPUT: 1035 n -- A long between 1 and self.cache_limit, inclusive 1036 1037 EXAMPLES: 1038 sage: A = PowComputer_ext_maker(5, 3, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "big") 1039 sage: a = ntl.ZZ_pX([4,2],5^2) 1040 sage: b = ntl.ZZ_pX([6,3],5^2) 1041 sage: A.get_modulus_test(a, b, 2) # indirect doctest 1042 [4 24] 1043 sage: a = ntl.ZZ_pX([4,2],5^6) 1044 sage: b = ntl.ZZ_pX([6,3],5^6) 1045 sage: A.get_modulus_test(a, b, 6) # indirect doctest 1046 [54 24] 1047 """ 1048 cdef ntl_ZZ_pX tmp 1049 cdef ntl_ZZ_pX_Modulus holder 1050 cdef ntl_ZZ_pContext_class c 1051 if n == 0: 1052 raise ValueError, "n must be positive" 1053 elif n <= self.cache_limit: 1054 return &(self.modulus_list[n]) 1055 elif n == self.prec_cap: 1056 return &self.top_mod 1057 else: 1058 try: 1059 holder = self.modulus_dict[n] 1060 return &(holder.x) 1061 except KeyError: 1062 c = self.get_context(n) 1063 c.restore_c() 1064 tmp = PY_NEW(ntl_ZZ_pX) 1065 tmp.c = c 1066 ZZ_pX_conv_modulus(tmp.x, self.top_mod.val(), c.x) 1067 holder = ntl_ZZ_pX_Modulus(tmp) 1068 self.modulus_dict[n] = holder 1069 return &(holder.x) 1070 1071 cdef ZZ_pX_Modulus_c* get_top_modulus(self): 1072 """ 1073 Returns the modulus corresponding to self.polynomial() (mod self.prime^self.prec_cap) 1074 1075 EXAMPLES: 1076 sage: A = PowComputer_ext_maker(5, 5, 10, False, ntl.ZZ_pX([-5,0,1],5^10), "big") 1077 sage: a = ntl.ZZ_pX([129223,1231],5^10) 1078 sage: b = ntl.ZZ_pX([289741,323],5^10) 1079 sage: A.get_top_modulus_test(a, b) #indirect doctest 1080 [1783058 7785200] 1081 """ 1082 return &self.top_mod 1083 1084 1085 def PowComputer_ext_maker(prime, cache_limit, prec_cap, in_field, poly, prec_type = "small", ext_type = "u"): 1086 """ 1087 Returns a PowComputer that caches the values $1, prime, prime^2, \ldots, prime^cache_limit$. 1088 1089 Once you create a PowComputer, merely call it to get values out. 1090 You can input any integer, even if it's outside of the precomputed range. 1091 1092 INPUT: 1093 prime -- An integer, the base that you want to exponentiate. 1094 cache_limit -- A positive integer that you want to cache powers up to. 1095 1096 EXAMPLES: 1097 sage: PC = PowComputer_ext_maker(5, 10, 10, False, ntl.ZZ_pX([-5, 0, 1], 5^10), "small") 1098 sage: PC 1099 PowComputer_ext for 5, with polynomial [9765620 0 1] 1100 """ 1101 cdef Integer _prime = Integer(prime) 1102 cdef Integer _cache_limit = Integer(cache_limit) 1103 cdef Integer _prec_cap = Integer(prec_cap) 1104 cdef bint inf = in_field 1105 if prec_type == "small" and ext_type == "u": 1106 return PowComputer_ZZ_pX_small(_prime, mpz_get_ui(_cache_limit.value), mpz_get_ui(_prec_cap.value), inf, poly) 1107 elif prec_type == "small" and ext_type == "e": 1108 return PowComputer_ZZ_pX_small_Eis(_prime, mpz_get_ui(_cache_limit.value), mpz_get_ui(_prec_cap.value), inf, poly) 1109 elif prec_type == "big" and ext_type == "u": 1110 return PowComputer_ZZ_pX_big(_prime, mpz_get_ui(_cache_limit.value), mpz_get_ui(_prec_cap.value), inf, poly) 1111 elif prec_type == "big" and ext_type == "e": 1112 return PowComputer_ZZ_pX_big_Eis(_prime, mpz_get_ui(_cache_limit.value), mpz_get_ui(_prec_cap.value), inf, poly) 1113 elif prec_type == "FM" and ext_type == "u": 1114 return PowComputer_ZZ_pX_FM(_prime, mpz_get_ui(_cache_limit.value), mpz_get_ui(_prec_cap.value), inf, poly) 1115 elif prec_type == "FM" and ext_type == "e": 1116 return PowComputer_ZZ_pX_FM_Eis(_prime, mpz_get_ui(_cache_limit.value), mpz_get_ui(_prec_cap.value), inf, poly) 1117 else: 1118 ValueError, "prec_type must be one of 'small', 'big' or 'FM' and ext_type must be one of 'u' or 'e'" 1119 1120 1121 cdef void Eis_init(PowComputer_ext prime_pow, ZZ_pX_Multiplier_c* low_shifter, ZZ_pX_Multiplier_c high_shifter, Integer prime, unsigned long cache_limit, unsigned long prec_cap, unsigned long deg, poly): 1122 cdef unsigned long D = self.deg - 1 1123 cdef int low_length = 0 1124 cdef int high_length = 0 1125 if sizeof(long) > 4 and D > 4294967295: # 2^32 - 1 1126 low_length += 32 1127 D = D >> 32 1128 if D >= 65536: # 2^16 1129 low_length += 16 1130 D = D >> 16 1131 if D >= 256: # 2^8 1132 low_length += 8 1133 D = D >> 8 1134 if D >= 16: # 2^4 1135 low_length += 4 1136 D = D >> 4 1137 if D >= 4: # 2^2 1138 low_length += 2 1139 D = D >> 2 1140 if D >= 2: # 2^1 1141 low_length += 1 1142 D = D >> 1 1143 low_length += 1 1144 # self.low_length is the number of elements in the list we need to store. 1145 # if self.deg = 2, self.low_length = 1 (store p/x) 1146 # if self.deg = 3,4, self.low_length = 2 (store p/x, p/x^2) 1147 # if self.deg = 5,6,7,8, self.low_length = 3 (store p/x, p/x^2, p/x^4) 1148 # if self.deg = 9,...,16, self.low_length = 4 (store p/x, p/x^2, p/x^4, p/x^8) 1149 1150 # Now we do the same process for powers of p, ie storing p^(2^k)/x^(e*2^k) 1151 D = self.prec_cap - 1 1152 high_length = 0 1153 if sizeof(long) > 4 and D > 4294967295: # 2^32 - 1 1154 high_length += 32 1155 D = D >> 32 1156 if D >= 65536: # 2^16 1157 high_length += 16 1158 D = D >> 16 1159 if D >= 256: # 2^8 1160 high_length += 8 1161 D = D >> 8 1162 if D >= 16: # 2^4 1163 high_length += 4 1164 D = D >> 4 1165 if D >= 4: # 2^2 1166 high_length += 2 1167 D = D >> 2 1168 if D >= 2: # 2^1 1169 high_length += 1 1170 D = D >> 1 1171 high_length += 1 1172 # self.high_length is the number of elements in the list we need to store. 1173 # if self.prec_cap = 2, self.high_length = 1 (store p/x^e) 1174 # if self.prec_cap = 3,4, self.high_length = 2 (store p/x^e, p^2/x^(2e)) 1175 # if self.prec_cap = 5,6,7,8, self.high_length = 3 (store p/x^e, p^2/x^(2e), p^4/x^(4e)) 1176 # if self.prec_cap = 9,...,16, self.high_length = 4 (store p/x, p^2/x^(2e), p^4/x^(4e), p^8/x^(8e)) 1177 1178 _sig_on 1179 low_shifter = <ZZ_pX_Multiplier_c *>sage_malloc(sizeof(ZZ_pX_Multiplier_c) * self.low_length) 1180 high_shifter = <ZZ_pX_Multiplier_c *>sage_malloc(sizeof(ZZ_pX_Multiplier_c) * self.high_length) 1181 _sig_off 1182 cdef long i 1183 cdef ZZ_pX_c tmp, modup, into_multiplier 1184 cdef ZZ_c a 1185 ZZ_construct(&a) 1186 # We obtain successive p/x^(2^i) by squaring and then dividing by p. So we need one extra digit of precision. 1187 self.c.restore_c() 1188 ZZ_pX_construct(&into_multiplier) 1189 cdef ntl_ZZ_pContext_class cup = self.get_context(self.prec_cap + self.low_length) 1190 cup.restore_c() 1191 ZZ_pX_construct(&tmp) 1192 ZZ_pX_construct(&modup) 1193 ZZ_pX_conv_modulus(modup, self.mod.val(), cup.x) 1194 ZZ_div(a, ZZ_p_rep(ZZ_pX_ConstTerm(modup)), self.small_powers[1]) 1195 ZZ_InvMod(a, a, self.pow_ZZ_tmp(self.prec_cap + self.low_length)[0]) 1196 ZZ_negate(a, a) 1197 #cdef ntl_ZZ_pX printer = ntl_ZZ_pX([],cup) 1198 #printer.x = modup 1199 #print printer 1200 # Note that we're losing one digit of precision here. 1201 # This is correct because right shifting does not preserve precision. 1202 # a is now the negative of the inverse of the unit part of the constant of the defining polynomial (there's a mouthful) 1203 ZZ_pX_RightShift(tmp, modup, 1) 1204 ## printer.x = modup 1205 ## print printer 1206 ZZ_pX_mul_ZZ_p(tmp, tmp, ZZ_to_ZZ_p(a)) 1207 # tmp is now p/x 1208 ZZ_pX_conv_modulus(into_multiplier, tmp, self.c.x) 1209 ZZ_pX_Multiplier_construct(self.low_shifter) 1210 ZZ_pX_Multiplier_build(self.low_shifter[0], into_multiplier, self.mod) 1211 for i from 1 <= i < self.low_length: 1212 # Currently tmp = p / x^(2^(i-1)). Squaring yields p^2 / x^(2^i) 1213 ZZ_pX_SqrMod(tmp, tmp, modup) 1214 # Now we divide by p. We don't really have the extra digit of precision that cup would imply, but we're about to reduce, and then square. 1215 # This should give us one digit of precision loss, as expected. 1216 ZZ_pX_right_pshift(tmp, tmp, self.small_powers[1], cup.x) 1217 ZZ_pX_conv_modulus(into_multiplier, tmp, self.c.x) 1218 ZZ_pX_Multiplier_construct(&(self.low_shifter[i])) 1219 ZZ_pX_Multiplier_build(self.low_shifter[i], into_multiplier, self.mod) 1220 1221 # Now we handle high_shifter. 1222 # We can obtain p/x^e by computing the inverse of x^e/p. 1223 # Note that modup is still defined from before 1224 cup.restore_c() 1225 1226 ZZ_pX_conv_modulus(modup, self.mod.val(), cup.x) 1227 ZZ_pX_SetCoeff_long(modup, self.deg, 0) 1228 ZZ_pX_negate(modup, modup) 1229 ZZ_pX_right_pshift(into_multiplier, modup, self.small_powers[1], self.c.x) 1230 1231 # into_multiplier now holds x^e/p 1232 # self.c.x should have been restored, but we make sure 1233 self.c.restore_c() 1234 ZZ_pX_InvMod_newton(into_multiplier, into_multiplier, self.mod, self.c.x, (<ntl_ZZ_pContext_class>self.get_context(1)).x) 1235 ZZ_pX_Multiplier_construct(self.high_shifter) 1236 ZZ_pX_Multiplier_build(self.high_shifter[0], into_multiplier, self.mod) 1237 # Now we cache powers of p/x^e. This is a unit, so we don't have to worry about precision issues (yay!) 1238 for i from 1 <= i < self.high_length: 1239 ZZ_pX_SqrMod_pre(into_multiplier, into_multiplier, self.mod) 1240 ZZ_pX_Multiplier_construct(&(self.high_shifter[i])) 1241 ZZ_pX_Multiplier_build(self.high_shifter[i], into_multiplier, self.mod) 1242 1243 # I'm not sure whether I need to destruct the temporary variables. 1244 # ZZ_pX_destruct(&tmp) 1245 # ZZ_pX_destruct(&modup) 1246 # ZZ_pX_destruct(&into_multiplier) 1247 # ZZ_destruct(&a)
Note: See TracChangeset
for help on using the changeset viewer.
