Skip to content

Commit

Permalink
Trac #32566: sage.rings.abc
Browse files Browse the repository at this point in the history
This new module will provide abstract base classes for the purpose of
`isinstance` and `issubclass` testing.  This helps with modularization
(#32432).

In this ticket, we add `RealField`, `RealDoubleField`, `ComplexField`,
`ComplexDoubleField`, which are in 1:1 correspondence to the
implementation classes `RealField_class`, `RealDoubleField_class`,
`ComplexField_class`, `ComplexDoubleField_class`.

To illustrate the use of these classes, we convert some uses of `is_...`
functions to `isinstance` with the new base classes.

Related:
- https://groups.google.com/g/sage-devel/c/T0A4JCOg9DY/m/q6WKsI1yBAAJ
(Sep 2021)

Part of meta-ticket #32414.

URL: https://trac.sagemath.org/32566
Reported by: mkoeppe
Ticket author(s): Matthias Koeppe
Reviewer(s): Jonathan Kliem
  • Loading branch information
Release Manager committed Oct 10, 2021
2 parents d569319 + 6e2c3c4 commit 6453bd7
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 32 deletions.
20 changes: 20 additions & 0 deletions src/sage/rings/abc.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from .ring cimport Field

cdef class RealField(Field):

pass


cdef class RealDoubleField(Field):

pass


cdef class ComplexField(Field):

pass


cdef class ComplexDoubleField(Field):

pass
34 changes: 34 additions & 0 deletions src/sage/rings/abc.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""
Abstract base classes for rings
"""

cdef class RealField(Field):
r"""
Abstract base class for :class:`~sage.rings.real_mpfr.RealField_class`.
"""

pass


cdef class RealDoubleField(Field):
r"""
Abstract base class for :class:`~sage.rings.real_double.RealDoubleField_class`.
"""

pass


cdef class ComplexField(Field):
r"""
Abstract base class for :class:`~sage.rings.complex_mpfr.ComplexField_class`.
"""

pass


cdef class ComplexDoubleField(Field):
r"""
Abstract base class for :class:`~sage.rings.complex_double.ComplexDoubleField_class`.
"""

pass
3 changes: 2 additions & 1 deletion src/sage/rings/complex_double.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ from sage.libs.gsl.types cimport gsl_complex

cimport sage.structure.element
cimport sage.rings.ring
cimport sage.rings.abc


cdef class ComplexDoubleField_class(sage.rings.ring.Field):
cdef class ComplexDoubleField_class(sage.rings.abc.ComplexDoubleField):
pass


Expand Down
2 changes: 1 addition & 1 deletion src/sage/rings/complex_double.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def is_ComplexDoubleField(x):
return isinstance(x, ComplexDoubleField_class)


cdef class ComplexDoubleField_class(sage.rings.ring.Field):
cdef class ComplexDoubleField_class(sage.rings.abc.ComplexDoubleField):
"""
An approximation to the field of complex numbers using double
precision floating point numbers. Answers derived from calculations
Expand Down
2 changes: 1 addition & 1 deletion src/sage/rings/complex_mpfr.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def ComplexField(prec=53, names=None):
return C


class ComplexField_class(ring.Field):
class ComplexField_class(sage.rings.abc.ComplexField):
"""
An approximation to the field of complex numbers using floating
point numbers with any specified precision. Answers derived from
Expand Down
48 changes: 23 additions & 25 deletions src/sage/rings/polynomial/polynomial_element.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ TESTS::
# https://www.gnu.org/licenses/
# ****************************************************************************

cdef is_FractionField, is_RealField, is_ComplexField
cdef is_FractionField
cdef ZZ, QQ, RR, CC, RDF, CDF

cimport cython
Expand Down Expand Up @@ -84,13 +84,14 @@ from sage.structure.richcmp cimport (richcmp, richcmp_item,
from sage.interfaces.singular import singular as singular_default, is_SingularElement
from sage.libs.all import pari, pari_gen, PariError

from sage.rings.real_mpfr import RealField, is_RealField, RR
cimport sage.rings.abc
from sage.rings.real_mpfr import RealField, RR

from sage.rings.complex_mpfr import is_ComplexField, ComplexField
from sage.rings.complex_mpfr import ComplexField
CC = ComplexField()

from sage.rings.real_double import is_RealDoubleField, RDF
from sage.rings.complex_double import is_ComplexDoubleField, CDF
from sage.rings.real_double import RDF
from sage.rings.complex_double import CDF
from sage.rings.real_mpfi import is_RealIntervalField

from sage.structure.coerce cimport coercion_model
Expand Down Expand Up @@ -7852,25 +7853,23 @@ cdef class Polynomial(CommutativeAlgebraElement):

late_import()

input_fp = (is_RealField(K)
or is_ComplexField(K)
or is_RealDoubleField(K)
or is_ComplexDoubleField(K))
output_fp = (is_RealField(L)
or is_ComplexField(L)
or is_RealDoubleField(L)
or is_ComplexDoubleField(L))
input_complex = (is_ComplexField(K)
or is_ComplexDoubleField(K))
output_complex = (is_ComplexField(L)
or is_ComplexDoubleField(L))
input_fp = isinstance(K, (sage.rings.abc.RealField,
sage.rings.abc.ComplexField,
sage.rings.abc.RealDoubleField,
sage.rings.abc.ComplexDoubleField))
output_fp = isinstance(L, (sage.rings.abc.RealField,
sage.rings.abc.ComplexField,
sage.rings.abc.RealDoubleField,
sage.rings.abc.ComplexDoubleField))
input_complex = isinstance(K, (sage.rings.abc.ComplexField, sage.rings.abc.ComplexDoubleField))
output_complex = isinstance(L, (sage.rings.abc.ComplexField, sage.rings.abc.ComplexDoubleField))
input_gaussian = (isinstance(K, NumberField_quadratic)
and list(K.polynomial()) == [1, 0, 1])

if input_fp and output_fp:
# allow for possibly using a fast but less reliable
# floating point algorithm from numpy
low_prec = is_RealDoubleField(K) or is_ComplexDoubleField(K)
low_prec = isinstance(K, (sage.rings.abc.RealDoubleField, sage.rings.abc.ComplexDoubleField))
if algorithm is None:
if low_prec:
algorithm = 'either'
Expand All @@ -7883,8 +7882,7 @@ cdef class Polynomial(CommutativeAlgebraElement):
# We should support GSL, too. We could also support PARI's
# old Newton-iteration algorithm.

input_arbprec = (is_RealField(K) or
is_ComplexField(K))
input_arbprec = isinstance(K, (sage.rings.abc.RealField, sage.rings.abc.ComplexField))

if algorithm == 'numpy' or algorithm == 'either':
if K.prec() > 53 and L.prec() > 53:
Expand Down Expand Up @@ -8022,7 +8020,7 @@ cdef class Polynomial(CommutativeAlgebraElement):
# If we want the complex roots, and the input is not
# floating point, we convert to a real polynomial
# (except when the input coefficients are Gaussian rationals).
if is_ComplexDoubleField(L):
if isinstance(L, sage.rings.abc.ComplexDoubleField):
real_field = RDF
else:
real_field = RealField(L.prec())
Expand Down Expand Up @@ -8190,7 +8188,7 @@ cdef class Polynomial(CommutativeAlgebraElement):
True
"""
K = self.base_ring()
if is_RealField(K) or is_RealDoubleField(K):
if isinstance(K, (sage.rings.abc.RealField, sage.rings.abc.RealDoubleField)):
return self.roots(multiplicities=False)

return self.roots(ring=RR, multiplicities=False)
Expand Down Expand Up @@ -8232,11 +8230,11 @@ cdef class Polynomial(CommutativeAlgebraElement):
True
"""
K = self.base_ring()
if is_RealField(K):
if isinstance(K, sage.rings.abc.RealField):
return self.roots(ring=ComplexField(K.prec()), multiplicities=False)
if is_RealDoubleField(K):
if isinstance(K, sage.rings.abc.RealDoubleField):
return self.roots(ring=CDF, multiplicities=False)
if is_ComplexField(K) or is_ComplexDoubleField(K):
if isinstance(K, (sage.rings.abc.ComplexField, sage.rings.abc.ComplexDoubleField)):
return self.roots(multiplicities=False)

return self.roots(ring=CC, multiplicities=False)
Expand Down
3 changes: 2 additions & 1 deletion src/sage/rings/real_double.pxd
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from sage.structure.element cimport RingElement, ModuleElement, Element, FieldElement
from sage.rings.ring cimport Field
cimport sage.rings.abc

cdef class RealDoubleField_class(Field):
cdef class RealDoubleField_class(sage.rings.abc.RealDoubleField):
cdef _new_c(self, double value)

cdef class RealDoubleElement(FieldElement):
Expand Down
2 changes: 1 addition & 1 deletion src/sage/rings/real_double.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def is_RealDoubleField(x):
"""
return isinstance(x, RealDoubleField_class)

cdef class RealDoubleField_class(Field):
cdef class RealDoubleField_class(sage.rings.abc.RealDoubleField):
"""
An approximation to the field of real numbers using double
precision floating point numbers. Answers derived from calculations
Expand Down
3 changes: 2 additions & 1 deletion src/sage/rings/real_mpfr.pxd
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from sage.libs.mpfr.types cimport mpfr_rnd_t, mpfr_t

cimport sage.rings.ring
cimport sage.rings.abc
cimport sage.structure.element
from cypari2.types cimport GEN
from sage.libs.mpfr.types cimport mpfr_prec_t

cdef class RealNumber(sage.structure.element.RingElement) # forward decl

cdef class RealField_class(sage.rings.ring.Field):
cdef class RealField_class(sage.rings.abc.RealField):
cdef mpfr_prec_t __prec
cdef bint sci_not
cdef mpfr_rnd_t rnd
Expand Down
2 changes: 1 addition & 1 deletion src/sage/rings/real_mpfr.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ cpdef RealField(mpfr_prec_t prec=53, int sci_not=0, rnd=MPFR_RNDN):
return R


cdef class RealField_class(sage.rings.ring.Field):
cdef class RealField_class(sage.rings.abc.RealField):
"""
An approximation to the field of real numbers using floating point
numbers with any specified precision. Answers derived from
Expand Down

0 comments on commit 6453bd7

Please sign in to comment.