passagemath-ntl 10.6.37__cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of passagemath-ntl might be problematic. Click here for more details.

Files changed (162) hide show
  1. passagemath_ntl/__init__.py +3 -0
  2. passagemath_ntl-10.6.37.dist-info/METADATA +122 -0
  3. passagemath_ntl-10.6.37.dist-info/RECORD +162 -0
  4. passagemath_ntl-10.6.37.dist-info/WHEEL +6 -0
  5. passagemath_ntl-10.6.37.dist-info/top_level.txt +3 -0
  6. passagemath_ntl.libs/libgf2x-fbd36f80.so.3.0.0 +0 -0
  7. passagemath_ntl.libs/libgmp-93ebf16a.so.10.5.0 +0 -0
  8. passagemath_ntl.libs/libmpfi-ad12a86d.so.0.0.0 +0 -0
  9. passagemath_ntl.libs/libmpfr-9d41ebf1.so.6.2.1 +0 -0
  10. passagemath_ntl.libs/libntl-0043a3a2.so.44.0.1 +0 -0
  11. sage/all__sagemath_ntl.py +7 -0
  12. sage/libs/all__sagemath_ntl.py +3 -0
  13. sage/libs/mpfi/__init__.pxd +287 -0
  14. sage/libs/mpfi/types.pxd +10 -0
  15. sage/libs/ntl/GF2.pxd +18 -0
  16. sage/libs/ntl/GF2E.pxd +28 -0
  17. sage/libs/ntl/GF2EX.pxd +12 -0
  18. sage/libs/ntl/GF2X.pxd +81 -0
  19. sage/libs/ntl/ZZ.pxd +93 -0
  20. sage/libs/ntl/ZZX.pxd +85 -0
  21. sage/libs/ntl/ZZ_p.pxd +28 -0
  22. sage/libs/ntl/ZZ_pE.pxd +37 -0
  23. sage/libs/ntl/ZZ_pEX.pxd +106 -0
  24. sage/libs/ntl/ZZ_pX.pxd +122 -0
  25. sage/libs/ntl/__init__.py +4 -0
  26. sage/libs/ntl/all.py +72 -0
  27. sage/libs/ntl/conversion.pxd +106 -0
  28. sage/libs/ntl/convert.cpython-311-aarch64-linux-gnu.so +0 -0
  29. sage/libs/ntl/convert.pxd +7 -0
  30. sage/libs/ntl/convert.pyx +38 -0
  31. sage/libs/ntl/decl.pxi +18 -0
  32. sage/libs/ntl/error.cpython-311-aarch64-linux-gnu.so +0 -0
  33. sage/libs/ntl/error.pyx +63 -0
  34. sage/libs/ntl/lzz_p.pxd +20 -0
  35. sage/libs/ntl/lzz_pX.pxd +59 -0
  36. sage/libs/ntl/mat_GF2.pxd +30 -0
  37. sage/libs/ntl/mat_GF2E.pxd +30 -0
  38. sage/libs/ntl/mat_ZZ.pxd +59 -0
  39. sage/libs/ntl/misc.pxi +33 -0
  40. sage/libs/ntl/ntl_GF2.cpython-311-aarch64-linux-gnu.so +0 -0
  41. sage/libs/ntl/ntl_GF2.pxd +5 -0
  42. sage/libs/ntl/ntl_GF2.pyx +281 -0
  43. sage/libs/ntl/ntl_GF2E.cpython-311-aarch64-linux-gnu.so +0 -0
  44. sage/libs/ntl/ntl_GF2E.pxd +8 -0
  45. sage/libs/ntl/ntl_GF2E.pyx +488 -0
  46. sage/libs/ntl/ntl_GF2EContext.cpython-311-aarch64-linux-gnu.so +0 -0
  47. sage/libs/ntl/ntl_GF2EContext.pxd +9 -0
  48. sage/libs/ntl/ntl_GF2EContext.pyx +134 -0
  49. sage/libs/ntl/ntl_GF2EX.cpython-311-aarch64-linux-gnu.so +0 -0
  50. sage/libs/ntl/ntl_GF2EX.pxd +10 -0
  51. sage/libs/ntl/ntl_GF2EX.pyx +251 -0
  52. sage/libs/ntl/ntl_GF2X.cpython-311-aarch64-linux-gnu.so +0 -0
  53. sage/libs/ntl/ntl_GF2X.pxd +5 -0
  54. sage/libs/ntl/ntl_GF2X.pyx +771 -0
  55. sage/libs/ntl/ntl_GF2X_linkage.pxi +404 -0
  56. sage/libs/ntl/ntl_ZZ.cpython-311-aarch64-linux-gnu.so +0 -0
  57. sage/libs/ntl/ntl_ZZ.pxd +7 -0
  58. sage/libs/ntl/ntl_ZZ.pyx +541 -0
  59. sage/libs/ntl/ntl_ZZX.cpython-311-aarch64-linux-gnu.so +0 -0
  60. sage/libs/ntl/ntl_ZZX.pxd +7 -0
  61. sage/libs/ntl/ntl_ZZX.pyx +1206 -0
  62. sage/libs/ntl/ntl_ZZ_p.cpython-311-aarch64-linux-gnu.so +0 -0
  63. sage/libs/ntl/ntl_ZZ_p.pxd +10 -0
  64. sage/libs/ntl/ntl_ZZ_p.pyx +509 -0
  65. sage/libs/ntl/ntl_ZZ_pContext.cpython-311-aarch64-linux-gnu.so +0 -0
  66. sage/libs/ntl/ntl_ZZ_pContext.pxd +22 -0
  67. sage/libs/ntl/ntl_ZZ_pContext.pyx +201 -0
  68. sage/libs/ntl/ntl_ZZ_pE.cpython-311-aarch64-linux-gnu.so +0 -0
  69. sage/libs/ntl/ntl_ZZ_pE.pxd +11 -0
  70. sage/libs/ntl/ntl_ZZ_pE.pyx +349 -0
  71. sage/libs/ntl/ntl_ZZ_pEContext.cpython-311-aarch64-linux-gnu.so +0 -0
  72. sage/libs/ntl/ntl_ZZ_pEContext.pxd +23 -0
  73. sage/libs/ntl/ntl_ZZ_pEContext.pyx +226 -0
  74. sage/libs/ntl/ntl_ZZ_pEX.cpython-311-aarch64-linux-gnu.so +0 -0
  75. sage/libs/ntl/ntl_ZZ_pEX.pxd +10 -0
  76. sage/libs/ntl/ntl_ZZ_pEX.pyx +1255 -0
  77. sage/libs/ntl/ntl_ZZ_pEX_linkage.pxi +420 -0
  78. sage/libs/ntl/ntl_ZZ_pX.cpython-311-aarch64-linux-gnu.so +0 -0
  79. sage/libs/ntl/ntl_ZZ_pX.pxd +17 -0
  80. sage/libs/ntl/ntl_ZZ_pX.pyx +1532 -0
  81. sage/libs/ntl/ntl_lzz_p.cpython-311-aarch64-linux-gnu.so +0 -0
  82. sage/libs/ntl/ntl_lzz_p.pxd +8 -0
  83. sage/libs/ntl/ntl_lzz_p.pyx +440 -0
  84. sage/libs/ntl/ntl_lzz_pContext.cpython-311-aarch64-linux-gnu.so +0 -0
  85. sage/libs/ntl/ntl_lzz_pContext.pxd +7 -0
  86. sage/libs/ntl/ntl_lzz_pContext.pyx +137 -0
  87. sage/libs/ntl/ntl_lzz_pX.cpython-311-aarch64-linux-gnu.so +0 -0
  88. sage/libs/ntl/ntl_lzz_pX.pxd +10 -0
  89. sage/libs/ntl/ntl_lzz_pX.pyx +902 -0
  90. sage/libs/ntl/ntl_mat_GF2.cpython-311-aarch64-linux-gnu.so +0 -0
  91. sage/libs/ntl/ntl_mat_GF2.pxd +8 -0
  92. sage/libs/ntl/ntl_mat_GF2.pyx +612 -0
  93. sage/libs/ntl/ntl_mat_GF2E.cpython-311-aarch64-linux-gnu.so +0 -0
  94. sage/libs/ntl/ntl_mat_GF2E.pxd +10 -0
  95. sage/libs/ntl/ntl_mat_GF2E.pyx +752 -0
  96. sage/libs/ntl/ntl_mat_ZZ.cpython-311-aarch64-linux-gnu.so +0 -0
  97. sage/libs/ntl/ntl_mat_ZZ.pxd +6 -0
  98. sage/libs/ntl/ntl_mat_ZZ.pyx +1523 -0
  99. sage/libs/ntl/ntl_tools.pxd +3 -0
  100. sage/libs/ntl/ntlwrap.h +53 -0
  101. sage/libs/ntl/ntlwrap_impl.h +743 -0
  102. sage/libs/ntl/types.pxd +157 -0
  103. sage/libs/ntl/vec_GF2.pxd +26 -0
  104. sage/libs/ntl/vec_GF2E.pxd +2 -0
  105. sage/matrix/all__sagemath_ntl.py +1 -0
  106. sage/matrix/matrix_modn_dense_double.pxd +10 -0
  107. sage/matrix/matrix_modn_dense_float.pxd +9 -0
  108. sage/matrix/matrix_modn_dense_template.pxi +3257 -0
  109. sage/matrix/matrix_modn_dense_template_header.pxi +15 -0
  110. sage/matrix/matrix_modn_sparse.pxd +8 -0
  111. sage/misc/all__sagemath_ntl.py +1 -0
  112. sage/rings/all__sagemath_ntl.py +7 -0
  113. sage/rings/bernmm.cpython-311-aarch64-linux-gnu.so +0 -0
  114. sage/rings/bernmm.pyx +161 -0
  115. sage/rings/bernoulli_mod_p.cpython-311-aarch64-linux-gnu.so +0 -0
  116. sage/rings/bernoulli_mod_p.pyx +313 -0
  117. sage/rings/finite_rings/all__sagemath_ntl.py +1 -0
  118. sage/rings/finite_rings/finite_field_ntl_gf2e.py +305 -0
  119. sage/rings/finite_rings/residue_field_ntl_gf2e.cpython-311-aarch64-linux-gnu.so +0 -0
  120. sage/rings/finite_rings/residue_field_ntl_gf2e.pyx +140 -0
  121. sage/rings/padics/all__sagemath_ntl.py +5 -0
  122. sage/rings/padics/padic_ZZ_pX_CA_element.cpython-311-aarch64-linux-gnu.so +0 -0
  123. sage/rings/padics/padic_ZZ_pX_CA_element.pxd +25 -0
  124. sage/rings/padics/padic_ZZ_pX_CA_element.pyx +2368 -0
  125. sage/rings/padics/padic_ZZ_pX_CR_element.cpython-311-aarch64-linux-gnu.so +0 -0
  126. sage/rings/padics/padic_ZZ_pX_CR_element.pxd +33 -0
  127. sage/rings/padics/padic_ZZ_pX_CR_element.pyx +3277 -0
  128. sage/rings/padics/padic_ZZ_pX_FM_element.cpython-311-aarch64-linux-gnu.so +0 -0
  129. sage/rings/padics/padic_ZZ_pX_FM_element.pxd +12 -0
  130. sage/rings/padics/padic_ZZ_pX_FM_element.pyx +1739 -0
  131. sage/rings/padics/padic_ZZ_pX_element.cpython-311-aarch64-linux-gnu.so +0 -0
  132. sage/rings/padics/padic_ZZ_pX_element.pxd +6 -0
  133. sage/rings/padics/padic_ZZ_pX_element.pyx +919 -0
  134. sage/rings/padics/padic_ext_element.cpython-311-aarch64-linux-gnu.so +0 -0
  135. sage/rings/padics/padic_ext_element.pxd +38 -0
  136. sage/rings/padics/padic_ext_element.pyx +512 -0
  137. sage/rings/padics/pow_computer_ext.cpython-311-aarch64-linux-gnu.so +0 -0
  138. sage/rings/padics/pow_computer_ext.pxd +107 -0
  139. sage/rings/padics/pow_computer_ext.pyx +2401 -0
  140. sage/rings/polynomial/all__sagemath_ntl.py +1 -0
  141. sage/rings/polynomial/evaluation_ntl.cpython-311-aarch64-linux-gnu.so +0 -0
  142. sage/rings/polynomial/evaluation_ntl.pxd +7 -0
  143. sage/rings/polynomial/evaluation_ntl.pyx +70 -0
  144. sage/rings/polynomial/polynomial_gf2x.cpython-311-aarch64-linux-gnu.so +0 -0
  145. sage/rings/polynomial/polynomial_gf2x.pxd +10 -0
  146. sage/rings/polynomial/polynomial_gf2x.pyx +364 -0
  147. sage/rings/polynomial/polynomial_integer_dense_ntl.cpython-311-aarch64-linux-gnu.so +0 -0
  148. sage/rings/polynomial/polynomial_integer_dense_ntl.pxd +8 -0
  149. sage/rings/polynomial/polynomial_integer_dense_ntl.pyx +1128 -0
  150. sage/rings/polynomial/polynomial_modn_dense_ntl.cpython-311-aarch64-linux-gnu.so +0 -0
  151. sage/rings/polynomial/polynomial_modn_dense_ntl.pxd +36 -0
  152. sage/rings/polynomial/polynomial_modn_dense_ntl.pyx +2049 -0
  153. sage/rings/polynomial/polynomial_template.pxi +842 -0
  154. sage/rings/polynomial/polynomial_template_header.pxi +11 -0
  155. sage/rings/polynomial/polynomial_zz_pex.cpython-311-aarch64-linux-gnu.so +0 -0
  156. sage/rings/polynomial/polynomial_zz_pex.pxd +12 -0
  157. sage/rings/polynomial/polynomial_zz_pex.pyx +778 -0
  158. sage/rings/real_mpfi.pxd +50 -0
  159. sage/schemes/all__sagemath_ntl.py +1 -0
  160. sage/schemes/hyperelliptic_curves/all__sagemath_ntl.py +1 -0
  161. sage/schemes/hyperelliptic_curves/hypellfrob.cpython-311-aarch64-linux-gnu.so +0 -0
  162. sage/schemes/hyperelliptic_curves/hypellfrob.pyx +252 -0
@@ -0,0 +1,2401 @@
1
+ # sage_setup: distribution = sagemath-ntl
2
+ # distutils: libraries = NTL_LIBRARIES gmp M_LIBRARIES
3
+ # distutils: extra_compile_args = NTL_CFLAGS
4
+ # distutils: include_dirs = NTL_INCDIR
5
+ # distutils: library_dirs = NTL_LIBDIR
6
+ # distutils: extra_link_args = NTL_LIBEXTRA
7
+ # distutils: language = c++
8
+ # sage.doctest: needs sage.rings.padics
9
+ """
10
+ PowComputer_ext
11
+
12
+ The classes in this file are designed to be attached to `p`-adic parents
13
+ and elements for Cython access to properties of the parent.
14
+
15
+ In addition to storing the defining polynomial (as an NTL polynomial)
16
+ at different precisions, they also cache powers of p and data to speed
17
+ right shifting of elements.
18
+
19
+ The hierarchy of PowComputers splits first at whether it's for a base
20
+ ring (Qp or Zp) or an extension.
21
+
22
+ Among the extension classes (those in this file), they are first split
23
+ by the type of NTL polynomial (ntl_ZZ_pX or ntl_ZZ_pEX), then by the
24
+ amount and style of caching (see below). Finally, there are
25
+ subclasses of the ntl_ZZ_pX PowComputers that cache additional
26
+ information for Eisenstein extensions.
27
+
28
+ There are three styles of caching:
29
+
30
+ * FM: caches powers of p up to the cache_limit, only caches the
31
+ polynomial modulus and the ntl_ZZ_pContext of precision
32
+ prec_cap.
33
+
34
+ * small: Requires cache_limit = prec_cap. Caches p^k for every k
35
+ up to the cache_limit and caches a polynomial modulus and a
36
+ ntl_ZZ_pContext for each such power of p.
37
+
38
+ * big: Caches as the small does up to cache_limit and caches
39
+ prec_cap. Also has a dictionary that caches values above the
40
+ cache_limit when they are computed (rather than at ring creation
41
+ time).
42
+
43
+ AUTHORS:
44
+
45
+ - David Roe (2008-01-01) initial version
46
+ """
47
+ # ****************************************************************************
48
+ # Copyright (C) 2008 David Roe <roed.math@gmail.com>
49
+ # William Stein <wstein@gmail.com>
50
+ #
51
+ # Distributed under the terms of the GNU General Public License (GPL)
52
+ # as published by the Free Software Foundation; either version 2 of
53
+ # the License, or (at your option) any later version.
54
+ #
55
+ # https://www.gnu.org/licenses/
56
+ # ****************************************************************************
57
+
58
+ from cpython.list cimport *
59
+ from cpython.dict cimport *
60
+
61
+ from cysignals.signals cimport sig_on, sig_off
62
+
63
+ include "../../libs/ntl/decl.pxi"
64
+
65
+ from sage.misc.timing import cputime
66
+ from sage.libs.gmp.mpz cimport *
67
+ from sage.libs.ntl.ntl_ZZ_pContext cimport ntl_ZZ_pContext_factory
68
+ from sage.libs.ntl.ntl_ZZ_pContext import ZZ_pContext_factory
69
+ from sage.libs.ntl.ntl_ZZ cimport ntl_ZZ
70
+ from sage.libs.ntl.ntl_ZZ_pX cimport ntl_ZZ_pX, ntl_ZZ_pX_Modulus
71
+ from sage.rings.integer cimport Integer
72
+
73
+ cdef extern from "../../ext/ccobject.h":
74
+ ZZ_c* Allocate_ZZ_array "Allocate_array<ZZ>"(size_t n)
75
+ void Delete_ZZ_array "Delete_array<ZZ>"(ZZ_c* v)
76
+ ZZ_pX_c* Allocate_ZZ_pX_array "Allocate_array<ZZ_pX>"(size_t n)
77
+ void Delete_ZZ_pX_array "Delete_array<ZZ_pX>"(ZZ_pX_c* v)
78
+ ZZ_pX_Multiplier_c* Allocate_ZZ_pX_Multiplier_array "Allocate_array<ZZ_pXMultiplier>"(size_t n)
79
+ void Delete_ZZ_pX_Multiplier_array "Delete_array<ZZ_pXMultiplier>"(ZZ_pX_Multiplier_c* v)
80
+ ZZ_pX_Modulus_c* Allocate_ZZ_pX_Modulus_array "Allocate_array<ZZ_pXModulus>"(size_t n)
81
+ void Delete_ZZ_pX_Modulus_array "Delete_array<ZZ_pXModulus>"(ZZ_pX_Modulus_c* v)
82
+
83
+ cdef int ZZ_pX_Eis_init(PowComputer_ZZ_pX prime_pow, ntl_ZZ_pX shift_seed) except -1:
84
+ """
85
+ Precomputes quantities for shifting right in Eisenstein extensions.
86
+
87
+ INPUT:
88
+
89
+ - ``prime_pow`` -- the PowComputer to be initialized
90
+ - ``shift_seed`` -- x^e/p as a polynomial of degree at most e-1 in x
91
+
92
+ EXAMPLES::
93
+
94
+ sage: A = PowComputer_ext_maker(5, 10, 10, 40, False, ntl.ZZ_pX([-5,65,125,0,1],5^10), 'small','e',ntl.ZZ_pX([1,-13,-25],5^10)) # indirect doctest
95
+ """
96
+ if prime_pow.deg <= 1:
97
+ raise ValueError("Eisenstein extension must have degree at least 2")
98
+ cdef unsigned long D = prime_pow.deg - 1
99
+ cdef int low_length = 0
100
+ cdef int high_length = 0
101
+ if sizeof(long) > 4 and D > 4294967295: # 2^32 - 1
102
+ low_length += 32
103
+ D = D >> 32
104
+ if D >= 65536: # 2^16
105
+ low_length += 16
106
+ D = D >> 16
107
+ if D >= 256: # 2^8
108
+ low_length += 8
109
+ D = D >> 8
110
+ if D >= 16: # 2^4
111
+ low_length += 4
112
+ D = D >> 4
113
+ if D >= 4: # 2^2
114
+ low_length += 2
115
+ D = D >> 2
116
+ if D >= 2: # 2^1
117
+ low_length += 1
118
+ D = D >> 1
119
+ low_length += 1
120
+ # low_length is the number of elements in the list we need to store.
121
+ # if deg = 2, low_length = 1 (store p/x)
122
+ # if deg = 3,4, low_length = 2 (store p/x, p/x^2)
123
+ # if deg = 5,6,7,8, low_length = 3 (store p/x, p/x^2, p/x^4)
124
+ # if deg = 9,...,16, low_length = 4 (store p/x, p/x^2, p/x^4, p/x^8)
125
+
126
+ # Now we do the same process for powers of p, ie storing p^(2^k)/x^(e*2^k)
127
+ D = prime_pow.prec_cap - 1
128
+ high_length = 0
129
+ if sizeof(long) > 4 and D > 4294967295: # 2^32 - 1
130
+ high_length += 32
131
+ D = D >> 32
132
+ if D >= 65536: # 2^16
133
+ high_length += 16
134
+ D = D >> 16
135
+ if D >= 256: # 2^8
136
+ high_length += 8
137
+ D = D >> 8
138
+ if D >= 16: # 2^4
139
+ high_length += 4
140
+ D = D >> 4
141
+ if D >= 4: # 2^2
142
+ high_length += 2
143
+ D = D >> 2
144
+ if D >= 2: # 2^1
145
+ high_length += 1
146
+ D = D >> 1
147
+ high_length += 1
148
+ # high_length is the number of elements in the list we need to store.
149
+ # if prec_cap = 2, high_length = 1 (store p/x^e)
150
+ # if prec_cap = 3,4, high_length = 2 (store p/x^e, p^2/x^(2e))
151
+ # if prec_cap = 5,6,7,8, high_length = 3 (store p/x^e, p^2/x^(2e), p^4/x^(4e))
152
+ # if prec_cap = 9,...,16, high_length = 4 (store p/x, p^2/x^(2e), p^4/x^(4e), p^8/x^(8e))
153
+
154
+ cdef ZZ_pX_Multiplier_c* low_shifter_m
155
+ cdef ZZ_pX_Multiplier_c* high_shifter_m
156
+ cdef ZZ_pX_c* low_shifter_p
157
+ cdef ZZ_pX_c* high_shifter_p
158
+ cdef bint multiplier
159
+ if isinstance(prime_pow, PowComputer_ZZ_pX_FM_Eis):
160
+ multiplier = 1
161
+ (<PowComputer_ZZ_pX_FM_Eis>prime_pow).low_length = low_length
162
+ (<PowComputer_ZZ_pX_FM_Eis>prime_pow).high_length = high_length
163
+
164
+ sig_on()
165
+ (<PowComputer_ZZ_pX_FM_Eis>prime_pow).low_shifter = Allocate_ZZ_pX_Multiplier_array(low_length)
166
+ (<PowComputer_ZZ_pX_FM_Eis>prime_pow).high_shifter = Allocate_ZZ_pX_Multiplier_array(high_length)
167
+ sig_off()
168
+ low_shifter_m = (<PowComputer_ZZ_pX_FM_Eis>prime_pow).low_shifter
169
+ high_shifter_m = (<PowComputer_ZZ_pX_FM_Eis>prime_pow).high_shifter
170
+ elif isinstance(prime_pow, PowComputer_ZZ_pX_small_Eis):
171
+ multiplier = 0
172
+ (<PowComputer_ZZ_pX_small_Eis>prime_pow).low_length = low_length
173
+ (<PowComputer_ZZ_pX_small_Eis>prime_pow).high_length = high_length
174
+
175
+ sig_on()
176
+ (<PowComputer_ZZ_pX_small_Eis>prime_pow).low_shifter = Allocate_ZZ_pX_array(low_length)
177
+ (<PowComputer_ZZ_pX_small_Eis>prime_pow).high_shifter = Allocate_ZZ_pX_array(high_length)
178
+ sig_off()
179
+ low_shifter_p = (<PowComputer_ZZ_pX_small_Eis>prime_pow).low_shifter
180
+ high_shifter_p = (<PowComputer_ZZ_pX_small_Eis>prime_pow).high_shifter
181
+ elif isinstance(prime_pow, PowComputer_ZZ_pX_big_Eis):
182
+ multiplier = 0
183
+ (<PowComputer_ZZ_pX_big_Eis>prime_pow).low_length = low_length
184
+ (<PowComputer_ZZ_pX_big_Eis>prime_pow).high_length = high_length
185
+
186
+ sig_on()
187
+ (<PowComputer_ZZ_pX_big_Eis>prime_pow).low_shifter = Allocate_ZZ_pX_array(low_length)
188
+ (<PowComputer_ZZ_pX_big_Eis>prime_pow).high_shifter = Allocate_ZZ_pX_array(high_length)
189
+ sig_off()
190
+ low_shifter_p = (<PowComputer_ZZ_pX_big_Eis>prime_pow).low_shifter
191
+ high_shifter_p = (<PowComputer_ZZ_pX_big_Eis>prime_pow).high_shifter
192
+ else:
193
+ raise TypeError("unrecognized Eisenstein type")
194
+
195
+ cdef long i
196
+ cdef ZZ_pX_c into_multiplier, shift_seed_inv
197
+ # We obtain successive p/x^(2^i) by squaring and then dividing by p. So we need one extra digit of precision.
198
+ prime_pow.restore_top_context()
199
+ #cdef ntl_ZZ_pContext_class cup = prime_pow.get_context(prime_pow.prec_cap + low_length)
200
+ #cup.restore_c()
201
+ #ZZ_pX_conv_modulus(modup, prime_pow.get_top_modulus()[0].val(), cup.x)
202
+ #ZZ_div(a, ZZ_p_rep(ZZ_pX_ConstTerm(modup)), prime_pow.small_powers[1])
203
+ #ZZ_InvMod(a, a, prime_pow.pow_ZZ_tmp(prime_pow.prec_cap + low_length)[0])
204
+ #ZZ_negate(a, a)
205
+ ##cdef ntl_ZZ_pX printer = ntl_ZZ_pX([], prime_pow.get_context(prime_pow.prec_cap))
206
+ ##printer.x = modup
207
+ # Note that we're losing one digit of precision here.
208
+ # This is correct because right shifting does not preserve precision.
209
+ # a is now the negative of the inverse of the unit part of the constant of the defining polynomial (there's a mouthful)
210
+ #ZZ_pX_RightShift(tmp, modup, 1)
211
+ ##printer.x = modup
212
+ #ZZ_pX_mul_ZZ_p(tmp, tmp, ZZ_to_ZZ_p(a))
213
+ # tmp is now p/x
214
+ #ZZ_pX_conv_modulus(into_multiplier, tmp, prime_pow.get_top_context().x)
215
+ ##printer.x = into_multiplier
216
+ #if multiplier:
217
+ # ZZ_pX_Multiplier_construct(low_shifter_m)
218
+ # ZZ_pX_Multiplier_build(low_shifter_m[0], into_multiplier, prime_pow.get_top_modulus()[0])
219
+ #else:
220
+ # ZZ_pX_construct(low_shifter_p)
221
+ # low_shifter_p[0] = into_multiplier
222
+ ##printer.x = (low_shifter[0]).val()
223
+ ZZ_pX_InvMod_newton_ram(shift_seed_inv, shift_seed.x, prime_pow.get_top_modulus()[0], prime_pow.get_top_context().x)
224
+ for i in range(low_length):
225
+ # Currently tmp = p / x^(2^(i-1)). Squaring yields p^2 / x^(2^i)
226
+ #ZZ_pX_SqrMod(tmp, tmp, modup)
227
+ # Now we divide by p.
228
+ #ZZ_pX_right_pshift(tmp, tmp, prime_pow.small_powers[1], cup.x)
229
+ #ZZ_pX_conv_modulus(into_multiplier, tmp, prime_pow.get_top_context().x)
230
+ ZZ_pX_PowerXMod_long_pre(into_multiplier, prime_pow.e - (1L << i), prime_pow.get_top_modulus()[0])
231
+ ZZ_pX_MulMod_pre(into_multiplier, into_multiplier, shift_seed_inv, prime_pow.get_top_modulus()[0])
232
+ ##printer.x = into_multiplier
233
+ if multiplier:
234
+ ZZ_pX_Multiplier_build(low_shifter_m[i], into_multiplier, prime_pow.get_top_modulus()[0])
235
+ else:
236
+ low_shifter_p[i] = into_multiplier
237
+
238
+ # Now we handle high_shifter.
239
+ # We can obtain p/x^e by computing the inverse of x^e/p.
240
+ # Note that modup is still defined from before
241
+ ###cup.restore_c()
242
+
243
+ ###ZZ_pX_conv_modulus(modup, prime_pow.get_top_modulus()[0].val(), cup.x)
244
+ ###ZZ_pX_SetCoeff_long(modup, prime_pow.deg, 0)
245
+ ###ZZ_pX_negate(modup, modup)
246
+ ###ZZ_pX_right_pshift(into_multiplier, modup, prime_pow.small_powers[1], prime_pow.get_top_context().x)
247
+
248
+ ###printer.x = into_multiplier
249
+
250
+ # into_multiplier now holds x^e/p
251
+ # prime_pow.c.x should have been restored, but we make sure
252
+ prime_pow.restore_top_context()
253
+ ##printer.x = prime_pow.get_top_modulus()[0].val()
254
+ into_multiplier = shift_seed_inv
255
+ #ZZ_pX_InvMod_newton_ram(into_multiplier, shift_seed.x, prime_pow.get_top_modulus()[0], prime_pow.get_top_context().x)
256
+ ##printer.x = into_multiplier
257
+ ##ZZ_pX_MulMod_pre(printer.x, into_multiplier, shift_seed.x, prime_pow.get_top_modulus()[0])
258
+ if multiplier:
259
+ ZZ_pX_Multiplier_build(high_shifter_m[0], into_multiplier, prime_pow.get_top_modulus()[0])
260
+ else:
261
+ high_shifter_p[0] = into_multiplier
262
+ # Now we cache powers of p/x^e. This is a unit, so we don't have to worry about precision issues (yay!)
263
+ for i in range(1, high_length):
264
+ ZZ_pX_SqrMod_pre(into_multiplier, into_multiplier, prime_pow.get_top_modulus()[0])
265
+ if multiplier:
266
+ ZZ_pX_Multiplier_build(high_shifter_m[i], into_multiplier, prime_pow.get_top_modulus()[0])
267
+ else:
268
+ high_shifter_p[i] = into_multiplier
269
+
270
+
271
+ def ZZ_pX_eis_shift_test(_shifter, _a, _n, _finalprec):
272
+ """
273
+ Shift ``_a`` right ``_n`` x-adic digits, where x is considered modulo the
274
+ polynomial in ``_shifter``.
275
+
276
+ EXAMPLES::
277
+
278
+ sage: from sage.rings.padics.pow_computer_ext import ZZ_pX_eis_shift_test
279
+ sage: A = PowComputer_ext_maker(5, 3, 10, 40, False, ntl.ZZ_pX([-5,75,15,0,1],5^10), 'big', 'e',ntl.ZZ_pX([1,-15,-3],5^10))
280
+ sage: ZZ_pX_eis_shift_test(A, [0, 1], 1, 5)
281
+ [1]
282
+ sage: ZZ_pX_eis_shift_test(A, [0, 0, 1], 1, 5)
283
+ [0 1]
284
+ sage: ZZ_pX_eis_shift_test(A, [5], 1, 5)
285
+ [75 15 0 1]
286
+ sage: ZZ_pX_eis_shift_test(A, [1], 1, 5)
287
+ []
288
+ sage: ZZ_pX_eis_shift_test(A, [17, 91, 8, -2], 1, 5)
289
+ [316 53 3123 3]
290
+ sage: ZZ_pX_eis_shift_test(A, [316, 53, 3123, 3], -1, 5)
291
+ [15 91 8 3123]
292
+ sage: ZZ_pX_eis_shift_test(A, [15, 91, 8, 3123], 1, 5)
293
+ [316 53 3123 3]
294
+ """
295
+ cdef PowComputer_ZZ_pX shifter = <PowComputer_ZZ_pX?>_shifter
296
+ cdef ntl_ZZ_pX x = <ntl_ZZ_pX>ntl_ZZ_pX(modulus=shifter._prime()**_finalprec)
297
+ cdef ntl_ZZ_pX a = <ntl_ZZ_pX>ntl_ZZ_pX(_a, modulus=shifter._prime()**_finalprec)
298
+ cdef long n = _n
299
+ cdef long finalprec = _finalprec
300
+ ZZ_pX_eis_shift_p(shifter, &x.x, &a.x, n, finalprec)
301
+ return x
302
+
303
+
304
+ cdef int ZZ_pX_eis_shift_p(PowComputer_ZZ_pX self, ZZ_pX_c* x, ZZ_pX_c* a, long n, long finalprec) except -1:
305
+ """
306
+ Eis-shifts a over by n and puts the result into x.
307
+
308
+ Negative n corresponds to multiplying by x^-n.
309
+
310
+ TESTS::
311
+
312
+ sage: R.<x> = QQ[]
313
+ sage: K = Qp(11,10)
314
+ sage: J.<a> = K.extension(x^30 - 11)
315
+ sage: M.<t> = PowerSeriesRing(J)
316
+ sage: S.<x,y> = QQ[]
317
+ sage: xr = O(a^152)*t + (8*a^2 + 10*a^32 + 7*a^62 + 10*a^92 + 7*a^122 + O(a^152))*t^2 + O(a^154)*t^3 + (2*a^4 + 10*a^64 + 2*a^124 + O(a^154))*t^4 + O(a^156)*t^5 + (5*a^6 + 2*a^96 + a^126 + O(a^156))*t^6 + O(a^158)*t^7 + (7*a^8 + 6*a^38 + 8*a^68 + 2*a^98 + 5*a^128 + O(a^158))*t^8 + O(a^160)*t^9 + (8*a^10 + 10*a^40 + a^70 + 5*a^130 + O(a^160))*t^10 + O(a^162)*t^11 + (9*a^12 + 7*a^42 + 8*a^72 + 6*a^102 + 9*a^132 + O(a^162))*t^12 + O(a^164)*t^13 + (2*a^14 + 5*a^44 + 3*a^74 + a^104 + 4*a^134 + O(a^164))*t^14 + O(a^166)*t^15 + (2*a^16 + 5*a^46 + 8*a^76 + 5*a^106 + 7*a^136 + O(a^166))*t^16 + O(a^168)*t^17 + (7*a^18 + 3*a^48 + 6*a^78 + 9*a^138 + O(a^168))*t^18 + O(a^172)*t^19 + (7*a^50 + 3*a^80 + 5*a^110 + 5*a^140 + 7*a^170 + O(a^172))*t^20 + O(a^172)*t^21 + (a^22 + a^52 + 3*a^82 + 3*a^112 + 2*a^142 + O(a^172))*t^22 + O(a^174)*t^23 + (4*a^24 + 7*a^54 + 9*a^84 + 4*a^114 + 7*a^144 + O(a^174))*t^24 + O(a^176)*t^25 + (3*a^26 + 8*a^56 + 8*a^116 + 5*a^146 + O(a^176))*t^26 + O(a^178)*t^27 + (2*a^28 + 2*a^58 + 6*a^88 + a^118 + 10*a^148 + O(a^178))*t^28 + O(a^180)*t^29 + (8*a^30 + 5*a^60 + 8*a^90 + 5*a^120 + 6*a^150 + O(a^180))*t^30 + O(a^184)*t^31 + (7*a^62 + 9*a^92 + 2*a^182 + O(a^184))*t^32
318
+ sage: yr = xr^2
319
+ sage: dtr = xr.derivative()
320
+ sage: f_dtr = yr*dtr; f_dtr
321
+ O(a^456)*t^2 + O(a^306)*t^3 + O(a^156)*t^4 + (a^6 + 6*a^36 + 2*a^66 + 7*a^96 + 4*a^126 + O(a^156))*t^5 + O(a^158)*t^6 + (a^8 + 2*a^38 + 8*a^68 + 3*a^98 + O(a^158))*t^7 + O(a^160)*t^8 + (8*a^40 + 10*a^100 + 5*a^130 + O(a^160))*t^9 + O(a^162)*t^10 + (2*a^12 + 5*a^42 + 3*a^72 + 7*a^102 + O(a^162))*t^11 + O(a^164)*t^12 + (8*a^14 + a^44 + 6*a^74 + 4*a^104 + 7*a^134 + O(a^164))*t^13 + O(a^166)*t^14 + (2*a^16 + 8*a^46 + 5*a^106 + 4*a^136 + O(a^166))*t^15 + O(a^168)*t^16 + (a^18 + 6*a^48 + 5*a^78 + 2*a^108 + 9*a^138 + O(a^168))*t^17 + O(a^170)*t^18 + (8*a^50 + 2*a^110 + O(a^170))*t^19 + O(a^172)*t^20 + (4*a^52 + 2*a^82 + 7*a^112 + 5*a^142 + O(a^172))*t^21 + O(a^174)*t^22 + (2*a^54 + 3*a^84 + 8*a^114 + 6*a^144 + O(a^174))*t^23 + O(a^176)*t^24 + (a^26 + 6*a^56 + 4*a^86 + 9*a^116 + 3*a^146 + O(a^176))*t^25 + O(a^178)*t^26 + (10*a^28 + 5*a^58 + 4*a^88 + 10*a^118 + 6*a^148 + O(a^178))*t^27 + O(a^180)*t^28 + (5*a^30 + 5*a^60 + 4*a^90 + 9*a^120 + 3*a^150 + O(a^180))*t^29 + O(a^182)*t^30 + (4*a^32 + 10*a^62 + 5*a^92 + 7*a^122 + 3*a^152 + O(a^182))*t^31 + O(a^184)*t^32 + (5*a^34 + 9*a^94 + 3*a^124 + 6*a^154 + O(a^184))*t^33 + O(a^186)*t^34 + (4*a^36 + 3*a^66 + 10*a^96 + 2*a^126 + 6*a^156 + O(a^186))*t^35 + O(a^188)*t^36 + (6*a^38 + 9*a^68 + 7*a^128 + 10*a^158 + O(a^188))*t^37 + O(a^190)*t^38 + (7*a^40 + 3*a^70 + 4*a^100 + 4*a^130 + 8*a^160 + O(a^190))*t^39 + O(a^192)*t^40 + (a^42 + 10*a^72 + 10*a^102 + a^132 + 7*a^162 + O(a^192))*t^41 + O(a^194)*t^42 + (8*a^74 + 8*a^104 + 9*a^134 + 7*a^164 + O(a^194))*t^43 + O(a^196)*t^44 + (10*a^136 + 2*a^166 + O(a^196))*t^45 + O(a^198)*t^46 + (7*a^48 + 10*a^78 + 5*a^108 + 8*a^138 + 3*a^168 + O(a^198))*t^47 + O(a^200)*t^48 + (6*a^50 + 5*a^80 + a^110 + 6*a^170 + O(a^200))*t^49 + O(a^202)*t^50 + (a^52 + 8*a^82 + 2*a^112 + 10*a^172 + O(a^202))*t^51 + O(a^204)*t^52 + (9*a^54 + 2*a^84 + 6*a^114 + 4*a^144 + O(a^204))*t^53 + O(a^206)*t^54 + (2*a^56 + 5*a^86 + 2*a^116 + 4*a^146 + a^176 + O(a^206))*t^55 + O(a^208)*t^56 + (3*a^58 + 3*a^88 + a^118 + 5*a^148 + 2*a^178 + O(a^208))*t^57 + O(a^210)*t^58 + (5*a^60 + 10*a^90 + 9*a^120 + a^150 + 6*a^180 + O(a^210))*t^59 + O(a^212)*t^60 + (4*a^62 + 9*a^92 + 7*a^122 + 7*a^152 + 9*a^182 + O(a^212))*t^61 + O(a^214)*t^62 + (10*a^64 + 8*a^94 + 6*a^124 + 8*a^154 + 4*a^184 + O(a^214))*t^63 + O(a^216)*t^64 + (4*a^126 + 10*a^156 + 9*a^186 + O(a^216))*t^65 + O(a^218)*t^66 + (7*a^98 + 4*a^128 + 6*a^158 + 6*a^188 + O(a^218))*t^67 + O(a^220)*t^68 + (3*a^70 + 6*a^100 + 8*a^130 + 9*a^160 + 10*a^190 + O(a^220))*t^69 + O(a^222)*t^70 + (9*a^72 + 5*a^102 + 9*a^132 + 3*a^162 + 10*a^192 + O(a^222))*t^71 + O(a^224)*t^72 + (3*a^74 + 8*a^104 + 7*a^134 + 2*a^164 + O(a^224))*t^73 + O(a^226)*t^74 + (10*a^76 + a^106 + 2*a^136 + 4*a^166 + 9*a^196 + O(a^226))*t^75 + O(a^228)*t^76 + (3*a^78 + 6*a^108 + 9*a^138 + 4*a^168 + 5*a^198 + O(a^228))*t^77 + O(a^230)*t^78 + (4*a^80 + 10*a^110 + 7*a^170 + 8*a^200 + O(a^230))*t^79 + O(a^232)*t^80 + (5*a^82 + 4*a^112 + 9*a^142 + 8*a^172 + 8*a^202 + O(a^232))*t^81 + O(a^234)*t^82 + (4*a^84 + 9*a^114 + 8*a^144 + 2*a^174 + 6*a^204 + O(a^234))*t^83 + O(a^236)*t^84 + (3*a^86 + 5*a^116 + 4*a^146 + 8*a^206 + O(a^236))*t^85 + O(a^238)*t^86 + (a^118 + 7*a^148 + 6*a^208 + O(a^238))*t^87 + O(a^240)*t^88 + (4*a^90 + 9*a^120 + 9*a^150 + 6*a^180 + 6*a^210 + O(a^240))*t^89 + O(a^244)*t^90 + (10*a^122 + 3*a^152 + 8*a^182 + 4*a^212 + 2*a^242 + O(a^244))*t^91 + O(a^276)*t^92 + (9*a^154 + 10*a^184 + 10*a^214 + 7*a^244 + 9*a^274 + O(a^276))*t^93 + O(a^308)*t^94 + (9*a^186 + 4*a^216 + 5*a^246 + a^276 + 10*a^306 + O(a^308))*t^95
322
+ """
323
+ cdef ZZ_pX_c low_part
324
+ cdef ZZ_pX_c shifted_high_part
325
+ cdef ZZ_pX_c powerx
326
+ cdef ZZ_pX_c lowshift
327
+ cdef ZZ_pX_c highshift
328
+ cdef ZZ_pX_c working, working2
329
+ cdef ntl_ZZ_pContext_class c
330
+ cdef ZZ_pX_Modulus_c* m
331
+ cdef long pshift = n / self.e
332
+ cdef long eis_part = n % self.e
333
+ cdef long two_shift = 1
334
+ cdef int i
335
+ cdef ZZ_pX_c* high_shifter
336
+ cdef ZZ_pX_c* low_shifter
337
+ cdef ZZ_pX_Multiplier_c* high_shifter_fm
338
+ cdef ZZ_pX_Multiplier_c* low_shifter_fm
339
+ cdef bint fm
340
+ cdef long high_length
341
+ if isinstance(self, PowComputer_ZZ_pX_small_Eis):
342
+ high_shifter = (<PowComputer_ZZ_pX_small_Eis>self).high_shifter
343
+ low_shifter = (<PowComputer_ZZ_pX_small_Eis>self).low_shifter
344
+ high_length = (<PowComputer_ZZ_pX_small_Eis>self).high_length
345
+ fm = False
346
+ elif isinstance(self, PowComputer_ZZ_pX_big_Eis):
347
+ high_shifter = (<PowComputer_ZZ_pX_big_Eis>self).high_shifter
348
+ low_shifter = (<PowComputer_ZZ_pX_big_Eis>self).low_shifter
349
+ high_length = (<PowComputer_ZZ_pX_big_Eis>self).high_length
350
+ fm = False
351
+ elif isinstance(self, PowComputer_ZZ_pX_FM_Eis):
352
+ high_shifter_fm = (<PowComputer_ZZ_pX_FM_Eis>self).high_shifter
353
+ low_shifter_fm = (<PowComputer_ZZ_pX_FM_Eis>self).low_shifter
354
+ high_length = (<PowComputer_ZZ_pX_FM_Eis>self).high_length
355
+ fm = True
356
+ else:
357
+ raise TypeError("inconsistent type")
358
+
359
+ if n < 0:
360
+ if fm:
361
+ c = self.get_top_context()
362
+ m = self.get_top_modulus()
363
+ else:
364
+ c = self.get_context(finalprec)
365
+ m = self.get_modulus(finalprec)
366
+ c.restore_c()
367
+ ##printer = ntl_ZZ_pX([],c)
368
+ ZZ_pX_PowerXMod_long_pre(powerx, -n, m[0])
369
+ ##printer.x = powerx
370
+ ZZ_pX_conv_modulus(x[0], a[0], c.x)
371
+ ZZ_pX_MulMod_pre(x[0], powerx, a[0], m[0])
372
+ ##printer.x = x[0]
373
+ return 0
374
+ elif n == 0:
375
+ if x != a:
376
+ if fm:
377
+ c = self.get_top_context()
378
+ else:
379
+ c = self.get_context(finalprec)
380
+ ZZ_pX_conv_modulus(x[0], a[0], c.x)
381
+ return 0
382
+
383
+ # The following doesn't work, sadly. It should be possible to precompute and do better than what I replace this code with.
384
+ # c = self.get_context(finalprec)
385
+ # m = self.get_modulus(finalprec)[0]
386
+ # printer = ntl_ZZ_pX([],c)
387
+ # if pshift:
388
+ # ZZ_pX_right_pshift(x[0], a[0], self.pow_ZZ_tmp(pshift)[0], c.x)
389
+ # else:
390
+ # ZZ_pX_conv_modulus(x[0], a[0], c.x)
391
+ # ##printer.x = a[0]
392
+ # c.restore_c()
393
+ # if pshift:
394
+ # i = 0
395
+ # # This line restores the top context
396
+ # #ZZ_pX_right_pshift(x[0], x[0], self.pow_ZZ_tmp(pshift)[0], c.x)
397
+ # ##printer.x = x[0]
398
+ # if pshift >= self.prec_cap:
399
+ # # shifter = p^(2^(high_length - 1))/x^(e*2^(high_length - 1))
400
+ # ZZ_pX_conv_modulus(shifter, high_shifter[high_length-1], c.x)
401
+ # ##printer.x = shifter
402
+ # # if val = r + s * 2^(high_length - 1)
403
+ # # then shifter = p^(s*2^(high_length - 1))/x^(e*s*2^(high_length - 1))
404
+ # ZZ_pX_PowerMod_long_pre(shifter, shifter, (pshift / (1L << (high_length - 1))), m)
405
+ # ##printer.x = shifter
406
+ # ZZ_pX_MulMod_pre(x[0], x[0], shifter, m)
407
+ # ##printer.x = shifter
408
+ # # Now we only need to multiply self.unit by p^r/x^(e*r) where r < 2^(high_length - 1), which is tractible.
409
+ # pshift = pshift % (1L << (high_length - 1))
410
+ # while pshift > 0:
411
+ # if pshift & 1:
412
+ # ##printer.x = x[0]
413
+ # ZZ_pX_conv_modulus(highshift, high_shifter[i], c.x)
414
+ # ZZ_pX_MulMod_pre(x[0], x[0], highshift, m)
415
+ # i += 1
416
+ # pshift = pshift >> 1
417
+ if fm:
418
+ c = self.get_top_context()
419
+ m = self.get_top_modulus()
420
+ else:
421
+ c = self.get_context(finalprec + pshift + 1)
422
+ c.restore_c()
423
+ ZZ_pX_conv_modulus(working, a[0], c.x)
424
+ if pshift:
425
+ while pshift > 0:
426
+ pshift -= 1
427
+ if fm:
428
+ ZZ_pX_right_pshift(working, working, self.pow_ZZ_tmp(1)[0],c.x)
429
+ ZZ_pX_MulMod_premul(working, working, high_shifter_fm[0], m[0])
430
+ else:
431
+ c = self.get_context(finalprec + pshift + 1)
432
+ m = self.get_modulus(finalprec + pshift + 1)
433
+ ZZ_pX_right_pshift(working, working, self.pow_ZZ_tmp(1)[0],c.x)
434
+ ZZ_pX_conv_modulus(highshift, high_shifter[0], c.x)
435
+ ZZ_pX_MulMod_pre(working, working, highshift, m[0])
436
+ elif not fm:
437
+ m = self.get_modulus(finalprec + 1)
438
+ ZZ_pX_conv_modulus(working2, working, c.x)
439
+ i = 0
440
+ two_shift = 1
441
+ while eis_part > 0:
442
+ if eis_part & 1:
443
+ ##printer.x = working2
444
+ ZZ_pX_RightShift(shifted_high_part, working2, two_shift)
445
+ ##printer.x = shifted_high_part
446
+ ZZ_pX_LeftShift(low_part, shifted_high_part, two_shift)
447
+ ZZ_pX_sub(low_part, working2, low_part)
448
+ ##printer.x = low_part
449
+ ZZ_pX_right_pshift(low_part, low_part, self.pow_ZZ_tmp(1)[0], c.x)
450
+ ##printer.x = low_part
451
+ if fm:
452
+ ZZ_pX_MulMod_premul(low_part, low_part, low_shifter_fm[i], m[0])
453
+ else:
454
+ ZZ_pX_conv_modulus(lowshift, low_shifter[i], c.x)
455
+ ZZ_pX_MulMod_pre(low_part, low_part, lowshift, m[0])
456
+ ##printer.x = low_part
457
+ ZZ_pX_add(working2, low_part, shifted_high_part)
458
+ ##printer.x = working2
459
+ i += 1
460
+ two_shift = two_shift << 1
461
+ eis_part = eis_part >> 1
462
+ c = self.get_context(finalprec)
463
+ ZZ_pX_conv_modulus(x[0], working2, c.x)
464
+
465
+ cdef class PowComputer_ext(PowComputer_class):
466
+ def __cinit__(self, Integer prime, long cache_limit, long prec_cap, long ram_prec_cap, bint in_field, poly, shift_seed=None):
467
+ """
468
+ Construct the storage for powers of prime as ZZ_c's.
469
+
470
+ EXAMPLES::
471
+
472
+ sage: PC = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5, 0, 1], 5^10), 'small', 'e',ntl.ZZ_pX([1],5^10)) # indirect doctest
473
+ """
474
+ PowComputer_class.__init__(self, prime, cache_limit, prec_cap, ram_prec_cap, in_field, poly, shift_seed)
475
+
476
+ self._initialized = 0
477
+ self.small_powers = Allocate_ZZ_array(cache_limit + 1)
478
+ if self.small_powers == NULL:
479
+ raise MemoryError("out of memory allocating power storing")
480
+
481
+ cdef Py_ssize_t i
482
+
483
+ ZZ_conv_from_int(self.small_powers[0], 1)
484
+
485
+ if cache_limit > 0:
486
+ mpz_to_ZZ(&(self.small_powers[1]), prime.value)
487
+
488
+ sig_on()
489
+ for i in range(2, cache_limit + 1):
490
+ ZZ_mul(self.small_powers[i], self.small_powers[i-1], self.small_powers[1])
491
+ mpz_to_ZZ(&self.top_power, prime.value)
492
+ ZZ_power(self.top_power, self.top_power, prec_cap)
493
+ sig_off()
494
+ mpz_init(self.temp_m)
495
+ mpz_init(self.temp_m2)
496
+
497
+ self._poly = poly
498
+ self._shift_seed = shift_seed
499
+
500
+ def __dealloc__(self):
501
+ """
502
+ Frees allocated memory.
503
+
504
+ EXAMPLES::
505
+
506
+ sage: PC = PowComputer_ext_maker(5, 5, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
507
+ sage: del PC # indirect doctest
508
+ """
509
+ if (<PowComputer_ext>self)._initialized:
510
+ self.cleanup_ext()
511
+
512
+ def __repr__(self):
513
+ """
514
+ Return a string representation of ``self``.
515
+
516
+ EXAMPLES::
517
+
518
+ sage: PC = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5, 0, 1], 5^10), 'small', 'e',ntl.ZZ_pX([1],5^10))
519
+ sage: PC # indirect doctest
520
+ PowComputer_ext for 5, with polynomial [9765620 0 1]
521
+ """
522
+ return "PowComputer_ext for %s, with polynomial %s" % (self.prime, self.polynomial())
523
+
524
+ def __reduce__(self):
525
+ """
526
+ For pickling.
527
+
528
+ EXAMPLES::
529
+
530
+ sage: PC = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5, 0, 1], 5^10), 'small', 'e',ntl.ZZ_pX([1],5^10)); PC
531
+ PowComputer_ext for 5, with polynomial [9765620 0 1]
532
+ sage: loads(dumps(PC))
533
+ PowComputer_ext for 5, with polynomial [9765620 0 1]
534
+ """
535
+ cdef Integer cache_limit, prec_cap, ram_prec_cap
536
+ cache_limit = Integer.__new__(Integer)
537
+ mpz_set_si(cache_limit.value, self.cache_limit)
538
+ prec_cap = Integer.__new__(Integer)
539
+ mpz_set_si(prec_cap.value, self.prec_cap)
540
+ ram_prec_cap = Integer.__new__(Integer)
541
+ mpz_set_si(ram_prec_cap.value, self.ram_prec_cap)
542
+ return PowComputer_ext_maker, (self.prime, cache_limit, prec_cap, ram_prec_cap, self.in_field, self._poly, self._prec_type, self._ext_type, self._shift_seed)
543
+
544
+ cdef void cleanup_ext(self) noexcept:
545
+ """
546
+ Frees memory allocated in PowComputer_ext.
547
+
548
+ EXAMPLES::
549
+
550
+ sage: PC = PowComputer_ext_maker(5, 5, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
551
+ sage: del PC # indirect doctest
552
+ """
553
+ Delete_ZZ_array(self.small_powers)
554
+ mpz_clear(self.temp_m)
555
+ mpz_clear(self.temp_m2)
556
+
557
+ cdef mpz_srcptr pow_mpz_t_tmp(self, long n) except NULL:
558
+ """
559
+ Provides fast access to an mpz_t* pointing to self.prime^n.
560
+
561
+ The location pointed to depends on the underlying
562
+ representation. In no circumstances should you mpz_clear the
563
+ result. The value pointed to may be an internal temporary
564
+ variable for the class. In particular, you should not try to
565
+ refer to the results of two pow_mpz_t_tmp calls at the same
566
+ time, because the second call may overwrite the memory pointed
567
+ to by the first.
568
+
569
+ In the case of PowComputer_exts, the mpz_t pointed to will
570
+ always be a temporary variable.
571
+
572
+ See pow_mpz_t_tmp_demo for an example of this phenomenon.
573
+
574
+ EXAMPLES::
575
+
576
+ sage: PC = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5, 0, 1], 5^10), 'small', 'e',ntl.ZZ_pX([1],5^10))
577
+ sage: PC._pow_mpz_t_tmp_test(4) # indirect doctest
578
+ 625
579
+ """
580
+ if n < 0:
581
+ raise ValueError("n must be nonnegative")
582
+ if n <= self.cache_limit:
583
+ ZZ_to_mpz(self.temp_m, &(self.small_powers[n]))
584
+ elif n == self.prec_cap:
585
+ ZZ_to_mpz(self.temp_m, &self.top_power)
586
+ else:
587
+ sig_on()
588
+ # n may exceed self.prec_cap. Very large values can, however, lead to
589
+ # out-of-memory situations in the following computation. This
590
+ # sig_on()/sig_off() prevents sage from crashing in such cases.
591
+ # It does not have a significant impact on performance. For small
592
+ # values of n the powers are taken from self.small_powers, for large
593
+ # values, the computation dominates the cost of the sig_on()/sig_off().
594
+ mpz_pow_ui(self.temp_m, self.prime.value, n)
595
+ sig_off()
596
+ return self.temp_m
597
+
598
+ cdef ZZ_c* pow_ZZ_tmp(self, long n) except NULL:
599
+ """
600
+ Provides fast access to a ZZ_c* pointing to self.prime^n.
601
+
602
+ The location pointed to depends on the underlying
603
+ representation. The value pointed to may be an internal temporary
604
+ variable for the class. In particular, you should not try to
605
+ refer to the results of two pow_ZZ_tmp calls at the same time,
606
+ because the second call may overwrite the memory pointed to by
607
+ the first.
608
+
609
+ See pow_ZZ_tmp_demo for an example of this phenomenon.
610
+
611
+ EXAMPLES::
612
+
613
+ sage: PC = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5, 0, 1], 5^10), 'small', 'e',ntl.ZZ_pX([1],5^10))
614
+ sage: PC._pow_mpz_t_tmp_test(4) # indirect doctest
615
+ 625
616
+ """
617
+ if n < 0:
618
+ raise ValueError("n must be nonnegative")
619
+ if n <= self.cache_limit:
620
+ return &(self.small_powers[n])
621
+ if n == self.prec_cap:
622
+ return &self.top_power
623
+ ZZ_power(self.temp_z, self.small_powers[1], n)
624
+ return &self.temp_z
625
+
626
+ def _pow_ZZ_tmp_test(self, n):
627
+ """
628
+ Test the ``pow_ZZ_tmp`` function.
629
+
630
+ EXAMPLES::
631
+
632
+ sage: PC = PowComputer_ext_maker(5, 6, 6, 12, False, ntl.ZZ_pX([-5,0,1],5^6),'small', 'e',ntl.ZZ_pX([1],5^6))
633
+ sage: PC._pow_ZZ_tmp_test(4)
634
+ 625
635
+ sage: PC._pow_ZZ_tmp_test(7)
636
+ 78125
637
+ """
638
+ cdef Integer _n = Integer(n)
639
+ if _n < 0: raise ValueError
640
+ cdef ntl_ZZ ans = ntl_ZZ.__new__(ntl_ZZ)
641
+ ans.x = self.pow_ZZ_tmp(mpz_get_ui(_n.value))[0]
642
+ return ans
643
+
644
+ def _pow_ZZ_tmp_demo(self, m, n):
645
+ """
646
+ This function demonstrates a danger in using pow_ZZ_tmp.
647
+
648
+ EXAMPLES::
649
+
650
+ sage: PC = PowComputer_ext_maker(5, 5, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'big', 'e',ntl.ZZ_pX([1],5^10))
651
+
652
+ When you cal pow_ZZ_tmp with an input that is not stored
653
+ (ie n > self.cache_limit and n != self.prec_cap),
654
+ it stores the result in self.temp_z and returns a pointer
655
+ to that ZZ_c. So if you try to use the results of two
656
+ calls at once, things will break.
657
+ sage: PC._pow_ZZ_tmp_demo(6, 8) # 244140625 on some architectures and 152587890625 on others: random
658
+ 244140625
659
+ sage: 5^6*5^8
660
+ 6103515625
661
+ sage: 5^6*5^6
662
+ 244140625
663
+
664
+ Note that this does not occur if you try a stored value,
665
+ because the result of one of the calls points to that
666
+ stored value.
667
+ sage: PC._pow_ZZ_tmp_demo(6, 10)
668
+ 152587890625
669
+ sage: 5^6*5^10
670
+ 152587890625
671
+ """
672
+ m = Integer(m)
673
+ n = Integer(n)
674
+ if m < 0 or n < 0:
675
+ raise ValueError("m, n must be nonnegative")
676
+ cdef ntl_ZZ ans = ntl_ZZ.__new__(ntl_ZZ)
677
+ 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])
678
+ return ans
679
+
680
+ cdef mpz_srcptr pow_mpz_t_top(self) noexcept:
681
+ """
682
+ Return ``self.prime^self.prec_cap`` as an ``mpz_srcptr``.
683
+
684
+ EXAMPLES::
685
+
686
+ sage: PC = PowComputer_ext_maker(5, 6, 6, 12, False, ntl.ZZ_pX([-5,0,1],5^6),'small', 'e',ntl.ZZ_pX([1],5^6))
687
+ sage: PC._pow_mpz_t_top_test() # indirect doctest
688
+ 15625
689
+ """
690
+ ZZ_to_mpz(self.temp_m, &self.top_power)
691
+ return self.temp_m
692
+
693
+ cdef ZZ_c* pow_ZZ_top(self) noexcept:
694
+ """
695
+ Return ``self.prime^self.prec_cap`` as a ZZ_c.
696
+
697
+ EXAMPLES::
698
+
699
+ sage: PC = PowComputer_ext_maker(5, 6, 6, 12, False, ntl.ZZ_pX([-5,0,1],5^6),'small', 'e',ntl.ZZ_pX([1],5^6))
700
+ sage: PC._pow_ZZ_top_test() # indirect doctest
701
+ 15625
702
+ """
703
+ return &self.top_power
704
+
705
+ def _pow_ZZ_top_test(self):
706
+ """
707
+ Test the ``pow_ZZ_top`` function.
708
+
709
+ EXAMPLES::
710
+
711
+ sage: PC = PowComputer_ext_maker(5, 6, 6, 12, False, ntl.ZZ_pX([-5,0,1],5^6),'small', 'e',ntl.ZZ_pX([1],5^6))
712
+ sage: PC._pow_ZZ_top_test()
713
+ 15625
714
+ """
715
+ cdef ntl_ZZ ans = ntl_ZZ.__new__(ntl_ZZ)
716
+ ans.x = self.pow_ZZ_top()[0]
717
+ return ans
718
+
719
+ def _ram_prec_cap(self):
720
+ """
721
+ Return the precision cap of self, considered as a power of the uniformizer.
722
+
723
+ EXAMPLES::
724
+
725
+ sage: PC = PowComputer_ext_maker(5, 6, 6, 12, False, ntl.ZZ_pX([-5,0,1],5^5),'small', 'e',ntl.ZZ_pX([1],5^5))
726
+ sage: PC._ram_prec_cap()
727
+ 12
728
+ """
729
+ return self.ram_prec_cap
730
+
731
+ cdef class PowComputer_ZZ_pX(PowComputer_ext):
732
+ def __cinit__(self, Integer prime, long cache_limit, long prec_cap, long ram_prec_cap, bint in_field, poly, shift_seed=None):
733
+ """
734
+ Initialization.
735
+
736
+ For input types see :func:`PowComputer_ext_maker`
737
+
738
+ TESTS::
739
+
740
+ sage: PC = PowComputer_ext_maker(5, 5, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
741
+ sage: TestSuite(PC).run()
742
+ """
743
+ if not isinstance(poly, ntl_ZZ_pX):
744
+ raise TypeError
745
+ self.deg = ZZ_pX_deg((<ntl_ZZ_pX>poly).x)
746
+
747
+ def polynomial(self):
748
+ """
749
+ Return the polynomial (with coefficient precision prec_cap) associated
750
+ to this ``PowComputer``.
751
+
752
+ The polynomial is output as an ntl_ZZ_pX.
753
+
754
+ EXAMPLES::
755
+
756
+ sage: PC = PowComputer_ext_maker(5, 5, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
757
+ sage: PC.polynomial()
758
+ [9765620 0 1]
759
+ """
760
+ self.restore_top_context()
761
+ cdef ntl_ZZ_pX r = ntl_ZZ_pX.__new__(ntl_ZZ_pX)
762
+ r.c = self.get_top_context()
763
+ r.x = (self.get_top_modulus()[0]).val()
764
+ return r
765
+
766
+ cdef ntl_ZZ_pContext_class get_context(self, long n):
767
+ """
768
+ Return a ``ZZ_pContext`` for ``self.prime^(abs(n))``.
769
+
770
+ EXAMPLES::
771
+
772
+ sage: PC = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5, 0, 1], 5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
773
+ sage: PC._get_context_test(15) # indirect doctest
774
+ NTL modulus 30517578125
775
+ """
776
+ cdef ntl_ZZ pn = ntl_ZZ.__new__(ntl_ZZ)
777
+ if n < 0:
778
+ n = -n
779
+ elif n == 0:
780
+ # Exception will be ignored by Cython
781
+ raise ValueError("n must be nonzero")
782
+ pn.x = self.pow_ZZ_tmp(n)[0]
783
+ cdef ntl_ZZ_pContext_class context = (<ntl_ZZ_pContext_factory>ZZ_pContext_factory).make_c(pn)
784
+ return context
785
+
786
+ def _get_context_test(self, n):
787
+ """
788
+ Return a ``ZZ_pContext`` for ``self.prime^n``.
789
+
790
+ EXAMPLES::
791
+
792
+ sage: PC = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5, 0, 1], 5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
793
+ sage: PC._get_context_test(15)
794
+ NTL modulus 30517578125
795
+ """
796
+ cdef Integer _n = Integer(n)
797
+ return self.get_context(mpz_get_si(_n.value))
798
+
799
+ cdef ntl_ZZ_pContext_class get_context_capdiv(self, long n):
800
+ """
801
+ Return a ``ZZ_pContext`` for ``self.prime^((n-1) // self.e + 1)``.
802
+
803
+ For Eisenstein extensions this gives the context used for an
804
+ element of relative precision n.
805
+
806
+ EXAMPLES::
807
+
808
+ sage: PC = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5, 0, 1], 5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
809
+ sage: PC._get_context_capdiv_test(30) # indirect doctest
810
+ NTL modulus 30517578125
811
+ """
812
+ return self.get_context(self.capdiv(n))
813
+
814
+ def _get_context_capdiv_test(self, n):
815
+ """
816
+ Return a ``ZZ_pContext`` for ``self.prime^((n-1) // self.e + 1)``.
817
+
818
+ For Eisenstein extensions this gives the context used for an
819
+ element of relative precision n.
820
+
821
+ EXAMPLES::
822
+
823
+ sage: PC = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5, 0, 1], 5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
824
+ sage: PC._get_context_capdiv_test(29)
825
+ NTL modulus 30517578125
826
+ """
827
+ cdef Integer _n = Integer(n)
828
+ return self.get_context_capdiv(mpz_get_si(_n.value))
829
+
830
+ def speed_test(self, n, runs):
831
+ """
832
+ Run a speed test.
833
+
834
+ INPUT:
835
+
836
+ - ``n`` -- input to a function to be tested (the function needs to be
837
+ set in the source code)
838
+ - ``runs`` -- the number of runs of that function
839
+
840
+ OUTPUT:
841
+
842
+ - The time in seconds that it takes to call the function on ``n``,
843
+ ``runs`` times.
844
+
845
+ EXAMPLES::
846
+
847
+ sage: PC = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5, 0, 1], 5^10), 'small', 'e',ntl.ZZ_pX([1],5^10))
848
+ sage: PC.speed_test(10, 10^6) # random
849
+ 0.0090679999999991878
850
+ """
851
+ cdef Py_ssize_t i, end, _n
852
+ end = mpz_get_ui((<Integer>Integer(runs)).value)
853
+ _n = mpz_get_ui((<Integer>Integer(n)).value)
854
+ t = cputime()
855
+ for i in range(end):
856
+ # Put the function you want speed tested here.
857
+ self.get_modulus(_n)
858
+ return cputime(t)
859
+
860
+ cdef ntl_ZZ_pContext_class get_top_context(self):
861
+ """
862
+ Return a ``ZZ_pContext`` for ``self.prime^self.prec_cap``.
863
+
864
+ TESTS::
865
+
866
+ sage: PC = PowComputer_ext_maker(5, 5, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
867
+ sage: PC._get_top_context_test() # indirect doctest
868
+ NTL modulus 9765625
869
+ """
870
+ return self.get_context(self.prec_cap)
871
+
872
+ def _get_top_context_test(self):
873
+ """
874
+ Return a ``ZZ_pContext`` for ``self.prime^self.prec_cap``.
875
+
876
+ TESTS::
877
+
878
+ sage: PC = PowComputer_ext_maker(5, 5, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
879
+ sage: PC._get_top_context_test()
880
+ NTL modulus 9765625
881
+ """
882
+ return self.get_top_context()
883
+
884
+ cdef restore_context(self, long n):
885
+ """
886
+ Restore the contest corresponding to ``self.prime^n``.
887
+
888
+ EXAMPLES::
889
+
890
+ sage: PC = PowComputer_ext_maker(5, 5, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
891
+ sage: PC._restore_context_test(4) # indirect doctest
892
+ """
893
+ self.get_context(n).restore_c()
894
+
895
+ def _restore_context_test(self, n):
896
+ """
897
+ Restore the contest corresponding to ``self.prime^n``.
898
+
899
+ EXAMPLES::
900
+
901
+ sage: PC = PowComputer_ext_maker(5, 5, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
902
+ sage: PC._restore_context_test(4)
903
+ """
904
+ cdef Integer _n = Integer(n)
905
+ self.restore_context(mpz_get_si(_n.value))
906
+
907
+ cdef restore_context_capdiv(self, long n):
908
+ """
909
+ Restore the context for ``self.prime^((n-1) // self.e + 1)``.
910
+
911
+ EXAMPLES::
912
+
913
+ sage: PC = PowComputer_ext_maker(5, 5, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
914
+ sage: PC._restore_context_capdiv_test(4) # indirect doctest
915
+ """
916
+ self.restore_context(self.capdiv(n))
917
+
918
+ def _restore_context_capdiv_test(self, n):
919
+ """
920
+ Restore the context for ``self.prime^((n-1) // self.e + 1)``.
921
+
922
+ EXAMPLES::
923
+
924
+ sage: PC = PowComputer_ext_maker(5, 5, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
925
+ sage: PC._restore_context_capdiv_test(8) # indirect doctest
926
+ """
927
+ cdef Integer _n = Integer(n)
928
+ self.restore_context_capdiv(mpz_get_si(_n.value))
929
+
930
+ cdef void restore_top_context(self) noexcept:
931
+ """
932
+ Restore the context corresponding to ``self.prime^self.prec_cap``.
933
+
934
+ EXAMPLES::
935
+
936
+ sage: PC = PowComputer_ext_maker(5, 5, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
937
+ sage: PC._restore_top_context_test()
938
+ """
939
+ (<ntl_ZZ_pContext_class>self.get_top_context()).restore_c()
940
+
941
+ def _restore_top_context_test(self):
942
+ """
943
+ Restore the context corresponding to ``self.prime^self.prec_cap``.
944
+
945
+ EXAMPLES::
946
+
947
+ sage: PC = PowComputer_ext_maker(5, 5, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
948
+ sage: PC._restore_top_context_test()
949
+ """
950
+ self.restore_top_context()
951
+
952
+ cdef ZZ_pX_Modulus_c* get_modulus(self, long n) noexcept:
953
+ """
954
+ Return the modulus corresponding to ``self.polynomial()`` (mod
955
+ ``self.prime^n``).
956
+
957
+ EXAMPLES::
958
+
959
+ sage: A = PowComputer_ext_maker(5, 10, 1000, 2000, False, ntl.ZZ_pX([-5,0,1],5^1000), 'big', 'e',ntl.ZZ_pX([1],5^1000))
960
+ sage: a = ntl.ZZ_pX([4,2],5^2)
961
+ sage: b = ntl.ZZ_pX([6,3],5^2)
962
+ sage: A._get_modulus_test(a, b, 2) # indirect doctest
963
+ [4 24]
964
+ """
965
+ # Exception will be ignored by Cython
966
+ raise NotImplementedError
967
+
968
+ def _get_modulus_test(self, ntl_ZZ_pX a, ntl_ZZ_pX b, Integer n):
969
+ """
970
+ Multiply ``a`` and ``b`` modulo the modulus corresponding to
971
+ ``self.polynomial()`` (mod ``self.prime^n``).
972
+
973
+ EXAMPLES::
974
+
975
+ sage: A = PowComputer_ext_maker(5, 10, 1000, 2000, False, ntl.ZZ_pX([-5,0,1],5^1000), 'big', 'e',ntl.ZZ_pX([1],5^1000))
976
+ sage: a = ntl.ZZ_pX([4,2],5^2)
977
+ sage: b = ntl.ZZ_pX([6,3],5^2)
978
+ sage: A._get_modulus_test(a, b, 2)
979
+ [4 24]
980
+ sage: a * b
981
+ [24 24 6]
982
+ sage: mod(6 * 5 + 24, 25) # needs sage.rings.finite_rings
983
+ 4
984
+ """
985
+ if self.pow_Integer(mpz_get_si(n.value)) != Integer(a.c.p):
986
+ raise ValueError("a context mismatch")
987
+ if self.pow_Integer(mpz_get_si(n.value)) != Integer(b.c.p):
988
+ raise ValueError("b context mismatch")
989
+ cdef ntl_ZZ_pX r = (<ntl_ZZ_pX>a)._new()
990
+ cdef ntl_ZZ_pX aa = (<ntl_ZZ_pX>a)._new()
991
+ cdef ntl_ZZ_pX bb = (<ntl_ZZ_pX>b)._new()
992
+ ZZ_pX_rem(aa.x, a.x, self.get_modulus(mpz_get_si(n.value))[0].val())
993
+ ZZ_pX_rem(bb.x, b.x, self.get_modulus(mpz_get_si(n.value))[0].val())
994
+ ZZ_pX_MulMod_pre(r.x, aa.x, bb.x, self.get_modulus(mpz_get_si(n.value))[0])
995
+ return r
996
+
997
+ cdef ZZ_pX_Modulus_c* get_modulus_capdiv(self, long n) noexcept:
998
+ """
999
+ Return the modulus corresponding to ``self.polynomial()`` (mod
1000
+ ``self.prime^((n-1) // self.e + 1``).
1001
+ """
1002
+ return self.get_modulus(self.capdiv(n))
1003
+
1004
+ cdef ZZ_pX_Modulus_c* get_top_modulus(self) noexcept:
1005
+ """
1006
+ Return the modulus corresponding to ``self.polynomial()`` (mod
1007
+ ``self.prime^self.prec_cap``).
1008
+
1009
+ EXAMPLES::
1010
+
1011
+ sage: A = PowComputer_ext_maker(5, 3, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
1012
+ sage: a = ntl.ZZ_pX([129223,1231],5^10)
1013
+ sage: b = ntl.ZZ_pX([289741,323],5^10)
1014
+ sage: A._get_top_modulus_test(a, b) # indirect doctest
1015
+ [1783058 7785200]
1016
+ """
1017
+ # Exception will be ignored by Cython
1018
+ raise NotImplementedError
1019
+
1020
+ def _get_top_modulus_test(self, ntl_ZZ_pX a, ntl_ZZ_pX b):
1021
+ """
1022
+ Multiply ``a`` and ``b`` modulo the modulus corresponding to
1023
+ ``self.polynomial()`` (mod ``self.prime^self.prec_cap``).
1024
+
1025
+ EXAMPLES::
1026
+
1027
+ sage: A = PowComputer_ext_maker(5, 3, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
1028
+ sage: a = ntl.ZZ_pX([129223,1231],5^10)
1029
+ sage: b = ntl.ZZ_pX([289741,323],5^10)
1030
+ sage: A._get_top_modulus_test(a, b)
1031
+ [1783058 7785200]
1032
+ sage: a*b
1033
+ [9560618 7785200 397613]
1034
+ sage: mod(397613 * 5 + 9560618, 5^10) # needs sage.rings.finite_rings
1035
+ 1783058
1036
+ """
1037
+ cdef ntl_ZZ_pX ans = a._new()
1038
+ ZZ_pX_MulMod_pre(ans.x, a.x, b.x, self.get_top_modulus()[0])
1039
+ return ans
1040
+
1041
+ cdef long capdiv(self, long n) noexcept:
1042
+ """
1043
+ If n >= 0 returns ceil(n / self.e)
1044
+
1045
+ If n < 0 returns ceil(-n / self.e)
1046
+
1047
+ EXAMPLES::
1048
+
1049
+ sage: PC = PowComputer_ext_maker(5, 3, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
1050
+ sage: PC._capdiv_test(15)
1051
+ 8
1052
+ sage: PC._capdiv_test(-7)
1053
+ 4
1054
+ """
1055
+ if self.e == 1:
1056
+ return n
1057
+ if n > 0:
1058
+ return (n-1) / self.e + 1
1059
+ elif n < 0:
1060
+ return (-1-n) / self.e + 1
1061
+ else:
1062
+ return 0
1063
+
1064
+ def _capdiv_test(self, n):
1065
+ """
1066
+ If n >= 0, return ceil(n / self.e).
1067
+
1068
+ If n < 0, return ceil(-n / self.e).
1069
+
1070
+ EXAMPLES::
1071
+
1072
+ sage: PC = PowComputer_ext_maker(5, 3, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
1073
+ sage: PC._capdiv_test(15)
1074
+ 8
1075
+ sage: PC._capdiv_test(-7)
1076
+ 4
1077
+ """
1078
+ cdef Integer _n = Integer(n)
1079
+ cdef Integer ans = Integer.__new__(Integer)
1080
+ mpz_set_si(ans.value, self.capdiv(mpz_get_si(_n.value)))
1081
+ return ans
1082
+
1083
+ cdef int eis_shift(self, ZZ_pX_c* x, ZZ_pX_c* a, long n, long finalprec) except -1:
1084
+ raise NotImplementedError
1085
+
1086
+ cdef int eis_shift_capdiv(self, ZZ_pX_c* x, ZZ_pX_c* a, long n, long finalprec) except -1:
1087
+ return self.eis_shift(x, a, n, self.capdiv(finalprec))
1088
+
1089
+ cdef int teichmuller_set_c (self, ZZ_pX_c* x, ZZ_pX_c* a, long absprec) except -1:
1090
+ r"""
1091
+ Set `x` to the Teichmuller lift congruent to a modulo the
1092
+ uniformizer, ie such that `x = a \mod \pi` and
1093
+ `x^q = x \mod \pi^{\mbox{absprec}}`.
1094
+
1095
+ If `a = 0 \mod \pi` this function does nothing and returns 1.
1096
+ Otherwise returns 0.
1097
+
1098
+ `x` should be created with context p^absprec.
1099
+
1100
+ Does not affect ``self``.
1101
+
1102
+ INPUT:
1103
+
1104
+ - ``x`` -- the ``ZZ_pX_c`` to be set
1105
+
1106
+ - ``a`` -- a ``ZZ_pX_c`` ``currently holding an approximation to the
1107
+ Teichmuller representative (this approximation can be any
1108
+ integer). It will be set to the actual Teichmuller lift.
1109
+
1110
+ - ``absprec`` -- the desired precision of the Teichmuller lift
1111
+
1112
+ OUTPUT:
1113
+
1114
+ - 1 -- `x` should be set to zero
1115
+ - 0 -- normal
1116
+
1117
+ EXAMPLES::
1118
+
1119
+ sage: R = Zp(17,5)
1120
+ sage: S.<x> = R[]
1121
+ sage: f = x^5 + 34*x^3 - 17*x^2 +289*x - 17
1122
+ sage: W.<w> = R.ext(f)
1123
+ sage: y = W.teichmuller(3,10); y
1124
+ 3 + 13*w^5 + 4*w^7 + 9*w^8 + 13*w^9 + O(w^10)
1125
+ sage: y^17 == y
1126
+ True
1127
+ sage: g = x^3 + 9*x^2 + 1
1128
+ sage: A.<a> = R.ext(g)
1129
+ sage: b = A.teichmuller(1 + 2*a - a^2, 3); b
1130
+ (16*a^2 + 2*a + 1) + (4*a^2 + 5*a + 3)*17 + (10*a^2 + 15*a + 11)*17^2 + O(17^3)
1131
+ sage: b^(17^3) == b
1132
+ True
1133
+ """
1134
+ cdef mpz_t u, xnew, value
1135
+ cdef ZZ_c tmp, q, u_q
1136
+ cdef ZZ_pX_c xnew_q
1137
+ cdef ntl_ZZ_pContext_class c
1138
+ cdef long mini = 0, minval = 0
1139
+ if absprec == 0:
1140
+ return 1
1141
+ if absprec < 0:
1142
+ absprec = -absprec
1143
+ if self.e != 1:
1144
+ mpz_init(value)
1145
+ tmp = ZZ_p_rep(ZZ_pX_ConstTerm(a[0]))
1146
+ ZZ_to_mpz(value, &tmp)
1147
+ if mpz_divisible_p(value, self.prime.value) != 0:
1148
+ mpz_clear(value)
1149
+ return 1
1150
+ self.pow_mpz_t_tmp(self.capdiv(absprec)) # sets self.temp_m
1151
+ if mpz_sgn(value) < 0 or mpz_cmp(value, self.temp_m) >= 0:
1152
+ mpz_mod(value, value, self.temp_m)
1153
+ mpz_init(u)
1154
+ mpz_init(xnew)
1155
+ # u = 1 / Mod(1 - p, self.temp_m)
1156
+ mpz_sub(u, self.temp_m, self.prime.value)
1157
+ mpz_add_ui(u, u, 1)
1158
+ mpz_invert(u, u, self.temp_m)
1159
+ # Consider x as Mod(self.value, self.temp_m)
1160
+ # xnew = x + u*(x^p - x)
1161
+ mpz_powm(xnew, value, self.prime.value, self.temp_m)
1162
+ mpz_sub(xnew, xnew, value)
1163
+ mpz_mul(xnew, xnew, u)
1164
+ mpz_add(xnew, xnew, value)
1165
+ mpz_mod(xnew, xnew, self.temp_m)
1166
+ # while x != xnew:
1167
+ # x = xnew
1168
+ # xnew = x + u*(x^p - x)
1169
+ while mpz_cmp(value, xnew) != 0:
1170
+ mpz_set(value, xnew)
1171
+ mpz_powm(xnew, value, self.prime.value, self.temp_m)
1172
+ mpz_sub(xnew, xnew, value)
1173
+ mpz_mul(xnew, xnew, u)
1174
+ mpz_add(xnew, xnew, value)
1175
+ mpz_mod(xnew, xnew, self.temp_m)
1176
+ mpz_clear(u)
1177
+ mpz_clear(xnew)
1178
+ mpz_to_ZZ(&tmp, value)
1179
+ self.restore_context_capdiv(absprec)
1180
+ if ZZ_pX_IsZero(x[0]): # shortcut for the case x = 0
1181
+ ZZ_pX_SetCoeff(x[0], 0, ZZ_to_ZZ_p(tmp))
1182
+ else:
1183
+ ZZ_pX_SetX(x[0])
1184
+ ZZ_pX_SetCoeff(x[0], 0, ZZ_to_ZZ_p(tmp))
1185
+ ZZ_pX_SetCoeff_long(x[0], 1, 0)
1186
+ mpz_clear(value)
1187
+ else:
1188
+ c = self.get_context(absprec)
1189
+ c.restore_c()
1190
+ q = self.pow_ZZ_tmp(self.f)[0]
1191
+ ZZ_pX_min_val_coeff(minval, mini, a[0], self.pow_ZZ_tmp(1)[0])
1192
+ if mini == -1 or minval > 0:
1193
+ return 1
1194
+ ZZ_pX_conv_modulus(x[0], a[0], c.x)
1195
+ # u = 1 / Mod(1 - q, p^absprec)
1196
+ ZZ_conv_from_long(u_q, 1)
1197
+ ZZ_sub(u_q, u_q, q)
1198
+ ZZ_rem(u_q, u_q, (<ntl_ZZ>c.p).x)
1199
+ ZZ_InvMod(u_q, u_q, (<ntl_ZZ>c.p).x)
1200
+ # xnew = x + u*(x^q - x)
1201
+ ZZ_pX_PowerMod_pre(xnew_q, x[0], q, self.get_modulus(absprec)[0])
1202
+ ZZ_pX_sub(xnew_q, xnew_q, x[0])
1203
+ ZZ_pX_mul_ZZ_p(xnew_q, xnew_q, ZZ_to_ZZ_p(u_q))
1204
+ ZZ_pX_add(xnew_q, xnew_q, x[0])
1205
+ # while x != xnew:
1206
+ # x = xnew
1207
+ # xnew = x + u*(x^q - x)
1208
+ while x[0] != xnew_q:
1209
+ x[0] = xnew_q
1210
+ ZZ_pX_PowerMod_pre(xnew_q, x[0], q, self.get_modulus(absprec)[0])
1211
+ ZZ_pX_sub(xnew_q, xnew_q, x[0])
1212
+ ZZ_pX_mul_ZZ_p(xnew_q, xnew_q, ZZ_to_ZZ_p(u_q))
1213
+ ZZ_pX_add(xnew_q, xnew_q, x[0])
1214
+ return 0
1215
+
1216
+
1217
+ cdef class PowComputer_ZZ_pX_FM(PowComputer_ZZ_pX):
1218
+ r"""
1219
+ This class only caches a context and modulus for p^prec_cap.
1220
+
1221
+ Designed for use with fixed modulus `p`-adic rings, in Eisenstein
1222
+ and unramified extensions of `\ZZ_p`.
1223
+ """
1224
+
1225
+ def __cinit__(self, Integer prime, long cache_limit, long prec_cap, long ram_prec_cap, bint in_field, poly, shift_seed=None):
1226
+ """
1227
+ Caches a context and modulus for ``prime^prec_cap``.
1228
+
1229
+ EXAMPLES::
1230
+
1231
+ sage: A = PowComputer_ext_maker(5, 3, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10)) # indirect doctest
1232
+ sage: A
1233
+ PowComputer_ext for 5, with polynomial [9765620 0 1]
1234
+ """
1235
+
1236
+ # The __new__ method for PowComputer_ext has already run, so we have access to small_powers, top_power.
1237
+
1238
+ # We use ntl_ZZ_pContexts so that contexts are cached centrally.
1239
+
1240
+ self._prec_type = 'FM'
1241
+ self._ext_type = 'u'
1242
+ self.c = self.get_context(prec_cap)
1243
+ self.c.restore_c()
1244
+ # For now, we don't do anything complicated with poly
1245
+ if isinstance(poly, ntl_ZZ_pX) and (<ntl_ZZ_pX>poly).c is self.c:
1246
+ ZZ_pX_Modulus_build(self.mod, (<ntl_ZZ_pX>poly).x)
1247
+ if prec_cap == ram_prec_cap:
1248
+ self.e = 1
1249
+ self.f = ZZ_pX_deg((<ntl_ZZ_pX>poly).x)
1250
+ else:
1251
+ self.e = ZZ_pX_deg((<ntl_ZZ_pX>poly).x)
1252
+ self.f = 1
1253
+ self.ram_prec_cap = ram_prec_cap
1254
+ else:
1255
+ raise NotImplementedError("NOT IMPLEMENTED IN PowComputer_ZZ_pX_FM")
1256
+
1257
+ cdef ntl_ZZ_pContext_class get_top_context(self):
1258
+ """
1259
+ Return a ``ZZ_pContext`` for ``self.prime^self.prec_cap``.
1260
+
1261
+ EXAMPLES::
1262
+
1263
+ sage: PC = PowComputer_ext_maker(5, 5, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
1264
+ sage: PC._get_top_context_test() # indirect doctest
1265
+ NTL modulus 9765625
1266
+ """
1267
+ return self.c
1268
+
1269
+ cdef void restore_top_context(self) noexcept:
1270
+ """
1271
+ Restore the context corresponding to ``self.prime^self.prec_cap``.
1272
+
1273
+ EXAMPLES::
1274
+
1275
+ sage: PC = PowComputer_ext_maker(5, 5, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
1276
+ sage: PC._restore_top_context_test() # indirect doctest
1277
+ """
1278
+ self.c.restore_c()
1279
+
1280
+ cdef ZZ_pX_Modulus_c* get_top_modulus(self) noexcept:
1281
+ """
1282
+ Return the modulus corresponding to ``self.polynomial()``
1283
+ (mod ``self.prime^self.prec_cap``).
1284
+
1285
+ EXAMPLES::
1286
+
1287
+ sage: A = PowComputer_ext_maker(5, 3, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
1288
+ sage: a = ntl.ZZ_pX([129223,1231],5^10)
1289
+ sage: b = ntl.ZZ_pX([289741,323],5^10)
1290
+ sage: A._get_top_modulus_test(a, b) # indirect doctest
1291
+ [1783058 7785200]
1292
+ """
1293
+ return &self.mod
1294
+
1295
+ cdef ZZ_pX_Modulus_c* get_modulus(self, long n) noexcept:
1296
+ """
1297
+ Duplicates functionality of get_top_modulus if n == self.prec_cap.
1298
+
1299
+ If not, raise an exception (which will be ignored by Cython).
1300
+
1301
+ EXAMPLES::
1302
+
1303
+ sage: A = PowComputer_ext_maker(5, 3, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
1304
+ sage: a = ntl.ZZ_pX([129223,1231],5^10)
1305
+ sage: b = ntl.ZZ_pX([289741,323],5^10)
1306
+ sage: A._get_modulus_test(a, b, 10) # indirect doctest
1307
+ [1783058 7785200]
1308
+ """
1309
+ if n == self.prec_cap:
1310
+ return &self.mod
1311
+ else:
1312
+ # Exception will be ignored by Cython
1313
+ raise ValueError("fixed modulus PowComputers only store top modulus")
1314
+
1315
+ cdef class PowComputer_ZZ_pX_FM_Eis(PowComputer_ZZ_pX_FM):
1316
+ """
1317
+ This class computes and stores ``low_shifter`` and ``high_shifter``, which aid in right shifting elements.
1318
+ """
1319
+
1320
+ def __cinit__(self, Integer prime, long cache_limit, long prec_cap, long ram_prec_cap, bint in_field, poly, shift_seed=None):
1321
+ """
1322
+ Call ``Eis_init``, which initializes ``high_shifter`` and
1323
+ ``low_shifter``.
1324
+
1325
+ TESTS::
1326
+
1327
+ sage: A = PowComputer_ext_maker(5, 3, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10)) # indirect doctest
1328
+ """
1329
+ # The __new__ method for PowComputer_ZZ_pX_FM has already run, so we have access to self.mod
1330
+ self._ext_type = 'e'
1331
+ if not isinstance(shift_seed, ntl_ZZ_pX):
1332
+ raise TypeError("shift_seed must be an ntl_ZZ_pX")
1333
+ ZZ_pX_Eis_init(self, <ntl_ZZ_pX>shift_seed)
1334
+
1335
+ def _low_shifter(self, i):
1336
+ """
1337
+ Accessor function for low_shifter, which are the polynomials used to shift right.
1338
+
1339
+ If low_length is the number of low_shifters, then:
1340
+ * if deg = 2, low_length = 1 (store p/x)
1341
+ * if deg = 3,4, low_length = 2 (store p/x, p/x^2)
1342
+ * if deg = 5,6,7,8, low_length = 3 (store p/x, p/x^2, p/x^4)
1343
+ * if deg = 9,...,16, low_length = 4 (store p/x, p/x^2, p/x^4, p/x^8)
1344
+
1345
+ These polynomials are used to shift by amounts less than the degree of the defining polynomial.
1346
+
1347
+ EXAMPLES::
1348
+
1349
+ sage: A = PowComputer_ext_maker(5, 3, 10, 40, False, ntl.ZZ_pX([-5,75,15,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1,-15,-3],5^10))
1350
+ sage: A._low_shifter(0)
1351
+ [75 15 0 1]
1352
+
1353
+ Note that if we multiply this by x and reduce using the relation that x^4 = 5 - 75x - 15x^2, we just get 5.
1354
+
1355
+ sage: A._low_shifter(1)
1356
+ [1140 225 1 15]
1357
+
1358
+ This one's a bit less obvious, but if we multiply by x^2, we get 5 (modulo x^4 = 5 - 75x - 15x^2).
1359
+ """
1360
+ cdef long _i = i
1361
+ cdef ntl_ZZ_pX ans
1362
+ if _i >= 0 and _i < self.low_length:
1363
+ ans = ntl_ZZ_pX([], self.get_top_context())
1364
+ ans.x = self.low_shifter[i].val()
1365
+ return ans
1366
+ else:
1367
+ raise IndexError
1368
+
1369
+ def _high_shifter(self, i):
1370
+ """
1371
+ Accessor function for high_shifter, which are the polynomials used to shift right.
1372
+
1373
+ If high_length is the number of high_shifters, then:
1374
+ * if prec_cap = 2, high_length = 1 (store p/x^e)
1375
+ * if prec_cap = 3,4, high_length = 2 (store p/x^e, p^2/x^(2e))
1376
+ * if prec_cap = 5,6,7,8, high_length = 3 (store p/x^e, p^2/x^(2e), p^4/x^(4e))
1377
+ * if prec_cap = 9,...,16, high_length = 4 (store p/x, p^2/x^(2e), p^4/x^(4e), p^8/x^(8e))
1378
+
1379
+ These polynomials are used to shift by amounts greater than the degree of the defining polynomial, but less than e*prec_cap.
1380
+
1381
+ EXAMPLES::
1382
+
1383
+ sage: A = PowComputer_ext_maker(5, 3, 10, 40, False, ntl.ZZ_pX([-5,75,15,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1,-15,-3],5^10))
1384
+ sage: A._high_shifter(0)
1385
+ [263296 51990 228 3465]
1386
+
1387
+ If we take this and multiply by x^4, and reduce modulo x^4 + 15*x^2 + 75*x - 5, we should get 5.::
1388
+
1389
+ sage: R.<x> = ZZ[]
1390
+ sage: f = 263296 + 51990*x + 228*x^2 + 3465*x^3
1391
+ sage: g = x^4 + 15*x^2 + 75*x - 5
1392
+ sage: f*x^4 % g
1393
+ 5
1394
+
1395
+ sage: A._high_shifter(1)
1396
+ [1420786 9298230 2217816 6212495]
1397
+
1398
+ Similarly::
1399
+
1400
+ sage: f = 1420786 + 9298230*x + 2217816*x^2 + 6212495*x^3
1401
+ sage: h = f*x^8 % g; h
1402
+ -1328125000000*x^3 + 2962646484375*x^2 + 22094970703125*x - 1466308593725
1403
+
1404
+ Here, we need to remember that we're working modulo 5^10::
1405
+
1406
+ sage: h[0].valuation(5), h[1].valuation(5), h[2].valuation(5), h[3].valuation(5)
1407
+ (2, 12, 13, 13)
1408
+ sage: (h[0] - 25).valuation(5)
1409
+ 12
1410
+ """
1411
+ cdef long _i = i
1412
+ cdef ntl_ZZ_pX ans
1413
+ if _i >= 0 and _i < self.high_length:
1414
+ ans = ntl_ZZ_pX([], self.get_top_context())
1415
+ ans.x = self.high_shifter[i].val()
1416
+ return ans
1417
+ else:
1418
+ raise IndexError
1419
+
1420
+ def __dealloc__(self):
1421
+ """
1422
+ Deallocate ``low_shifter`` and ``high_shifter``.
1423
+
1424
+ TESTS::
1425
+
1426
+ sage: A = PowComputer_ext_maker(5, 3, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
1427
+ sage: del A # indirect doctest
1428
+ """
1429
+ if self._initialized:
1430
+ self.cleanup_ZZ_pX_FM_Eis()
1431
+
1432
+ cdef void cleanup_ZZ_pX_FM_Eis(self) noexcept:
1433
+ """
1434
+ Do the actual work of deallocating ``low_shifter`` and
1435
+ ``high_shifter``.
1436
+
1437
+ TESTS::
1438
+
1439
+ sage: A = PowComputer_ext_maker(5, 3, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
1440
+ sage: del A # indirect doctest
1441
+ """
1442
+ Delete_ZZ_pX_Multiplier_array(self.low_shifter)
1443
+ Delete_ZZ_pX_Multiplier_array(self.high_shifter)
1444
+
1445
+ cdef int eis_shift(self, ZZ_pX_c* x, ZZ_pX_c* a, long n, long finalprec) except -1:
1446
+ """
1447
+ Shift ``a`` right ``n`` pi-adic digits, where pi is considered modulo
1448
+ the polynomial in ``self``.
1449
+
1450
+ Puts the result in ``x``.
1451
+
1452
+ EXAMPLES::
1453
+
1454
+ sage: from sage.rings.padics.pow_computer_ext import ZZ_pX_eis_shift_test
1455
+ sage: A = PowComputer_ext_maker(5, 3, 10, 40, False, ntl.ZZ_pX([-5,75,15,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1,-15,-3],5^10))
1456
+ sage: ZZ_pX_eis_shift_test(A, [0, 1], 1, 5) # indirect doctest
1457
+ [1]
1458
+ sage: ZZ_pX_eis_shift_test(A, [0, 0, 1], 1, 5)
1459
+ [0 1]
1460
+ sage: ZZ_pX_eis_shift_test(A, [5], 1, 5)
1461
+ [75 15 0 1]
1462
+ sage: ZZ_pX_eis_shift_test(A, [1], 1, 5)
1463
+ []
1464
+ sage: ZZ_pX_eis_shift_test(A, [17, 91, 8, -2], 1, 5)
1465
+ [316 53 3123 3]
1466
+ sage: ZZ_pX_eis_shift_test(A, [316, 53, 3123, 3], -1, 5)
1467
+ [15 91 8 3123]
1468
+ sage: ZZ_pX_eis_shift_test(A, [15, 91, 8, 3123], 1, 5)
1469
+ [316 53 3123 3]
1470
+ """
1471
+ return ZZ_pX_eis_shift_p(self, x, a, n, finalprec)
1472
+
1473
+ # cdef ZZ_pX_c low_part
1474
+ # cdef ZZ_pX_c shifted_high_part
1475
+ # cdef ZZ_pX_c high_shifter
1476
+
1477
+ # ##cdef ntl_ZZ_pX printer
1478
+ # if n < 0:
1479
+ # self.restore_top_context()
1480
+ # ##printer = ntl_ZZ_pX([],self.get_top_context())
1481
+ # ZZ_pX_PowerXMod_long_pre(high_shifter, -n, self.get_top_modulus()[0])
1482
+ # ##printer.x = high_shifter
1483
+ # ZZ_pX_MulMod_pre(x[0],high_shifter,a[0],self.get_top_modulus()[0])
1484
+ # ##printer.x = x[0]
1485
+ # return 0
1486
+ # elif n == 0:
1487
+ # if x != a:
1488
+ # x[0] = a[0]
1489
+ # return 0
1490
+ # cdef long pshift = n / self.e
1491
+ # cdef long eis_part = n % self.e
1492
+ # cdef long two_shift = 1
1493
+ # cdef int i
1494
+
1495
+ # ##printer = ntl_ZZ_pX([],self.get_top_context())
1496
+ # if x != a:
1497
+ # x[0] = a[0]
1498
+ # ##printer.x = a[0]
1499
+ # if pshift:
1500
+ # i = 0
1501
+ # # This line restores the top context
1502
+ # ZZ_pX_right_pshift(x[0], x[0], self.pow_ZZ_tmp(pshift)[0], self.get_top_context().x)
1503
+ # ##printer.x = x[0]
1504
+ # if pshift >= self.prec_cap:
1505
+ # # high_shifter = p^(2^(high_length - 1))/x^(e*2^(high_length - 1))
1506
+ # # if val = r + s * 2^(high_length - 1)
1507
+ # # then high_shifter = p^(s*2^(high_length - 1))/x^(e*s*2^(high_length - 1))
1508
+ # ZZ_pX_PowerMod_long_pre(high_shifter, self.high_shifter[self.high_length-1].val(), (pshift / (1L << (self.high_length - 1))), self.get_top_modulus()[0])
1509
+ # ##printer.x = high_shifter
1510
+ # ZZ_pX_MulMod_pre(x[0], x[0], high_shifter, self.get_top_modulus()[0])
1511
+ # ##printer.x = high_shifter
1512
+ # # Now we only need to multiply self.unit by p^r/x^(e*r) where r < 2^(high_length - 1), which is tractible.
1513
+ # pshift = pshift % (1L << (self.high_length - 1))
1514
+ # while pshift > 0:
1515
+ # if pshift & 1:
1516
+ # ##printer.x = x[0]
1517
+ # ZZ_pX_MulMod_premul(x[0], x[0], self.high_shifter[i], self.get_top_modulus()[0])
1518
+ # i += 1
1519
+ # pshift = pshift >> 1
1520
+ # else:
1521
+ # self.restore_top_context()
1522
+ # i = 0
1523
+ # two_shift = 1
1524
+ # while eis_part > 0:
1525
+ # if eis_part & 1:
1526
+ # ZZ_pX_RightShift(shifted_high_part, x[0], two_shift)
1527
+ # ##printer.x = shifted_high_part
1528
+ # ZZ_pX_LeftShift(low_part, shifted_high_part, two_shift)
1529
+ # ZZ_pX_sub(low_part, x[0], low_part)
1530
+ # ##printer.x = low_part
1531
+ # ZZ_pX_right_pshift(low_part, low_part, self.pow_ZZ_tmp(1)[0], self.get_top_context().x)
1532
+ # ##printer.x = low_part
1533
+ # ZZ_pX_MulMod_premul(low_part, low_part, self.low_shifter[i], self.get_top_modulus()[0])
1534
+ # ##printer.x = low_part
1535
+ # ZZ_pX_add(x[0], low_part, shifted_high_part)
1536
+ # ##printer.x = x[0]
1537
+ # i += 1
1538
+ # two_shift = two_shift << 1
1539
+ # eis_part = eis_part >> 1
1540
+
1541
+ cdef class PowComputer_ZZ_pX_small(PowComputer_ZZ_pX):
1542
+ """
1543
+ This class caches contexts and moduli densely between 1 and cache_limit. It requires cache_limit == prec_cap.
1544
+
1545
+ It is intended for use with capped relative and capped absolute rings and fields, in Eisenstein and unramified
1546
+ extensions of the base `p`-adic fields.
1547
+ """
1548
+
1549
+ def __cinit__(self, Integer prime, long cache_limit, long prec_cap, long ram_prec_cap, bint in_field, poly, shift_seed=None):
1550
+ """
1551
+ Caches contexts and moduli densely between 1 and cache_limit.
1552
+
1553
+ EXAMPLES::
1554
+
1555
+ sage: A = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'small', 'e',ntl.ZZ_pX([1],5^10)) # indirect doctest
1556
+ sage: A
1557
+ PowComputer_ext for 5, with polynomial [9765620 0 1]
1558
+ """
1559
+ # The __new__ method for PowComputer_ext has already run, so we have access to small_powers, top_power.
1560
+
1561
+ # We use ntl_ZZ_pContexts so that contexts are cached centrally.
1562
+
1563
+ self._prec_type = 'small'
1564
+ self._ext_type = 'u'
1565
+ if not isinstance(poly, ntl_ZZ_pX):
1566
+ self.cleanup_ext()
1567
+ raise TypeError
1568
+
1569
+ if cache_limit != prec_cap:
1570
+ self.cleanup_ext()
1571
+ raise ValueError("prec_cap and cache_limit must be equal in the small case")
1572
+
1573
+ self.c = []
1574
+ # We cache from 0 to cache_limit inclusive, and provide one extra slot to return moduli above the cache_limit
1575
+ sig_on()
1576
+ self.mod = Allocate_ZZ_pX_Modulus_array(cache_limit + 2)
1577
+ sig_off()
1578
+ if self.mod == NULL:
1579
+ self.cleanup_ext()
1580
+ raise MemoryError("out of memory allocating moduli")
1581
+
1582
+ cdef Py_ssize_t i
1583
+ cdef ZZ_pX_c tmp, pol
1584
+ if isinstance(poly, ntl_ZZ_pX):
1585
+ pol = (<ntl_ZZ_pX>poly).x
1586
+ self.c.append(None)
1587
+ for i in range(1, cache_limit + 1):
1588
+ self.c.append(PowComputer_ZZ_pX.get_context(self,i))
1589
+
1590
+ # create a temporary polynomial with the highest modulus to
1591
+ # ensure all mod[i]'s will fit into it
1592
+ (<ntl_ZZ_pContext_class>self.c[cache_limit]).restore_c()
1593
+ tmp = (<ntl_ZZ_pX>poly).x
1594
+
1595
+ for i in range(1, cache_limit + 1):
1596
+ (<ntl_ZZ_pContext_class>self.c[i]).restore_c()
1597
+ ZZ_pX_conv_modulus(tmp, pol, (<ntl_ZZ_pContext_class>self.c[i]).x)
1598
+ ZZ_pX_Modulus_build(self.mod[i], tmp)
1599
+ if prec_cap == ram_prec_cap:
1600
+ self.e = 1
1601
+ self.f = ZZ_pX_deg((<ntl_ZZ_pX>poly).x)
1602
+ else:
1603
+ self.e = ZZ_pX_deg((<ntl_ZZ_pX>poly).x)
1604
+ self.f = 1
1605
+ self.ram_prec_cap = ram_prec_cap
1606
+ else:
1607
+ raise NotImplementedError("NOT IMPLEMENTED IN PowComputer_ZZ_pX_FM")
1608
+
1609
+ def __dealloc__(self):
1610
+ """
1611
+ Deallocate cache of contexts, moduli.
1612
+
1613
+ EXAMPLES::
1614
+
1615
+ sage: A = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'small','e',ntl.ZZ_pX([1],5^10))
1616
+ sage: del A # indirect doctest
1617
+ """
1618
+ if self._initialized:
1619
+ self.cleanup_ZZ_pX_small()
1620
+
1621
+ cdef void cleanup_ZZ_pX_small(self) noexcept:
1622
+ """
1623
+ Deallocate cache of contexts, moduli.
1624
+
1625
+ EXAMPLES::
1626
+
1627
+ sage: A = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'small','e',ntl.ZZ_pX([1],5^10))
1628
+ sage: del A # indirect doctest
1629
+ """
1630
+ Delete_ZZ_pX_Modulus_array(self.mod)
1631
+
1632
+ cdef ntl_ZZ_pContext_class get_context(self, long n):
1633
+ """
1634
+ Return the context for p^n. This will use the cache if
1635
+ ``abs(n) <= self.cache_limit``.
1636
+
1637
+ INPUT:
1638
+
1639
+ - ``n`` -- nonzero long
1640
+
1641
+ OUTPUT: a context for p^n
1642
+
1643
+ EXAMPLES::
1644
+
1645
+ sage: A = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'small','e',ntl.ZZ_pX([1],5^10))
1646
+ sage: A._get_context_test(4) # indirect doctest
1647
+ NTL modulus 625
1648
+ """
1649
+ if n < 0:
1650
+ n = -n
1651
+ try:
1652
+ return self.c[n]
1653
+ except IndexError:
1654
+ return PowComputer_ZZ_pX.get_context(self, n)
1655
+
1656
+ cdef restore_context(self, long n):
1657
+ """
1658
+ Restore the context for p^n. This will use the cache if
1659
+ ``abs(n) <= self.cache_limit``.
1660
+
1661
+ INPUT:
1662
+
1663
+ - ``n`` -- nonzero long
1664
+
1665
+ EXAMPLES::
1666
+
1667
+ sage: A = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'small','e',ntl.ZZ_pX([1],5^10))
1668
+ sage: A._restore_context_test(4) # indirect doctest
1669
+ """
1670
+ if n < 0:
1671
+ n = -n
1672
+ try:
1673
+ (<ntl_ZZ_pContext_class>self.c[n]).restore_c()
1674
+ except IndexError:
1675
+ (<ntl_ZZ_pContext_class>PowComputer_ZZ_pX.get_context(self, n)).restore_c()
1676
+
1677
+ cdef ntl_ZZ_pContext_class get_top_context(self):
1678
+ """
1679
+ Return a ``ZZ_pContext`` for ``self.prime^self.prec_cap``.
1680
+
1681
+ EXAMPLES::
1682
+
1683
+ sage: PC = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'small','e',ntl.ZZ_pX([1],5^10))
1684
+ sage: PC._get_top_context_test() # indirect doctest
1685
+ NTL modulus 9765625
1686
+ """
1687
+ return self.c[self.prec_cap]
1688
+
1689
+ cdef void restore_top_context(self) noexcept:
1690
+ """
1691
+ Restore the context corresponding to ``self.prime^self.prec_cap``.
1692
+
1693
+ EXAMPLES::
1694
+
1695
+ sage: PC = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'small','e',ntl.ZZ_pX([1],5^10))
1696
+ sage: PC._restore_top_context_test() # indirect doctest
1697
+ """
1698
+ (<ntl_ZZ_pContext_class>self.c[self.prec_cap]).restore_c()
1699
+
1700
+ cdef ZZ_pX_Modulus_c* get_modulus(self, long n) noexcept:
1701
+ """
1702
+ Return the modulus corresponding to ``self.polynomial()`` (mod
1703
+ ``self.prime^n``).
1704
+
1705
+ INPUT:
1706
+
1707
+ - ``n`` -- a long between 1 and ``self.cache_limit``, inclusive.
1708
+ If `n` is larger, this function will return ``self.mod[prec_cap]``
1709
+ lifted to that precision.
1710
+
1711
+ EXAMPLES::
1712
+
1713
+ sage: A = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'small','e',ntl.ZZ_pX([1],5^10))
1714
+ sage: a = ntl.ZZ_pX([4,2],5^2)
1715
+ sage: b = ntl.ZZ_pX([6,3],5^2)
1716
+ sage: A._get_modulus_test(a, b, 2)
1717
+ [4 24]
1718
+ """
1719
+ cdef ZZ_pX_c tmp
1720
+ if n < 0:
1721
+ n = -n
1722
+ if n <= self.prec_cap:
1723
+ return &(self.mod[n])
1724
+ else:
1725
+ ZZ_pX_conv_modulus(tmp, self.mod[self.prec_cap].val(), (<ntl_ZZ_pContext_class>self.get_context(n)).x)
1726
+ ZZ_pX_Modulus_build(self.mod[self.prec_cap+1], tmp)
1727
+ return &(self.mod[self.prec_cap+1])
1728
+
1729
+ cdef ZZ_pX_Modulus_c* get_top_modulus(self) noexcept:
1730
+ """
1731
+ Return the modulus corresponding to ``self.polynomial()``
1732
+ (mod ``self.prime^self.prec_cap``).
1733
+
1734
+ EXAMPLES::
1735
+
1736
+ sage: A = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'small','e',ntl.ZZ_pX([1],5^10))
1737
+ sage: a = ntl.ZZ_pX([129223,1231],5^10)
1738
+ sage: b = ntl.ZZ_pX([289741,323],5^10)
1739
+ sage: A._get_top_modulus_test(a, b) # indirect doctest
1740
+ [1783058 7785200]
1741
+ """
1742
+ return &(self.mod[self.prec_cap])
1743
+
1744
+ cdef class PowComputer_ZZ_pX_small_Eis(PowComputer_ZZ_pX_small):
1745
+ """
1746
+ This class computes and stores ``low_shifter`` and ``high_shifter``, which aid in right shifting elements.
1747
+ These are only stored at maximal precision: in order to get lower precision versions just reduce mod p^n.
1748
+ """
1749
+ def __cinit__(self, Integer prime, long cache_limit, long prec_cap, long ram_prec_cap, bint in_field, poly, shift_seed=None):
1750
+ """
1751
+ Initialization.
1752
+
1753
+ For input types see :func:`PowComputer_ext_maker`
1754
+
1755
+ TESTS::
1756
+
1757
+ sage: A = PowComputer_ext_maker(5, 10, 10, 40, False, ntl.ZZ_pX([-5,75,15,0,1],5^10), 'small', 'e',ntl.ZZ_pX([1,-15,-3],5^10))
1758
+ sage: type(A)
1759
+ <class 'sage.rings.padics.pow_computer_ext.PowComputer_ZZ_pX_small_Eis'>
1760
+ sage: TestSuite(A).run()
1761
+ """
1762
+ self._ext_type = 'e'
1763
+ if not isinstance(shift_seed, ntl_ZZ_pX):
1764
+ raise TypeError("shift_seed must be an ntl_ZZ_pX")
1765
+ ZZ_pX_Eis_init(self, <ntl_ZZ_pX>shift_seed)
1766
+
1767
+ def _low_shifter(self, i):
1768
+ """
1769
+ Accessor function for low_shifter, which are the polynomials used to shift right.
1770
+
1771
+ If low_length is the number of low_shifters, then:
1772
+ * if deg = 2, low_length = 1 (store p/x)
1773
+ * if deg = 3,4, low_length = 2 (store p/x, p/x^2)
1774
+ * if deg = 5,6,7,8, low_length = 3 (store p/x, p/x^2, p/x^4)
1775
+ * if deg = 9,...,16, low_length = 4 (store p/x, p/x^2, p/x^4, p/x^8)
1776
+
1777
+ These polynomials are used to shift by amounts less than the degree of the defining polynomial.
1778
+
1779
+ EXAMPLES::
1780
+
1781
+ sage: A = PowComputer_ext_maker(5, 10, 10, 40, False, ntl.ZZ_pX([-5,75,15,0,1],5^10), 'small', 'e',ntl.ZZ_pX([1,-15,-3],5^10))
1782
+ sage: A._low_shifter(0)
1783
+ [75 15 0 1]
1784
+
1785
+ Note that if we multiply this by x and reduce using the relation that x^4 = 5 - 75x - 15x^2, we just get 5.
1786
+
1787
+ sage: A._low_shifter(1)
1788
+ [1140 225 1 15]
1789
+
1790
+ This one's a bit less obvious, but if we multiply by x^2, we get 5 (modulo x^4 = 5 - 75x - 15x^2).
1791
+ """
1792
+ cdef long _i = i
1793
+ cdef ntl_ZZ_pX ans
1794
+ if _i >= 0 and _i < self.low_length:
1795
+ ans = ntl_ZZ_pX([], self.get_top_context())
1796
+ ans.x = self.low_shifter[i]
1797
+ return ans
1798
+ else:
1799
+ raise IndexError
1800
+
1801
+ def _high_shifter(self, i):
1802
+ """
1803
+ Accessor function for high_shifter, which are the polynomials used to shift right.
1804
+
1805
+ If high_length is the number of high_shifters, then:
1806
+ * if prec_cap = 2, high_length = 1 (store p/x^e)
1807
+ * if prec_cap = 3,4, high_length = 2 (store p/x^e, p^2/x^(2e))
1808
+ * if prec_cap = 5,6,7,8, high_length = 3 (store p/x^e, p^2/x^(2e), p^4/x^(4e))
1809
+ * if prec_cap = 9,...,16, high_length = 4 (store p/x, p^2/x^(2e), p^4/x^(4e), p^8/x^(8e))
1810
+
1811
+ These polynomials are used to shift by amounts greater than the degree of the defining polynomial, but less than e*prec_cap.
1812
+
1813
+ EXAMPLES::
1814
+
1815
+ sage: A = PowComputer_ext_maker(5, 10, 10, 40, False, ntl.ZZ_pX([-5,75,15,0,1],5^10), 'small', 'e',ntl.ZZ_pX([1,-15,-3],5^10))
1816
+ sage: A._high_shifter(0)
1817
+ [263296 51990 228 3465]
1818
+
1819
+ If we take this and multiply by x^4, and reduce modulo x^4 + 15*x^2 + 75*x - 5, we should get 5. ::
1820
+
1821
+ sage: R.<x> = ZZ[]
1822
+ sage: f = 263296 + 51990*x + 228*x^2 + 3465*x^3
1823
+ sage: g = x^4 + 15*x^2 + 75*x - 5
1824
+ sage: f*x^4 % g
1825
+ 5
1826
+
1827
+ sage: A._high_shifter(1)
1828
+ [1420786 9298230 2217816 6212495]
1829
+
1830
+ Similarly::
1831
+
1832
+ sage: f = 1420786 + 9298230*x + 2217816*x^2 + 6212495*x^3
1833
+ sage: h = f*x^8 % g; h
1834
+ -1328125000000*x^3 + 2962646484375*x^2 + 22094970703125*x - 1466308593725
1835
+
1836
+ Here, we need to remember that we're working modulo 5^10::
1837
+
1838
+ sage: h[0].valuation(5), h[1].valuation(5), h[2].valuation(5), h[3].valuation(5)
1839
+ (2, 12, 13, 13)
1840
+ sage: (h[0] - 25).valuation(5)
1841
+ 12
1842
+ """
1843
+ cdef long _i = i
1844
+ cdef ntl_ZZ_pX ans
1845
+ if _i >= 0 and _i < self.high_length:
1846
+ ans = ntl_ZZ_pX([], self.get_top_context())
1847
+ ans.x = self.high_shifter[i]
1848
+ return ans
1849
+ else:
1850
+ raise IndexError
1851
+
1852
+ def __dealloc__(self):
1853
+ """
1854
+ Deallocate ``low_shifter`` and ``high_shifter``.
1855
+
1856
+ TESTS::
1857
+
1858
+ sage: A = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'small', 'e',ntl.ZZ_pX([1],5^10))
1859
+ sage: del A # indirect doctest
1860
+ """
1861
+ if self._initialized:
1862
+ self.cleanup_ZZ_pX_small_Eis()
1863
+
1864
+ cdef void cleanup_ZZ_pX_small_Eis(self) noexcept:
1865
+ """
1866
+ Do the actual work of deallocating ``low_shifter`` and
1867
+ ``high_shifter``.
1868
+
1869
+ TESTS::
1870
+
1871
+ sage: A = PowComputer_ext_maker(5, 3, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
1872
+ sage: del A # indirect doctest
1873
+ """
1874
+ Delete_ZZ_pX_array(self.low_shifter)
1875
+ Delete_ZZ_pX_array(self.high_shifter)
1876
+
1877
+ cdef int eis_shift(self, ZZ_pX_c* x, ZZ_pX_c* a, long n, long finalprec) except -1:
1878
+ """
1879
+ Shift ``a`` right ``n`` pi-adic digits, where pi is considered modulo
1880
+ the polynomial in ``self``.
1881
+
1882
+ Puts the result in ``x``.
1883
+
1884
+ EXAMPLES::
1885
+
1886
+ sage: from sage.rings.padics.pow_computer_ext import ZZ_pX_eis_shift_test
1887
+ sage: A = PowComputer_ext_maker(5, 10, 10, 40, False, ntl.ZZ_pX([-5,75,15,0,1],5^10), 'small', 'e',ntl.ZZ_pX([1,-15,-3],5^10))
1888
+ sage: ZZ_pX_eis_shift_test(A, [0, 1], 1, 5) # indirect doctest
1889
+ [1]
1890
+ sage: ZZ_pX_eis_shift_test(A, [0, 0, 1], 1, 5)
1891
+ [0 1]
1892
+ sage: ZZ_pX_eis_shift_test(A, [5], 1, 5)
1893
+ [75 15 0 1]
1894
+ sage: ZZ_pX_eis_shift_test(A, [1], 1, 5)
1895
+ []
1896
+ sage: ZZ_pX_eis_shift_test(A, [17, 91, 8, -2], 1, 5)
1897
+ [316 53 3123 3]
1898
+ sage: ZZ_pX_eis_shift_test(A, [316, 53, 3123, 3], -1, 5)
1899
+ [15 91 8 3123]
1900
+ sage: ZZ_pX_eis_shift_test(A, [15, 91, 8, 3123], 1, 5)
1901
+ [316 53 3123 3]
1902
+ """
1903
+ return ZZ_pX_eis_shift_p(self, x, a, n, finalprec)
1904
+
1905
+ cdef class PowComputer_ZZ_pX_big(PowComputer_ZZ_pX):
1906
+ """
1907
+ This class caches all contexts and moduli between 1 and cache_limit, and also caches for prec_cap. In addition, it stores
1908
+ a dictionary of contexts and moduli of
1909
+ """
1910
+
1911
+ def __cinit__(self, Integer prime, long cache_limit, long prec_cap, long ram_prec_cap, bint in_field, poly, shift_seed=None):
1912
+ """
1913
+ Caches contexts and moduli densely between 1 and cache_limit. Caches a context and modulus for prec_cap.
1914
+ Also creates the dictionaries.
1915
+
1916
+ EXAMPLES::
1917
+
1918
+ sage: A = PowComputer_ext_maker(5, 6, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'big','e',ntl.ZZ_pX([1],5^10)) # indirect doctest
1919
+ sage: A
1920
+ PowComputer_ext for 5, with polynomial [9765620 0 1]
1921
+ """
1922
+ # The __new__ method for PowComputer_ext has already run, so we have access to small_powers, top_power.
1923
+
1924
+ # We use ntl_ZZ_pContexts so that contexts are cached centrally.
1925
+
1926
+ self._prec_type = 'big'
1927
+ self._ext_type = 'u'
1928
+ if not isinstance(poly, ntl_ZZ_pX):
1929
+ self.cleanup_ext()
1930
+ raise TypeError
1931
+
1932
+ self.context_list = []
1933
+ #if self.c == NULL:
1934
+ # self.cleanup_ext()
1935
+ # raise MemoryError("out of memory allocating contexts")
1936
+ sig_on()
1937
+ self.modulus_list = Allocate_ZZ_pX_Modulus_array(cache_limit + 1)
1938
+ sig_off()
1939
+ if self.modulus_list == NULL:
1940
+ self.cleanup_ext()
1941
+ raise MemoryError("out of memory allocating moduli")
1942
+
1943
+ cdef Py_ssize_t i
1944
+ cdef ZZ_pX_c tmp, pol
1945
+ if isinstance(poly, ntl_ZZ_pX):
1946
+ pol = (<ntl_ZZ_pX>poly).x
1947
+ self.context_list.append(None)
1948
+ for i in range(1, cache_limit + 1):
1949
+ self.context_list.append(PowComputer_ZZ_pX.get_context(self,i))
1950
+
1951
+ # create a temporary polynomial with the highest modulus to
1952
+ # ensure all mod[i]'s will fit into it
1953
+ self.top_context = PowComputer_ZZ_pX.get_context(self, prec_cap)
1954
+ (<ntl_ZZ_pContext_class>self.top_context).restore_c()
1955
+ tmp = (<ntl_ZZ_pX>poly).x
1956
+
1957
+ for i in range(1, cache_limit + 1):
1958
+ (<ntl_ZZ_pContext_class>self.context_list[i]).restore_c()
1959
+ ZZ_pX_conv_modulus(tmp, pol, (<ntl_ZZ_pContext_class>self.context_list[i]).x)
1960
+ ZZ_pX_Modulus_build(self.modulus_list[i], tmp)
1961
+ (<ntl_ZZ_pContext_class>self.top_context).restore_c()
1962
+ ZZ_pX_conv_modulus(tmp, pol, self.top_context.x)
1963
+ ZZ_pX_Modulus_build(self.top_mod, tmp)
1964
+ self.context_dict = {}
1965
+ self.modulus_dict = {}
1966
+ if prec_cap == ram_prec_cap:
1967
+ self.e = 1
1968
+ self.f = ZZ_pX_deg((<ntl_ZZ_pX>poly).x)
1969
+ else:
1970
+ self.e = ZZ_pX_deg((<ntl_ZZ_pX>poly).x)
1971
+ self.f = 1
1972
+ self.ram_prec_cap = ram_prec_cap
1973
+ else:
1974
+ raise NotImplementedError("NOT IMPLEMENTED IN PowComputer_ZZ_pX_FM")
1975
+
1976
+ def __dealloc__(self):
1977
+ """
1978
+ Deallocate the stored moduli and contexts.
1979
+
1980
+ EXAMPLES::
1981
+
1982
+ sage: A = PowComputer_ext_maker(5, 6, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'big','e',ntl.ZZ_pX([1],5^10))
1983
+ sage: del A # indirect doctest
1984
+ """
1985
+ if self._initialized:
1986
+ self.cleanup_ZZ_pX_big()
1987
+
1988
+ cdef void cleanup_ZZ_pX_big(self) noexcept:
1989
+ """
1990
+ Deallocate the stored moduli and contexts.
1991
+
1992
+ EXAMPLES::
1993
+
1994
+ sage: A = PowComputer_ext_maker(5, 6, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'big','e',ntl.ZZ_pX([1],5^10))
1995
+ sage: del A # indirect doctest
1996
+ """
1997
+ Delete_ZZ_pX_Modulus_array(self.modulus_list)
1998
+
1999
+ def reset_dictionaries(self):
2000
+ """
2001
+ Reset the dictionaries. Note that if there are elements
2002
+ lying around that need access to these dictionaries, calling
2003
+ this function and then doing arithmetic with those elements
2004
+ could cause trouble (if the context object gets garbage
2005
+ collected for example. The bugs introduced could be very
2006
+ subtle, because NTL will generate a new context object and use
2007
+ it, but there's the potential for the object to be
2008
+ incompatible with the different context object).
2009
+
2010
+ EXAMPLES::
2011
+
2012
+ sage: A = PowComputer_ext_maker(5, 6, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'big','e',ntl.ZZ_pX([1],5^10))
2013
+ sage: P = A._get_context_test(8)
2014
+ sage: A._context_dict()
2015
+ {8: NTL modulus 390625}
2016
+ sage: A.reset_dictionaries()
2017
+ sage: A._context_dict()
2018
+ {}
2019
+ """
2020
+ self.context_dict = {}
2021
+ self.modulus_dict = {}
2022
+
2023
+ def _context_dict(self):
2024
+ """
2025
+ Return the context dictionary.
2026
+
2027
+ EXAMPLES::
2028
+
2029
+ sage: A = PowComputer_ext_maker(5, 6, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'big','e',ntl.ZZ_pX([1],5^10))
2030
+ sage: P = A._get_context_test(8)
2031
+ sage: A._context_dict()
2032
+ {8: NTL modulus 390625}
2033
+ """
2034
+ return self.context_dict
2035
+
2036
+ def _modulus_dict(self):
2037
+ """
2038
+ Return the context dictionary.
2039
+
2040
+ EXAMPLES::
2041
+
2042
+ sage: A = PowComputer_ext_maker(5, 6, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'big','e',ntl.ZZ_pX([1],5^10))
2043
+ sage: P = A._get_context_test(8)
2044
+ sage: A._modulus_dict()
2045
+ {}
2046
+ sage: a = ntl.ZZ_pX([4,2],5^8)
2047
+ sage: b = ntl.ZZ_pX([6,3],5^8)
2048
+ sage: A._get_modulus_test(a, b, 8)
2049
+ [54 24]
2050
+ sage: A._modulus_dict()
2051
+ {8: NTL ZZ_pXModulus [390620 0 1] (mod 390625)}
2052
+ """
2053
+ return self.modulus_dict
2054
+
2055
+ cdef ntl_ZZ_pContext_class get_context(self, long n):
2056
+ """
2057
+ Return the context for p^n.
2058
+
2059
+ INPUT:
2060
+
2061
+ - ``n`` -- nonzero long
2062
+
2063
+ OUTPUT: a context for p^n
2064
+
2065
+ EXAMPLES::
2066
+
2067
+ sage: A = PowComputer_ext_maker(5, 6, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'big')
2068
+ sage: A._get_context_test(4) # indirect doctest
2069
+ NTL modulus 625
2070
+ sage: A._get_context_test(8) # indirect doctest
2071
+ NTL modulus 390625
2072
+ """
2073
+ if n == 0:
2074
+ # Exception will be ignored by Cython
2075
+ raise ValueError("n must be nonzero")
2076
+ if n < 0:
2077
+ n = -n
2078
+ if n <= self.cache_limit:
2079
+ return self.context_list[n]
2080
+ elif n == self.prec_cap:
2081
+ return self.top_context
2082
+ else:
2083
+ try:
2084
+ return self.context_dict[n]
2085
+ except KeyError:
2086
+ self.context_dict[n] = PowComputer_ZZ_pX.get_context(self, n)
2087
+ return self.context_dict[n]
2088
+
2089
+ cdef ntl_ZZ_pContext_class get_top_context(self):
2090
+ """
2091
+ Return a ``ZZ_pContext`` for ``self.prime^self.prec_cap``.
2092
+
2093
+ EXAMPLES::
2094
+
2095
+ sage: PC = PowComputer_ext_maker(5, 5, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'big','e',ntl.ZZ_pX([1],5^10))
2096
+ sage: PC._get_top_context_test() # indirect doctest
2097
+ NTL modulus 9765625
2098
+ """
2099
+ return self.top_context
2100
+
2101
+ cdef void restore_top_context(self) noexcept:
2102
+ """
2103
+ Restore the context corresponding to ``self.prime^self.prec_cap``.
2104
+
2105
+ EXAMPLES::
2106
+
2107
+ sage: PC = PowComputer_ext_maker(5, 5, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'big','e',ntl.ZZ_pX([1],5^10))
2108
+ sage: PC._restore_top_context_test() # indirect doctest
2109
+ """
2110
+ self.top_context.restore_c()
2111
+
2112
+ cdef ZZ_pX_Modulus_c* get_modulus(self, long n) noexcept:
2113
+ """
2114
+ Return the modulus corresponding to ``self.polynomial()`` (mod
2115
+ ``self.prime^n``).
2116
+
2117
+ INPUT:
2118
+
2119
+ - ``n`` -- nonzero long
2120
+
2121
+ EXAMPLES::
2122
+
2123
+ sage: A = PowComputer_ext_maker(5, 3, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'big','e',ntl.ZZ_pX([1],5^10))
2124
+ sage: a = ntl.ZZ_pX([4,2],5^2)
2125
+ sage: b = ntl.ZZ_pX([6,3],5^2)
2126
+ sage: A._get_modulus_test(a, b, 2) # indirect doctest
2127
+ [4 24]
2128
+ sage: a = ntl.ZZ_pX([4,2],5^6)
2129
+ sage: b = ntl.ZZ_pX([6,3],5^6)
2130
+ sage: A._get_modulus_test(a, b, 6) # indirect doctest
2131
+ [54 24]
2132
+ sage: A._get_modulus_test(a, b, 6) # indirect doctest
2133
+ [54 24]
2134
+ """
2135
+ cdef ntl_ZZ_pX tmp
2136
+ cdef ntl_ZZ_pX_Modulus holder
2137
+ cdef ntl_ZZ_pContext_class c
2138
+ if n == 0:
2139
+ # Exception will be ignored by Cython
2140
+ raise ValueError("n must be nonzero")
2141
+ if n < 0:
2142
+ n = -n
2143
+ elif n <= self.cache_limit:
2144
+ return &(self.modulus_list[n])
2145
+ elif n == self.prec_cap:
2146
+ return &self.top_mod
2147
+ else:
2148
+ if n in self.modulus_dict:
2149
+ return &((<ntl_ZZ_pX_Modulus>self.modulus_dict[n]).x)
2150
+ else:
2151
+ c = self.get_context(n)
2152
+ c.restore_c()
2153
+ tmp = ntl_ZZ_pX.__new__(ntl_ZZ_pX)
2154
+ tmp.c = c
2155
+ ZZ_pX_conv_modulus(tmp.x, self.top_mod.val(), c.x)
2156
+ holder = ntl_ZZ_pX_Modulus(tmp)
2157
+ self.modulus_dict[n] = holder
2158
+ return &(holder.x)
2159
+
2160
+ cdef ZZ_pX_Modulus_c* get_top_modulus(self) noexcept:
2161
+ """
2162
+ Return the modulus corresponding to ``self.polynomial()``
2163
+ (mod ``self.prime^self.prec_cap``).
2164
+
2165
+ EXAMPLES::
2166
+
2167
+ sage: A = PowComputer_ext_maker(5, 5, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'big','e',ntl.ZZ_pX([1],5^10))
2168
+ sage: a = ntl.ZZ_pX([129223,1231],5^10)
2169
+ sage: b = ntl.ZZ_pX([289741,323],5^10)
2170
+ sage: A._get_top_modulus_test(a, b) # indirect doctest
2171
+ [1783058 7785200]
2172
+ """
2173
+ return &self.top_mod
2174
+
2175
+ cdef class PowComputer_ZZ_pX_big_Eis(PowComputer_ZZ_pX_big):
2176
+ """
2177
+ This class computes and stores ``low_shifter`` and ``high_shifter``, which
2178
+ aid in right shifting elements.
2179
+ These are only stored at maximal precision: in order to get lower precision
2180
+ versions just reduce mod p^n.
2181
+ """
2182
+ def __cinit__(self, Integer prime, long cache_limit, long prec_cap, long ram_prec_cap, bint in_field, poly, shift_seed=None):
2183
+ """
2184
+ Initialization.
2185
+
2186
+ For input types see :func:`PowComputer_ext_maker`
2187
+
2188
+ TESTS::
2189
+
2190
+ sage: A = PowComputer_ext_maker(5, 3, 10, 40, False, ntl.ZZ_pX([-5,75,15,0,1],5^10), 'big', 'e',ntl.ZZ_pX([1,-15,-3],5^10))
2191
+ sage: type(A)
2192
+ <class 'sage.rings.padics.pow_computer_ext.PowComputer_ZZ_pX_big_Eis'>
2193
+ sage: TestSuite(A).run()
2194
+ """
2195
+ self._ext_type = 'e'
2196
+ if not isinstance(shift_seed, ntl_ZZ_pX):
2197
+ raise TypeError("shift_seed must be an ntl_ZZ_pX")
2198
+ ZZ_pX_Eis_init(self, <ntl_ZZ_pX>shift_seed)
2199
+
2200
+ def _low_shifter(self, i):
2201
+ """
2202
+ Accessor function for low_shifter, which are the polynomials used to shift right.
2203
+
2204
+ If low_length is the number of low_shifters, then:
2205
+ * if deg = 2, low_length = 1 (store p/x)
2206
+ * if deg = 3,4, low_length = 2 (store p/x, p/x^2)
2207
+ * if deg = 5,6,7,8, low_length = 3 (store p/x, p/x^2, p/x^4)
2208
+ * if deg = 9,...,16, low_length = 4 (store p/x, p/x^2, p/x^4, p/x^8)
2209
+
2210
+ These polynomials are used to shift by amounts less than the degree of the defining polynomial.
2211
+
2212
+ EXAMPLES::
2213
+
2214
+ sage: A = PowComputer_ext_maker(5, 3, 10, 40, False, ntl.ZZ_pX([-5,75,15,0,1],5^10), 'big', 'e',ntl.ZZ_pX([1,-15,-3],5^10))
2215
+ sage: A._low_shifter(0)
2216
+ [75 15 0 1]
2217
+
2218
+ Note that if we multiply this by x and reduce using the relation that x^4 = 5 - 75x - 15x^2, we just get 5.
2219
+
2220
+ sage: A._low_shifter(1)
2221
+ [1140 225 1 15]
2222
+
2223
+ This one's a bit less obvious, but if we multiply by x^2, we get 5 (modulo x^4 = 5 - 75x - 15x^2).
2224
+ """
2225
+ cdef long _i = i
2226
+ cdef ntl_ZZ_pX ans
2227
+ if _i >= 0 and _i < self.low_length:
2228
+ ans = ntl_ZZ_pX([], self.get_top_context())
2229
+ ans.x = self.low_shifter[i]
2230
+ return ans
2231
+ else:
2232
+ raise IndexError
2233
+
2234
+ def _high_shifter(self, i):
2235
+ """
2236
+ Accessor function for high_shifter, which are the polynomials used to shift right.
2237
+
2238
+ If high_length is the number of high_shifters, then:
2239
+ * if prec_cap = 2, high_length = 1 (store p/x^e)
2240
+ * if prec_cap = 3,4, high_length = 2 (store p/x^e, p^2/x^(2e))
2241
+ * if prec_cap = 5,6,7,8, high_length = 3 (store p/x^e, p^2/x^(2e), p^4/x^(4e))
2242
+ * if prec_cap = 9,...,16, high_length = 4 (store p/x, p^2/x^(2e), p^4/x^(4e), p^8/x^(8e))
2243
+
2244
+ These polynomials are used to shift by amounts greater than the degree of the defining polynomial, but less than e*prec_cap.
2245
+
2246
+ EXAMPLES::
2247
+
2248
+ sage: A = PowComputer_ext_maker(5, 3, 10, 40, False, ntl.ZZ_pX([-5,75,15,0,1],5^10), 'big', 'e',ntl.ZZ_pX([1,-15,-3],5^10))
2249
+ sage: A._high_shifter(0)
2250
+ [263296 51990 228 3465]
2251
+
2252
+ If we take this and multiply by x^4, and reduce modulo x^4 + 15*x^2 + 75*x - 5, we should get 5. ::
2253
+
2254
+ sage: R.<x> = ZZ[]
2255
+ sage: f = 263296 + 51990*x + 228*x^2 + 3465*x^3
2256
+ sage: g = x^4 + 15*x^2 + 75*x - 5
2257
+ sage: f*x^4 % g
2258
+ 5
2259
+
2260
+ sage: A._high_shifter(1)
2261
+ [1420786 9298230 2217816 6212495]
2262
+
2263
+ Similarly::
2264
+
2265
+ sage: f = 1420786 + 9298230*x + 2217816*x^2 + 6212495*x^3
2266
+ sage: h = f*x^8 % g; h
2267
+ -1328125000000*x^3 + 2962646484375*x^2 + 22094970703125*x - 1466308593725
2268
+
2269
+ Here, we need to remember that we're working modulo 5^10::
2270
+
2271
+ sage: h[0].valuation(5), h[1].valuation(5), h[2].valuation(5), h[3].valuation(5)
2272
+ (2, 12, 13, 13)
2273
+ sage: (h[0] - 25).valuation(5)
2274
+ 12
2275
+ """
2276
+ cdef long _i = i
2277
+ cdef ntl_ZZ_pX ans
2278
+ if _i >= 0 and _i < self.high_length:
2279
+ ans = ntl_ZZ_pX([], self.get_top_context())
2280
+ ans.x = self.high_shifter[i]
2281
+ return ans
2282
+ else:
2283
+ raise IndexError
2284
+
2285
+ def __dealloc__(self):
2286
+ """
2287
+ Deallocate ``low_shifter`` and ``high_shifter``.
2288
+
2289
+ TESTS::
2290
+
2291
+ sage: A = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'big', 'e',ntl.ZZ_pX([1],5^10))
2292
+ sage: del A # indirect doctest
2293
+ """
2294
+ if self._initialized:
2295
+ self.cleanup_ZZ_pX_big_Eis()
2296
+
2297
+ cdef void cleanup_ZZ_pX_big_Eis(self) noexcept:
2298
+ """
2299
+ Do the actual work of deallocating ``low_shifter`` and
2300
+ ``high_shifter``.
2301
+
2302
+ TESTS::
2303
+
2304
+ sage: A = PowComputer_ext_maker(5, 3, 10, 20, False, ntl.ZZ_pX([-5,0,1],5^10), 'FM', 'e',ntl.ZZ_pX([1],5^10))
2305
+ sage: del A # indirect doctest
2306
+ """
2307
+ Delete_ZZ_pX_array(self.low_shifter)
2308
+ Delete_ZZ_pX_array(self.high_shifter)
2309
+
2310
+ cdef int eis_shift(self, ZZ_pX_c* x, ZZ_pX_c* a, long n, long finalprec) except -1:
2311
+ """
2312
+ Shift ``a`` right ``n`` pi-adic digits, where pi is considered modulo
2313
+ the polynomial in ``self``.
2314
+
2315
+ Puts the result in ``x``.
2316
+
2317
+ EXAMPLES::
2318
+
2319
+ sage: from sage.rings.padics.pow_computer_ext import ZZ_pX_eis_shift_test
2320
+ sage: A = PowComputer_ext_maker(5, 10, 10, 40, False, ntl.ZZ_pX([-5,75,15,0,1],5^10), 'big', 'e',ntl.ZZ_pX([1,-15,-3],5^10))
2321
+ sage: ZZ_pX_eis_shift_test(A, [0, 1], 1, 5) # indirect doctest
2322
+ [1]
2323
+ sage: ZZ_pX_eis_shift_test(A, [0, 0, 1], 1, 5)
2324
+ [0 1]
2325
+ sage: ZZ_pX_eis_shift_test(A, [5], 1, 5)
2326
+ [75 15 0 1]
2327
+ sage: ZZ_pX_eis_shift_test(A, [1], 1, 5)
2328
+ []
2329
+ sage: ZZ_pX_eis_shift_test(A, [17, 91, 8, -2], 1, 5)
2330
+ [316 53 3123 3]
2331
+ sage: ZZ_pX_eis_shift_test(A, [316, 53, 3123, 3], -1, 5)
2332
+ [15 91 8 3123]
2333
+ sage: ZZ_pX_eis_shift_test(A, [15, 91, 8, 3123], 1, 5)
2334
+ [316 53 3123 3]
2335
+ """
2336
+ return ZZ_pX_eis_shift_p(self, x, a, n, finalprec)
2337
+
2338
+
2339
+ def PowComputer_ext_maker(prime, cache_limit, prec_cap, ram_prec_cap, in_field, poly, prec_type="small", ext_type="u", shift_seed=None):
2340
+ r"""
2341
+ Return a ``PowComputer`` that caches the values `1, p, p^2, \ldots, p^C`,
2342
+ where `C` is ``cache_limit``.
2343
+
2344
+ Once you create a ``PowComputer``, merely call it to get values out.
2345
+ You can input any integer, even if it's outside of the precomputed range.
2346
+
2347
+ INPUT:
2348
+
2349
+ - ``prime`` -- integer; the base that you want to exponentiate
2350
+
2351
+ - ``cache_limit`` -- positive integer that you want to cache
2352
+ powers up to
2353
+
2354
+ - ``prec_cap`` -- the cap on precisions of elements. For ramified
2355
+ extensions, p^((prec_cap - 1) // e) will be the largest
2356
+ power of p distinguishable from zero.
2357
+
2358
+ - ``in_field`` -- boolean indicating whether this PowComputer is
2359
+ attached to a field or not
2360
+
2361
+ - ``poly`` -- an ``ntl_ZZ_pX`` or ``ntl_ZZ_pEX`` defining the extension.
2362
+ It should be defined modulo ``p^((prec_cap - 1) // e + 1)``.
2363
+
2364
+ - ``prec_type`` -- ``'FM'``, ``'small'``, or ``'big'``, defining how
2365
+ caching is done
2366
+
2367
+ - ``ext_type`` -- ``'u'`` = unramified, ``'e'`` = Eisenstein, ``'t'`` =
2368
+ two-step
2369
+
2370
+ - ``shift_seed`` -- (required only for Eisenstein and two-step)
2371
+ for Eisenstein and two-step extensions, if f = a_n x^n - p
2372
+ a_{n-1} x^{n-1} - ... - p a_0 with a_n a unit, then
2373
+ shift_seed should be 1/a_n (a_{n-1} x^{n-1} + ... + a_0)
2374
+
2375
+ EXAMPLES::
2376
+
2377
+ sage: PC = PowComputer_ext_maker(5, 10, 10, 20, False, ntl.ZZ_pX([-5, 0, 1], 5^10), 'small','e',ntl.ZZ_pX([1],5^10))
2378
+ sage: PC
2379
+ PowComputer_ext for 5, with polynomial [9765620 0 1]
2380
+ """
2381
+ cdef Integer _prime = <Integer>Integer(prime)
2382
+ cdef long _cache_limit = mpz_get_si((<Integer>Integer(cache_limit)).value)
2383
+ cdef long _prec_cap = mpz_get_si((<Integer>Integer(prec_cap)).value)
2384
+ cdef long _ram_prec_cap = mpz_get_si((<Integer>Integer(ram_prec_cap)).value)
2385
+ cdef bint inf = in_field
2386
+ if ext_type != "u" and shift_seed is None:
2387
+ raise ValueError("must provide shift seed")
2388
+ if prec_type == "small" and ext_type == "u":
2389
+ return PowComputer_ZZ_pX_small(_prime, _cache_limit, _prec_cap, _ram_prec_cap, inf, poly, None)
2390
+ elif prec_type == "small" and ext_type == "e":
2391
+ return PowComputer_ZZ_pX_small_Eis(_prime, _cache_limit, _prec_cap, _ram_prec_cap, inf, poly, shift_seed)
2392
+ elif prec_type == "big" and ext_type == "u":
2393
+ return PowComputer_ZZ_pX_big(_prime, _cache_limit, _prec_cap, _ram_prec_cap, inf, poly, None)
2394
+ elif prec_type == "big" and ext_type == "e":
2395
+ return PowComputer_ZZ_pX_big_Eis(_prime, _cache_limit, _prec_cap, _ram_prec_cap, inf, poly, shift_seed)
2396
+ elif prec_type == "FM" and ext_type == "u":
2397
+ return PowComputer_ZZ_pX_FM(_prime, _cache_limit, _prec_cap, _ram_prec_cap, inf, poly, None)
2398
+ elif prec_type == "FM" and ext_type == "e":
2399
+ return PowComputer_ZZ_pX_FM_Eis(_prime, _cache_limit, _prec_cap, _ram_prec_cap, inf, poly, shift_seed)
2400
+ else:
2401
+ raise ValueError("prec_type must be one of 'small', 'big' or 'FM' and ext_type must be one of 'u' or 'e' or 't'")