Esempio n. 1
0
    def _eval_expand_trig(self, **hints):
        from sympy import expand_mul
        arg = self.args[0]
        x = None
        if arg.is_Add:  # TODO, implement more if deep stuff here
            # TODO: Do this more efficiently for more than two terms
            x, y = arg.as_two_terms()
            sx = sin(x, evaluate=False)._eval_expand_trig()
            sy = sin(y, evaluate=False)._eval_expand_trig()
            cx = cos(x, evaluate=False)._eval_expand_trig()
            cy = cos(y, evaluate=False)._eval_expand_trig()
            return sx * cy + sy * cx
        else:
            n, x = arg.as_coeff_Mul(rational=True)
            if n.is_Integer:  # n will be positive because of .eval
                # canonicalization

                # See http://mathworld.wolfram.com/Multiple-AngleFormulas.html
                if n.is_odd:
                    return (-1)**((n - 1) / 2) * C.chebyshevt(n, sin(x))
                else:
                    return expand_mul((-1)**(n / 2 - 1) * cos(x) *
                                      C.chebyshevu(n - 1, sin(x)),
                                      deep=False)
            pi_coeff = _pi_coeff(arg)
            if pi_coeff is not None:
                if pi_coeff.is_Rational:
                    return self.rewrite(sqrt)
        return sin(arg)
Esempio n. 2
0
    def _eval_expand_trig(self, **hints):
        from sympy import expand_mul
        arg = self.args[0]
        x = None
        if arg.is_Add:  # TODO, implement more if deep stuff here
            # TODO: Do this more efficiently for more than two terms
            x, y = arg.as_two_terms()
            sx = sin(x, evaluate=False)._eval_expand_trig()
            sy = sin(y, evaluate=False)._eval_expand_trig()
            cx = cos(x, evaluate=False)._eval_expand_trig()
            cy = cos(y, evaluate=False)._eval_expand_trig()
            return sx*cy + sy*cx
        else:
            n, x = arg.as_coeff_Mul(rational=True)
            if n.is_Integer:  # n will be positive because of .eval
                # canonicalization

                # See http://mathworld.wolfram.com/Multiple-AngleFormulas.html
                if n.is_odd:
                    return (-1)**((n - 1)/2)*C.chebyshevt(n, sin(x))
                else:
                    return expand_mul((-1)**(n/2 - 1)*cos(x)*C.chebyshevu(n -
                        1, sin(x)), deep=False)
            pi_coeff = _pi_coeff(arg)
            if pi_coeff is not None:
                if pi_coeff.is_Rational:
                    return self.rewrite(sqrt)
        return sin(arg)
Esempio n. 3
0
 def _eval_expand_trig(self, *args):
     arg = self.args[0].expand()
     x = None
     if arg.is_Add:
         x = arg.args[0]
         y = C.Add(*arg.args[1:])
         return (cos(x)*cos(y) - sin(y)*sin(x)).expand(trig=True)
     else:
         coeff, terms = arg.as_coeff_terms()
         if not (coeff is S.One) and coeff.is_Integer and terms:
             x = C.Mul(*terms)
             return C.chebyshevt(coeff, cos(x))
     return cos(arg)
Esempio n. 4
0
 def _eval_expand_trig(self, *args):
     arg = self.args[0].expand()
     x = None
     if arg.is_Add:
         x = arg.args[0]
         y = C.Add(*arg.args[1:])
         return (cos(x) * cos(y) - sin(y) * sin(x)).expand(trig=True)
     else:
         coeff, terms = arg.as_coeff_terms()
         if not (coeff is S.One) and coeff.is_Integer and terms:
             x = C.Mul(*terms)
             return C.chebyshevt(coeff, cos(x))
     return cos(arg)
Esempio n. 5
0
 def _eval_expand_trig(self, deep=True, **hints):
     if deep:
         arg = self.args[0].expand()
     else:
         arg = self.args[0]
     x = None
     if arg.is_Add: # TODO, implement more if deep stuff here
         x, y = arg.as_two_terms()
         return (cos(x)*cos(y) - sin(y)*sin(x)).expand(trig=True)
     else:
         coeff, terms = arg.as_coeff_Mul(rational=True)
         if coeff is not S.One and coeff.is_Integer and terms is not S.One:
             return C.chebyshevt(coeff, cos(terms))
     return cos(arg)
Esempio n. 6
0
 def _eval_expand_trig(self, deep=True, **hints):
     if deep:
         arg = self.args[0].expand()
     else:
         arg = self.args[0]
     x = None
     if arg.is_Add: # TODO, implement more if deep stuff here
         x, y = arg.as_two_terms()
         return (cos(x)*cos(y) - sin(y)*sin(x)).expand(trig=True)
     else:
         coeff, terms = arg.as_coeff_Mul(rational=True)
         if coeff is not S.One and coeff.is_Integer and terms is not S.One:
             return C.chebyshevt(coeff, cos(terms))
     return cos(arg)
Esempio n. 7
0
 def _eval_expand_trig(self, deep=True, **hints):
     if deep:
         arg = self.args[0].expand()
     else:
         arg = self.args[0]
     x = None
     if arg.is_Add:  # TODO, implement more if deep stuff here
         x, y = arg.as_two_terms()
         return (cos(x) * cos(y) - sin(y) * sin(x)).expand(trig=True)
     else:
         coeff, terms = arg.as_coeff_mul()
         if not (coeff is S.One) and coeff.is_Integer and terms:
             x = arg._new_rawargs(*terms)
             return C.chebyshevt(coeff, cos(x))
     return cos(arg)
Esempio n. 8
0
 def _eval_expand_trig(self, deep=True, **hints):
     if deep:
         arg = self.args[0].expand()
     else:
         arg = self.args[0]
     x = None
     if arg.is_Add: # TODO, implement more if deep stuff here
         x, y = arg.as_two_terms()
         return (cos(x)*cos(y) - sin(y)*sin(x)).expand(trig=True)
     else:
         coeff, terms = arg.as_coeff_mul()
         if not (coeff is S.One) and coeff.is_Integer and terms:
             x = arg._new_rawargs(*terms)
             return C.chebyshevt(coeff, cos(x))
     return cos(arg)
Esempio n. 9
0
 def _eval_expand_trig(self, **hints):
     arg = self.args[0]
     x = None
     if arg.is_Add: # TODO: Do this more efficiently for more than two terms
         x, y = arg.as_two_terms()
         sx = sin(x)._eval_expand_trig()
         sy = sin(y)._eval_expand_trig()
         cx = cos(x)._eval_expand_trig()
         cy = cos(y)._eval_expand_trig()
         return cx*cy - sx*sy
     else:
         coeff, terms = arg.as_coeff_Mul(rational=True)
         if coeff.is_Integer:
             return C.chebyshevt(coeff, cos(terms))
     return cos(arg)
Esempio n. 10
0
 def _eval_expand_trig(self, **hints):
     arg = self.args[0]
     x = None
     if arg.is_Add:  # TODO: Do this more efficiently for more than two terms
         x, y = arg.as_two_terms()
         sx = sin(x)._eval_expand_trig()
         sy = sin(y)._eval_expand_trig()
         cx = cos(x)._eval_expand_trig()
         cy = cos(y)._eval_expand_trig()
         return cx * cy - sx * sy
     else:
         coeff, terms = arg.as_coeff_Mul(rational=True)
         if coeff.is_Integer:
             return C.chebyshevt(coeff, cos(terms))
     return cos(arg)
Esempio n. 11
0
 def _eval_expand_trig(self, **hints):
     arg = self.args[0]
     x = None
     if arg.is_Add:  # TODO: Do this more efficiently for more than two terms
         x, y = arg.as_two_terms()
         sx = sin(x, evaluate=False)._eval_expand_trig()
         sy = sin(y, evaluate=False)._eval_expand_trig()
         cx = cos(x, evaluate=False)._eval_expand_trig()
         cy = cos(y, evaluate=False)._eval_expand_trig()
         return cx * cy - sx * sy
     else:
         coeff, terms = arg.as_coeff_Mul(rational=True)
         if coeff.is_Integer:
             return C.chebyshevt(coeff, cos(terms))
         pi_coeff = _pi_coeff(arg)
         if pi_coeff is not None:
             if pi_coeff.is_Rational:
                 return self.rewrite(sqrt)
     return cos(arg)
Esempio n. 12
0
 def _eval_expand_trig(self, **hints):
     arg = self.args[0]
     x = None
     if arg.is_Add:  # TODO: Do this more efficiently for more than two terms
         x, y = arg.as_two_terms()
         sx = sin(x, evaluate=False)._eval_expand_trig()
         sy = sin(y, evaluate=False)._eval_expand_trig()
         cx = cos(x, evaluate=False)._eval_expand_trig()
         cy = cos(y, evaluate=False)._eval_expand_trig()
         return cx*cy - sx*sy
     else:
         coeff, terms = arg.as_coeff_Mul(rational=True)
         if coeff.is_Integer:
             return C.chebyshevt(coeff, cos(terms))
         pi_coeff = _pi_coeff(arg)
         if pi_coeff is not None:
             if pi_coeff.is_Rational:
                 return self.rewrite(sqrt)
     return cos(arg)
Esempio n. 13
0
    def _eval_rewrite_as_sqrt(self, arg):
        _EXPAND_INTS = False

        def migcdex(x):
            # recursive calcuation of gcd and linear combination
            # for a sequence of integers.
            # Given  (x1, x2, x3)
            # Returns (y1, y1, y3, g)
            # such that g is the gcd and x1*y1+x2*y2+x3*y3 - g = 0
            # Note, that this is only one such linear combination.
            if len(x) == 1:
                return (1, x[0])
            if len(x) == 2:
                return igcdex(x[0], x[-1])
            g = migcdex(x[1:])
            u, v, h = igcdex(x[0], g[-1])
            return tuple([u] + [v * i for i in g[0:-1]] + [h])

        def ipartfrac(r, factors=None):
            if isinstance(r, int):
                return r
            assert isinstance(r, C.Rational)
            n = r.q
            if 2 > r.q * r.q:
                return r.q

            if None == factors:
                a = [n // x**y for x, y in factorint(r.q).iteritems()]
            else:
                a = [n // x for x in factors]
            if len(a) == 1:
                return [r]
            h = migcdex(a)
            ans = [r.p * C.Rational(i * j, r.q) for i, j in zip(h[:-1], a)]
            assert r == sum(ans)
            return ans

        pi_coeff = _pi_coeff(arg)
        if pi_coeff is None:
            return None

        assert not pi_coeff.is_integer, "should have been simplified already"

        if not pi_coeff.is_Rational:
            return None

        cst_table_some = {
            3:
            S.Half,
            5: (sqrt(5) + 1) / 4,
            17:
            sqrt((15 + sqrt(17)) / 32 + sqrt(2) * (sqrt(17 - sqrt(17)) + sqrt(
                sqrt(2) *
                (-8 * sqrt(17 + sqrt(17)) -
                 (1 - sqrt(17)) * sqrt(17 - sqrt(17))) + 6 * sqrt(17) + 34)) /
                 32)
            # 65537 and 257 are the only other known Fermat primes
            # Please add if you would like them
        }

        def fermatCoords(n):
            assert isinstance(n, int)
            assert n > 0
            if n == 1 or 0 == n % 2:
                return False
            primes = dict([(p, 0) for p in cst_table_some])
            assert 1 not in primes
            for p_i in primes:
                while 0 == n % p_i:
                    n = n / p_i
                    primes[p_i] += 1
            if 1 != n:
                return False
            if max(primes.values()) > 1:
                return False
            return tuple([p for p in primes if primes[p] == 1])

        if pi_coeff.q in cst_table_some:
            return C.chebyshevt(pi_coeff.p,
                                cst_table_some[pi_coeff.q]).expand()

        if 0 == pi_coeff.q % 2:  # recursively remove powers of 2
            narg = (pi_coeff * 2) * S.Pi
            nval = cos(narg)
            if None == nval:
                return None
            nval = nval.rewrite(sqrt)
            if not _EXPAND_INTS:
                if (isinstance(nval, cos) or isinstance(-nval, cos)):
                    return None
            x = (2 * pi_coeff + 1) / 2
            sign_cos = (-1)**((-1 if x < 0 else 1) * int(abs(x)))
            return sign_cos * sqrt((1 + nval) / 2)

        FC = fermatCoords(pi_coeff.q)
        if FC:
            decomp = ipartfrac(pi_coeff, FC)
            X = [(x[1], x[0] * S.Pi)
                 for x in zip(decomp, numbered_symbols('z'))]
            pcls = cos(sum([x[0] for x in X]))._eval_expand_trig().subs(X)
            return pcls.rewrite(sqrt)
        if _EXPAND_INTS:
            decomp = ipartfrac(pi_coeff)
            X = [(x[1], x[0] * S.Pi)
                 for x in zip(decomp, numbered_symbols('z'))]
            pcls = cos(sum([x[0] for x in X]))._eval_expand_trig().subs(X)
            return pcls
        return None
Esempio n. 14
0
    def eval(cls, arg):
        if arg.is_Number:
            if arg is S.NaN:
                return S.NaN
            elif arg is S.Zero:
                return S.One
            elif arg is S.Infinity or arg is S.NegativeInfinity:
                # In this cases, it is unclear if we should
                # return S.NaN or leave un-evaluated.  One
                # useful test case is how "limit(sin(x)/x,x,oo)"
                # is handled.
                # See test_sin_cos_with_infinity() an
                # Test for issue 209
                # http://code.google.com/p/sympy/issues/detail?id=2097
                # For now, we return un-evaluated.
                return

        if arg.could_extract_minus_sign():
            return cls(-arg)

        i_coeff = arg.as_coefficient(S.ImaginaryUnit)
        if i_coeff is not None:
            return C.cosh(i_coeff)

        pi_coeff = _pi_coeff(arg)
        if pi_coeff is not None:
            if pi_coeff.is_integer:
                return (S.NegativeOne)**pi_coeff
            if not pi_coeff.is_Rational:
                narg = pi_coeff * S.Pi
                if narg != arg:
                    return cls(narg)
                return None

            # cosine formula #####################
            # http://code.google.com/p/sympy/issues/detail?id=2949
            # explicit calculations are preformed for
            # cos(k pi / 8), cos(k pi /10), and cos(k pi / 12)
            # Some other exact values like cos(k pi/15) can be
            # calculated using a partial-fraction decomposition
            # by calling cos( X ).rewrite(sqrt)
            cst_table_some = {
                3: S.Half,
                5: (sqrt(5) + 1) / 4,
            }
            if pi_coeff.is_Rational:
                q = pi_coeff.q
                p = pi_coeff.p % (2 * q)
                if p > q:
                    narg = (pi_coeff - 1) * S.Pi
                    return -cls(narg)
                if 2 * p > q:
                    narg = (1 - pi_coeff) * S.Pi
                    return -cls(narg)

                # If nested sqrt's are worse than un-evaluation
                # you can require q in (1, 2, 3, 4, 6)
                # q <= 12 returns expressions with 2 or fewer nestings.
                if q > 12:
                    return None

                if q in cst_table_some:
                    cts = cst_table_some[pi_coeff.q]
                    return C.chebyshevt(pi_coeff.p, cts).expand()

                if 0 == q % 2:
                    narg = (pi_coeff * 2) * S.Pi
                    nval = cls(narg)
                    if None == nval:
                        return None
                    x = (2 * pi_coeff + 1) / 2
                    sign_cos = (-1)**((-1 if x < 0 else 1) * int(abs(x)))
                    return sign_cos * sqrt((1 + nval) / 2)
            return None

        if arg.is_Add:
            x, m = _peeloff_pi(arg)
            if m:
                return cos(m) * cos(x) - sin(m) * sin(x)

        if arg.func is acos:
            return arg.args[0]

        if arg.func is atan:
            x = arg.args[0]
            return 1 / sqrt(1 + x**2)

        if arg.func is atan2:
            y, x = arg.args
            return x / sqrt(x**2 + y**2)

        if arg.func is asin:
            x = arg.args[0]
            return sqrt(1 - x**2)

        if arg.func is acot:
            x = arg.args[0]
            return 1 / sqrt(1 + 1 / x**2)
Esempio n. 15
0
    def _eval_rewrite_as_sqrt(self, arg):
        _EXPAND_INTS = False

        def migcdex(x):
            # recursive calcuation of gcd and linear combination
            # for a sequence of integers.
            # Given  (x1, x2, x3)
            # Returns (y1, y1, y3, g)
            # such that g is the gcd and x1*y1+x2*y2+x3*y3 - g = 0
            # Note, that this is only one such linear combination.
            if len(x) == 1:
                return (1, x[0])
            if len(x) == 2:
                return igcdex(x[0], x[-1])
            g = migcdex(x[1:])
            u, v, h = igcdex(x[0], g[-1])
            return tuple([u] + [v*i for i in g[0:-1] ] + [h])

        def ipartfrac(r, factors=None):
            if isinstance(r, int):
                return r
            assert isinstance(r, C.Rational)
            n = r.q
            if 2 > r.q*r.q:
                return r.q

            if None == factors:
                a = [n/x**y for x, y in factorint(r.q).iteritems()]
            else:
                a = [n/x for x in factors]
            if len(a) == 1:
                return [ r ]
            h = migcdex(a)
            ans = [ r.p*C.Rational(i*j, r.q) for i, j in zip(h[:-1], a) ]
            assert r == sum(ans)
            return ans
        pi_coeff = _pi_coeff(arg)
        if pi_coeff is None:
            return None

        assert not pi_coeff.is_integer, "should have been simplified already"

        if not pi_coeff.is_Rational:
            return None

        cst_table_some = {
            3: S.Half,
            5: (sqrt(5) + 1)/4,
            17: sqrt((15 + sqrt(17))/32 + sqrt(2)*(sqrt(17 - sqrt(17)) +
                sqrt(sqrt(2)*(-8*sqrt(17 + sqrt(17)) - (1 - sqrt(17))
                *sqrt(17 - sqrt(17))) + 6*sqrt(17) + 34))/32)
            # 65537 and 257 are the only other known Fermat primes
            # Please add if you would like them
        }

        def fermatCoords(n):
            assert isinstance(n, int)
            assert n > 0
            if n == 1 or 0 == n % 2:
                return False
            primes = dict( [(p, 0) for p in cst_table_some ] )
            assert 1 not in primes
            for p_i in primes:
                while 0 == n % p_i:
                    n = n/p_i
                    primes[p_i] += 1
            if 1 != n:
                return False
            if max(primes.values()) > 1:
                return False
            return tuple([ p for p in primes if primes[p] == 1])

        if pi_coeff.q in cst_table_some:
            return C.chebyshevt(pi_coeff.p, cst_table_some[pi_coeff.q]).expand()

        if 0 == pi_coeff.q % 2:  # recursively remove powers of 2
            narg = (pi_coeff*2)*S.Pi
            nval = cos(narg)
            if None == nval:
                return None
            nval = nval.rewrite(sqrt)
            if not _EXPAND_INTS:
                if (isinstance(nval, cos) or isinstance(-nval, cos)):
                    return None
            x = (2*pi_coeff + 1)/2
            sign_cos = (-1)**((-1 if x < 0 else 1)*int(abs(x)))
            return sign_cos*sqrt( (1 + nval)/2 )

        FC = fermatCoords(pi_coeff.q)
        if FC:
            decomp = ipartfrac(pi_coeff, FC)
            X = [(x[1], x[0]*S.Pi) for x in zip(decomp, numbered_symbols('z'))]
            pcls = cos(sum([x[0] for x in X]))._eval_expand_trig().subs(X)
            return pcls.rewrite(sqrt)
        if _EXPAND_INTS:
            decomp = ipartfrac(pi_coeff)
            X = [(x[1], x[0]*S.Pi) for x in zip(decomp, numbered_symbols('z'))]
            pcls = cos(sum([x[0] for x in X]))._eval_expand_trig().subs(X)
            return pcls
        return None
Esempio n. 16
0
    def eval(cls, arg):
        if arg.is_Number:
            if arg is S.NaN:
                return S.NaN
            elif arg is S.Zero:
                return S.One
            elif arg is S.Infinity or arg is S.NegativeInfinity:
                # In this cases, it is unclear if we should
                # return S.NaN or leave un-evaluated.  One
                # useful test case is how "limit(sin(x)/x,x,oo)"
                # is handled.
                # See test_sin_cos_with_infinity() an
                # Test for issue 209
                # http://code.google.com/p/sympy/issues/detail?id=2097
                # For now, we return un-evaluated.
                return

        if arg.could_extract_minus_sign():
            return cls(-arg)

        i_coeff = arg.as_coefficient(S.ImaginaryUnit)
        if i_coeff is not None:
            return C.cosh(i_coeff)

        pi_coeff = _pi_coeff(arg)
        if pi_coeff is not None:
            if pi_coeff.is_integer:
                return (S.NegativeOne)**pi_coeff
            if not pi_coeff.is_Rational:
                narg = pi_coeff*S.Pi
                if narg != arg:
                    return cls(narg)
                return None

            # cosine formula #####################
            # http://code.google.com/p/sympy/issues/detail?id=2949
            # explicit calculations are preformed for
            # cos(k pi / 8), cos(k pi /10), and cos(k pi / 12)
            # Some other exact values like cos(k pi/15) can be
            # calculated using a partial-fraction decomposition
            # by calling cos( X ).rewrite(sqrt)
            cst_table_some = {
                3: S.Half,
                5: (sqrt(5) + 1)/4,
            }
            if pi_coeff.is_Rational:
                q = pi_coeff.q
                p = pi_coeff.p % (2*q)
                if p > q:
                    narg = (pi_coeff - 1)*S.Pi
                    return -cls(narg)
                if 2*p > q:
                    narg = (1 - pi_coeff)*S.Pi
                    return -cls(narg)

                # If nested sqrt's are worse than un-evaluation
                # you can require q in (1, 2, 3, 4, 6)
                # q <= 12 returns expressions with 2 or fewer nestings.
                if q > 12:
                    return None

                if q in cst_table_some:
                    cts = cst_table_some[pi_coeff.q]
                    return C.chebyshevt(pi_coeff.p, cts).expand()

                if 0 == q % 2:
                    narg = (pi_coeff*2)*S.Pi
                    nval = cls(narg)
                    if None == nval:
                        return None
                    x = (2*pi_coeff + 1)/2
                    sign_cos = (-1)**((-1 if x < 0 else 1)*int(abs(x)))
                    return sign_cos*sqrt( (1 + nval)/2 )
            return None

        if arg.is_Add:
            x, m = _peeloff_pi(arg)
            if m:
                return cos(m)*cos(x) - sin(m)*sin(x)

        if arg.func is acos:
            return arg.args[0]

        if arg.func is atan:
            x = arg.args[0]
            return 1 / sqrt(1 + x**2)

        if arg.func is atan2:
            y, x = arg.args
            return x / sqrt(x**2 + y**2)

        if arg.func is asin:
            x = arg.args[0]
            return sqrt(1 - x ** 2)

        if arg.func is acot:
            x = arg.args[0]
            return 1 / sqrt(1 + 1 / x**2)