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

396 statements  

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

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

2 

3from __future__ import annotations 

4from typing import Any 

5 

6from sympy.core.numbers import AlgebraicNumber 

7from sympy.core import Basic, sympify 

8from sympy.core.sorting import default_sort_key, ordered 

9from sympy.external.gmpy import HAS_GMPY 

10from sympy.polys.domains.domainelement import DomainElement 

11from sympy.polys.orderings import lex 

12from sympy.polys.polyerrors import UnificationFailed, CoercionFailed, DomainError 

13from sympy.polys.polyutils import _unify_gens, _not_a_coeff 

14from sympy.utilities import public 

15from sympy.utilities.iterables import is_sequence 

16 

17 

18@public 

19class Domain: 

20 """Superclass for all domains in the polys domains system. 

21 

22 See :ref:`polys-domainsintro` for an introductory explanation of the 

23 domains system. 

24 

25 The :py:class:`~.Domain` class is an abstract base class for all of the 

26 concrete domain types. There are many different :py:class:`~.Domain` 

27 subclasses each of which has an associated ``dtype`` which is a class 

28 representing the elements of the domain. The coefficients of a 

29 :py:class:`~.Poly` are elements of a domain which must be a subclass of 

30 :py:class:`~.Domain`. 

31 

32 Examples 

33 ======== 

34 

35 The most common example domains are the integers :ref:`ZZ` and the 

36 rationals :ref:`QQ`. 

37 

38 >>> from sympy import Poly, symbols, Domain 

39 >>> x, y = symbols('x, y') 

40 >>> p = Poly(x**2 + y) 

41 >>> p 

42 Poly(x**2 + y, x, y, domain='ZZ') 

43 >>> p.domain 

44 ZZ 

45 >>> isinstance(p.domain, Domain) 

46 True 

47 >>> Poly(x**2 + y/2) 

48 Poly(x**2 + 1/2*y, x, y, domain='QQ') 

49 

50 The domains can be used directly in which case the domain object e.g. 

51 (:ref:`ZZ` or :ref:`QQ`) can be used as a constructor for elements of 

52 ``dtype``. 

53 

54 >>> from sympy import ZZ, QQ 

55 >>> ZZ(2) 

56 2 

57 >>> ZZ.dtype # doctest: +SKIP 

58 <class 'int'> 

59 >>> type(ZZ(2)) # doctest: +SKIP 

60 <class 'int'> 

61 >>> QQ(1, 2) 

62 1/2 

63 >>> type(QQ(1, 2)) # doctest: +SKIP 

64 <class 'sympy.polys.domains.pythonrational.PythonRational'> 

65 

66 The corresponding domain elements can be used with the arithmetic 

67 operations ``+,-,*,**`` and depending on the domain some combination of 

68 ``/,//,%`` might be usable. For example in :ref:`ZZ` both ``//`` (floor 

69 division) and ``%`` (modulo division) can be used but ``/`` (true 

70 division) cannot. Since :ref:`QQ` is a :py:class:`~.Field` its elements 

71 can be used with ``/`` but ``//`` and ``%`` should not be used. Some 

72 domains have a :py:meth:`~.Domain.gcd` method. 

73 

74 >>> ZZ(2) + ZZ(3) 

75 5 

76 >>> ZZ(5) // ZZ(2) 

77 2 

78 >>> ZZ(5) % ZZ(2) 

79 1 

80 >>> QQ(1, 2) / QQ(2, 3) 

81 3/4 

82 >>> ZZ.gcd(ZZ(4), ZZ(2)) 

83 2 

84 >>> QQ.gcd(QQ(2,7), QQ(5,3)) 

85 1/21 

86 >>> ZZ.is_Field 

87 False 

88 >>> QQ.is_Field 

89 True 

90 

91 There are also many other domains including: 

92 

93 1. :ref:`GF(p)` for finite fields of prime order. 

94 2. :ref:`RR` for real (floating point) numbers. 

95 3. :ref:`CC` for complex (floating point) numbers. 

96 4. :ref:`QQ(a)` for algebraic number fields. 

97 5. :ref:`K[x]` for polynomial rings. 

98 6. :ref:`K(x)` for rational function fields. 

99 7. :ref:`EX` for arbitrary expressions. 

100 

101 Each domain is represented by a domain object and also an implementation 

102 class (``dtype``) for the elements of the domain. For example the 

103 :ref:`K[x]` domains are represented by a domain object which is an 

104 instance of :py:class:`~.PolynomialRing` and the elements are always 

105 instances of :py:class:`~.PolyElement`. The implementation class 

106 represents particular types of mathematical expressions in a way that is 

107 more efficient than a normal SymPy expression which is of type 

108 :py:class:`~.Expr`. The domain methods :py:meth:`~.Domain.from_sympy` and 

109 :py:meth:`~.Domain.to_sympy` are used to convert from :py:class:`~.Expr` 

110 to a domain element and vice versa. 

111 

112 >>> from sympy import Symbol, ZZ, Expr 

113 >>> x = Symbol('x') 

114 >>> K = ZZ[x] # polynomial ring domain 

115 >>> K 

116 ZZ[x] 

117 >>> type(K) # class of the domain 

118 <class 'sympy.polys.domains.polynomialring.PolynomialRing'> 

119 >>> K.dtype # class of the elements 

120 <class 'sympy.polys.rings.PolyElement'> 

121 >>> p_expr = x**2 + 1 # Expr 

122 >>> p_expr 

123 x**2 + 1 

124 >>> type(p_expr) 

125 <class 'sympy.core.add.Add'> 

126 >>> isinstance(p_expr, Expr) 

127 True 

128 >>> p_domain = K.from_sympy(p_expr) 

129 >>> p_domain # domain element 

130 x**2 + 1 

131 >>> type(p_domain) 

132 <class 'sympy.polys.rings.PolyElement'> 

133 >>> K.to_sympy(p_domain) == p_expr 

134 True 

135 

136 The :py:meth:`~.Domain.convert_from` method is used to convert domain 

137 elements from one domain to another. 

138 

139 >>> from sympy import ZZ, QQ 

140 >>> ez = ZZ(2) 

141 >>> eq = QQ.convert_from(ez, ZZ) 

142 >>> type(ez) # doctest: +SKIP 

143 <class 'int'> 

144 >>> type(eq) # doctest: +SKIP 

145 <class 'sympy.polys.domains.pythonrational.PythonRational'> 

146 

147 Elements from different domains should not be mixed in arithmetic or other 

148 operations: they should be converted to a common domain first. The domain 

149 method :py:meth:`~.Domain.unify` is used to find a domain that can 

150 represent all the elements of two given domains. 

151 

152 >>> from sympy import ZZ, QQ, symbols 

153 >>> x, y = symbols('x, y') 

154 >>> ZZ.unify(QQ) 

155 QQ 

156 >>> ZZ[x].unify(QQ) 

157 QQ[x] 

158 >>> ZZ[x].unify(QQ[y]) 

159 QQ[x,y] 

160 

161 If a domain is a :py:class:`~.Ring` then is might have an associated 

162 :py:class:`~.Field` and vice versa. The :py:meth:`~.Domain.get_field` and 

163 :py:meth:`~.Domain.get_ring` methods will find or create the associated 

164 domain. 

165 

166 >>> from sympy import ZZ, QQ, Symbol 

167 >>> x = Symbol('x') 

168 >>> ZZ.has_assoc_Field 

169 True 

170 >>> ZZ.get_field() 

171 QQ 

172 >>> QQ.has_assoc_Ring 

173 True 

174 >>> QQ.get_ring() 

175 ZZ 

176 >>> K = QQ[x] 

177 >>> K 

178 QQ[x] 

179 >>> K.get_field() 

180 QQ(x) 

181 

182 See also 

183 ======== 

184 

185 DomainElement: abstract base class for domain elements 

186 construct_domain: construct a minimal domain for some expressions 

187 

188 """ 

189 

190 dtype: type | None = None 

191 """The type (class) of the elements of this :py:class:`~.Domain`: 

192 

193 >>> from sympy import ZZ, QQ, Symbol 

194 >>> ZZ.dtype 

195 <class 'int'> 

196 >>> z = ZZ(2) 

197 >>> z 

198 2 

199 >>> type(z) 

200 <class 'int'> 

201 >>> type(z) == ZZ.dtype 

202 True 

203 

204 Every domain has an associated **dtype** ("datatype") which is the 

205 class of the associated domain elements. 

206 

207 See also 

208 ======== 

209 

210 of_type 

211 """ 

212 

213 zero: Any = None 

214 """The zero element of the :py:class:`~.Domain`: 

215 

216 >>> from sympy import QQ 

217 >>> QQ.zero 

218 0 

219 >>> QQ.of_type(QQ.zero) 

220 True 

221 

222 See also 

223 ======== 

224 

225 of_type 

226 one 

227 """ 

228 

229 one: Any = None 

230 """The one element of the :py:class:`~.Domain`: 

231 

232 >>> from sympy import QQ 

233 >>> QQ.one 

234 1 

235 >>> QQ.of_type(QQ.one) 

236 True 

237 

238 See also 

239 ======== 

240 

241 of_type 

242 zero 

243 """ 

244 

245 is_Ring = False 

246 """Boolean flag indicating if the domain is a :py:class:`~.Ring`. 

247 

248 >>> from sympy import ZZ 

249 >>> ZZ.is_Ring 

250 True 

251 

252 Basically every :py:class:`~.Domain` represents a ring so this flag is 

253 not that useful. 

254 

255 See also 

256 ======== 

257 

258 is_PID 

259 is_Field 

260 get_ring 

261 has_assoc_Ring 

262 """ 

263 

264 is_Field = False 

265 """Boolean flag indicating if the domain is a :py:class:`~.Field`. 

266 

267 >>> from sympy import ZZ, QQ 

268 >>> ZZ.is_Field 

269 False 

270 >>> QQ.is_Field 

271 True 

272 

273 See also 

274 ======== 

275 

276 is_PID 

277 is_Ring 

278 get_field 

279 has_assoc_Field 

280 """ 

281 

282 has_assoc_Ring = False 

283 """Boolean flag indicating if the domain has an associated 

284 :py:class:`~.Ring`. 

285 

286 >>> from sympy import QQ 

287 >>> QQ.has_assoc_Ring 

288 True 

289 >>> QQ.get_ring() 

290 ZZ 

291 

292 See also 

293 ======== 

294 

295 is_Field 

296 get_ring 

297 """ 

298 

299 has_assoc_Field = False 

300 """Boolean flag indicating if the domain has an associated 

301 :py:class:`~.Field`. 

302 

303 >>> from sympy import ZZ 

304 >>> ZZ.has_assoc_Field 

305 True 

306 >>> ZZ.get_field() 

307 QQ 

308 

309 See also 

310 ======== 

311 

312 is_Field 

313 get_field 

314 """ 

315 

316 is_FiniteField = is_FF = False 

317 is_IntegerRing = is_ZZ = False 

318 is_RationalField = is_QQ = False 

319 is_GaussianRing = is_ZZ_I = False 

320 is_GaussianField = is_QQ_I = False 

321 is_RealField = is_RR = False 

322 is_ComplexField = is_CC = False 

323 is_AlgebraicField = is_Algebraic = False 

324 is_PolynomialRing = is_Poly = False 

325 is_FractionField = is_Frac = False 

326 is_SymbolicDomain = is_EX = False 

327 is_SymbolicRawDomain = is_EXRAW = False 

328 is_FiniteExtension = False 

329 

330 is_Exact = True 

331 is_Numerical = False 

332 

333 is_Simple = False 

334 is_Composite = False 

335 

336 is_PID = False 

337 """Boolean flag indicating if the domain is a `principal ideal domain`_. 

338 

339 >>> from sympy import ZZ 

340 >>> ZZ.has_assoc_Field 

341 True 

342 >>> ZZ.get_field() 

343 QQ 

344 

345 .. _principal ideal domain: https://en.wikipedia.org/wiki/Principal_ideal_domain 

346 

347 See also 

348 ======== 

349 

350 is_Field 

351 get_field 

352 """ 

353 

354 has_CharacteristicZero = False 

355 

356 rep: str | None = None 

357 alias: str | None = None 

358 

359 def __init__(self): 

360 raise NotImplementedError 

361 

362 def __str__(self): 

363 return self.rep 

364 

365 def __repr__(self): 

366 return str(self) 

367 

368 def __hash__(self): 

369 return hash((self.__class__.__name__, self.dtype)) 

370 

371 def new(self, *args): 

372 return self.dtype(*args) 

373 

374 @property 

375 def tp(self): 

376 """Alias for :py:attr:`~.Domain.dtype`""" 

377 return self.dtype 

378 

379 def __call__(self, *args): 

380 """Construct an element of ``self`` domain from ``args``. """ 

381 return self.new(*args) 

382 

383 def normal(self, *args): 

384 return self.dtype(*args) 

385 

386 def convert_from(self, element, base): 

387 """Convert ``element`` to ``self.dtype`` given the base domain. """ 

388 if base.alias is not None: 

389 method = "from_" + base.alias 

390 else: 

391 method = "from_" + base.__class__.__name__ 

392 

393 _convert = getattr(self, method) 

394 

395 if _convert is not None: 

396 result = _convert(element, base) 

397 

398 if result is not None: 

399 return result 

400 

401 raise CoercionFailed("Cannot convert %s of type %s from %s to %s" % (element, type(element), base, self)) 

402 

403 def convert(self, element, base=None): 

404 """Convert ``element`` to ``self.dtype``. """ 

405 

406 if base is not None: 

407 if _not_a_coeff(element): 

408 raise CoercionFailed('%s is not in any domain' % element) 

409 return self.convert_from(element, base) 

410 

411 if self.of_type(element): 

412 return element 

413 

414 if _not_a_coeff(element): 

415 raise CoercionFailed('%s is not in any domain' % element) 

416 

417 from sympy.polys.domains import ZZ, QQ, RealField, ComplexField 

418 

419 if ZZ.of_type(element): 

420 return self.convert_from(element, ZZ) 

421 

422 if isinstance(element, int): 

423 return self.convert_from(ZZ(element), ZZ) 

424 

425 if HAS_GMPY: 

426 integers = ZZ 

427 if isinstance(element, integers.tp): 

428 return self.convert_from(element, integers) 

429 

430 rationals = QQ 

431 if isinstance(element, rationals.tp): 

432 return self.convert_from(element, rationals) 

433 

434 if isinstance(element, float): 

435 parent = RealField(tol=False) 

436 return self.convert_from(parent(element), parent) 

437 

438 if isinstance(element, complex): 

439 parent = ComplexField(tol=False) 

440 return self.convert_from(parent(element), parent) 

441 

442 if isinstance(element, DomainElement): 

443 return self.convert_from(element, element.parent()) 

444 

445 # TODO: implement this in from_ methods 

446 if self.is_Numerical and getattr(element, 'is_ground', False): 

447 return self.convert(element.LC()) 

448 

449 if isinstance(element, Basic): 

450 try: 

451 return self.from_sympy(element) 

452 except (TypeError, ValueError): 

453 pass 

454 else: # TODO: remove this branch 

455 if not is_sequence(element): 

456 try: 

457 element = sympify(element, strict=True) 

458 if isinstance(element, Basic): 

459 return self.from_sympy(element) 

460 except (TypeError, ValueError): 

461 pass 

462 

463 raise CoercionFailed("Cannot convert %s of type %s to %s" % (element, type(element), self)) 

464 

465 def of_type(self, element): 

466 """Check if ``a`` is of type ``dtype``. """ 

467 return isinstance(element, self.tp) # XXX: this isn't correct, e.g. PolyElement 

468 

469 def __contains__(self, a): 

470 """Check if ``a`` belongs to this domain. """ 

471 try: 

472 if _not_a_coeff(a): 

473 raise CoercionFailed 

474 self.convert(a) # this might raise, too 

475 except CoercionFailed: 

476 return False 

477 

478 return True 

479 

480 def to_sympy(self, a): 

481 """Convert domain element *a* to a SymPy expression (Expr). 

482 

483 Explanation 

484 =========== 

485 

486 Convert a :py:class:`~.Domain` element *a* to :py:class:`~.Expr`. Most 

487 public SymPy functions work with objects of type :py:class:`~.Expr`. 

488 The elements of a :py:class:`~.Domain` have a different internal 

489 representation. It is not possible to mix domain elements with 

490 :py:class:`~.Expr` so each domain has :py:meth:`~.Domain.to_sympy` and 

491 :py:meth:`~.Domain.from_sympy` methods to convert its domain elements 

492 to and from :py:class:`~.Expr`. 

493 

494 Parameters 

495 ========== 

496 

497 a: domain element 

498 An element of this :py:class:`~.Domain`. 

499 

500 Returns 

501 ======= 

502 

503 expr: Expr 

504 A normal SymPy expression of type :py:class:`~.Expr`. 

505 

506 Examples 

507 ======== 

508 

509 Construct an element of the :ref:`QQ` domain and then convert it to 

510 :py:class:`~.Expr`. 

511 

512 >>> from sympy import QQ, Expr 

513 >>> q_domain = QQ(2) 

514 >>> q_domain 

515 2 

516 >>> q_expr = QQ.to_sympy(q_domain) 

517 >>> q_expr 

518 2 

519 

520 Although the printed forms look similar these objects are not of the 

521 same type. 

522 

523 >>> isinstance(q_domain, Expr) 

524 False 

525 >>> isinstance(q_expr, Expr) 

526 True 

527 

528 Construct an element of :ref:`K[x]` and convert to 

529 :py:class:`~.Expr`. 

530 

531 >>> from sympy import Symbol 

532 >>> x = Symbol('x') 

533 >>> K = QQ[x] 

534 >>> x_domain = K.gens[0] # generator x as a domain element 

535 >>> p_domain = x_domain**2/3 + 1 

536 >>> p_domain 

537 1/3*x**2 + 1 

538 >>> p_expr = K.to_sympy(p_domain) 

539 >>> p_expr 

540 x**2/3 + 1 

541 

542 The :py:meth:`~.Domain.from_sympy` method is used for the opposite 

543 conversion from a normal SymPy expression to a domain element. 

544 

545 >>> p_domain == p_expr 

546 False 

547 >>> K.from_sympy(p_expr) == p_domain 

548 True 

549 >>> K.to_sympy(p_domain) == p_expr 

550 True 

551 >>> K.from_sympy(K.to_sympy(p_domain)) == p_domain 

552 True 

553 >>> K.to_sympy(K.from_sympy(p_expr)) == p_expr 

554 True 

555 

556 The :py:meth:`~.Domain.from_sympy` method makes it easier to construct 

557 domain elements interactively. 

558 

559 >>> from sympy import Symbol 

560 >>> x = Symbol('x') 

561 >>> K = QQ[x] 

562 >>> K.from_sympy(x**2/3 + 1) 

563 1/3*x**2 + 1 

564 

565 See also 

566 ======== 

567 

568 from_sympy 

569 convert_from 

570 """ 

571 raise NotImplementedError 

572 

573 def from_sympy(self, a): 

574 """Convert a SymPy expression to an element of this domain. 

575 

576 Explanation 

577 =========== 

578 

579 See :py:meth:`~.Domain.to_sympy` for explanation and examples. 

580 

581 Parameters 

582 ========== 

583 

584 expr: Expr 

585 A normal SymPy expression of type :py:class:`~.Expr`. 

586 

587 Returns 

588 ======= 

589 

590 a: domain element 

591 An element of this :py:class:`~.Domain`. 

592 

593 See also 

594 ======== 

595 

596 to_sympy 

597 convert_from 

598 """ 

599 raise NotImplementedError 

600 

601 def sum(self, args): 

602 return sum(args) 

603 

604 def from_FF(K1, a, K0): 

605 """Convert ``ModularInteger(int)`` to ``dtype``. """ 

606 return None 

607 

608 def from_FF_python(K1, a, K0): 

609 """Convert ``ModularInteger(int)`` to ``dtype``. """ 

610 return None 

611 

612 def from_ZZ_python(K1, a, K0): 

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

614 return None 

615 

616 def from_QQ_python(K1, a, K0): 

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

618 return None 

619 

620 def from_FF_gmpy(K1, a, K0): 

621 """Convert ``ModularInteger(mpz)`` to ``dtype``. """ 

622 return None 

623 

624 def from_ZZ_gmpy(K1, a, K0): 

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

626 return None 

627 

628 def from_QQ_gmpy(K1, a, K0): 

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

630 return None 

631 

632 def from_RealField(K1, a, K0): 

633 """Convert a real element object to ``dtype``. """ 

634 return None 

635 

636 def from_ComplexField(K1, a, K0): 

637 """Convert a complex element to ``dtype``. """ 

638 return None 

639 

640 def from_AlgebraicField(K1, a, K0): 

641 """Convert an algebraic number to ``dtype``. """ 

642 return None 

643 

644 def from_PolynomialRing(K1, a, K0): 

645 """Convert a polynomial to ``dtype``. """ 

646 if a.is_ground: 

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

648 

649 def from_FractionField(K1, a, K0): 

650 """Convert a rational function to ``dtype``. """ 

651 return None 

652 

653 def from_MonogenicFiniteExtension(K1, a, K0): 

654 """Convert an ``ExtensionElement`` to ``dtype``. """ 

655 return K1.convert_from(a.rep, K0.ring) 

656 

657 def from_ExpressionDomain(K1, a, K0): 

658 """Convert a ``EX`` object to ``dtype``. """ 

659 return K1.from_sympy(a.ex) 

660 

661 def from_ExpressionRawDomain(K1, a, K0): 

662 """Convert a ``EX`` object to ``dtype``. """ 

663 return K1.from_sympy(a) 

664 

665 def from_GlobalPolynomialRing(K1, a, K0): 

666 """Convert a polynomial to ``dtype``. """ 

667 if a.degree() <= 0: 

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

669 

670 def from_GeneralizedPolynomialRing(K1, a, K0): 

671 return K1.from_FractionField(a, K0) 

672 

673 def unify_with_symbols(K0, K1, symbols): 

674 if (K0.is_Composite and (set(K0.symbols) & set(symbols))) or (K1.is_Composite and (set(K1.symbols) & set(symbols))): 

675 raise UnificationFailed("Cannot unify %s with %s, given %s generators" % (K0, K1, tuple(symbols))) 

676 

677 return K0.unify(K1) 

678 

679 def unify(K0, K1, symbols=None): 

680 """ 

681 Construct a minimal domain that contains elements of ``K0`` and ``K1``. 

682 

683 Known domains (from smallest to largest): 

684 

685 - ``GF(p)`` 

686 - ``ZZ`` 

687 - ``QQ`` 

688 - ``RR(prec, tol)`` 

689 - ``CC(prec, tol)`` 

690 - ``ALG(a, b, c)`` 

691 - ``K[x, y, z]`` 

692 - ``K(x, y, z)`` 

693 - ``EX`` 

694 

695 """ 

696 if symbols is not None: 

697 return K0.unify_with_symbols(K1, symbols) 

698 

699 if K0 == K1: 

700 return K0 

701 

702 if K0.is_EXRAW: 

703 return K0 

704 if K1.is_EXRAW: 

705 return K1 

706 

707 if K0.is_EX: 

708 return K0 

709 if K1.is_EX: 

710 return K1 

711 

712 if K0.is_FiniteExtension or K1.is_FiniteExtension: 

713 if K1.is_FiniteExtension: 

714 K0, K1 = K1, K0 

715 if K1.is_FiniteExtension: 

716 # Unifying two extensions. 

717 # Try to ensure that K0.unify(K1) == K1.unify(K0) 

718 if list(ordered([K0.modulus, K1.modulus]))[1] == K0.modulus: 

719 K0, K1 = K1, K0 

720 return K1.set_domain(K0) 

721 else: 

722 # Drop the generator from other and unify with the base domain 

723 K1 = K1.drop(K0.symbol) 

724 K1 = K0.domain.unify(K1) 

725 return K0.set_domain(K1) 

726 

727 if K0.is_Composite or K1.is_Composite: 

728 K0_ground = K0.dom if K0.is_Composite else K0 

729 K1_ground = K1.dom if K1.is_Composite else K1 

730 

731 K0_symbols = K0.symbols if K0.is_Composite else () 

732 K1_symbols = K1.symbols if K1.is_Composite else () 

733 

734 domain = K0_ground.unify(K1_ground) 

735 symbols = _unify_gens(K0_symbols, K1_symbols) 

736 order = K0.order if K0.is_Composite else K1.order 

737 

738 if ((K0.is_FractionField and K1.is_PolynomialRing or 

739 K1.is_FractionField and K0.is_PolynomialRing) and 

740 (not K0_ground.is_Field or not K1_ground.is_Field) and domain.is_Field 

741 and domain.has_assoc_Ring): 

742 domain = domain.get_ring() 

743 

744 if K0.is_Composite and (not K1.is_Composite or K0.is_FractionField or K1.is_PolynomialRing): 

745 cls = K0.__class__ 

746 else: 

747 cls = K1.__class__ 

748 

749 from sympy.polys.domains.old_polynomialring import GlobalPolynomialRing 

750 if cls == GlobalPolynomialRing: 

751 return cls(domain, symbols) 

752 

753 return cls(domain, symbols, order) 

754 

755 def mkinexact(cls, K0, K1): 

756 prec = max(K0.precision, K1.precision) 

757 tol = max(K0.tolerance, K1.tolerance) 

758 return cls(prec=prec, tol=tol) 

759 

760 if K1.is_ComplexField: 

761 K0, K1 = K1, K0 

762 if K0.is_ComplexField: 

763 if K1.is_ComplexField or K1.is_RealField: 

764 return mkinexact(K0.__class__, K0, K1) 

765 else: 

766 return K0 

767 

768 if K1.is_RealField: 

769 K0, K1 = K1, K0 

770 if K0.is_RealField: 

771 if K1.is_RealField: 

772 return mkinexact(K0.__class__, K0, K1) 

773 elif K1.is_GaussianRing or K1.is_GaussianField: 

774 from sympy.polys.domains.complexfield import ComplexField 

775 return ComplexField(prec=K0.precision, tol=K0.tolerance) 

776 else: 

777 return K0 

778 

779 if K1.is_AlgebraicField: 

780 K0, K1 = K1, K0 

781 if K0.is_AlgebraicField: 

782 if K1.is_GaussianRing: 

783 K1 = K1.get_field() 

784 if K1.is_GaussianField: 

785 K1 = K1.as_AlgebraicField() 

786 if K1.is_AlgebraicField: 

787 return K0.__class__(K0.dom.unify(K1.dom), *_unify_gens(K0.orig_ext, K1.orig_ext)) 

788 else: 

789 return K0 

790 

791 if K0.is_GaussianField: 

792 return K0 

793 if K1.is_GaussianField: 

794 return K1 

795 

796 if K0.is_GaussianRing: 

797 if K1.is_RationalField: 

798 K0 = K0.get_field() 

799 return K0 

800 if K1.is_GaussianRing: 

801 if K0.is_RationalField: 

802 K1 = K1.get_field() 

803 return K1 

804 

805 if K0.is_RationalField: 

806 return K0 

807 if K1.is_RationalField: 

808 return K1 

809 

810 if K0.is_IntegerRing: 

811 return K0 

812 if K1.is_IntegerRing: 

813 return K1 

814 

815 if K0.is_FiniteField and K1.is_FiniteField: 

816 return K0.__class__(max(K0.mod, K1.mod, key=default_sort_key)) 

817 

818 from sympy.polys.domains import EX 

819 return EX 

820 

821 def __eq__(self, other): 

822 """Returns ``True`` if two domains are equivalent. """ 

823 return isinstance(other, Domain) and self.dtype == other.dtype 

824 

825 def __ne__(self, other): 

826 """Returns ``False`` if two domains are equivalent. """ 

827 return not self == other 

828 

829 def map(self, seq): 

830 """Rersively apply ``self`` to all elements of ``seq``. """ 

831 result = [] 

832 

833 for elt in seq: 

834 if isinstance(elt, list): 

835 result.append(self.map(elt)) 

836 else: 

837 result.append(self(elt)) 

838 

839 return result 

840 

841 def get_ring(self): 

842 """Returns a ring associated with ``self``. """ 

843 raise DomainError('there is no ring associated with %s' % self) 

844 

845 def get_field(self): 

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

847 raise DomainError('there is no field associated with %s' % self) 

848 

849 def get_exact(self): 

850 """Returns an exact domain associated with ``self``. """ 

851 return self 

852 

853 def __getitem__(self, symbols): 

854 """The mathematical way to make a polynomial ring. """ 

855 if hasattr(symbols, '__iter__'): 

856 return self.poly_ring(*symbols) 

857 else: 

858 return self.poly_ring(symbols) 

859 

860 def poly_ring(self, *symbols, order=lex): 

861 """Returns a polynomial ring, i.e. `K[X]`. """ 

862 from sympy.polys.domains.polynomialring import PolynomialRing 

863 return PolynomialRing(self, symbols, order) 

864 

865 def frac_field(self, *symbols, order=lex): 

866 """Returns a fraction field, i.e. `K(X)`. """ 

867 from sympy.polys.domains.fractionfield import FractionField 

868 return FractionField(self, symbols, order) 

869 

870 def old_poly_ring(self, *symbols, **kwargs): 

871 """Returns a polynomial ring, i.e. `K[X]`. """ 

872 from sympy.polys.domains.old_polynomialring import PolynomialRing 

873 return PolynomialRing(self, *symbols, **kwargs) 

874 

875 def old_frac_field(self, *symbols, **kwargs): 

876 """Returns a fraction field, i.e. `K(X)`. """ 

877 from sympy.polys.domains.old_fractionfield import FractionField 

878 return FractionField(self, *symbols, **kwargs) 

879 

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

881 r"""Returns an algebraic field, i.e. `K(\alpha, \ldots)`. """ 

882 raise DomainError("Cannot create algebraic field over %s" % self) 

883 

884 def alg_field_from_poly(self, poly, alias=None, root_index=-1): 

885 r""" 

886 Convenience method to construct an algebraic extension on a root of a 

887 polynomial, chosen by root index. 

888 

889 Parameters 

890 ========== 

891 

892 poly : :py:class:`~.Poly` 

893 The polynomial whose root generates the extension. 

894 alias : str, optional (default=None) 

895 Symbol name for the generator of the extension. 

896 E.g. "alpha" or "theta". 

897 root_index : int, optional (default=-1) 

898 Specifies which root of the polynomial is desired. The ordering is 

899 as defined by the :py:class:`~.ComplexRootOf` class. The default of 

900 ``-1`` selects the most natural choice in the common cases of 

901 quadratic and cyclotomic fields (the square root on the positive 

902 real or imaginary axis, resp. $\mathrm{e}^{2\pi i/n}$). 

903 

904 Examples 

905 ======== 

906 

907 >>> from sympy import QQ, Poly 

908 >>> from sympy.abc import x 

909 >>> f = Poly(x**2 - 2) 

910 >>> K = QQ.alg_field_from_poly(f) 

911 >>> K.ext.minpoly == f 

912 True 

913 >>> g = Poly(8*x**3 - 6*x - 1) 

914 >>> L = QQ.alg_field_from_poly(g, "alpha") 

915 >>> L.ext.minpoly == g 

916 True 

917 >>> L.to_sympy(L([1, 1, 1])) 

918 alpha**2 + alpha + 1 

919 

920 """ 

921 from sympy.polys.rootoftools import CRootOf 

922 root = CRootOf(poly, root_index) 

923 alpha = AlgebraicNumber(root, alias=alias) 

924 return self.algebraic_field(alpha, alias=alias) 

925 

926 def cyclotomic_field(self, n, ss=False, alias="zeta", gen=None, root_index=-1): 

927 r""" 

928 Convenience method to construct a cyclotomic field. 

929 

930 Parameters 

931 ========== 

932 

933 n : int 

934 Construct the nth cyclotomic field. 

935 ss : boolean, optional (default=False) 

936 If True, append *n* as a subscript on the alias string. 

937 alias : str, optional (default="zeta") 

938 Symbol name for the generator. 

939 gen : :py:class:`~.Symbol`, optional (default=None) 

940 Desired variable for the cyclotomic polynomial that defines the 

941 field. If ``None``, a dummy variable will be used. 

942 root_index : int, optional (default=-1) 

943 Specifies which root of the polynomial is desired. The ordering is 

944 as defined by the :py:class:`~.ComplexRootOf` class. The default of 

945 ``-1`` selects the root $\mathrm{e}^{2\pi i/n}$. 

946 

947 Examples 

948 ======== 

949 

950 >>> from sympy import QQ, latex 

951 >>> K = QQ.cyclotomic_field(5) 

952 >>> K.to_sympy(K([-1, 1])) 

953 1 - zeta 

954 >>> L = QQ.cyclotomic_field(7, True) 

955 >>> a = L.to_sympy(L([-1, 1])) 

956 >>> print(a) 

957 1 - zeta7 

958 >>> print(latex(a)) 

959 1 - \zeta_{7} 

960 

961 """ 

962 from sympy.polys.specialpolys import cyclotomic_poly 

963 if ss: 

964 alias += str(n) 

965 return self.alg_field_from_poly(cyclotomic_poly(n, gen), alias=alias, 

966 root_index=root_index) 

967 

968 def inject(self, *symbols): 

969 """Inject generators into this domain. """ 

970 raise NotImplementedError 

971 

972 def drop(self, *symbols): 

973 """Drop generators from this domain. """ 

974 if self.is_Simple: 

975 return self 

976 raise NotImplementedError # pragma: no cover 

977 

978 def is_zero(self, a): 

979 """Returns True if ``a`` is zero. """ 

980 return not a 

981 

982 def is_one(self, a): 

983 """Returns True if ``a`` is one. """ 

984 return a == self.one 

985 

986 def is_positive(self, a): 

987 """Returns True if ``a`` is positive. """ 

988 return a > 0 

989 

990 def is_negative(self, a): 

991 """Returns True if ``a`` is negative. """ 

992 return a < 0 

993 

994 def is_nonpositive(self, a): 

995 """Returns True if ``a`` is non-positive. """ 

996 return a <= 0 

997 

998 def is_nonnegative(self, a): 

999 """Returns True if ``a`` is non-negative. """ 

1000 return a >= 0 

1001 

1002 def canonical_unit(self, a): 

1003 if self.is_negative(a): 

1004 return -self.one 

1005 else: 

1006 return self.one 

1007 

1008 def abs(self, a): 

1009 """Absolute value of ``a``, implies ``__abs__``. """ 

1010 return abs(a) 

1011 

1012 def neg(self, a): 

1013 """Returns ``a`` negated, implies ``__neg__``. """ 

1014 return -a 

1015 

1016 def pos(self, a): 

1017 """Returns ``a`` positive, implies ``__pos__``. """ 

1018 return +a 

1019 

1020 def add(self, a, b): 

1021 """Sum of ``a`` and ``b``, implies ``__add__``. """ 

1022 return a + b 

1023 

1024 def sub(self, a, b): 

1025 """Difference of ``a`` and ``b``, implies ``__sub__``. """ 

1026 return a - b 

1027 

1028 def mul(self, a, b): 

1029 """Product of ``a`` and ``b``, implies ``__mul__``. """ 

1030 return a * b 

1031 

1032 def pow(self, a, b): 

1033 """Raise ``a`` to power ``b``, implies ``__pow__``. """ 

1034 return a ** b 

1035 

1036 def exquo(self, a, b): 

1037 """Exact quotient of *a* and *b*. Analogue of ``a / b``. 

1038 

1039 Explanation 

1040 =========== 

1041 

1042 This is essentially the same as ``a / b`` except that an error will be 

1043 raised if the division is inexact (if there is any remainder) and the 

1044 result will always be a domain element. When working in a 

1045 :py:class:`~.Domain` that is not a :py:class:`~.Field` (e.g. :ref:`ZZ` 

1046 or :ref:`K[x]`) ``exquo`` should be used instead of ``/``. 

1047 

1048 The key invariant is that if ``q = K.exquo(a, b)`` (and ``exquo`` does 

1049 not raise an exception) then ``a == b*q``. 

1050 

1051 Examples 

1052 ======== 

1053 

1054 We can use ``K.exquo`` instead of ``/`` for exact division. 

1055 

1056 >>> from sympy import ZZ 

1057 >>> ZZ.exquo(ZZ(4), ZZ(2)) 

1058 2 

1059 >>> ZZ.exquo(ZZ(5), ZZ(2)) 

1060 Traceback (most recent call last): 

1061 ... 

1062 ExactQuotientFailed: 2 does not divide 5 in ZZ 

1063 

1064 Over a :py:class:`~.Field` such as :ref:`QQ`, division (with nonzero 

1065 divisor) is always exact so in that case ``/`` can be used instead of 

1066 :py:meth:`~.Domain.exquo`. 

1067 

1068 >>> from sympy import QQ 

1069 >>> QQ.exquo(QQ(5), QQ(2)) 

1070 5/2 

1071 >>> QQ(5) / QQ(2) 

1072 5/2 

1073 

1074 Parameters 

1075 ========== 

1076 

1077 a: domain element 

1078 The dividend 

1079 b: domain element 

1080 The divisor 

1081 

1082 Returns 

1083 ======= 

1084 

1085 q: domain element 

1086 The exact quotient 

1087 

1088 Raises 

1089 ====== 

1090 

1091 ExactQuotientFailed: if exact division is not possible. 

1092 ZeroDivisionError: when the divisor is zero. 

1093 

1094 See also 

1095 ======== 

1096 

1097 quo: Analogue of ``a // b`` 

1098 rem: Analogue of ``a % b`` 

1099 div: Analogue of ``divmod(a, b)`` 

1100 

1101 Notes 

1102 ===== 

1103 

1104 Since the default :py:attr:`~.Domain.dtype` for :ref:`ZZ` is ``int`` 

1105 (or ``mpz``) division as ``a / b`` should not be used as it would give 

1106 a ``float``. 

1107 

1108 >>> ZZ(4) / ZZ(2) 

1109 2.0 

1110 >>> ZZ(5) / ZZ(2) 

1111 2.5 

1112 

1113 Using ``/`` with :ref:`ZZ` will lead to incorrect results so 

1114 :py:meth:`~.Domain.exquo` should be used instead. 

1115 

1116 """ 

1117 raise NotImplementedError 

1118 

1119 def quo(self, a, b): 

1120 """Quotient of *a* and *b*. Analogue of ``a // b``. 

1121 

1122 ``K.quo(a, b)`` is equivalent to ``K.div(a, b)[0]``. See 

1123 :py:meth:`~.Domain.div` for more explanation. 

1124 

1125 See also 

1126 ======== 

1127 

1128 rem: Analogue of ``a % b`` 

1129 div: Analogue of ``divmod(a, b)`` 

1130 exquo: Analogue of ``a / b`` 

1131 """ 

1132 raise NotImplementedError 

1133 

1134 def rem(self, a, b): 

1135 """Modulo division of *a* and *b*. Analogue of ``a % b``. 

1136 

1137 ``K.rem(a, b)`` is equivalent to ``K.div(a, b)[1]``. See 

1138 :py:meth:`~.Domain.div` for more explanation. 

1139 

1140 See also 

1141 ======== 

1142 

1143 quo: Analogue of ``a // b`` 

1144 div: Analogue of ``divmod(a, b)`` 

1145 exquo: Analogue of ``a / b`` 

1146 """ 

1147 raise NotImplementedError 

1148 

1149 def div(self, a, b): 

1150 """Quotient and remainder for *a* and *b*. Analogue of ``divmod(a, b)`` 

1151 

1152 Explanation 

1153 =========== 

1154 

1155 This is essentially the same as ``divmod(a, b)`` except that is more 

1156 consistent when working over some :py:class:`~.Field` domains such as 

1157 :ref:`QQ`. When working over an arbitrary :py:class:`~.Domain` the 

1158 :py:meth:`~.Domain.div` method should be used instead of ``divmod``. 

1159 

1160 The key invariant is that if ``q, r = K.div(a, b)`` then 

1161 ``a == b*q + r``. 

1162 

1163 The result of ``K.div(a, b)`` is the same as the tuple 

1164 ``(K.quo(a, b), K.rem(a, b))`` except that if both quotient and 

1165 remainder are needed then it is more efficient to use 

1166 :py:meth:`~.Domain.div`. 

1167 

1168 Examples 

1169 ======== 

1170 

1171 We can use ``K.div`` instead of ``divmod`` for floor division and 

1172 remainder. 

1173 

1174 >>> from sympy import ZZ, QQ 

1175 >>> ZZ.div(ZZ(5), ZZ(2)) 

1176 (2, 1) 

1177 

1178 If ``K`` is a :py:class:`~.Field` then the division is always exact 

1179 with a remainder of :py:attr:`~.Domain.zero`. 

1180 

1181 >>> QQ.div(QQ(5), QQ(2)) 

1182 (5/2, 0) 

1183 

1184 Parameters 

1185 ========== 

1186 

1187 a: domain element 

1188 The dividend 

1189 b: domain element 

1190 The divisor 

1191 

1192 Returns 

1193 ======= 

1194 

1195 (q, r): tuple of domain elements 

1196 The quotient and remainder 

1197 

1198 Raises 

1199 ====== 

1200 

1201 ZeroDivisionError: when the divisor is zero. 

1202 

1203 See also 

1204 ======== 

1205 

1206 quo: Analogue of ``a // b`` 

1207 rem: Analogue of ``a % b`` 

1208 exquo: Analogue of ``a / b`` 

1209 

1210 Notes 

1211 ===== 

1212 

1213 If ``gmpy`` is installed then the ``gmpy.mpq`` type will be used as 

1214 the :py:attr:`~.Domain.dtype` for :ref:`QQ`. The ``gmpy.mpq`` type 

1215 defines ``divmod`` in a way that is undesirable so 

1216 :py:meth:`~.Domain.div` should be used instead of ``divmod``. 

1217 

1218 >>> a = QQ(1) 

1219 >>> b = QQ(3, 2) 

1220 >>> a # doctest: +SKIP 

1221 mpq(1,1) 

1222 >>> b # doctest: +SKIP 

1223 mpq(3,2) 

1224 >>> divmod(a, b) # doctest: +SKIP 

1225 (mpz(0), mpq(1,1)) 

1226 >>> QQ.div(a, b) # doctest: +SKIP 

1227 (mpq(2,3), mpq(0,1)) 

1228 

1229 Using ``//`` or ``%`` with :ref:`QQ` will lead to incorrect results so 

1230 :py:meth:`~.Domain.div` should be used instead. 

1231 

1232 """ 

1233 raise NotImplementedError 

1234 

1235 def invert(self, a, b): 

1236 """Returns inversion of ``a mod b``, implies something. """ 

1237 raise NotImplementedError 

1238 

1239 def revert(self, a): 

1240 """Returns ``a**(-1)`` if possible. """ 

1241 raise NotImplementedError 

1242 

1243 def numer(self, a): 

1244 """Returns numerator of ``a``. """ 

1245 raise NotImplementedError 

1246 

1247 def denom(self, a): 

1248 """Returns denominator of ``a``. """ 

1249 raise NotImplementedError 

1250 

1251 def half_gcdex(self, a, b): 

1252 """Half extended GCD of ``a`` and ``b``. """ 

1253 s, t, h = self.gcdex(a, b) 

1254 return s, h 

1255 

1256 def gcdex(self, a, b): 

1257 """Extended GCD of ``a`` and ``b``. """ 

1258 raise NotImplementedError 

1259 

1260 def cofactors(self, a, b): 

1261 """Returns GCD and cofactors of ``a`` and ``b``. """ 

1262 gcd = self.gcd(a, b) 

1263 cfa = self.quo(a, gcd) 

1264 cfb = self.quo(b, gcd) 

1265 return gcd, cfa, cfb 

1266 

1267 def gcd(self, a, b): 

1268 """Returns GCD of ``a`` and ``b``. """ 

1269 raise NotImplementedError 

1270 

1271 def lcm(self, a, b): 

1272 """Returns LCM of ``a`` and ``b``. """ 

1273 raise NotImplementedError 

1274 

1275 def log(self, a, b): 

1276 """Returns b-base logarithm of ``a``. """ 

1277 raise NotImplementedError 

1278 

1279 def sqrt(self, a): 

1280 """Returns square root of ``a``. """ 

1281 raise NotImplementedError 

1282 

1283 def evalf(self, a, prec=None, **options): 

1284 """Returns numerical approximation of ``a``. """ 

1285 return self.to_sympy(a).evalf(prec, **options) 

1286 

1287 n = evalf 

1288 

1289 def real(self, a): 

1290 return a 

1291 

1292 def imag(self, a): 

1293 return self.zero 

1294 

1295 def almosteq(self, a, b, tolerance=None): 

1296 """Check if ``a`` and ``b`` are almost equal. """ 

1297 return a == b 

1298 

1299 def characteristic(self): 

1300 """Return the characteristic of this domain. """ 

1301 raise NotImplementedError('characteristic()') 

1302 

1303 

1304__all__ = ['Domain']