Skip to content
This repository was archived by the owner on Feb 1, 2023. It is now read-only.

Commit cf5228b

Browse files
committed
new implicit coercions to QQbar and AA
let python integers and number fields equipped with a complex (resp. real) embedding coerce into QQbar (AA)
1 parent 43511e4 commit cf5228b

File tree

2 files changed

+67
-25
lines changed

2 files changed

+67
-25
lines changed

src/sage/rings/number_field/number_field_element.pyx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2789,6 +2789,10 @@ cdef class NumberFieldElement(FieldElement):
27892789
sage: E = C.algebraic_closure()
27902790
sage: E(a)
27912791
-4.949886207424724? - 0.2195628712241434?*I
2792+
2793+
sage: NF.<sqrt2> = QuadraticField(2)
2794+
sage: AA(sqrt2)
2795+
1.414213562373095?
27922796
"""
27932797
if self.is_rational():
27942798
return parent(self._rational_())

src/sage/rings/qqbar.py

Lines changed: 63 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,6 @@
115115
3.146264369941973?
116116
sage: QQbar(I)
117117
I
118-
sage: AA(I)
119-
Traceback (most recent call last):
120-
...
121-
ValueError: Cannot coerce algebraic number with non-zero imaginary part to algebraic real
122118
sage: QQbar(I * golden_ratio)
123119
1.618033988749895?*I
124120
sage: AA(golden_ratio)^2 - AA(golden_ratio)
@@ -150,24 +146,30 @@
150146
sage: QQbar(-1)^(1/3)
151147
0.500000000000000? + 0.866025403784439?*I
152148
153-
We can explicitly coerce from `\QQ[I]`. (Technically, this is not quite
154-
kosher, since `\QQ[I]` does not come with an embedding; we do not know
155-
whether the field generator is supposed to map to `+I` or `-I`. We assume
156-
that for any quadratic field with polynomial `x^2+1`, the generator maps
157-
to `+I`.)::
158-
159-
sage: K.<im> = QQ[I]
160-
sage: pythag = QQbar(3/5 + 4*im/5); pythag
161-
4/5*I + 3/5
162-
sage: pythag.abs() == 1
163-
True
149+
However, implicit coercion from `\QQ[I]` is only allowed when it is equipped
150+
with a complex embedding::
164151
165-
However, implicit coercion from `\QQ[I]` is not allowed::
152+
sage: i.parent()
153+
Number Field in I with defining polynomial x^2 + 1 with I = 1*I
154+
sage: QQbar(1) + i
155+
I + 1
166156
157+
sage: K.<im> = QuadraticField(-1, embedding=None)
167158
sage: QQbar(1) + im
168159
Traceback (most recent call last):
169160
...
170-
TypeError: unsupported operand parent(s) for +: 'Algebraic Field' and 'Number Field in I with defining polynomial x^2 + 1 with I = 1*I'
161+
TypeError: unsupported operand parent(s) for +: 'Algebraic Field' and
162+
'Number Field in im with defining polynomial x^2 + 1'
163+
164+
However, we can explicitly coerce from the abstract number field `\QQ[I]`.
165+
(Technically, this is not quite kosher, since we do not know whether the field
166+
generator is supposed to map to `+I` or `-I`. We assume that for any quadratic
167+
field with polynomial `x^2+1`, the generator maps to `+I`.)::
168+
169+
sage: pythag = QQbar(3/5 + 4*im/5); pythag
170+
4/5*I + 3/5
171+
sage: pythag.abs() == 1
172+
True
171173
172174
We can implicitly coerce from algebraic reals to algebraic numbers::
173175
@@ -553,8 +555,10 @@
553555
import operator
554556

555557
import sage.rings.ring
558+
import sage.rings.number_field.number_field_base
556559
from sage.misc.fast_methods import Singleton
557560
from sage.misc.cachefunc import cached_method
561+
from sage.structure.coerce import parent_is_numerical, parent_is_real_numerical
558562
from sage.structure.sage_object import SageObject
559563
from sage.structure.richcmp import (richcmp, richcmp_method,
560564
rich_to_bool, richcmp_not_equal,
@@ -1063,9 +1067,17 @@ def __init__(self):
10631067
10641068
sage: QQbar.category() # indirect doctest
10651069
Category of infinite fields
1070+
1071+
Coercions::
1072+
1073+
sage: AA.has_coerce_map_from(ZZ)
1074+
True
1075+
sage: AA.has_coerce_map_from(int)
1076+
True
10661077
"""
10671078
from sage.categories.fields import Fields
10681079
AlgebraicField_common.__init__(self, self, ('x',), normalize=False, category=Fields().Infinite())
1080+
self._populate_coercion_lists_([ZZ, QQ])
10691081

10701082
def _element_constructor_(self, x):
10711083
r"""
@@ -1157,8 +1169,6 @@ def _coerce_map_from_(self, from_par):
11571169
11581170
TESTS::
11591171
1160-
sage: AA.has_coerce_map_from(ZZ) # indirect doctest
1161-
True
11621172
sage: K.<a> = QuadraticField(7, embedding=AA(7).sqrt()); AA.has_coerce_map_from(K)
11631173
True
11641174
sage: a in AA
@@ -1167,9 +1177,20 @@ def _coerce_map_from_(self, from_par):
11671177
5.645751311064590?
11681178
sage: AA.has_coerce_map_from(SR)
11691179
False
1180+
1181+
sage: K.<s> = QuadraticField(3, embedding=-2.)
1182+
sage: s + AA(1)
1183+
-0.732050807568878?
1184+
sage: K.<s> = QuadraticField(3, embedding=2.)
1185+
sage: s + AA(1)
1186+
2.732050807568878?
1187+
sage: K.<s> = QuadraticField(-5)
1188+
sage: AA.has_coerce_map_from(K)
1189+
False
11701190
"""
1171-
return (from_par is ZZ or from_par is QQ
1172-
or from_par is AA)
1191+
if isinstance(from_par, sage.rings.number_field.number_field_base.NumberField):
1192+
emb = from_par.coerce_embedding()
1193+
return emb is not None and parent_is_real_numerical(emb.codomain())
11731194

11741195
def completion(self, p, prec, extras={}):
11751196
r"""
@@ -1497,9 +1518,15 @@ def __init__(self):
14971518
14981519
sage: QQbar._repr_option('element_is_atomic')
14991520
False
1521+
1522+
sage: QQbar.has_coerce_map_from(ZZ)
1523+
True
1524+
sage: QQbar.has_coerce_map_from(int)
1525+
True
15001526
"""
15011527
from sage.categories.fields import Fields
15021528
AlgebraicField_common.__init__(self, AA, ('I',), normalize=False, category=Fields().Infinite())
1529+
self._populate_coercion_lists_([ZZ, QQ])
15031530

15041531
def _element_constructor_(self, x):
15051532
"""
@@ -1565,17 +1592,28 @@ def _coerce_map_from_(self, from_par):
15651592
15661593
TESTS::
15671594
1568-
sage: QQbar.has_coerce_map_from(ZZ) # indirect doctest
1569-
True
15701595
sage: QQbar.has_coerce_map_from(AA)
15711596
True
15721597
sage: QQbar.has_coerce_map_from(CC)
15731598
False
15741599
sage: QQbar.has_coerce_map_from(SR)
15751600
False
1601+
1602+
sage: i + QQbar(2)
1603+
I + 2
1604+
sage: K.<ii> = QuadraticField(-1, embedding=ComplexField(13)(0,-1))
1605+
sage: ii + QQbar(2)
1606+
-I + 2
1607+
1608+
sage: L.<a> = QuadraticField(-1, embedding=Zp(5).teichmuller(2))
1609+
sage: QQbar.has_coerce_map_from(L)
1610+
False
15761611
"""
1577-
return (from_par is ZZ or from_par is QQ
1578-
or from_par is AA or from_par is QQbar)
1612+
if from_par is AA:
1613+
return True
1614+
if isinstance(from_par, sage.rings.number_field.number_field_base.NumberField):
1615+
emb = from_par.coerce_embedding()
1616+
return emb is not None and parent_is_numerical(emb.codomain())
15791617

15801618
def completion(self, p, prec, extras={}):
15811619
r"""

0 commit comments

Comments
 (0)