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

1"""Implementation of :class:`FractionField` class. """ 

2 

3 

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 

8 

9@public 

10class FractionField(Field, CompositeDomain): 

11 """A class for representing multivariate rational function fields. """ 

12 

13 is_FractionField = is_Frac = True 

14 

15 has_assoc_Ring = True 

16 has_assoc_Field = True 

17 

18 def __init__(self, domain_or_field, symbols=None, order=None): 

19 from sympy.polys.fields import FracField 

20 

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) 

25 

26 self.field = field 

27 self.dtype = field.dtype 

28 

29 self.gens = field.gens 

30 self.ngens = field.ngens 

31 self.symbols = field.symbols 

32 self.domain = field.domain 

33 

34 # TODO: remove this 

35 self.dom = self.domain 

36 

37 def new(self, element): 

38 return self.field.field_new(element) 

39 

40 @property 

41 def zero(self): 

42 return self.field.zero 

43 

44 @property 

45 def one(self): 

46 return self.field.one 

47 

48 @property 

49 def order(self): 

50 return self.field.order 

51 

52 @property 

53 def is_Exact(self): 

54 return self.domain.is_Exact 

55 

56 def get_exact(self): 

57 return FractionField(self.domain.get_exact(), self.symbols) 

58 

59 def __str__(self): 

60 return str(self.domain) + '(' + ','.join(map(str, self.symbols)) + ')' 

61 

62 def __hash__(self): 

63 return hash((self.__class__.__name__, self.dtype.field, self.domain, self.symbols)) 

64 

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) 

70 

71 def to_sympy(self, a): 

72 """Convert ``a`` to a SymPy object. """ 

73 return a.as_expr() 

74 

75 def from_sympy(self, a): 

76 """Convert SymPy's expression to ``dtype``. """ 

77 return self.field.from_expr(a) 

78 

79 def from_ZZ(K1, a, K0): 

80 """Convert a Python ``int`` object to ``dtype``. """ 

81 return K1(K1.domain.convert(a, K0)) 

82 

83 def from_ZZ_python(K1, a, K0): 

84 """Convert a Python ``int`` object to ``dtype``. """ 

85 return K1(K1.domain.convert(a, K0)) 

86 

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)) 

95 

96 def from_QQ_python(K1, a, K0): 

97 """Convert a Python ``Fraction`` object to ``dtype``. """ 

98 return K1(K1.domain.convert(a, K0)) 

99 

100 def from_ZZ_gmpy(K1, a, K0): 

101 """Convert a GMPY ``mpz`` object to ``dtype``. """ 

102 return K1(K1.domain.convert(a, K0)) 

103 

104 def from_QQ_gmpy(K1, a, K0): 

105 """Convert a GMPY ``mpq`` object to ``dtype``. """ 

106 return K1(K1.domain.convert(a, K0)) 

107 

108 def from_GaussianRationalField(K1, a, K0): 

109 """Convert a ``GaussianRational`` object to ``dtype``. """ 

110 return K1(K1.domain.convert(a, K0)) 

111 

112 def from_GaussianIntegerRing(K1, a, K0): 

113 """Convert a ``GaussianInteger`` object to ``dtype``. """ 

114 return K1(K1.domain.convert(a, K0)) 

115 

116 def from_RealField(K1, a, K0): 

117 """Convert a mpmath ``mpf`` object to ``dtype``. """ 

118 return K1(K1.domain.convert(a, K0)) 

119 

120 def from_ComplexField(K1, a, K0): 

121 """Convert a mpmath ``mpf`` object to ``dtype``. """ 

122 return K1(K1.domain.convert(a, K0)) 

123 

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) 

130 

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 

146 

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 

153 

154 def get_ring(self): 

155 """Returns a field associated with ``self``. """ 

156 return self.field.to_ring().to_domain() 

157 

158 def is_positive(self, a): 

159 """Returns True if ``LC(a)`` is positive. """ 

160 return self.domain.is_positive(a.numer.LC) 

161 

162 def is_negative(self, a): 

163 """Returns True if ``LC(a)`` is negative. """ 

164 return self.domain.is_negative(a.numer.LC) 

165 

166 def is_nonpositive(self, a): 

167 """Returns True if ``LC(a)`` is non-positive. """ 

168 return self.domain.is_nonpositive(a.numer.LC) 

169 

170 def is_nonnegative(self, a): 

171 """Returns True if ``LC(a)`` is non-negative. """ 

172 return self.domain.is_nonnegative(a.numer.LC) 

173 

174 def numer(self, a): 

175 """Returns numerator of ``a``. """ 

176 return a.numer 

177 

178 def denom(self, a): 

179 """Returns denominator of ``a``. """ 

180 return a.denom 

181 

182 def factorial(self, a): 

183 """Returns factorial of ``a``. """ 

184 return self.dtype(self.domain.factorial(a))