def as_numer_denom(self): # clear rational denominator content, expr = self.primitive() ncon, dcon = content.as_numer_denom() # collect numerators and denominators of the terms nd = defaultdict(list) for f in expr.args: ni, di = f.as_numer_denom() nd[di].append(ni) # put infinity in the numerator if S.Zero in nd: n = nd.pop(S.Zero) assert len(n) == 1 n = n[0] nd[S.One].append(n / S.Zero) # check for quick exit if len(nd) == 1: d, n = nd.popitem() return Add(*[_keep_coeff(ncon, ni) for ni in n]), _keep_coeff(dcon, d) # sum up the terms having a common denominator for d, n in nd.iteritems(): if len(n) == 1: nd[d] = n[0] else: nd[d] = Add(*n) # assemble single numerator and denominator denoms, numers = [list(i) for i in zip(*nd.iteritems())] n, d = Add(*[Mul(*(denoms[:i] + [numers[i]] + denoms[i + 1 :])) for i in xrange(len(numers))]), Mul(*denoms) return _keep_coeff(ncon, n), _keep_coeff(dcon, d)
def as_content_primitive(self): """Return the tuple (R, self/R) where R is the positive Rational extracted from self. **Examples** >>> from sympy import sqrt >>> (3 + 3*sqrt(2)).as_content_primitive() (3, 1 + sqrt(2)) Radical content is also factored out of the primitive: >>> (2*sqrt(2) + 4*sqrt(10)).as_content_primitive() (2, sqrt(2)*(1 + 2*sqrt(5))) See docstring of Expr.as_content_primitive for more examples. """ con, prim = Add(*[_keep_coeff(*a.as_content_primitive()) for a in self.args]).primitive() if prim.is_Add: # look for common radicals that can be removed args = prim.args rads = [] common_q = None for m in args: term_rads = defaultdict(list) for ai in Mul.make_args(m): if ai.is_Pow: b, e = ai.as_base_exp() if e.is_Rational and b.is_Integer and b > 0: term_rads[e.q].append(int(b)**e.p) if not term_rads: break if common_q is None: common_q = set(term_rads.keys()) else: common_q = common_q & set(term_rads.keys()) if not common_q: break rads.append(term_rads) else: # process rads # keep only those in common_q for r in rads: for q in r.keys(): if q not in common_q: r.pop(q) for q in r: r[q] = prod(r[q]) # find the gcd of bases for each q G = [] for q in common_q: g = reduce(igcd, [r[q] for r in rads], 0) if g != 1: G.append(Pow(g, Rational(1, q))) if G: G = Mul(*G) args = [ai/G for ai in args] prim = G*Add(*args) return con, prim
def as_content_primitive(self): """Return the tuple (R, self/R) where R is the positive Rational extracted from self. **Example** >>> from sympy import sqrt >>> (3 + 3*sqrt(2)).as_content_primitive() (3, 1 + sqrt(2)) See docstring of Expr.as_content_primitive for more examples. """ return Add(*[_keep_coeff(*a.as_content_primitive()) for a in self.args]).primitive()
def as_numer_denom(self): # clear rational denominator content, expr = self.primitive() ncon, dcon = content.as_numer_denom() # collect numerators and denominators of the terms nd = defaultdict(list) for f in expr.args: ni, di = f.as_numer_denom() nd[di].append(ni) # put infinity in the numerator if S.Zero in nd: n = nd.pop(S.Zero) assert len(n) == 1 n = n[0] nd[S.One].append(n / S.Zero) # check for quick exit if len(nd) == 1: d, n = nd.popitem() return Add(*[_keep_coeff(ncon, ni) for ni in n]), _keep_coeff(dcon, d) # sum up the terms having a common denominator for d, n in nd.iteritems(): if len(n) == 1: nd[d] = n[0] else: nd[d] = Add(*n) # assemble single numerator and denominator denoms, numers = [list(i) for i in zip(*nd.iteritems())] n, d = Add(*[ Mul(*(denoms[:i] + [numers[i]] + denoms[i + 1:])) for i in xrange(len(numers)) ]), Mul(*denoms) return _keep_coeff(ncon, n), _keep_coeff(dcon, d)
def primitive(self): """ Return ``(R, self/R)`` where ``R``` is the Rational GCD of ``self```. ``R`` is collected only from the leading coefficient of each term. Examples ======== >>> from sympy.abc import x, y >>> (2*x + 4*y).primitive() (2, x + 2*y) >>> (2*x/3 + 4*y/9).primitive() (2/9, 3*x + 2*y) >>> (2*x/3 + 4.2*y).primitive() (1/3, 2*x + 12.6*y) No subprocessing of term factors is performed: >>> ((2 + 2*x)*x + 2).primitive() (1, x*(2*x + 2) + 2) Recursive subprocessing can be done with the as_content_primitive() method: >>> ((2 + 2*x)*x + 2).as_content_primitive() (2, x*(x + 1) + 1) See also: primitive() function in polytools.py """ terms = [] inf = False for a in self.args: c, m = a.as_coeff_Mul() if not c.is_Rational: c = S.One m = a inf = inf or m is S.ComplexInfinity terms.append((c.p, c.q, m)) if not inf: ngcd = reduce(igcd, [t[0] for t in terms], 0) dlcm = reduce(ilcm, [t[1] for t in terms], 1) else: ngcd = reduce(igcd, [t[0] for t in terms if t[1]], 0) dlcm = reduce(ilcm, [t[1] for t in terms if t[1]], 1) if ngcd == dlcm == 1: return S.One, self if not inf: for i, (p, q, term) in enumerate(terms): terms[i] = _keep_coeff(Rational((p//ngcd)*(dlcm//q)), term) else: for i, (p, q, term) in enumerate(terms): if q: terms[i] = _keep_coeff(Rational((p//ngcd)*(dlcm//q)), term) else: terms[i] = _keep_coeff(Rational(p, q), term) # we don't need a complete re-flattening since no new terms will join # so we just use the same sort as is used in Add.flatten. When the # coefficient changes, the ordering of terms may change, e.g. # (3*x, 6*y) -> (2*y, x) # # We do need to make sure that term[0] stays in position 0, however. # if terms[0].is_Number or terms[0] is S.ComplexInfinity: c = terms.pop(0) else: c = None terms.sort(key=hash) if c: terms.insert(0, c) return Rational(ngcd, dlcm), self._new_rawargs(*terms)
def as_content_primitive(self, radical=False): """Return the tuple (R, self/R) where R is the positive Rational extracted from self. Examples ======== >>> from sympy import sqrt >>> sqrt(4 + 4*sqrt(2)).as_content_primitive() (2, sqrt(1 + sqrt(2))) >>> sqrt(3 + 3*sqrt(2)).as_content_primitive() (1, sqrt(3)*sqrt(1 + sqrt(2))) >>> from sympy import separate, powsimp, Mul >>> from sympy.abc import x, y >>> ((2*x + 2)**2).as_content_primitive() (4, (x + 1)**2) >>> (4**((1 + y)/2)).as_content_primitive() (2, 4**(y/2)) >>> (3**((1 + y)/2)).as_content_primitive() (1, 3**((y + 1)/2)) >>> (3**((5 + y)/2)).as_content_primitive() (9, 3**((y + 1)/2)) >>> eq = 3**(2 + 2*x) >>> powsimp(eq) == eq True >>> eq.as_content_primitive() (9, 3**(2*x)) >>> powsimp(Mul(*_)) 9*9**x >>> eq = (2 + 2*x)**y >>> s = separate(eq); s.is_Mul, s (False, (2*x + 2)**y) >>> eq.as_content_primitive() (1, (2*(x + 1))**y) >>> s = separate(_[1]); s.is_Mul, s (True, 2**y*(x + 1)**y) See docstring of Expr.as_content_primitive for more examples. """ b, e = self.as_base_exp() b = _keep_coeff(*b.as_content_primitive(radical=radical)) ce, pe = e.as_content_primitive(radical=radical) if b.is_Rational: #e #= ce*pe #= ce*(h + t) #= ce*h + ce*t #=> self #= b**(ce*h)*b**(ce*t) #= b**(cehp/cehq)*b**(ce*t) #= b**(iceh+r/cehq)*b**(ce*t) #= b**(iceh)*b**(r/cehq)*b**(ce*t) #= b**(iceh)*b**(ce*t + r/cehq) h, t = pe.as_coeff_Add() if h.is_Rational: ceh = ce * h c = Pow(b, ceh) r = S.Zero if not c.is_Rational: iceh, r = divmod(ceh.p, ceh.q) c = Pow(b, iceh) return c, Pow(b, _keep_coeff(ce, t + r / ce / ceh.q)) e = _keep_coeff(ce, pe) # b**e = (h*t)**e = h**e*t**e = c*m*t**e if e.is_Rational and b.is_Mul: h, t = b.as_content_primitive(radical=radical) # h is positive c, m = Pow(h, e).as_coeff_Mul() # so c is positive m, me = m.as_base_exp() if m is S.One or me == e: # probably always true # return the following, not return c, m*Pow(t, e) # which would change Pow into Mul; we let sympy # decide what to do by using the unevaluated Mul, e.g # should it stay as sqrt(2 + 2*sqrt(5)) or become # sqrt(2)*sqrt(1 + sqrt(5)) return c, Pow(_keep_coeff(m, t), e) return S.One, Pow(b, e)
def as_content_primitive(self, radical=False): """Return the tuple (R, self/R) where R is the positive Rational extracted from self. Examples ======== >>> from sympy import sqrt >>> sqrt(4 + 4*sqrt(2)).as_content_primitive() (2, sqrt(1 + sqrt(2))) >>> sqrt(3 + 3*sqrt(2)).as_content_primitive() (1, sqrt(3)*sqrt(1 + sqrt(2))) >>> from sympy import expand_power_base, powsimp, Mul >>> from sympy.abc import x, y >>> ((2*x + 2)**2).as_content_primitive() (4, (x + 1)**2) >>> (4**((1 + y)/2)).as_content_primitive() (2, 4**(y/2)) >>> (3**((1 + y)/2)).as_content_primitive() (1, 3**((y + 1)/2)) >>> (3**((5 + y)/2)).as_content_primitive() (9, 3**((y + 1)/2)) >>> eq = 3**(2 + 2*x) >>> powsimp(eq) == eq True >>> eq.as_content_primitive() (9, 3**(2*x)) >>> powsimp(Mul(*_)) 3**(2*x + 2) >>> eq = (2 + 2*x)**y >>> s = expand_power_base(eq); s.is_Mul, s (False, (2*x + 2)**y) >>> eq.as_content_primitive() (1, (2*(x + 1))**y) >>> s = expand_power_base(_[1]); s.is_Mul, s (True, 2**y*(x + 1)**y) See docstring of Expr.as_content_primitive for more examples. """ b, e = self.as_base_exp() b = _keep_coeff(*b.as_content_primitive(radical=radical)) ce, pe = e.as_content_primitive(radical=radical) if b.is_Rational: #e #= ce*pe #= ce*(h + t) #= ce*h + ce*t #=> self #= b**(ce*h)*b**(ce*t) #= b**(cehp/cehq)*b**(ce*t) #= b**(iceh+r/cehq)*b**(ce*t) #= b**(iceh)*b**(r/cehq)*b**(ce*t) #= b**(iceh)*b**(ce*t + r/cehq) h, t = pe.as_coeff_Add() if h.is_Rational: ceh = ce*h c = Pow(b, ceh) r = S.Zero if not c.is_Rational: iceh, r = divmod(ceh.p, ceh.q) c = Pow(b, iceh) return c, Pow(b, _keep_coeff(ce, t + r/ce/ceh.q)) e = _keep_coeff(ce, pe) # b**e = (h*t)**e = h**e*t**e = c*m*t**e if e.is_Rational and b.is_Mul: h, t = b.as_content_primitive(radical=radical) # h is positive c, m = Pow(h, e).as_coeff_Mul() # so c is positive m, me = m.as_base_exp() if m is S.One or me == e: # probably always true # return the following, not return c, m*Pow(t, e) # which would change Pow into Mul; we let sympy # decide what to do by using the unevaluated Mul, e.g # should it stay as sqrt(2 + 2*sqrt(5)) or become # sqrt(2)*sqrt(1 + sqrt(5)) return c, Pow(_keep_coeff(m, t), e) return S.One, Pow(b, e)
def as_content_primitive(self, radical=False): """Return the tuple (R, self/R) where R is the positive Rational extracted from self. If radical is True (default is False) then common radicals will be removed and included as a factor of the primitive expression. **Examples** >>> from sympy import sqrt >>> (3 + 3*sqrt(2)).as_content_primitive() (3, 1 + sqrt(2)) Radical content can also be factored out of the primitive: >>> (2*sqrt(2) + 4*sqrt(10)).as_content_primitive(radical=True) (2, sqrt(2)*(1 + 2*sqrt(5))) See docstring of Expr.as_content_primitive for more examples. """ con, prim = Add(*[_keep_coeff(*a.as_content_primitive(radical=radical)) for a in self.args]).primitive() if radical and prim.is_Add: # look for common radicals that can be removed args = prim.args rads = [] common_q = None for m in args: term_rads = defaultdict(list) for ai in Mul.make_args(m): if ai.is_Pow: b, e = ai.as_base_exp() if e.is_Rational and b.is_Integer and b > 0: term_rads[e.q].append(int(b)**e.p) if not term_rads: break if common_q is None: common_q = set(term_rads.keys()) else: common_q = common_q & set(term_rads.keys()) if not common_q: break rads.append(term_rads) else: # process rads # keep only those in common_q for r in rads: for q in r.keys(): if q not in common_q: r.pop(q) for q in r: r[q] = prod(r[q]) # find the gcd of bases for each q G = [] for q in common_q: g = reduce(igcd, [r[q] for r in rads], 0) if g != 1: G.append(Pow(g, Rational(1, q))) if G: G = Mul(*G) args = [ai/G for ai in args] prim = G*Add(*args) return con, prim
def primitive(self): """ Return ``(R, self/R)`` where ``R``` is the Rational GCD of ``self```. ``R`` is collected only from the leading coefficient of each term. **Examples** >>> from sympy.abc import x, y >>> (2*x + 4*y).primitive() (2, x + 2*y) >>> (2*x/3 + 4*y/9).primitive() (2/9, 3*x + 2*y) >>> (2*x/3 + 4.2*y).primitive() (1/3, 2*x + 12.6*y) No subprocessing of term factors is performed: >>> ((2 + 2*x)*x + 2).primitive() (1, x*(2*x + 2) + 2) Recursive subprocessing can be done with the as_content_primitive() method: >>> ((2 + 2*x)*x + 2).as_content_primitive() (2, x*(x + 1) + 1) See also: primitive() function in polytools.py """ terms = [] inf = False for a in self.args: c, m = a.as_coeff_Mul() if not c.is_Rational: c = S.One m = a inf = inf or m is S.ComplexInfinity terms.append((c.p, c.q, m)) if not inf: ngcd = reduce(igcd, [t[0] for t in terms], 0) dlcm = reduce(ilcm, [t[1] for t in terms], 1) else: ngcd = reduce(igcd, [t[0] for t in terms if t[1]], 0) dlcm = reduce(ilcm, [t[1] for t in terms if t[1]], 1) if ngcd == dlcm == 1: return S.One, self if not inf: for i, (p, q, term) in enumerate(terms): terms[i] = _keep_coeff(Rational((p//ngcd)*(dlcm//q)), term) else: for i, (p, q, term) in enumerate(terms): if q: terms[i] = _keep_coeff(Rational((p//ngcd)*(dlcm//q)), term) else: terms[i] = _keep_coeff(Rational(p, q), term) # we don't need a complete re-flattening since no new terms will join # so we just use the same sort as is used in Add.flatten. When the # coefficient changes, the ordering of terms may change, e.g. # (3*x, 6*y) -> (2*y, x) # # We do need to make sure that term[0] stays in position 0, however. # if terms[0].is_Number or terms[0] is S.ComplexInfinity: c = terms.pop(0) else: c = None terms.sort(key=hash) if c: terms.insert(0, c) return Rational(ngcd, dlcm), self._new_rawargs(*terms)