passagemath-ntl 10.6.38__cp314-cp314-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.
- passagemath_ntl/__init__.py +3 -0
- passagemath_ntl-10.6.38.dist-info/METADATA +122 -0
- passagemath_ntl-10.6.38.dist-info/RECORD +162 -0
- passagemath_ntl-10.6.38.dist-info/WHEEL +6 -0
- passagemath_ntl-10.6.38.dist-info/top_level.txt +3 -0
- passagemath_ntl.libs/libgf2x-fbd36f80.so.3.0.0 +0 -0
- passagemath_ntl.libs/libgmp-93ebf16a.so.10.5.0 +0 -0
- passagemath_ntl.libs/libmpfi-ad12a86d.so.0.0.0 +0 -0
- passagemath_ntl.libs/libmpfr-9d41ebf1.so.6.2.1 +0 -0
- passagemath_ntl.libs/libntl-1bc30f7e.so.45.0.0 +0 -0
- sage/all__sagemath_ntl.py +7 -0
- sage/libs/all__sagemath_ntl.py +3 -0
- sage/libs/mpfi/__init__.pxd +287 -0
- sage/libs/mpfi/types.pxd +10 -0
- sage/libs/ntl/GF2.pxd +18 -0
- sage/libs/ntl/GF2E.pxd +28 -0
- sage/libs/ntl/GF2EX.pxd +12 -0
- sage/libs/ntl/GF2X.pxd +81 -0
- sage/libs/ntl/ZZ.pxd +93 -0
- sage/libs/ntl/ZZX.pxd +85 -0
- sage/libs/ntl/ZZ_p.pxd +28 -0
- sage/libs/ntl/ZZ_pE.pxd +37 -0
- sage/libs/ntl/ZZ_pEX.pxd +106 -0
- sage/libs/ntl/ZZ_pX.pxd +122 -0
- sage/libs/ntl/__init__.py +4 -0
- sage/libs/ntl/all.py +72 -0
- sage/libs/ntl/conversion.pxd +106 -0
- sage/libs/ntl/convert.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/convert.pxd +7 -0
- sage/libs/ntl/convert.pyx +38 -0
- sage/libs/ntl/decl.pxi +18 -0
- sage/libs/ntl/error.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/error.pyx +63 -0
- sage/libs/ntl/lzz_p.pxd +20 -0
- sage/libs/ntl/lzz_pX.pxd +59 -0
- sage/libs/ntl/mat_GF2.pxd +30 -0
- sage/libs/ntl/mat_GF2E.pxd +30 -0
- sage/libs/ntl/mat_ZZ.pxd +59 -0
- sage/libs/ntl/misc.pxi +33 -0
- sage/libs/ntl/ntl_GF2.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_GF2.pxd +5 -0
- sage/libs/ntl/ntl_GF2.pyx +281 -0
- sage/libs/ntl/ntl_GF2E.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_GF2E.pxd +8 -0
- sage/libs/ntl/ntl_GF2E.pyx +488 -0
- sage/libs/ntl/ntl_GF2EContext.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_GF2EContext.pxd +9 -0
- sage/libs/ntl/ntl_GF2EContext.pyx +134 -0
- sage/libs/ntl/ntl_GF2EX.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_GF2EX.pxd +10 -0
- sage/libs/ntl/ntl_GF2EX.pyx +251 -0
- sage/libs/ntl/ntl_GF2X.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_GF2X.pxd +5 -0
- sage/libs/ntl/ntl_GF2X.pyx +771 -0
- sage/libs/ntl/ntl_GF2X_linkage.pxi +404 -0
- sage/libs/ntl/ntl_ZZ.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_ZZ.pxd +7 -0
- sage/libs/ntl/ntl_ZZ.pyx +541 -0
- sage/libs/ntl/ntl_ZZX.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_ZZX.pxd +7 -0
- sage/libs/ntl/ntl_ZZX.pyx +1206 -0
- sage/libs/ntl/ntl_ZZ_p.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_ZZ_p.pxd +10 -0
- sage/libs/ntl/ntl_ZZ_p.pyx +509 -0
- sage/libs/ntl/ntl_ZZ_pContext.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_ZZ_pContext.pxd +22 -0
- sage/libs/ntl/ntl_ZZ_pContext.pyx +201 -0
- sage/libs/ntl/ntl_ZZ_pE.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_ZZ_pE.pxd +11 -0
- sage/libs/ntl/ntl_ZZ_pE.pyx +349 -0
- sage/libs/ntl/ntl_ZZ_pEContext.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_ZZ_pEContext.pxd +23 -0
- sage/libs/ntl/ntl_ZZ_pEContext.pyx +226 -0
- sage/libs/ntl/ntl_ZZ_pEX.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_ZZ_pEX.pxd +10 -0
- sage/libs/ntl/ntl_ZZ_pEX.pyx +1255 -0
- sage/libs/ntl/ntl_ZZ_pEX_linkage.pxi +420 -0
- sage/libs/ntl/ntl_ZZ_pX.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_ZZ_pX.pxd +17 -0
- sage/libs/ntl/ntl_ZZ_pX.pyx +1532 -0
- sage/libs/ntl/ntl_lzz_p.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_lzz_p.pxd +8 -0
- sage/libs/ntl/ntl_lzz_p.pyx +440 -0
- sage/libs/ntl/ntl_lzz_pContext.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_lzz_pContext.pxd +7 -0
- sage/libs/ntl/ntl_lzz_pContext.pyx +137 -0
- sage/libs/ntl/ntl_lzz_pX.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_lzz_pX.pxd +10 -0
- sage/libs/ntl/ntl_lzz_pX.pyx +902 -0
- sage/libs/ntl/ntl_mat_GF2.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_mat_GF2.pxd +8 -0
- sage/libs/ntl/ntl_mat_GF2.pyx +612 -0
- sage/libs/ntl/ntl_mat_GF2E.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_mat_GF2E.pxd +10 -0
- sage/libs/ntl/ntl_mat_GF2E.pyx +752 -0
- sage/libs/ntl/ntl_mat_ZZ.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/libs/ntl/ntl_mat_ZZ.pxd +6 -0
- sage/libs/ntl/ntl_mat_ZZ.pyx +1523 -0
- sage/libs/ntl/ntl_tools.pxd +3 -0
- sage/libs/ntl/ntlwrap.h +53 -0
- sage/libs/ntl/ntlwrap_impl.h +743 -0
- sage/libs/ntl/types.pxd +157 -0
- sage/libs/ntl/vec_GF2.pxd +26 -0
- sage/libs/ntl/vec_GF2E.pxd +2 -0
- sage/matrix/all__sagemath_ntl.py +1 -0
- sage/matrix/matrix_modn_dense_double.pxd +10 -0
- sage/matrix/matrix_modn_dense_float.pxd +9 -0
- sage/matrix/matrix_modn_dense_template.pxi +3257 -0
- sage/matrix/matrix_modn_dense_template_header.pxi +15 -0
- sage/matrix/matrix_modn_sparse.pxd +8 -0
- sage/misc/all__sagemath_ntl.py +1 -0
- sage/rings/all__sagemath_ntl.py +7 -0
- sage/rings/bernmm.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/bernmm.pyx +161 -0
- sage/rings/bernoulli_mod_p.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/bernoulli_mod_p.pyx +313 -0
- sage/rings/finite_rings/all__sagemath_ntl.py +1 -0
- sage/rings/finite_rings/finite_field_ntl_gf2e.py +305 -0
- sage/rings/finite_rings/residue_field_ntl_gf2e.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/finite_rings/residue_field_ntl_gf2e.pyx +140 -0
- sage/rings/padics/all__sagemath_ntl.py +5 -0
- sage/rings/padics/padic_ZZ_pX_CA_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/padics/padic_ZZ_pX_CA_element.pxd +25 -0
- sage/rings/padics/padic_ZZ_pX_CA_element.pyx +2368 -0
- sage/rings/padics/padic_ZZ_pX_CR_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/padics/padic_ZZ_pX_CR_element.pxd +33 -0
- sage/rings/padics/padic_ZZ_pX_CR_element.pyx +3277 -0
- sage/rings/padics/padic_ZZ_pX_FM_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/padics/padic_ZZ_pX_FM_element.pxd +12 -0
- sage/rings/padics/padic_ZZ_pX_FM_element.pyx +1739 -0
- sage/rings/padics/padic_ZZ_pX_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/padics/padic_ZZ_pX_element.pxd +6 -0
- sage/rings/padics/padic_ZZ_pX_element.pyx +919 -0
- sage/rings/padics/padic_ext_element.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/padics/padic_ext_element.pxd +38 -0
- sage/rings/padics/padic_ext_element.pyx +512 -0
- sage/rings/padics/pow_computer_ext.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/padics/pow_computer_ext.pxd +107 -0
- sage/rings/padics/pow_computer_ext.pyx +2401 -0
- sage/rings/polynomial/all__sagemath_ntl.py +1 -0
- sage/rings/polynomial/evaluation_ntl.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/evaluation_ntl.pxd +7 -0
- sage/rings/polynomial/evaluation_ntl.pyx +70 -0
- sage/rings/polynomial/polynomial_gf2x.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_gf2x.pxd +10 -0
- sage/rings/polynomial/polynomial_gf2x.pyx +364 -0
- sage/rings/polynomial/polynomial_integer_dense_ntl.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_integer_dense_ntl.pxd +8 -0
- sage/rings/polynomial/polynomial_integer_dense_ntl.pyx +1128 -0
- sage/rings/polynomial/polynomial_modn_dense_ntl.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_modn_dense_ntl.pxd +36 -0
- sage/rings/polynomial/polynomial_modn_dense_ntl.pyx +2049 -0
- sage/rings/polynomial/polynomial_template.pxi +842 -0
- sage/rings/polynomial/polynomial_template_header.pxi +11 -0
- sage/rings/polynomial/polynomial_zz_pex.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/rings/polynomial/polynomial_zz_pex.pxd +12 -0
- sage/rings/polynomial/polynomial_zz_pex.pyx +778 -0
- sage/rings/real_mpfi.pxd +50 -0
- sage/schemes/all__sagemath_ntl.py +1 -0
- sage/schemes/hyperelliptic_curves/all__sagemath_ntl.py +1 -0
- sage/schemes/hyperelliptic_curves/hypellfrob.cpython-314-aarch64-linux-gnu.so +0 -0
- sage/schemes/hyperelliptic_curves/hypellfrob.pyx +252 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-ntl
|
|
2
|
+
"""
|
|
3
|
+
Dense Matrix Template for C/C++ Library Interfaces
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from sage.ext.mod_int cimport *
|
|
7
|
+
from sage.matrix.matrix_dense cimport Matrix_dense
|
|
8
|
+
|
|
9
|
+
cdef class Matrix_modn_dense_template(Matrix_dense):
|
|
10
|
+
cdef celement **_matrix
|
|
11
|
+
cdef celement *_entries
|
|
12
|
+
cdef mod_int p
|
|
13
|
+
cdef xgcd_eliminate (self, celement * row1, celement* row2, Py_ssize_t start_col)
|
|
14
|
+
cpdef _export_as_string(self)
|
|
15
|
+
cdef int _copy_row_to_mod_int_array(self, mod_int *to, Py_ssize_t i) noexcept
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-ntl
|
|
2
|
+
from sage.matrix.matrix_sparse cimport Matrix_sparse
|
|
3
|
+
from sage.modules.vector_modn_sparse cimport *
|
|
4
|
+
|
|
5
|
+
cdef class Matrix_modn_sparse(Matrix_sparse):
|
|
6
|
+
cdef c_vector_modint* rows
|
|
7
|
+
cdef public int p
|
|
8
|
+
cdef swap_rows_c(self, Py_ssize_t n1, Py_ssize_t n2)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-ntl
|
|
Binary file
|
sage/rings/bernmm.pyx
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-ntl
|
|
2
|
+
# distutils: sources = sage/rings/bernmm/bern_modp.cpp sage/rings/bernmm/bern_modp_util.cpp sage/rings/bernmm/bern_rat.cpp
|
|
3
|
+
# distutils: libraries = NTL_LIBRARIES pthread gmp
|
|
4
|
+
# distutils: extra_compile_args = NTL_CFLAGS
|
|
5
|
+
# distutils: include_dirs = NTL_INCDIR
|
|
6
|
+
# distutils: library_dirs = NTL_LIBDIR
|
|
7
|
+
# distutils: extra_link_args = NTL_LIBEXTRA
|
|
8
|
+
# distutils: depends = sage/rings/bernmm/bern_modp.h sage/rings/bernmm/bern_modp_util.h sage/rings/bernmm/bern_rat.h
|
|
9
|
+
# distutils: language = c++
|
|
10
|
+
# distutils: define_macros = USE_THREADS=1 THREAD_STACK_SIZE=4096
|
|
11
|
+
|
|
12
|
+
r"""
|
|
13
|
+
Cython wrapper for bernmm library
|
|
14
|
+
|
|
15
|
+
AUTHOR:
|
|
16
|
+
|
|
17
|
+
- David Harvey (2008-06): initial version
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
#*****************************************************************************
|
|
21
|
+
# Copyright (C) 2008 William Stein <wstein@gmail.com>
|
|
22
|
+
# 2008 David Harvey <dmharvey@math.harvard.edu>
|
|
23
|
+
#
|
|
24
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
25
|
+
# http://www.gnu.org/licenses/
|
|
26
|
+
#*****************************************************************************
|
|
27
|
+
|
|
28
|
+
from cysignals.signals cimport sig_on, sig_off
|
|
29
|
+
|
|
30
|
+
from sage.libs.gmp.types cimport mpq_t
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
cdef extern from "bernmm/bern_rat.h":
|
|
34
|
+
void bern_rat "bernmm::bern_rat" (mpq_t res, long k, int num_threads)
|
|
35
|
+
|
|
36
|
+
cdef extern from "bernmm/bern_modp.h":
|
|
37
|
+
long bern_modp "bernmm::bern_modp" (long p, long k)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
from sage.rings.rational cimport Rational
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def bernmm_bern_rat(long k, int num_threads=1):
|
|
44
|
+
r"""
|
|
45
|
+
Compute `k`-th Bernoulli number using a multimodular algorithm.
|
|
46
|
+
(Wrapper for bernmm library.)
|
|
47
|
+
|
|
48
|
+
INPUT:
|
|
49
|
+
|
|
50
|
+
- ``k`` -- nonnegative integer
|
|
51
|
+
- ``num_threads`` -- integer `\geq 1`, number of threads to use
|
|
52
|
+
|
|
53
|
+
COMPLEXITY:
|
|
54
|
+
|
|
55
|
+
Pretty much quadratic in `k`. See the paper "A multimodular algorithm
|
|
56
|
+
for computing Bernoulli numbers", David Harvey, 2008, for more details.
|
|
57
|
+
|
|
58
|
+
EXAMPLES::
|
|
59
|
+
|
|
60
|
+
sage: from sage.rings.bernmm import bernmm_bern_rat
|
|
61
|
+
|
|
62
|
+
sage: bernmm_bern_rat(0)
|
|
63
|
+
1
|
|
64
|
+
sage: bernmm_bern_rat(1)
|
|
65
|
+
-1/2
|
|
66
|
+
sage: bernmm_bern_rat(2)
|
|
67
|
+
1/6
|
|
68
|
+
sage: bernmm_bern_rat(3)
|
|
69
|
+
0
|
|
70
|
+
sage: bernmm_bern_rat(100)
|
|
71
|
+
-94598037819122125295227433069493721872702841533066936133385696204311395415197247711/33330
|
|
72
|
+
sage: bernmm_bern_rat(100, 3)
|
|
73
|
+
-94598037819122125295227433069493721872702841533066936133385696204311395415197247711/33330
|
|
74
|
+
|
|
75
|
+
TESTS::
|
|
76
|
+
|
|
77
|
+
sage: lst1 = [ bernoulli(2*k, algorithm='bernmm', num_threads=2) for k in [2932, 2957, 3443, 3962, 3973] ]
|
|
78
|
+
sage: lst2 = [ bernoulli(2*k, algorithm='pari') for k in [2932, 2957, 3443, 3962, 3973] ] # needs sage.libs.pari
|
|
79
|
+
sage: lst1 == lst2 # needs sage.libs.pari
|
|
80
|
+
True
|
|
81
|
+
sage: [ Zmod(101)(t) for t in lst1 ]
|
|
82
|
+
[77, 72, 89, 98, 86]
|
|
83
|
+
sage: [ Zmod(101)(t) for t in lst2 ] # needs sage.libs.pari
|
|
84
|
+
[77, 72, 89, 98, 86]
|
|
85
|
+
"""
|
|
86
|
+
cdef Rational x
|
|
87
|
+
|
|
88
|
+
if k < 0:
|
|
89
|
+
raise ValueError("k must be nonnegative")
|
|
90
|
+
|
|
91
|
+
x = Rational()
|
|
92
|
+
sig_on()
|
|
93
|
+
bern_rat(x.value, k, num_threads)
|
|
94
|
+
sig_off()
|
|
95
|
+
|
|
96
|
+
return x
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def bernmm_bern_modp(long p, long k):
|
|
100
|
+
r"""
|
|
101
|
+
Compute `B_k \mod p`, where `B_k` is the `k`-th Bernoulli number.
|
|
102
|
+
|
|
103
|
+
If `B_k` is not `p`-integral, return `-1`.
|
|
104
|
+
|
|
105
|
+
INPUT:
|
|
106
|
+
|
|
107
|
+
- ``p`` -- a prime
|
|
108
|
+
- ``k`` -- nonnegative integer
|
|
109
|
+
|
|
110
|
+
COMPLEXITY:
|
|
111
|
+
|
|
112
|
+
Pretty much linear in `p`.
|
|
113
|
+
|
|
114
|
+
EXAMPLES::
|
|
115
|
+
|
|
116
|
+
sage: from sage.rings.bernmm import bernmm_bern_modp
|
|
117
|
+
|
|
118
|
+
sage: # needs sage.libs.flint
|
|
119
|
+
sage: bernoulli(0) % 5, bernmm_bern_modp(5, 0)
|
|
120
|
+
(1, 1)
|
|
121
|
+
sage: bernoulli(1) % 5, bernmm_bern_modp(5, 1)
|
|
122
|
+
(2, 2)
|
|
123
|
+
sage: bernoulli(2) % 5, bernmm_bern_modp(5, 2)
|
|
124
|
+
(1, 1)
|
|
125
|
+
sage: bernoulli(3) % 5, bernmm_bern_modp(5, 3)
|
|
126
|
+
(0, 0)
|
|
127
|
+
sage: bernoulli(4), bernmm_bern_modp(5, 4)
|
|
128
|
+
(-1/30, -1)
|
|
129
|
+
sage: bernoulli(18) % 5, bernmm_bern_modp(5, 18)
|
|
130
|
+
(4, 4)
|
|
131
|
+
sage: bernoulli(19) % 5, bernmm_bern_modp(5, 19)
|
|
132
|
+
(0, 0)
|
|
133
|
+
|
|
134
|
+
sage: p = 10000019; k = 1000
|
|
135
|
+
sage: bernoulli(k) % p # needs sage.libs.flint
|
|
136
|
+
1972762
|
|
137
|
+
sage: bernmm_bern_modp(p, k)
|
|
138
|
+
1972762
|
|
139
|
+
|
|
140
|
+
TESTS:
|
|
141
|
+
|
|
142
|
+
Check that bernmm works with the new NTL single precision modular
|
|
143
|
+
arithmetic from :issue:`19874`::
|
|
144
|
+
|
|
145
|
+
sage: from sage.rings.bernmm import bernmm_bern_modp
|
|
146
|
+
sage: bernmm_bern_modp(7, 128) == bernoulli(128) % 7 # needs sage.libs.flint
|
|
147
|
+
True
|
|
148
|
+
"""
|
|
149
|
+
cdef long x
|
|
150
|
+
|
|
151
|
+
if k < 0:
|
|
152
|
+
raise ValueError("k must be nonnegative")
|
|
153
|
+
|
|
154
|
+
sig_on()
|
|
155
|
+
x = bern_modp(p, k)
|
|
156
|
+
sig_off()
|
|
157
|
+
|
|
158
|
+
return x
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
# ============ end of file
|
|
Binary file
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-ntl
|
|
2
|
+
# distutils: libraries = NTL_LIBRARIES gmp
|
|
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.libs.pari
|
|
9
|
+
r"""
|
|
10
|
+
Bernoulli numbers modulo p
|
|
11
|
+
|
|
12
|
+
AUTHOR:
|
|
13
|
+
|
|
14
|
+
- David Harvey (2006-07-26): initial version
|
|
15
|
+
- William Stein (2006-07-28): some touch up.
|
|
16
|
+
- David Harvey (2006-08-06): new, faster algorithm, also using faster NTL interface
|
|
17
|
+
- David Harvey (2007-08-31): algorithm for a single Bernoulli number mod p
|
|
18
|
+
- David Harvey (2008-06): added interface to bernmm, removed old code
|
|
19
|
+
"""
|
|
20
|
+
# ****************************************************************************
|
|
21
|
+
# Copyright (C) 2006 William Stein <wstein@gmail.com>
|
|
22
|
+
# 2006 David Harvey <dmharvey@math.harvard.edu>
|
|
23
|
+
#
|
|
24
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
25
|
+
# https://www.gnu.org/licenses/
|
|
26
|
+
# ****************************************************************************
|
|
27
|
+
|
|
28
|
+
from sage.arith.misc import is_prime, primitive_root
|
|
29
|
+
|
|
30
|
+
cimport sage.rings.fast_arith
|
|
31
|
+
import sage.rings.fast_arith
|
|
32
|
+
cdef sage.rings.fast_arith.arith_int arith_int
|
|
33
|
+
arith_int = sage.rings.fast_arith.arith_int()
|
|
34
|
+
|
|
35
|
+
ctypedef long long llong
|
|
36
|
+
|
|
37
|
+
import sage.arith.all
|
|
38
|
+
|
|
39
|
+
from sage.libs.ntl import all as ntl
|
|
40
|
+
from sage.libs.ntl.ntl_ZZ_pX cimport ntl_ZZ_pX
|
|
41
|
+
from sage.rings.bernmm import bernmm_bern_modp
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def verify_bernoulli_mod_p(data):
|
|
45
|
+
r"""
|
|
46
|
+
Compute checksum for Bernoulli numbers.
|
|
47
|
+
|
|
48
|
+
It checks the identity
|
|
49
|
+
|
|
50
|
+
.. MATH::
|
|
51
|
+
|
|
52
|
+
\sum_{n=0}^{(p-3)/2} 2^{2n} (2n+1) B_{2n} \equiv -2 \pmod p
|
|
53
|
+
|
|
54
|
+
(see "Irregular Primes to One Million", Buhler et al)
|
|
55
|
+
|
|
56
|
+
INPUT:
|
|
57
|
+
|
|
58
|
+
- ``data`` -- list; same format as output of :func:`bernoulli_mod_p` function
|
|
59
|
+
|
|
60
|
+
OUTPUT: boolean; ``True`` if checksum passed
|
|
61
|
+
|
|
62
|
+
EXAMPLES::
|
|
63
|
+
|
|
64
|
+
sage: from sage.rings.bernoulli_mod_p import verify_bernoulli_mod_p
|
|
65
|
+
sage: verify_bernoulli_mod_p(bernoulli_mod_p(next_prime(3)))
|
|
66
|
+
True
|
|
67
|
+
sage: verify_bernoulli_mod_p(bernoulli_mod_p(next_prime(1000)))
|
|
68
|
+
True
|
|
69
|
+
sage: verify_bernoulli_mod_p([1, 2, 4, 5, 4])
|
|
70
|
+
True
|
|
71
|
+
sage: verify_bernoulli_mod_p([1, 2, 3, 4, 5])
|
|
72
|
+
False
|
|
73
|
+
|
|
74
|
+
This one should test that long longs are working::
|
|
75
|
+
|
|
76
|
+
sage: verify_bernoulli_mod_p(bernoulli_mod_p(next_prime(20000)))
|
|
77
|
+
True
|
|
78
|
+
|
|
79
|
+
AUTHOR: David Harvey
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
cdef int N, p, i, product, sum, value, element
|
|
83
|
+
N = len(data)
|
|
84
|
+
p = N*2 + 1
|
|
85
|
+
product = 1
|
|
86
|
+
sum = 0
|
|
87
|
+
for i from 0 <= i < N:
|
|
88
|
+
element = data[i]
|
|
89
|
+
value = <int> (((((<llong> product) * (2*i+1)) % p) * element) % p)
|
|
90
|
+
sum = (sum + value) % p
|
|
91
|
+
product = (4 * product) % p
|
|
92
|
+
|
|
93
|
+
if (sum + 2) % p == 0:
|
|
94
|
+
return True
|
|
95
|
+
else:
|
|
96
|
+
return False
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def bernoulli_mod_p(int p):
|
|
100
|
+
r"""
|
|
101
|
+
Return the Bernoulli numbers `B_0, B_2, ... B_{p-3}` modulo `p`.
|
|
102
|
+
|
|
103
|
+
INPUT:
|
|
104
|
+
|
|
105
|
+
- ``p`` -- integer; a prime
|
|
106
|
+
|
|
107
|
+
OUTPUT:
|
|
108
|
+
|
|
109
|
+
list -- Bernoulli numbers modulo `p` as a list
|
|
110
|
+
of integers [B(0), B(2), ... B(p-3)].
|
|
111
|
+
|
|
112
|
+
ALGORITHM:
|
|
113
|
+
|
|
114
|
+
Described in accompanying latex file.
|
|
115
|
+
|
|
116
|
+
PERFORMANCE:
|
|
117
|
+
|
|
118
|
+
Should be complexity `O(p \log p)`.
|
|
119
|
+
|
|
120
|
+
EXAMPLES:
|
|
121
|
+
|
|
122
|
+
Check the results against PARI's C-library implementation (that
|
|
123
|
+
computes exact rationals) for `p = 37`::
|
|
124
|
+
|
|
125
|
+
sage: bernoulli_mod_p(37)
|
|
126
|
+
[1, 31, 16, 15, 16, 4, 17, 32, 22, 31, 15, 15, 17, 12, 29, 2, 0, 2]
|
|
127
|
+
sage: [bernoulli(n) % 37 for n in range(0, 36, 2)]
|
|
128
|
+
[1, 31, 16, 15, 16, 4, 17, 32, 22, 31, 15, 15, 17, 12, 29, 2, 0, 2]
|
|
129
|
+
|
|
130
|
+
Boundary case::
|
|
131
|
+
|
|
132
|
+
sage: bernoulli_mod_p(3)
|
|
133
|
+
[1]
|
|
134
|
+
|
|
135
|
+
AUTHOR:
|
|
136
|
+
|
|
137
|
+
- David Harvey (2006-08-06)
|
|
138
|
+
"""
|
|
139
|
+
if p <= 2:
|
|
140
|
+
raise ValueError("p (=%s) must be a prime >= 3" % p)
|
|
141
|
+
|
|
142
|
+
if not is_prime(p):
|
|
143
|
+
raise ValueError("p (=%s) must be a prime" % p)
|
|
144
|
+
|
|
145
|
+
cdef int g, gSqr, gInv, gInvSqr, isOdd
|
|
146
|
+
|
|
147
|
+
g = primitive_root(p)
|
|
148
|
+
gInv = arith_int.c_inverse_mod_int(g, p)
|
|
149
|
+
gSqr = ((<llong> g) * g) % p
|
|
150
|
+
gInvSqr = ((<llong> gInv) * gInv) % p
|
|
151
|
+
isOdd = ((p-1)/2) % 2
|
|
152
|
+
|
|
153
|
+
# STEP 1: compute the polynomials G(X) and J(X)
|
|
154
|
+
|
|
155
|
+
# These hold g^{i-1} and g^{-i} at the beginning of each iteration
|
|
156
|
+
cdef llong gPower, gPowerInv
|
|
157
|
+
gPower = gInv
|
|
158
|
+
gPowerInv = 1
|
|
159
|
+
|
|
160
|
+
# "constant" is (g-1)/2 mod p
|
|
161
|
+
cdef int constant
|
|
162
|
+
if g % 2:
|
|
163
|
+
constant = (g-1)/2
|
|
164
|
+
else:
|
|
165
|
+
constant = (g+p-1)/2
|
|
166
|
+
|
|
167
|
+
# fudge holds g^{i^2}, fudgeInv holds g^{-i^2}
|
|
168
|
+
cdef int fudge, fudgeInv
|
|
169
|
+
fudge = fudgeInv = 1
|
|
170
|
+
|
|
171
|
+
cdef ntl_ZZ_pX G, J
|
|
172
|
+
G = ntl.ZZ_pX([], ntl.ZZ(p))
|
|
173
|
+
J = ntl.ZZ_pX([], ntl.ZZ(p))
|
|
174
|
+
G.preallocate_space((p-1)/2)
|
|
175
|
+
J.preallocate_space((p-1)/2)
|
|
176
|
+
|
|
177
|
+
cdef int i
|
|
178
|
+
cdef llong temp, h
|
|
179
|
+
for i from 0 <= i < (p-1)/2:
|
|
180
|
+
# compute h = h(g^i)/g^i (h(x) is as in latex notes)
|
|
181
|
+
temp = g * gPower
|
|
182
|
+
h = ((p + constant - (temp / p)) * gPowerInv) % p
|
|
183
|
+
gPower = temp % p
|
|
184
|
+
gPowerInv = (gPowerInv * gInv) % p
|
|
185
|
+
|
|
186
|
+
# store the coefficient g^{i^2} h(g^i)/g^i
|
|
187
|
+
G.setitem_from_int(i, <int> ((h * fudge) % p))
|
|
188
|
+
|
|
189
|
+
# store the coefficient g^{-i^2}
|
|
190
|
+
J.setitem_from_int(i, fudgeInv)
|
|
191
|
+
|
|
192
|
+
# update fudge and fudgeInv
|
|
193
|
+
fudge = (((fudge * gPower) % p) * ((gPower * g) % p)) % p
|
|
194
|
+
fudgeInv = (((fudgeInv * gPowerInv) % p) * ((gPowerInv * g) % p)) % p
|
|
195
|
+
|
|
196
|
+
J.setitem_from_int(0, 0)
|
|
197
|
+
|
|
198
|
+
# STEP 2: multiply the polynomials
|
|
199
|
+
|
|
200
|
+
cdef ntl_ZZ_pX product
|
|
201
|
+
product = G * J
|
|
202
|
+
|
|
203
|
+
# STEP 3: assemble the result
|
|
204
|
+
|
|
205
|
+
cdef int gSqrPower, value
|
|
206
|
+
output = [1]
|
|
207
|
+
gSqrPower = gSqr
|
|
208
|
+
fudge = g
|
|
209
|
+
for i from 1 <= i < (p-1)/2:
|
|
210
|
+
value = product.getitem_as_int(i + (p-1)/2)
|
|
211
|
+
|
|
212
|
+
if isOdd:
|
|
213
|
+
value = (G.getitem_as_int(i) + product.getitem_as_int(i) - value + p) % p
|
|
214
|
+
else:
|
|
215
|
+
value = (G.getitem_as_int(i) + product.getitem_as_int(i) + value) % p
|
|
216
|
+
|
|
217
|
+
value = (((4 * i * (<llong> fudge)) % p) * (<llong> value)) % p
|
|
218
|
+
value = ((<llong> value) * (arith_int.c_inverse_mod_int(1 - gSqrPower, p))) % p
|
|
219
|
+
|
|
220
|
+
output.append(value)
|
|
221
|
+
|
|
222
|
+
gSqrPower = ((<llong> gSqrPower) * g) % p
|
|
223
|
+
fudge = ((<llong> fudge) * gSqrPower) % p
|
|
224
|
+
gSqrPower = ((<llong> gSqrPower) * g) % p
|
|
225
|
+
|
|
226
|
+
return output
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def bernoulli_mod_p_single(long p, long k):
|
|
230
|
+
r"""
|
|
231
|
+
Return the Bernoulli number `B_k` mod `p`.
|
|
232
|
+
|
|
233
|
+
If `B_k` is not `p`-integral, an :exc:`ArithmeticError` is raised.
|
|
234
|
+
|
|
235
|
+
INPUT:
|
|
236
|
+
|
|
237
|
+
- ``p`` -- integer; a prime
|
|
238
|
+
- ``k`` -- nonnegative integer
|
|
239
|
+
|
|
240
|
+
OUTPUT: the `k`-th Bernoulli number mod `p`
|
|
241
|
+
|
|
242
|
+
EXAMPLES::
|
|
243
|
+
|
|
244
|
+
sage: bernoulli_mod_p_single(1009, 48)
|
|
245
|
+
628
|
|
246
|
+
sage: bernoulli(48) % 1009
|
|
247
|
+
628
|
|
248
|
+
|
|
249
|
+
sage: bernoulli_mod_p_single(1, 5)
|
|
250
|
+
Traceback (most recent call last):
|
|
251
|
+
...
|
|
252
|
+
ValueError: p (=1) must be a prime >= 3
|
|
253
|
+
|
|
254
|
+
sage: bernoulli_mod_p_single(100, 4)
|
|
255
|
+
Traceback (most recent call last):
|
|
256
|
+
...
|
|
257
|
+
ValueError: p (=100) must be a prime
|
|
258
|
+
|
|
259
|
+
sage: bernoulli_mod_p_single(19, 5)
|
|
260
|
+
0
|
|
261
|
+
|
|
262
|
+
sage: bernoulli_mod_p_single(19, 18)
|
|
263
|
+
Traceback (most recent call last):
|
|
264
|
+
...
|
|
265
|
+
ArithmeticError: B_k is not integral at p
|
|
266
|
+
|
|
267
|
+
sage: bernoulli_mod_p_single(19, -4)
|
|
268
|
+
Traceback (most recent call last):
|
|
269
|
+
...
|
|
270
|
+
ValueError: k must be nonnegative
|
|
271
|
+
|
|
272
|
+
Check results against :class:`bernoulli_mod_p`::
|
|
273
|
+
|
|
274
|
+
sage: bernoulli_mod_p(37)
|
|
275
|
+
[1, 31, 16, 15, 16, 4, 17, 32, 22, 31, 15, 15, 17, 12, 29, 2, 0, 2]
|
|
276
|
+
sage: [bernoulli_mod_p_single(37, n) % 37 for n in range(0, 36, 2)]
|
|
277
|
+
[1, 31, 16, 15, 16, 4, 17, 32, 22, 31, 15, 15, 17, 12, 29, 2, 0, 2]
|
|
278
|
+
|
|
279
|
+
sage: bernoulli_mod_p(31)
|
|
280
|
+
[1, 26, 1, 17, 1, 9, 11, 27, 14, 23, 13, 22, 14, 8, 14]
|
|
281
|
+
sage: [bernoulli_mod_p_single(31, n) % 31 for n in range(0, 30, 2)]
|
|
282
|
+
[1, 26, 1, 17, 1, 9, 11, 27, 14, 23, 13, 22, 14, 8, 14]
|
|
283
|
+
|
|
284
|
+
sage: bernoulli_mod_p(3)
|
|
285
|
+
[1]
|
|
286
|
+
sage: [bernoulli_mod_p_single(3, n) % 3 for n in range(0, 2, 2)]
|
|
287
|
+
[1]
|
|
288
|
+
|
|
289
|
+
sage: bernoulli_mod_p(5)
|
|
290
|
+
[1, 1]
|
|
291
|
+
sage: [bernoulli_mod_p_single(5, n) % 5 for n in range(0, 4, 2)]
|
|
292
|
+
[1, 1]
|
|
293
|
+
|
|
294
|
+
sage: bernoulli_mod_p(7)
|
|
295
|
+
[1, 6, 3]
|
|
296
|
+
sage: [bernoulli_mod_p_single(7, n) % 7 for n in range(0, 6, 2)]
|
|
297
|
+
[1, 6, 3]
|
|
298
|
+
|
|
299
|
+
AUTHOR:
|
|
300
|
+
|
|
301
|
+
- David Harvey (2007-08-31)
|
|
302
|
+
- David Harvey (2008-06): rewrote to use bernmm library
|
|
303
|
+
"""
|
|
304
|
+
if p <= 2:
|
|
305
|
+
raise ValueError("p (=%s) must be a prime >= 3" % p)
|
|
306
|
+
|
|
307
|
+
if not is_prime(p):
|
|
308
|
+
raise ValueError("p (=%s) must be a prime" % p)
|
|
309
|
+
|
|
310
|
+
cdef long x = bernmm_bern_modp(p, k)
|
|
311
|
+
if x == -1:
|
|
312
|
+
raise ArithmeticError("B_k is not integral at p")
|
|
313
|
+
return x
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-ntl
|