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
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: 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 not pi_coeff.is_Rational: if pi_coeff.is_integer: even = pi_coeff.is_even if even: return S.One elif even is False: return S.NegativeOne narg = pi_coeff * S.Pi if narg != arg: return cls(narg) return None cst_table_some = { 1: S.One, 2: S.Zero, 3: S.Half, 4: S.Half * sqrt(2), 6: S.Half * sqrt(3), } cst_table_more = { (1, 5): (sqrt(5) + 1) / 4, (2, 5): (sqrt(5) - 1) / 4 } p = pi_coeff.p q = pi_coeff.q Q, P = 2 * p // q, p % q try: result = cst_table_some[q] except KeyError: if abs(P) > q // 2: P = q - P try: result = cst_table_more[(P, q)] except KeyError: if P != p: result = cls(C.Rational(P, q) * S.Pi) else: return None if Q % 4 in (1, 2): return -result else: return result 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 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)
def eval(cls, arg): if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Zero: return S.Zero elif arg is S.Infinity: return if arg.could_extract_minus_sign(): return -cls(-arg) i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return S.ImaginaryUnit * C.sinh(i_coeff) pi_coeff = _pi_coeff(arg) if pi_coeff is not None: if pi_coeff.is_integer: return S.Zero if not pi_coeff.is_Rational: narg = pi_coeff * S.Pi if narg != arg: return cls(narg) return None cst_table_some = { 2: S.One, 3: S.Half * sqrt(3), 4: S.Half * sqrt(2), 6: S.Half, } cst_table_more = { (1, 5): sqrt((5 - sqrt(5)) / 8), (2, 5): sqrt((5 + sqrt(5)) / 8) } p = pi_coeff.p q = pi_coeff.q Q, P = p // q, p % q try: result = cst_table_some[q] except KeyError: if abs(P) > q // 2: P = q - P try: result = cst_table_more[(P, q)] except KeyError: if P != p: result = cls(C.Rational(P, q) * S.Pi) else: return None if Q % 2 == 1: return -result else: return result if arg.is_Add: x, m = _peeloff_pi(arg) if m: return sin(m) * cos(x) + cos(m) * sin(x) if arg.func is asin: return arg.args[0] if arg.func is atan: x = arg.args[0] return x / sqrt(1 + x**2) if arg.func is acos: 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) * x)
def eval(cls, arg): if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Zero: return S.Zero elif arg.is_negative: return -cls(-arg) else: i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return S.ImaginaryUnit * C.sinh(i_coeff) else: pi_coeff = arg.as_coefficient(S.Pi) if pi_coeff is not None: if pi_coeff.is_integer: return S.Zero elif pi_coeff.is_Rational: cst_table_some = { 2: S.One, 3: S.Half * sqrt(3), 4: S.Half * sqrt(2), 6: S.Half, } cst_table_more = { (1, 5): sqrt((5 - sqrt(5)) / 8), (2, 5): sqrt((5 + sqrt(5)) / 8) } p = pi_coeff.p q = pi_coeff.q Q, P = p // q, p % q try: result = cst_table_some[q] except KeyError: if abs(P) > q // 2: P = q - P try: result = cst_table_more[(P, q)] except KeyError: if P != p: result = cls(C.Rational(P, q) * S.Pi) else: return None if Q % 2 == 1: return -result else: return result if arg.is_Mul and arg.args[0].is_negative: return -cls(-arg) if arg.is_Add: x, m = arg.as_independent(S.Pi) if m in [S.Pi / 2, S.Pi]: return sin(m) * cos(x) + cos(m) * sin(x) # normalize sin(-x-y) to -sin(x+y) if arg.args[0].is_Mul: if arg.args[0].args[0].is_negative: # e.g. arg = -x - y if (-arg).args[0].is_Mul: if (-arg).args[0].args[0].is_negative: # This is to prevent infinite recursion in # the case sin(-x+y), for which # -arg = -y + x. See also #838 for the # root of the problem here. return # convert sin(-x-y) to -sin(x+y) return -cls(-arg) if arg.args[0].is_negative: if (-arg).args[0].is_negative: # This is to avoid infinite recursion in the case # sin(-x-1) return return -cls(-arg) if isinstance(arg, asin): return arg.args[0] if isinstance(arg, atan): x = arg.args[0] return x / sqrt(1 + x**2) if isinstance(arg, acos): x = arg.args[0] return sqrt(1 - x**2) if isinstance(arg, acot): x = arg.args[0] return 1 / (sqrt(1 + 1 / x**2) * x)
def _pi_coeff(arg, cycles=1): """ When arg is a Number times pi (e.g. 3*pi/2) then return the Number normalized to be in the range [0, 2], else None. When an even multiple of pi is encountered, if it is multiplying something with known parity then the multiple is returned as 0 otherwise as 2. Examples ======== >>> from sympy.functions.elementary.trigonometric import _pi_coeff as coeff >>> from sympy import pi >>> from sympy.abc import x, y >>> coeff(3*x*pi) 3*x >>> coeff(11*pi/7) 11/7 >>> coeff(-11*pi/7) 3/7 >>> coeff(4*pi) 0 >>> coeff(5*pi) 1 >>> coeff(5.0*pi) 1 >>> coeff(5.5*pi) 3/2 >>> coeff(2 + pi) """ arg = sympify(arg) if arg is S.Pi: return S.One elif not arg: return S.Zero elif arg.is_Mul: cx = arg.coeff(S.Pi) if cx: c, x = cx.as_coeff_Mul() # pi is not included as coeff if c.is_Float: # recast exact binary fractions to Rationals f = abs(c) % 1 if f != 0: p = -int(round(log(f, 2).evalf())) m = 2**p cm = c * m i = int(cm) if i == cm: c = C.Rational(i, m) cx = c * x else: c = C.Rational(int(c)) cx = c * x if x.is_integer: c2 = c % 2 if c2 == 1: return x elif not c2: if x.is_even is not None: # known parity return S.Zero return 2 * x else: return c2 * x return cx
def eval(cls, arg): if arg.is_Number: if arg is S.NaN: return S.NaN elif arg is S.Zero: return S.Zero elif arg is S.Infinity or arg is S.NegativeInfinity: return if arg.could_extract_minus_sign(): return -cls(-arg) i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return S.ImaginaryUnit * C.sinh(i_coeff) pi_coeff = _pi_coeff(arg) if pi_coeff is not None: if pi_coeff.is_integer: return S.Zero if not pi_coeff.is_Rational: narg = pi_coeff * S.Pi if narg != arg: return cls(narg) return None # http://code.google.com/p/sympy/issues/detail?id=2949 # transform a sine to a cosine, to avoid redundant code if pi_coeff.is_Rational: x = pi_coeff % 2 if x > 1: return -cls((x % 1) * S.Pi) if 2 * x > 1: return cls((1 - x) * S.Pi) narg = ((pi_coeff + C.Rational(3, 2)) % 2) * S.Pi result = cos(narg) if not isinstance(result, cos): return result if pi_coeff * S.Pi != arg: return cls(pi_coeff * S.Pi) return None if arg.is_Add: x, m = _peeloff_pi(arg) if m: return sin(m) * cos(x) + cos(m) * sin(x) if arg.func is asin: return arg.args[0] if arg.func is atan: x = arg.args[0] return x / sqrt(1 + x**2) if arg.func is atan2: y, x = arg.args return y / sqrt(x**2 + y**2) if arg.func is acos: 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) * x)
def eval(cls, arg): if arg.is_Number: if arg is S.NaN: return S.NaN if arg is S.Zero: return S.ComplexInfinity if arg.could_extract_minus_sign(): return -cls(-arg) i_coeff = arg.as_coefficient(S.ImaginaryUnit) if i_coeff is not None: return -S.ImaginaryUnit * C.coth(i_coeff) pi_coeff = _pi_coeff(arg, 2) if pi_coeff is not None: if pi_coeff.is_integer: return S.ComplexInfinity if not pi_coeff.is_Rational: narg = pi_coeff*S.Pi if narg != arg: return cls(narg) return None cst_table = { 2 : S.Zero, 3 : 1 / sqrt(3), 4 : S.One, 6 : sqrt(3) } try: result = cst_table[pi_coeff.q] if (2*pi_coeff.p // pi_coeff.q) % 4 in (1, 3): return -result else: return result except KeyError: if pi_coeff.p > pi_coeff.q: p, q = pi_coeff.p % pi_coeff.q, pi_coeff.q if 2 * p > q: return -cls(C.Rational(q - p, q)*S.Pi) return cls(C.Rational(p, q)*S.Pi) else: newarg = pi_coeff*S.Pi if newarg != arg: return cls(newarg) return None if arg.is_Add: x, m = _peeloff_pi(arg) if m: if (m*2/S.Pi) % 2 == 0: return cot(x) else: return -tan(x) if arg.func is acot: return arg.args[0] if arg.func is atan: x = arg.args[0] return 1 / x if arg.func is atan2: y, x = arg.args return x/y if arg.func is asin: x = arg.args[0] return sqrt(1 - x**2) / x if arg.func is acos: x = arg.args[0] return x / sqrt(1 - x**2)