Skip to content

Commit

Permalink
ideals of non-maximal orders, for quadratic fields in particular
Browse files Browse the repository at this point in the history
  • Loading branch information
yyyyx4 committed Jun 13, 2023
1 parent aaca562 commit 346b1ad
Show file tree
Hide file tree
Showing 7 changed files with 802 additions and 50 deletions.
1 change: 1 addition & 0 deletions src/doc/en/reference/number_fields/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Orders, Ideals, Ideal Classes
sage/rings/number_field/order
sage/rings/number_field/number_field_ideal
sage/rings/number_field/number_field_ideal_rel
sage/rings/number_field/order_ideal
sage/rings/number_field/class_group
sage/rings/number_field/unit_group
sage/rings/number_field/S_unit_solver
Expand Down
16 changes: 7 additions & 9 deletions src/sage/rings/number_field/class_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,11 @@
sage: I * I.ideal() # ideal classes coerce to their representative ideal
Fractional ideal (4, 1/2*a + 3/2)
sage: O = K.OK(); O
Maximal Order in Number Field in a with defining polynomial x^2 + 23
sage: O*(2, 1/2*a + 1/2)
sage: K*(2, 1/2*a + 1/2)
Fractional ideal (2, 1/2*a + 1/2)
sage: (O*(2, 1/2*a + 1/2)).is_principal()
sage: (K*(2, 1/2*a + 1/2)).is_principal()
False
sage: (O*(2, 1/2*a + 1/2))^3
sage: (K*(2, 1/2*a + 1/2))^3
Fractional ideal (1/2*a - 3/2)
"""

Expand Down Expand Up @@ -66,7 +64,7 @@ class FractionalIdealClass(AbelianGroupWithValuesElement):
sage: K.<w> = QuadraticField(-23)
sage: OK = K.ring_of_integers()
sage: C = OK.class_group()
sage: P2a, P2b = [P for P, e in (2*OK).factor()]
sage: P2a, P2b = [P for P, e in (2*K).factor()]
sage: c = C(P2a); c
Fractional ideal class (2, 1/2*w - 1/2)
sage: c.gens()
Expand Down Expand Up @@ -208,7 +206,7 @@ def is_principal(self):
sage: K.<w> = QuadraticField(-23)
sage: OK = K.ring_of_integers()
sage: C = OK.class_group()
sage: P2a, P2b = [P for P, e in (2*OK).factor()]
sage: P2a, P2b = [P for P, e in (2*K).factor()]
sage: c = C(P2a)
sage: c.is_principal()
False
Expand Down Expand Up @@ -250,7 +248,7 @@ def ideal(self):
sage: K.<w> = QuadraticField(-23)
sage: OK = K.ring_of_integers()
sage: C = OK.class_group()
sage: P2a, P2b = [P for P, e in (2*OK).factor()]
sage: P2a, P2b = [P for P, e in (2*K).factor()]
sage: c = C(P2a); c
Fractional ideal class (2, 1/2*w - 1/2)
sage: c.ideal()
Expand Down Expand Up @@ -315,7 +313,7 @@ def gens(self):
sage: K.<w> = QuadraticField(-23)
sage: OK = K.ring_of_integers()
sage: C = OK.class_group()
sage: P2a, P2b = [P for P, e in (2*OK).factor()]
sage: P2a, P2b = [P for P, e in (2*K).factor()]
sage: c = C(P2a); c
Fractional ideal class (2, 1/2*w - 1/2)
sage: c.gens()
Expand Down
9 changes: 3 additions & 6 deletions src/sage/rings/number_field/number_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -10207,7 +10207,7 @@ def hilbert_symbol(self, a, b, P=None):
0
sage: K.hilbert_symbol(a, a + 5, K.ideal(5))
1
sage: K.hilbert_symbol(a + 1, 13, (a+6)*K.maximal_order())
sage: K.hilbert_symbol(a + 1, 13, (a+6)*K)
-1
sage: [emb1, emb2] = K.embeddings(AA)
sage: K.hilbert_symbol(a, -1, emb1)
Expand Down Expand Up @@ -10239,8 +10239,7 @@ def hilbert_symbol(self, a, b, P=None):
Primes above 2::
sage: K.<a> = NumberField(x^5 - 23)
sage: O = K.maximal_order()
sage: p = [p[0] for p in (2*O).factor() if p[0].norm() == 16][0]
sage: p = [p[0] for p in (2*K).factor() if p[0].norm() == 16][0]
sage: K.hilbert_symbol(a, a + 5, p)
1
sage: K.hilbert_symbol(a, 2, p)
Expand Down Expand Up @@ -10288,8 +10287,7 @@ def hilbert_symbol(self, a, b, P=None):
`a` and `b` do not have to be integral or coprime::
sage: K.<i> = QuadraticField(-1)
sage: O = K.maximal_order()
sage: K.hilbert_symbol(1/2, 1/6, 3*O)
sage: K.hilbert_symbol(1/2, 1/6, 3*K)
1
sage: p = 1 + i
sage: K.hilbert_symbol(p, p, p)
Expand Down Expand Up @@ -12794,7 +12792,6 @@ def _splitting_classes_gens_(K, m, d):
"""
from sage.groups.abelian_gps.abelian_group import AbelianGroup

R = K.ring_of_integers()
Zm = IntegerModRing(m)
unit_gens = Zm.unit_gens()
Zmstar = AbelianGroup(len(unit_gens), [x.multiplicative_order() for x in unit_gens])
Expand Down
20 changes: 8 additions & 12 deletions src/sage/rings/number_field/number_field_element.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,13 @@ def _inverse_mod_generic(elt, I):
sage: x = polygen(ZZ, 'x')
sage: OE.<w> = EquationOrder(x^3 - x + 2)
sage: from sage.rings.number_field.number_field_element import _inverse_mod_generic
sage: _inverse_mod_generic(w, 13*OE)
sage: _inverse_mod_generic(w, 13)
6*w^2 - 6
"""
from sage.matrix.constructor import matrix
R = elt.parent()
if not R.is_maximal():
raise NotImplementedError('not implemented for non-maximal orders')
I = R.number_field().fractional_ideal(I)
if not I.is_integral():
raise ValueError("inverse is only defined modulo integral ideals")
Expand Down Expand Up @@ -2097,15 +2099,9 @@ cdef class NumberFieldElement(NumberFieldElement_base):
sage: R = K.maximal_order()
sage: R(i+1).gcd(2)
i + 1
Non-maximal orders are not supported::
sage: R = K.order(2*i)
sage: R(1).gcd(R(4*i))
Traceback (most recent call last):
...
NotImplementedError: gcd() for Order in Number Field in i
with defining polynomial x^2 + 1 with i = 1*I is not implemented
1
The following field has class number 3, but if the ideal
``(self, other)`` happens to be principal, this still works::
Expand Down Expand Up @@ -2137,7 +2133,7 @@ cdef class NumberFieldElement(NumberFieldElement_base):
return R.one()

from .order import is_NumberFieldOrder
if not is_NumberFieldOrder(R) or not R.is_maximal():
if not is_NumberFieldOrder(R):
raise NotImplementedError("gcd() for %r is not implemented" % R)

K = R.number_field()
Expand Down Expand Up @@ -5354,13 +5350,13 @@ cdef class OrderElement_absolute(NumberFieldElement_absolute):
sage: x = polygen(ZZ, 'x')
sage: OE.<w> = EquationOrder(x^3 - x + 2)
sage: w.inverse_mod(13*OE)
sage: w.inverse_mod(13)
6*w^2 - 6
sage: w * (w.inverse_mod(13)) - 1 in 13*OE
sage: w * (w.inverse_mod(13)) - 1 in 13*OE.number_field()
True
sage: w.inverse_mod(13).parent() == OE
True
sage: w.inverse_mod(2*OE)
sage: w.inverse_mod(2)
Traceback (most recent call last):
...
ZeroDivisionError: w is not invertible modulo Fractional ideal (2)
Expand Down
5 changes: 2 additions & 3 deletions src/sage/rings/number_field/number_field_ideal.py
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,7 @@ def gens_reduced(self, proof=None):
def gens_two(self):
r"""
Express this ideal using exactly two generators, the first of
which is a generator for the intersection of the ideal with `Q`.
which is a generator for the intersection of the ideal with `\QQ`.
ALGORITHM: uses PARI's :pari:`idealtwoelt` function, which runs in
randomized polynomial time and is very fast in practice.
Expand Down Expand Up @@ -2444,8 +2444,7 @@ def is_coprime(self, other):
See :trac:`4536`::
sage: E.<a> = NumberField(x^5 + 7*x^4 + 18*x^2 + x - 3)
sage: OE = E.ring_of_integers()
sage: i,j,k = [u[0] for u in factor(3*OE)]
sage: i,j,k = [u[0] for u in factor(3*E)]
sage: (i/j).is_coprime(j/k)
False
sage: (j/k).is_coprime(j/k)
Expand Down
48 changes: 28 additions & 20 deletions src/sage/rings/number_field/order.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
We compute a basis for an order in a relative extension
that is generated by 2 elements::
sage: K.<a,b> = NumberField([x^2 + 1, x^2 - 3]); O = K.order([3*a, 2*b])
sage: K.<a,b> = NumberField([x^2 + 1, x^2 - 3])
sage: O = K.order([3*a, 2*b])
sage: O.basis()
[1, 3*a - 2*b, -6*b*a + 6, 3*a]
Expand Down Expand Up @@ -493,32 +494,40 @@ def ideal(self, *args, **kwds):
Fractional ideal (7)
sage: R = K.order(4*a)
sage: R.ideal(8)
Traceback (most recent call last):
...
NotImplementedError: ideals of non-maximal orders are not yet supported
doctest:warning ... FutureWarning: ...
Ideal (8, 32*a) of Order in Number Field in a with defining polynomial x^2 + 7
This function is called implicitly below::
sage: R = EquationOrder(x^2 + 2, 'a'); R
Maximal Order in Number Field in a with defining polynomial x^2 + 2
sage: (3,15)*R
doctest:warning ... DeprecationWarning: ...
Fractional ideal (3)
The zero ideal is handled properly::
sage: R.ideal(0)
Ideal (0) of Number Field in a with defining polynomial x^2 + 2
"""
if not self.is_maximal():
raise NotImplementedError("ideals of non-maximal orders not yet supported.")
from sage.misc.superseded import deprecation
deprecation(34806, 'In the future, constructing an ideal of the ring of '
'integers of a number field will use an implementation '
'compatible with ideals of other (non-maximal) orders, '
'rather than returning an integral fractional ideal of '
'its containing number field. Use .fractional_ideal(), '
'together with an .is_integral() check if desired, to '
'avoid your code breaking with future changes to Sage.')
if kwds.get('future', False) or not self.is_maximal():
if 'future' in kwds:
del kwds['future']
from sage.rings.number_field.order_ideal import NumberFieldOrderIdeal
return NumberFieldOrderIdeal(self, *args, **kwds)
if kwds.get('warn', True):
if 'warn' in kwds:
del kwds['warn']
from sage.misc.superseded import deprecation
deprecation(34198, 'In the future, constructing an ideal of the ring of '
'integers of a number field will use an implementation '
'compatible with ideals of other (non-maximal) orders, '
'rather than returning an integral fractional ideal of '
'its containing number field. Use .fractional_ideal(), '
'together with an .is_integral() check if desired, to '
'emulate the current behavior.\nSet warn=0 to silence '
'this warning, and future=1 to activate the upcoming '
'behavior already.')
I = self.number_field().ideal(*args, **kwds)
if not I.is_integral():
raise ValueError("ideal must be integral; use fractional_ideal to create a non-integral ideal.")
Expand All @@ -542,7 +551,7 @@ def _coerce_map_from_(self, R):

def __mul__(self, right):
"""
Create an ideal in this order using the notation ``Ok*gens``
Create an ideal in this order using the syntax ``O * gens``
EXAMPLES::
Expand All @@ -554,17 +563,16 @@ def __mul__(self, right):
sage: Ok = k.maximal_order(); Ok
Maximal Order in Number Field in a with defining polynomial x^2 + 5077
sage: Ok * (11, a + 7)
doctest:warning ... DeprecationWarning: ...
Fractional ideal (11, a + 7)
sage: (11, a + 7) * Ok
Fractional ideal (11, a + 7)
"""
if self.is_maximal():
return self._K.ideal(right)
raise TypeError
return self.ideal(right)

def __rmul__(self, left):
"""
Create an ideal in this order using the notation ``gens*Ok``.
Create an ideal in this order using the syntax ``gens * O``.
EXAMPLES::
Expand All @@ -580,7 +588,7 @@ def __rmul__(self, left):
sage: 17*Ok
Fractional ideal (17)
"""
return self * left
return self.ideal(left)

def is_field(self, proof=True):
r"""
Expand Down
Loading

0 comments on commit 346b1ad

Please sign in to comment.