Coverage for /usr/lib/python3/dist-packages/sympy/polys/domains/fractionfield.py: 43%
107 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
1"""Implementation of :class:`FractionField` class. """
4from sympy.polys.domains.compositedomain import CompositeDomain
5from sympy.polys.domains.field import Field
6from sympy.polys.polyerrors import CoercionFailed, GeneratorsError
7from sympy.utilities import public
9@public
10class FractionField(Field, CompositeDomain):
11 """A class for representing multivariate rational function fields. """
13 is_FractionField = is_Frac = True
15 has_assoc_Ring = True
16 has_assoc_Field = True
18 def __init__(self, domain_or_field, symbols=None, order=None):
19 from sympy.polys.fields import FracField
21 if isinstance(domain_or_field, FracField) and symbols is None and order is None:
22 field = domain_or_field
23 else:
24 field = FracField(symbols, domain_or_field, order)
26 self.field = field
27 self.dtype = field.dtype
29 self.gens = field.gens
30 self.ngens = field.ngens
31 self.symbols = field.symbols
32 self.domain = field.domain
34 # TODO: remove this
35 self.dom = self.domain
37 def new(self, element):
38 return self.field.field_new(element)
40 @property
41 def zero(self):
42 return self.field.zero
44 @property
45 def one(self):
46 return self.field.one
48 @property
49 def order(self):
50 return self.field.order
52 @property
53 def is_Exact(self):
54 return self.domain.is_Exact
56 def get_exact(self):
57 return FractionField(self.domain.get_exact(), self.symbols)
59 def __str__(self):
60 return str(self.domain) + '(' + ','.join(map(str, self.symbols)) + ')'
62 def __hash__(self):
63 return hash((self.__class__.__name__, self.dtype.field, self.domain, self.symbols))
65 def __eq__(self, other):
66 """Returns ``True`` if two domains are equivalent. """
67 return isinstance(other, FractionField) and \
68 (self.dtype.field, self.domain, self.symbols) ==\
69 (other.dtype.field, other.domain, other.symbols)
71 def to_sympy(self, a):
72 """Convert ``a`` to a SymPy object. """
73 return a.as_expr()
75 def from_sympy(self, a):
76 """Convert SymPy's expression to ``dtype``. """
77 return self.field.from_expr(a)
79 def from_ZZ(K1, a, K0):
80 """Convert a Python ``int`` object to ``dtype``. """
81 return K1(K1.domain.convert(a, K0))
83 def from_ZZ_python(K1, a, K0):
84 """Convert a Python ``int`` object to ``dtype``. """
85 return K1(K1.domain.convert(a, K0))
87 def from_QQ(K1, a, K0):
88 """Convert a Python ``Fraction`` object to ``dtype``. """
89 dom = K1.domain
90 conv = dom.convert_from
91 if dom.is_ZZ:
92 return K1(conv(K0.numer(a), K0)) / K1(conv(K0.denom(a), K0))
93 else:
94 return K1(conv(a, K0))
96 def from_QQ_python(K1, a, K0):
97 """Convert a Python ``Fraction`` object to ``dtype``. """
98 return K1(K1.domain.convert(a, K0))
100 def from_ZZ_gmpy(K1, a, K0):
101 """Convert a GMPY ``mpz`` object to ``dtype``. """
102 return K1(K1.domain.convert(a, K0))
104 def from_QQ_gmpy(K1, a, K0):
105 """Convert a GMPY ``mpq`` object to ``dtype``. """
106 return K1(K1.domain.convert(a, K0))
108 def from_GaussianRationalField(K1, a, K0):
109 """Convert a ``GaussianRational`` object to ``dtype``. """
110 return K1(K1.domain.convert(a, K0))
112 def from_GaussianIntegerRing(K1, a, K0):
113 """Convert a ``GaussianInteger`` object to ``dtype``. """
114 return K1(K1.domain.convert(a, K0))
116 def from_RealField(K1, a, K0):
117 """Convert a mpmath ``mpf`` object to ``dtype``. """
118 return K1(K1.domain.convert(a, K0))
120 def from_ComplexField(K1, a, K0):
121 """Convert a mpmath ``mpf`` object to ``dtype``. """
122 return K1(K1.domain.convert(a, K0))
124 def from_AlgebraicField(K1, a, K0):
125 """Convert an algebraic number to ``dtype``. """
126 if K1.domain != K0:
127 a = K1.domain.convert_from(a, K0)
128 if a is not None:
129 return K1.new(a)
131 def from_PolynomialRing(K1, a, K0):
132 """Convert a polynomial to ``dtype``. """
133 if a.is_ground:
134 return K1.convert_from(a.coeff(1), K0.domain)
135 try:
136 return K1.new(a.set_ring(K1.field.ring))
137 except (CoercionFailed, GeneratorsError):
138 # XXX: We get here if K1=ZZ(x,y) and K0=QQ[x,y]
139 # and the poly a in K0 has non-integer coefficients.
140 # It seems that K1.new can handle this but K1.new doesn't work
141 # when K0.domain is an algebraic field...
142 try:
143 return K1.new(a)
144 except (CoercionFailed, GeneratorsError):
145 return None
147 def from_FractionField(K1, a, K0):
148 """Convert a rational function to ``dtype``. """
149 try:
150 return a.set_field(K1.field)
151 except (CoercionFailed, GeneratorsError):
152 return None
154 def get_ring(self):
155 """Returns a field associated with ``self``. """
156 return self.field.to_ring().to_domain()
158 def is_positive(self, a):
159 """Returns True if ``LC(a)`` is positive. """
160 return self.domain.is_positive(a.numer.LC)
162 def is_negative(self, a):
163 """Returns True if ``LC(a)`` is negative. """
164 return self.domain.is_negative(a.numer.LC)
166 def is_nonpositive(self, a):
167 """Returns True if ``LC(a)`` is non-positive. """
168 return self.domain.is_nonpositive(a.numer.LC)
170 def is_nonnegative(self, a):
171 """Returns True if ``LC(a)`` is non-negative. """
172 return self.domain.is_nonnegative(a.numer.LC)
174 def numer(self, a):
175 """Returns numerator of ``a``. """
176 return a.numer
178 def denom(self, a):
179 """Returns denominator of ``a``. """
180 return a.denom
182 def factorial(self, a):
183 """Returns factorial of ``a``. """
184 return self.dtype(self.domain.factorial(a))