Coverage for /usr/lib/python3/dist-packages/sympy/polys/domains/integerring.py: 60%

82 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-14 15:55 +0200

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

2 

3from sympy.external.gmpy import MPZ, HAS_GMPY 

4 

5from sympy.polys.domains.groundtypes import ( 

6 SymPyInteger, 

7 factorial, 

8 gcdex, gcd, lcm, sqrt, 

9) 

10 

11from sympy.polys.domains.characteristiczero import CharacteristicZero 

12from sympy.polys.domains.ring import Ring 

13from sympy.polys.domains.simpledomain import SimpleDomain 

14from sympy.polys.polyerrors import CoercionFailed 

15from sympy.utilities import public 

16 

17import math 

18 

19@public 

20class IntegerRing(Ring, CharacteristicZero, SimpleDomain): 

21 r"""The domain ``ZZ`` representing the integers `\mathbb{Z}`. 

22 

23 The :py:class:`IntegerRing` class represents the ring of integers as a 

24 :py:class:`~.Domain` in the domain system. :py:class:`IntegerRing` is a 

25 super class of :py:class:`PythonIntegerRing` and 

26 :py:class:`GMPYIntegerRing` one of which will be the implementation for 

27 :ref:`ZZ` depending on whether or not ``gmpy`` or ``gmpy2`` is installed. 

28 

29 See also 

30 ======== 

31 

32 Domain 

33 """ 

34 

35 rep = 'ZZ' 

36 alias = 'ZZ' 

37 dtype = MPZ 

38 zero = dtype(0) 

39 one = dtype(1) 

40 tp = type(one) 

41 

42 

43 is_IntegerRing = is_ZZ = True 

44 is_Numerical = True 

45 is_PID = True 

46 

47 has_assoc_Ring = True 

48 has_assoc_Field = True 

49 

50 def __init__(self): 

51 """Allow instantiation of this domain. """ 

52 

53 def to_sympy(self, a): 

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

55 return SymPyInteger(int(a)) 

56 

57 def from_sympy(self, a): 

58 """Convert SymPy's Integer to ``dtype``. """ 

59 if a.is_Integer: 

60 return MPZ(a.p) 

61 elif a.is_Float and int(a) == a: 

62 return MPZ(int(a)) 

63 else: 

64 raise CoercionFailed("expected an integer, got %s" % a) 

65 

66 def get_field(self): 

67 r"""Return the associated field of fractions :ref:`QQ` 

68 

69 Returns 

70 ======= 

71 

72 :ref:`QQ`: 

73 The associated field of fractions :ref:`QQ`, a 

74 :py:class:`~.Domain` representing the rational numbers 

75 `\mathbb{Q}`. 

76 

77 Examples 

78 ======== 

79 

80 >>> from sympy import ZZ 

81 >>> ZZ.get_field() 

82 QQ 

83 """ 

84 from sympy.polys.domains import QQ 

85 return QQ 

86 

87 def algebraic_field(self, *extension, alias=None): 

88 r"""Returns an algebraic field, i.e. `\mathbb{Q}(\alpha, \ldots)`. 

89 

90 Parameters 

91 ========== 

92 

93 *extension : One or more :py:class:`~.Expr`. 

94 Generators of the extension. These should be expressions that are 

95 algebraic over `\mathbb{Q}`. 

96 

97 alias : str, :py:class:`~.Symbol`, None, optional (default=None) 

98 If provided, this will be used as the alias symbol for the 

99 primitive element of the returned :py:class:`~.AlgebraicField`. 

100 

101 Returns 

102 ======= 

103 

104 :py:class:`~.AlgebraicField` 

105 A :py:class:`~.Domain` representing the algebraic field extension. 

106 

107 Examples 

108 ======== 

109 

110 >>> from sympy import ZZ, sqrt 

111 >>> ZZ.algebraic_field(sqrt(2)) 

112 QQ<sqrt(2)> 

113 """ 

114 return self.get_field().algebraic_field(*extension, alias=alias) 

115 

116 def from_AlgebraicField(K1, a, K0): 

117 """Convert a :py:class:`~.ANP` object to :ref:`ZZ`. 

118 

119 See :py:meth:`~.Domain.convert`. 

120 """ 

121 if a.is_ground: 

122 return K1.convert(a.LC(), K0.dom) 

123 

124 def log(self, a, b): 

125 r"""Logarithm of *a* to the base *b*. 

126 

127 Parameters 

128 ========== 

129 

130 a: number 

131 b: number 

132 

133 Returns 

134 ======= 

135 

136 $\\lfloor\log(a, b)\\rfloor$: 

137 Floor of the logarithm of *a* to the base *b* 

138 

139 Examples 

140 ======== 

141 

142 >>> from sympy import ZZ 

143 >>> ZZ.log(ZZ(8), ZZ(2)) 

144 3 

145 >>> ZZ.log(ZZ(9), ZZ(2)) 

146 3 

147 

148 Notes 

149 ===== 

150 

151 This function uses ``math.log`` which is based on ``float`` so it will 

152 fail for large integer arguments. 

153 """ 

154 return self.dtype(math.log(int(a), b)) 

155 

156 def from_FF(K1, a, K0): 

157 """Convert ``ModularInteger(int)`` to GMPY's ``mpz``. """ 

158 return MPZ(a.to_int()) 

159 

160 def from_FF_python(K1, a, K0): 

161 """Convert ``ModularInteger(int)`` to GMPY's ``mpz``. """ 

162 return MPZ(a.to_int()) 

163 

164 def from_ZZ(K1, a, K0): 

165 """Convert Python's ``int`` to GMPY's ``mpz``. """ 

166 return MPZ(a) 

167 

168 def from_ZZ_python(K1, a, K0): 

169 """Convert Python's ``int`` to GMPY's ``mpz``. """ 

170 return MPZ(a) 

171 

172 def from_QQ(K1, a, K0): 

173 """Convert Python's ``Fraction`` to GMPY's ``mpz``. """ 

174 if a.denominator == 1: 

175 return MPZ(a.numerator) 

176 

177 def from_QQ_python(K1, a, K0): 

178 """Convert Python's ``Fraction`` to GMPY's ``mpz``. """ 

179 if a.denominator == 1: 

180 return MPZ(a.numerator) 

181 

182 def from_FF_gmpy(K1, a, K0): 

183 """Convert ``ModularInteger(mpz)`` to GMPY's ``mpz``. """ 

184 return a.to_int() 

185 

186 def from_ZZ_gmpy(K1, a, K0): 

187 """Convert GMPY's ``mpz`` to GMPY's ``mpz``. """ 

188 return a 

189 

190 def from_QQ_gmpy(K1, a, K0): 

191 """Convert GMPY ``mpq`` to GMPY's ``mpz``. """ 

192 if a.denominator == 1: 

193 return a.numerator 

194 

195 def from_RealField(K1, a, K0): 

196 """Convert mpmath's ``mpf`` to GMPY's ``mpz``. """ 

197 p, q = K0.to_rational(a) 

198 

199 if q == 1: 

200 return MPZ(p) 

201 

202 def from_GaussianIntegerRing(K1, a, K0): 

203 if a.y == 0: 

204 return a.x 

205 

206 def gcdex(self, a, b): 

207 """Compute extended GCD of ``a`` and ``b``. """ 

208 h, s, t = gcdex(a, b) 

209 if HAS_GMPY: 

210 return s, t, h 

211 else: 

212 return h, s, t 

213 

214 def gcd(self, a, b): 

215 """Compute GCD of ``a`` and ``b``. """ 

216 return gcd(a, b) 

217 

218 def lcm(self, a, b): 

219 """Compute LCM of ``a`` and ``b``. """ 

220 return lcm(a, b) 

221 

222 def sqrt(self, a): 

223 """Compute square root of ``a``. """ 

224 return sqrt(a) 

225 

226 def factorial(self, a): 

227 """Compute factorial of ``a``. """ 

228 return factorial(a) 

229 

230 

231ZZ = IntegerRing()