Coverage for /usr/lib/python3/dist-packages/sympy/polys/rationaltools.py: 83%

23 statements  

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

1"""Tools for manipulation of rational expressions. """ 

2 

3 

4from sympy.core import Basic, Add, sympify 

5from sympy.core.exprtools import gcd_terms 

6from sympy.utilities import public 

7from sympy.utilities.iterables import iterable 

8 

9 

10@public 

11def together(expr, deep=False, fraction=True): 

12 """ 

13 Denest and combine rational expressions using symbolic methods. 

14 

15 This function takes an expression or a container of expressions 

16 and puts it (them) together by denesting and combining rational 

17 subexpressions. No heroic measures are taken to minimize degree 

18 of the resulting numerator and denominator. To obtain completely 

19 reduced expression use :func:`~.cancel`. However, :func:`~.together` 

20 can preserve as much as possible of the structure of the input 

21 expression in the output (no expansion is performed). 

22 

23 A wide variety of objects can be put together including lists, 

24 tuples, sets, relational objects, integrals and others. It is 

25 also possible to transform interior of function applications, 

26 by setting ``deep`` flag to ``True``. 

27 

28 By definition, :func:`~.together` is a complement to :func:`~.apart`, 

29 so ``apart(together(expr))`` should return expr unchanged. Note 

30 however, that :func:`~.together` uses only symbolic methods, so 

31 it might be necessary to use :func:`~.cancel` to perform algebraic 

32 simplification and minimize degree of the numerator and denominator. 

33 

34 Examples 

35 ======== 

36 

37 >>> from sympy import together, exp 

38 >>> from sympy.abc import x, y, z 

39 

40 >>> together(1/x + 1/y) 

41 (x + y)/(x*y) 

42 >>> together(1/x + 1/y + 1/z) 

43 (x*y + x*z + y*z)/(x*y*z) 

44 

45 >>> together(1/(x*y) + 1/y**2) 

46 (x + y)/(x*y**2) 

47 

48 >>> together(1/(1 + 1/x) + 1/(1 + 1/y)) 

49 (x*(y + 1) + y*(x + 1))/((x + 1)*(y + 1)) 

50 

51 >>> together(exp(1/x + 1/y)) 

52 exp(1/y + 1/x) 

53 >>> together(exp(1/x + 1/y), deep=True) 

54 exp((x + y)/(x*y)) 

55 

56 >>> together(1/exp(x) + 1/(x*exp(x))) 

57 (x + 1)*exp(-x)/x 

58 

59 >>> together(1/exp(2*x) + 1/(x*exp(3*x))) 

60 (x*exp(x) + 1)*exp(-3*x)/x 

61 

62 """ 

63 def _together(expr): 

64 if isinstance(expr, Basic): 

65 if expr.is_Atom or (expr.is_Function and not deep): 

66 return expr 

67 elif expr.is_Add: 

68 return gcd_terms(list(map(_together, Add.make_args(expr))), fraction=fraction) 

69 elif expr.is_Pow: 

70 base = _together(expr.base) 

71 

72 if deep: 

73 exp = _together(expr.exp) 

74 else: 

75 exp = expr.exp 

76 

77 return expr.__class__(base, exp) 

78 else: 

79 return expr.__class__(*[ _together(arg) for arg in expr.args ]) 

80 elif iterable(expr): 

81 return expr.__class__([ _together(ex) for ex in expr ]) 

82 

83 return expr 

84 

85 return _together(sympify(expr))