@@ -2137,19 +2137,57 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute):
2137
2137
True
2138
2138
sage: for _ in range( 20) :
2139
2139
.... : assert O. random_element( ) . is_integral( )
2140
+
2141
+ Check that :issue:`34800` is fixed::
2142
+
2143
+ sage: K. <t> = QuadraticField( -10007^ 2)
2144
+ sage: ( t/10007) . is_integral( )
2145
+ True
2140
2146
"""
2147
+ cdef mpz_t m, n, q, r, s, t, u
2148
+ cdef bint result = False
2149
+
2150
+ # Shortcut for "obviously integral" elements
2141
2151
if mpz_cmp_ui(self .denom, 1 ) == 0 :
2142
2152
return True
2143
2153
2144
- # Check for an element of the form x + y sqrt(D) where x and y
2145
- # are half-integers.
2146
- if mpz_even_p(self .a) or mpz_even_p(self .b):
2147
- return False
2148
- if mpz_cmp_ui(self .denom, 2 ) != 0 :
2149
- return False
2150
- # Numbers with half-integral components are integral only for
2151
- # D = 1 mod 4
2152
- return mpz_fdiv_ui(self .D.value, 4 ) == 1
2154
+ # a + b*sqrt(D) is integral if and only if
2155
+ # denom | 2*a and denom^2 | a^2 - D*b^2.
2156
+ # Do division with remainder: 2*a = denom*m + n.
2157
+ mpz_init(t)
2158
+ mpz_init(m)
2159
+ mpz_init(n)
2160
+ mpz_mul_ui(t, self .a, 2 )
2161
+ mpz_fdiv_qr(m, n, t, self .denom)
2162
+ if mpz_cmp_ui(n, 0 ) == 0 :
2163
+ # Now 2*a = denom*m.
2164
+ # If m is even, then denom | a and gcd(denom, b) = 1, so
2165
+ # a + b*sqrt(D) is integral if and only if denom^2 | D.
2166
+ # If m is odd, then denom is even; put u = denom/2.
2167
+ # Then a + b*sqrt(D) is integral if and only if
2168
+ # b is odd, u^2 | D and D/u^2 is congruent to 1 mod 4.
2169
+ if mpz_even_p(m):
2170
+ mpz_init(s)
2171
+ mpz_mul(s, self .denom, self .denom)
2172
+ result = mpz_divisible_p(self .D.value, s)
2173
+ mpz_clear(s)
2174
+ elif mpz_odd_p(self .b):
2175
+ mpz_init(u)
2176
+ mpz_init(s)
2177
+ mpz_init(q)
2178
+ mpz_init(r)
2179
+ mpz_divexact_ui(u, self .denom, 2 )
2180
+ mpz_mul(s, u, u)
2181
+ mpz_fdiv_qr(q, r, self .D.value, s)
2182
+ result = mpz_cmp_ui(r, 0 ) == 0 and mpz_fdiv_ui(q, 4 ) == 1
2183
+ mpz_clear(u)
2184
+ mpz_clear(s)
2185
+ mpz_clear(q)
2186
+ mpz_clear(r)
2187
+ mpz_clear(t)
2188
+ mpz_clear(m)
2189
+ mpz_clear(n)
2190
+ return result
2153
2191
2154
2192
def charpoly (self , var = ' x' , algorithm = None ):
2155
2193
r """
0 commit comments