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

Commit 1471238

Browse files
author
Release Manager
committed
Trac #28508: An API for testing if a parent's element “are” real/complex numbers
See commit messages. URL: https://trac.sagemath.org/28508 Reported by: mmezzarobba Ticket author(s): Marc Mezzarobba Reviewer(s): Vincent Delecroix
2 parents 68926f8 + 25658d6 commit 1471238

File tree

8 files changed

+99
-19
lines changed

8 files changed

+99
-19
lines changed

src/sage/numerical/linear_functions.pyx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -716,11 +716,8 @@ cdef class LinearFunctionsParent_class(Parent):
716716
sage: parent._coerce_map_from_(int)
717717
True
718718
"""
719-
if R in [int, float, long, complex]:
720-
return True
721-
from sage.rings.real_mpfr import mpfr_prec_min
722-
from sage.rings.all import RealField
723-
if RealField(mpfr_prec_min()).has_coerce_map_from(R):
719+
from sage.structure.coerce import parent_is_real_numerical
720+
if parent_is_real_numerical(R) or R is complex:
724721
return True
725722
return False
726723

src/sage/rings/infinity.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,8 +1243,8 @@ def _coerce_map_from_(self, R):
12431243
sage: CC(0, oo) < CC(1) # does not coerce to infinity ring
12441244
True
12451245
"""
1246-
from sage.rings.real_mpfr import mpfr_prec_min, RealField
1247-
if RealField(mpfr_prec_min()).has_coerce_map_from(R):
1246+
from sage.structure.coerce import parent_is_real_numerical
1247+
if parent_is_real_numerical(R):
12481248
return True
12491249
from sage.rings.real_mpfi import RealIntervalField_class
12501250
if isinstance(R, RealIntervalField_class):

src/sage/rings/number_field/number_field.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2950,11 +2950,8 @@ def specified_complex_embedding(self):
29502950
Defn: a -> 3 + 7 + 2*7^2 + 6*7^3 + 7^4 + 2*7^5 + 7^6 + 2*7^7 + 4*7^8 + 6*7^9 + 6*7^10 + 2*7^11 + 7^12 + 7^13 + 2*7^15 + 7^16 + 7^17 + 4*7^18 + 6*7^19 + O(7^20)
29512951
"""
29522952
embedding = self.coerce_embedding()
2953-
if embedding is not None:
2954-
from sage.rings.real_mpfr import mpfr_prec_min
2955-
from sage.rings.complex_field import ComplexField
2956-
if ComplexField(mpfr_prec_min()).has_coerce_map_from(embedding.codomain()):
2957-
return embedding
2953+
if embedding is not None and embedding.codomain()._is_numerical():
2954+
return embedding
29582955

29592956
def gen_embedding(self):
29602957
"""

src/sage/rings/number_field/number_field_morphisms.pyx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -488,9 +488,9 @@ def root_from_approx(f, a):
488488
P = a.parent()
489489
if P.is_exact() and not f(a):
490490
return a
491-
elif RealField(mpfr_prec_min()).has_coerce_map_from(P):
491+
elif P._is_real_numerical():
492492
return LazyAlgebraic(RLF, f, a, prec=0)
493-
elif ComplexField(mpfr_prec_min()).has_coerce_map_from(P):
493+
elif P._is_numerical():
494494
return LazyAlgebraic(CLF, f, a, prec=0)
495495
# p-adic lazy, when implemented, would go here
496496
else:

src/sage/structure/coerce.pyx

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,55 @@ cpdef bint parent_is_integers(P) except -1:
365365
from sage.rings.integer_ring import ZZ
366366
return P is ZZ
367367

368+
def parent_is_numerical(P):
369+
r"""
370+
Test if elements of the parent or type ``P`` can be numerically evaluated
371+
as complex numbers (in a canonical way).
372+
373+
EXAMPLES::
374+
375+
sage: from sage.structure.coerce import parent_is_numerical
376+
sage: import gmpy2, numpy
377+
sage: [parent_is_numerical(R) for R in [RR, CC, QQ, QuadraticField(-1),
378+
....: int, complex, gmpy2.mpc, numpy.complexfloating]]
379+
[True, True, True, True, True, True, True, True]
380+
sage: [parent_is_numerical(R) for R in [SR, QQ['x'], QQ[['x']], str]]
381+
[False, False, False, False]
382+
sage: [parent_is_numerical(R) for R in [RIF, RBF, CIF, CBF]]
383+
[False, False, False, False]
384+
"""
385+
if not isinstance(P, Parent):
386+
P = py_scalar_parent(P)
387+
if P is None:
388+
return False
389+
return P._is_numerical()
390+
391+
def parent_is_real_numerical(P):
392+
r"""
393+
Test if elements of the parent or type ``P`` can be numerically evaluated
394+
as real numbers (in a canonical way).
395+
396+
EXAMPLES::
397+
398+
sage: from sage.structure.coerce import parent_is_real_numerical
399+
sage: import gmpy2, numpy
400+
sage: [parent_is_real_numerical(R) for R in [RR, QQ, ZZ, RLF,
401+
....: QuadraticField(2), int, float, gmpy2.mpq, numpy.integer]]
402+
[True, True, True, True, True, True, True, True, True]
403+
sage: [parent_is_real_numerical(R) for R in [CC, QuadraticField(-1),
404+
....: complex, gmpy2.mpc, numpy.complexfloating]]
405+
[False, False, False, False, False]
406+
sage: [parent_is_real_numerical(R) for R in [SR, QQ['x'], QQ[['x']], str]]
407+
[False, False, False, False]
408+
sage: [parent_is_real_numerical(R) for R in [RIF, RBF, CIF, CBF]]
409+
[False, False, False, False]
410+
"""
411+
if not isinstance(P, Parent):
412+
P = py_scalar_parent(P)
413+
if P is None:
414+
return False
415+
return P._is_real_numerical()
416+
368417

369418
cpdef bint is_numpy_type(t):
370419
"""

src/sage/structure/parent.pyx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ cimport sage.categories.map as map
117117
from sage.structure.debug_options cimport debug
118118
from sage.structure.richcmp cimport rich_to_bool
119119
from sage.structure.sage_object cimport SageObject
120+
from sage.misc.cachefunc import cached_method
120121
from sage.misc.lazy_attribute import lazy_attribute
121122
from sage.categories.sets_cat import Sets, EmptySetError
122123
from sage.misc.lazy_format import LazyFormat
@@ -2703,6 +2704,44 @@ cdef class Parent(sage.structure.category_object.CategoryObject):
27032704
"""
27042705
return True
27052706

2707+
@cached_method
2708+
def _is_numerical(self):
2709+
r"""
2710+
Test if elements of this parent can be numerically evaluated as complex
2711+
numbers (in a canonical way).
2712+
2713+
EXAMPLES::
2714+
2715+
sage: [R._is_numerical() for R in [RR, CC, QQ, QuadraticField(-1)]]
2716+
[True, True, True, True]
2717+
sage: [R._is_numerical() for R in [SR, QQ['x'], QQ[['x']]]]
2718+
[False, False, False]
2719+
sage: [R._is_numerical() for R in [RIF, RBF, CIF, CBF]]
2720+
[False, False, False, False]
2721+
"""
2722+
from sage.rings.complex_field import ComplexField
2723+
from sage.rings.real_mpfr import mpfr_prec_min
2724+
return ComplexField(mpfr_prec_min()).has_coerce_map_from(self)
2725+
2726+
@cached_method
2727+
def _is_real_numerical(self):
2728+
r"""
2729+
Test if elements of this parent can be numerically evaluated as real
2730+
numbers (in a canonical way).
2731+
2732+
EXAMPLES::
2733+
2734+
sage: [R._is_real_numerical() for R in [RR, QQ, ZZ, RLF, QuadraticField(2)]]
2735+
[True, True, True, True, True]
2736+
sage: [R._is_real_numerical() for R in [CC, QuadraticField(-1)]]
2737+
[False, False]
2738+
sage: [R._is_real_numerical() for R in [SR, QQ['x'], QQ[['x']]]]
2739+
[False, False, False]
2740+
sage: [R._is_real_numerical() for R in [RIF, RBF, CIF, CBF]]
2741+
[False, False, False, False]
2742+
"""
2743+
from sage.rings.real_mpfr import RealField, mpfr_prec_min
2744+
return RealField(mpfr_prec_min()).has_coerce_map_from(self)
27062745

27072746
############################################################################
27082747
# Set base class --

src/sage/symbolic/ring.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ cdef class SymbolicRing(CommutativeRing):
203203

204204
from .subring import GenericSymbolicSubring
205205

206-
if ComplexField(mpfr_prec_min()).has_coerce_map_from(R):
206+
if R._is_numerical():
207207
# Almost anything with a coercion into any precision of CC
208208
return R not in (RLF, CLF)
209209
elif is_PolynomialRing(R) or is_MPolynomialRing(R) or is_FractionField(R) or is_LaurentPolynomialRing(R):

src/sage/symbolic/subring.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -411,9 +411,7 @@ def _coerce_map_from_(self, P):
411411
# Workaround; can be deleted once #19231 is fixed
412412
return False
413413

414-
from sage.rings.real_mpfr import mpfr_prec_min
415-
from sage.rings.all import (ComplexField,
416-
RLF, CLF, AA, QQbar, InfinityRing)
414+
from sage.rings.all import RLF, CLF, AA, QQbar, InfinityRing
417415
from sage.rings.real_mpfi import is_RealIntervalField
418416
from sage.rings.complex_interval_field import is_ComplexIntervalField
419417

@@ -430,7 +428,7 @@ def _coerce_map_from_(self, P):
430428
is_RealIntervalField(P) or is_ComplexIntervalField(P)):
431429
return True
432430

433-
elif ComplexField(mpfr_prec_min()).has_coerce_map_from(P):
431+
elif P._is_numerical():
434432
return P not in (RLF, CLF, AA, QQbar)
435433

436434
def __eq__(self, other):

0 commit comments

Comments
 (0)