Skip to content

Commit 65ceff8

Browse files
author
Release Manager
committed
gh-35809: Ensure GCD in `normalize_coordinates` for projective morphisms <!-- Please provide a concise, informative and self-explanatory title. --> <!-- Don't put issue numbers in the title. Put it in the Description below. --> <!-- For example, instead of "Fixes #12345", use "Add a new method to multiply two integers" --> ### 📚 Description This PR also attempts to address and fixes #35797. <!-- Describe your changes here in detail. --> <!-- Why is this change required? What problem does it solve? --> <!-- If this PR resolves an open issue, please link to it here. For example "Fixes #12345". --> <!-- If your change requires a documentation PR, please link it appropriately. --> ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. It should be `[x]` not `[x ]`. --> - [x] The title is concise, informative, and self-explanatory. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [x] I have created tests covering the changes. - [x] I have updated the documentation accordingly. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on - #12345: short description why this is a dependency - #34567: ... --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> URL: #35809 Reported by: Jing Guo Reviewer(s): bhutz
2 parents 404d9e5 + 6425e9e commit 65ceff8

File tree

1 file changed

+51
-17
lines changed

1 file changed

+51
-17
lines changed

src/sage/schemes/projective/projective_morphism.py

Lines changed: 51 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -792,25 +792,24 @@ def scale_by(self, t):
792792

793793
def normalize_coordinates(self, **kwds):
794794
"""
795-
Ensures that this morphism has integral coefficients, and,
796-
if the coordinate ring has a GCD, then it ensures that the
795+
Ensures that this morphism has integral coefficients.
796+
If the coordinate ring has a GCD, then it ensures that the
797797
coefficients have no common factor.
798798
799-
Also, makes the leading coefficients of the first polynomial
799+
It also makes the leading coefficients of the first polynomial
800800
positive (if positive has meaning in the coordinate ring).
801801
This is done in place.
802802
803-
When ``ideal`` or ``valuation`` is specified,
804-
normalization occurs with respect to the absolute value
805-
defined by the ``ideal`` or ``valuation``. That is, the
806-
coefficients are scaled such that one coefficient has
807-
absolute value 1 while the others have absolute value
808-
less than or equal to 1. Only supported when the base
809-
ring is a number field.
803+
When ``ideal`` or ``valuation`` is specified, normalization occurs
804+
with respect to the absolute value defined by the ``ideal`` or
805+
``valuation``. That is, the coefficients are scaled such that
806+
one coefficient has absolute value 1 while the others have
807+
absolute value less than or equal to 1.
808+
Only supported when the base ring is a number field.
810809
811810
INPUT:
812811
813-
keywords:
812+
kwds:
814813
815814
- ``ideal`` -- (optional) a prime ideal of the base ring of this
816815
morphism.
@@ -915,8 +914,33 @@ def normalize_coordinates(self, **kwds):
915914
3-adic Field with capped relative precision 20
916915
Defn: Defined on coordinates by sending (x : y) to
917916
(x^2 + (2 + O(3^20))*y^2 : (3 + O(3^21))*x*y)
917+
918+
Check that #35797 is fixed::
919+
920+
sage: R.<x> = QQ[]
921+
sage: K.<a> = NumberField(3*x^2 + 1)
922+
sage: P.<z,w> = ProjectiveSpace(K, 1)
923+
sage: f = DynamicalSystem_projective([a*(z^2 + w^2), z*w])
924+
sage: f.normalize_coordinates(); f
925+
Dynamical System of Projective Space of dimension 1 over
926+
Number Field in a with defining polynomial 3*x^2 + 1
927+
Defn: Defined on coordinates by sending (z : w) to
928+
((-3/2*a + 1/2)*z^2 + (-3/2*a + 1/2)*w^2 : (-3/2*a - 3/2)*z*w)
929+
930+
::
931+
932+
sage: R.<a,b> = QQ[]
933+
sage: P.<x,y,z> = ProjectiveSpace(FractionField(R), 2)
934+
sage: H = End(P)
935+
sage: f = H([a/b*(x*z + y^2)*x^2, a*b*(x*z + y^2)*y^2, a*(x*z + y^2)*z^2])
936+
sage: f.normalize_coordinates(); f
937+
Scheme endomorphism of Projective Space of dimension 2 over Fraction
938+
Field of Multivariate Polynomial Ring in a, b over Rational Field
939+
Defn: Defined on coordinates by sending (x : y : z) to
940+
(x^2 : (b^2)*y^2 : b*z^2)
918941
"""
919-
# if ideal or valuation is specified, we scale according the norm defined by the ideal/valuation
942+
# If ideal or valuation is specified, we scale according the norm
943+
# defined by the ideal/valuation
920944
ideal = kwds.pop('ideal', None)
921945
if ideal is not None:
922946
from sage.rings.number_field.number_field_ideal import NumberFieldFractionalIdeal
@@ -948,6 +972,7 @@ def normalize_coordinates(self, **kwds):
948972
min_val = min(valuations)
949973
self.scale_by(uniformizer**(-1 * min_val))
950974
return
975+
951976
valuation = kwds.pop('valuation', None)
952977
if valuation is not None:
953978
from sage.rings.padics.padic_valuation import pAdicValuation_base
@@ -967,13 +992,21 @@ def normalize_coordinates(self, **kwds):
967992
self.scale_by(uniformizer**(-1 * min_val))
968993
return
969994

970-
# clear any denominators from the coefficients
971995
N = self.codomain().ambient_space().dimension_relative() + 1
972-
LCM = lcm([self[i].denominator() for i in range(N)])
973-
self.scale_by(LCM)
974996

975997
R = self.domain().base_ring()
976998

999+
# Clear any denominators from the coefficients
1000+
if R in NumberFields():
1001+
if R.maximal_order() is ZZ:
1002+
denom = lcm([self[i].denominator() for i in range(N)])
1003+
else:
1004+
denom = R.ideal([c for poly in self for c in poly.coefficients()]).norm().denominator()
1005+
1006+
self.scale_by(denom)
1007+
else:
1008+
self.scale_by(lcm([self[i].denominator() for i in range(N)]))
1009+
9771010
# There are cases, such as the example above over GF(7),
9781011
# where we want to compute GCDs, but NOT in the case
9791012
# where R is a NumberField of class number > 1.
@@ -993,7 +1026,7 @@ def normalize_coordinates(self, **kwds):
9931026
if GCD != 1:
9941027
self.scale_by(R(1) / GCD)
9951028

996-
# scales by 1/gcd of the coefficients.
1029+
# Scale by 1/GCD of the coefficients.
9971030
if R in _NumberFields:
9981031
O = R.maximal_order()
9991032
elif isinstance(R, FiniteField):
@@ -1008,8 +1041,9 @@ def normalize_coordinates(self, **kwds):
10081041

10091042
if GCD != 1:
10101043
self.scale_by(1 / GCD)
1044+
1045+
# If R is not p-adic, we make the first coordinate positive
10111046
from sage.rings.padics.padic_base_generic import pAdicGeneric
1012-
# if R is not padic, we make the first coordinate positive
10131047
if not isinstance(R, pAdicGeneric):
10141048
if self[0].lc() < 0:
10151049
self.scale_by(-1)

0 commit comments

Comments
 (0)