Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/quadratic_forms/extras.py
4056 views
1
2
from sage.matrix.constructor import matrix
3
from sage.matrix.matrix import is_Matrix
4
from sage.rings.arith import legendre_symbol
5
from sage.rings.integer_ring import ZZ
6
7
def is_triangular_number(n):
8
"""
9
Determines if the integer n is a triangular number.
10
(I.e. determine if n = a*(a+1)/2 for some natural number a.)
11
If so, return the number a, otherwise return False.
12
13
Note: As a convention, n=0 is considered triangular for the
14
number a=0 only (and not for a=-1).
15
16
WARNING: Any non-zero value will return True, so this will test as
17
True iff n is triangular and not zero. If n is zero, then this
18
will return the integer zero, which tests as False, so one must test
19
20
if is_triangular_number(n) != False:
21
22
instead of
23
24
if is_triangular_number(n):
25
26
to get zero to appear triangular.
27
28
29
INPUT:
30
an integer
31
32
OUTPUT:
33
either False or a non-negative integer
34
35
EXAMPLES:
36
sage: is_triangular_number(3)
37
2
38
sage: is_triangular_number(1)
39
1
40
sage: is_triangular_number(2)
41
False
42
sage: is_triangular_number(0)
43
0
44
sage: is_triangular_number(-1)
45
False
46
sage: is_triangular_number(-11)
47
False
48
sage: is_triangular_number(-1000)
49
False
50
sage: is_triangular_number(-0)
51
0
52
sage: is_triangular_number(10^6 * (10^6 +1)/2)
53
1000000
54
"""
55
if n < 0:
56
return False
57
elif n == 0:
58
return ZZ(0)
59
else:
60
from sage.functions.all import sqrt
61
## Try to solve for the integer a
62
try:
63
disc_sqrt = ZZ(sqrt(1+8*n))
64
a = ZZ( (ZZ(-1) + disc_sqrt) / ZZ(2) )
65
return a
66
except:
67
return False
68
69
70
71
def extend_to_primitive(A_input):
72
"""
73
Given a matrix (resp. list of vectors), extend it to a square
74
matrix (resp. list of vectors), such that its determinant is the
75
gcd of its minors (i.e. extend the basis of a lattice to a
76
"maximal" one in Z^n).
77
78
Author(s): Gonzalo Tornaria and Jonathan Hanke.
79
80
INPUT:
81
a matrix, or a list of length n vectors (in the same space)
82
83
OUTPUT:
84
a square matrix, or a list of n vectors (resp.)
85
86
EXAMPLES:
87
sage: A = Matrix(ZZ, 3, 2, range(6))
88
sage: extend_to_primitive(A)
89
[ 0 1 0]
90
[ 2 3 0]
91
[ 4 5 -1]
92
93
sage: extend_to_primitive([vector([1,2,3])])
94
[(1, 2, 3), (0, 1, 0), (0, 0, 1)]
95
96
"""
97
## Deal with a list of vectors
98
if not is_Matrix(A_input):
99
A = matrix(A_input) ## Make a matrix A with the given rows.
100
vec_output_flag = True
101
else:
102
A = A_input
103
vec_output_flag = False
104
105
106
## Arrange for A to have more columns than rows.
107
if A.is_square():
108
return A
109
if A.nrows() > A.ncols():
110
return extend_to_primitive(A.transpose()).transpose()
111
112
## Setup
113
k = A.nrows()
114
n = A.ncols()
115
R = A.base_ring()
116
117
# Smith normal form transformation, assuming more columns than rows
118
V = A.smith_form()[2]
119
120
## Extend the matrix in new coordinates, then switch back.
121
B = A * V
122
B_new = matrix(R, n-k, n)
123
for i in range(n-k):
124
B_new[i, n-i-1] = 1
125
C = B.stack(B_new)
126
D = C * V**(-1)
127
128
## DIAGNOSTIC
129
#print "A = ", A, "\n"
130
#print "B = ", B, "\n"
131
#print "C = ", C, "\n"
132
#print "D = ", D, "\n"
133
134
# Normalize for a positive determinant
135
if D.det() < 0:
136
D.rescale_row(n-1, -1)
137
138
## Return the current information
139
if vec_output_flag:
140
return D.rows()
141
else:
142
return D
143
144
def least_quadratic_nonresidue(p):
145
"""
146
Returns the smallest positive integer quadratic non-residue in Z/pZ for primes p>2.
147
148
EXAMPLES::
149
150
sage: least_quadratic_nonresidue(5)
151
2
152
sage: [least_quadratic_nonresidue(p) for p in prime_range(3,100)]
153
[2, 2, 3, 2, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 2, 2, 2, 7, 5, 3, 2, 3, 5]
154
155
TESTS:
156
157
Raises an error if input is a positive composite integer.
158
159
::
160
161
sage: least_quadratic_nonresidue(20)
162
Traceback (most recent call last):
163
...
164
ValueError: Oops! p must be a prime number > 2.
165
166
167
Raises an error if input is 2. This is because every integer is a
168
quadratic residue modulo 2.
169
170
::
171
172
sage: least_quadratic_nonresidue(2)
173
Traceback (most recent call last):
174
...
175
ValueError: Oops! There are no quadratic non-residues in Z/2Z.
176
"""
177
from sage.functions.all import floor
178
p1 = abs(p)
179
180
## Deal with the prime p = 2 and |p| <= 1.
181
if p1 == 2:
182
raise ValueError, "Oops! There are no quadratic non-residues in Z/2Z."
183
if p1 < 2:
184
raise ValueError, "Oops! p must be a prime number > 2."
185
186
## Find the smallest non-residue mod p
187
## For 7/8 of primes the answer is 2, 3 or 5:
188
if p%8 in (3,5):
189
return ZZ(2)
190
if p%12 in (5,7):
191
return ZZ(3)
192
if p%5 in (2,3):
193
return ZZ(5)
194
## default case (first needed for p=71):
195
if not p.is_prime():
196
raise ValueError, "Oops! p must be a prime number > 2."
197
from sage.misc.misc import xsrange
198
for r in xsrange(7,p):
199
if legendre_symbol(r, p) == -1:
200
return ZZ(r)
201
202
203