Use sympify instead of Basic.sympify (#667)
[sympy.git] / sympy / functions / elementary / trigonometric.py
blob1e32f740fc56044fa7e4af9fb4ded76d1da9d10b
2 from sympy.core.basic import Basic, S, C, sympify
3 from sympy.core.function import Lambda, Function
4 from miscellaneous import sqrt
5 from sympy.core.cache import cache_it, cache_it_immutable
7 ###############################################################################
8 ########################## TRIGONOMETRIC FUNCTIONS ############################
9 ###############################################################################
11 class sin(Function):
13 nargs = 1
15 def fdiff(self, argindex=1):
16 if argindex == 1:
17 return cos(self.args[0])
18 else:
19 raise ArgumentIndexError(self, argindex)
21 def inverse(self, argindex=1):
22 return asin
24 @classmethod
25 def _eval_apply_subs(self, *args):
26 return
28 @classmethod
29 def canonize(cls, arg):
30 arg = sympify(arg)
32 if isinstance(arg, C.Number):
33 if arg is S.NaN:
34 return S.NaN
35 elif arg is S.Zero:
36 return S.Zero
37 elif arg.is_negative:
38 return -cls(-arg)
39 else:
40 i_coeff = arg.as_coefficient(S.ImaginaryUnit)
42 if i_coeff is not None:
43 return S.ImaginaryUnit * C.sinh(i_coeff)
44 else:
45 pi_coeff = arg.as_coefficient(S.Pi)
47 if pi_coeff is not None:
48 if pi_coeff.is_integer:
49 return S.Zero
50 elif isinstance(pi_coeff, C.Rational):
51 cst_table = {
52 2 : S.One,
53 3 : S.Half*sqrt(3),
54 4 : S.Half*sqrt(2),
55 6 : S.Half,
58 try:
59 result = cst_table[pi_coeff.q]
61 if (pi_coeff.p // pi_coeff.q) % 2 == 1:
62 return -result
63 else:
64 return result
65 except KeyError:
66 pass
68 coeff, terms = arg.as_coeff_terms()
70 if coeff.is_negative:
71 return -cls(-arg)
74 @staticmethod
75 @cache_it_immutable
76 def taylor_term(n, x, *previous_terms):
77 if n < 0 or n % 2 == 0:
78 return S.Zero
79 else:
80 x = sympify(x)
82 if len(previous_terms) > 2:
83 p = previous_terms[-2]
84 return -p * x**2 / (n*(n-1))
85 else:
86 return (-1)**(n//2) * x**(n)/C.Factorial(n)
88 def _eval_rewrite_as_exp(self, arg):
89 exp, I = C.exp, S.ImaginaryUnit
90 return (exp(arg*I) - exp(-arg*I)) / (2*I)
92 def _eval_rewrite_as_cos(self, arg):
93 return -cos(arg + S.Pi/2)
95 def _eval_rewrite_as_tan(self, arg):
96 tan_half = tan(S.Half*arg)
97 return 2*tan_half/(1 + tan_half**2)
99 def _eval_rewrite_as_cot(self, arg):
100 cot_half = S.Cot(S.Half*arg)
101 return 2*cot_half/(1 + cot_half**2)
103 def _eval_conjugate(self):
104 return self.func(self.args[0].conjugate())
106 def _eval_expand_complex(self, *args):
107 if self.args[0].is_real:
108 return self
109 re, im = self.args[0].as_real_imag()
110 return sin(re)*C.cosh(im) + S.ImaginaryUnit*cos(re)*C.sinh(im)
112 def _eval_expand_trig(self, *args):
113 arg = self.args[0].expand()
114 x = None
115 if isinstance(arg, C.Add):
116 x = arg.args[0]
117 y = C.Add(*arg.args[1:])
118 else:
119 coeff, terms = arg.as_coeff_terms()
120 if not (coeff is S.One) and isinstance(coeff, C.Integer) and terms:
121 x = C.Mul(*terms)
122 y = (coeff-1)*x
123 if x is not None:
124 return (sin(x)*cos(y) + sin(y)*cos(x)).expand(trig=True)
125 return sin(arg)
127 def _eval_as_leading_term(self, x):
128 arg = self.args[0].as_leading_term(x)
130 if C.Order(1,x).contains(arg):
131 return arg
132 else:
133 return self.func(arg)
135 def _eval_is_real(self):
136 return self.args[0].is_real
138 def _eval_is_bounded(self):
139 arg = self.args[0]
140 if arg.is_real:
141 return True
143 def _sage_(self):
144 import sage.all as sage
145 return sage.sin(self.args[0]._sage_())
147 class cos(Function):
149 nargs = 1
151 def fdiff(self, argindex=1):
152 if argindex == 1:
153 return -sin(self.args[0])
154 else:
155 raise ArgumentIndexError(self, argindex)
157 def inverse(self, argindex=1):
158 return acos
160 @classmethod
161 def _eval_apply_subs(self, *args):
162 return
164 @classmethod
165 def canonize(cls, arg):
166 arg = sympify(arg)
168 if isinstance(arg, C.Number):
169 if arg is S.NaN:
170 return S.NaN
171 elif arg is S.Zero:
172 return S.One
173 elif arg.is_negative:
174 return cls(-arg)
175 else:
176 i_coeff = arg.as_coefficient(S.ImaginaryUnit)
178 if i_coeff is not None:
179 return C.cosh(i_coeff)
180 else:
181 pi_coeff = arg.as_coefficient(S.Pi)
183 if pi_coeff is not None:
184 if isinstance(pi_coeff, C.Rational):
185 cst_table = {
186 1 : S.One,
187 2 : S.Zero,
188 3 : S.Half,
189 4 : S.Half*sqrt(2),
190 6 : S.Half*sqrt(3),
193 try:
194 result = cst_table[pi_coeff.q]
196 if (2*pi_coeff.p // pi_coeff.q) % 4 in (1, 2):
197 return -result
198 else:
199 return result
200 except KeyError:
201 pass
203 coeff, terms = arg.as_coeff_terms()
205 if coeff.is_negative:
206 return cls(-arg)
209 @staticmethod
210 @cache_it_immutable
211 def taylor_term(n, x, *previous_terms):
212 if n < 0 or n % 2 == 1:
213 return S.Zero
214 else:
215 x = sympify(x)
217 if len(previous_terms) > 2:
218 p = previous_terms[-2]
219 return -p * x**2 / (n*(n-1))
220 else:
221 return (-1)**(n//2)*x**(n)/C.Factorial(n)
223 def _eval_rewrite_as_exp(self, arg):
224 exp, I = C.exp, S.ImaginaryUnit
225 return (exp(arg*I) + exp(-arg*I)) / 2
227 def _eval_rewrite_as_sin(self, arg):
228 return sin(arg + S.Pi/2)
230 def _eval_rewrite_as_tan(self, arg):
231 tan_half = tan(S.Half*arg)**2
232 return (1-tan_half)/(1+tan_half)
234 def _eval_rewrite_as_cot(self, arg):
235 cot_half = S.Cot(S.Half*arg)**2
236 return (cot_half-1)/(cot_half+1)
238 def _eval_conjugate(self):
239 return self.func(self.args[0].conjugate())
241 def _eval_expand_complex(self, *args):
242 if self.args[0].is_real:
243 return self
244 re, im = self.args[0].as_real_imag()
245 return cos(re)*C.cosh(im) - \
246 S.ImaginaryUnit*sin(re)*C.sinh(im)
248 def _eval_expand_trig(self, *args):
249 arg = self.args[0].expand()
250 x = None
251 if isinstance(arg, C.Add):
252 x = arg.args[0]
253 y = C.Add(*arg.args[1:])
254 return (cos(x)*cos(y) - sin(y)*sin(x)).expand(trig=True)
255 else:
256 coeff, terms = arg.as_coeff_terms()
257 if not (coeff is S.One) and isinstance(coeff, C.Integer) and terms:
258 x = C.Mul(*terms)
259 return C.chebyshevt(coeff, cos(x))
260 return cos(arg)
262 def _eval_as_leading_term(self, x):
263 arg = self.args[0].as_leading_term(x)
265 if C.Order(1,x).contains(arg):
266 return S.One
267 else:
268 return self.func(arg)
270 def _eval_is_real(self):
271 return self.args[0].is_real
273 def _eval_is_bounded(self):
274 arg = self.args[0]
276 if arg.is_real:
277 return True
279 def _sage_(self):
280 import sage.all as sage
281 return sage.cos(self.args[0]._sage_())
283 class tan(Function):
285 nargs = 1
287 def fdiff(self, argindex=1):
288 if argindex==1:
289 return S.One + self**2
290 else:
291 raise ArgumentIndexError(self, argindex)
293 def inverse(self, argindex=1):
294 return atan
296 @classmethod
297 def _eval_apply_subs(self, *args):
298 return
300 @classmethod
301 def canonize(cls, arg):
302 arg = sympify(arg)
304 if isinstance(arg, C.Number):
305 if arg is S.NaN:
306 return S.NaN
307 elif arg is S.Zero:
308 return S.Zero
309 elif arg.is_negative:
310 return -cls(-arg)
311 else:
312 i_coeff = arg.as_coefficient(S.ImaginaryUnit)
314 if i_coeff is not None:
315 return S.ImaginaryUnit * C.tanh(i_coeff)
316 else:
317 pi_coeff = arg.as_coefficient(S.Pi)
319 if pi_coeff is not None:
320 if pi_coeff.is_integer:
321 return S.Zero
322 elif isinstance(pi_coeff, C.Rational):
323 cst_table = {
324 #2 : S.ComplexInfinity,
325 3 : sqrt(3),
326 4 : S.One,
327 6 : 1 / sqrt(3),
330 try:
331 result = cst_table[pi_coeff.q]
333 if (2*pi_coeff.p // pi_coeff.q) % 4 in (1, 3):
334 return -result
335 else:
336 return result
337 except KeyError:
338 pass
340 coeff, terms = arg.as_coeff_terms()
342 if coeff.is_negative:
343 return -cls(-arg)
346 @staticmethod
347 @cache_it_immutable
348 def taylor_term(n, x, *previous_terms):
349 if n < 0 or n % 2 == 0:
350 return S.Zero
351 else:
352 x = sympify(x)
354 a, b = ((n-1)//2), 2**(n+1)
356 B = C.bernoulli(n+1)
357 F = C.Factorial(n+1)
359 return (-1)**a * b*(b-1) * B/F * x**n
361 def _eval_conjugate(self):
362 return self.func(self.args[0].conjugate())
364 def _eval_expand_complex(self, *args):
365 if self.args[0].is_real:
366 return self
367 re, im = self.args[0].as_real_imag()
368 denom = cos(re)**2 + C.sinh(im)**2
369 return (sin(re)*cos(re) + \
370 S.ImaginaryUnit*C.sinh(im)*C.cosh(im))/denom
372 def _eval_expand_trig(self, *args):
373 return self
375 def _eval_rewrite_as_exp(self, arg):
376 exp, I = C.exp, S.ImaginaryUnit
377 neg_exp, pos_exp = exp(-arg*I), exp(arg*I)
378 return I*(neg_exp-pos_exp)/(neg_exp+pos_exp)
380 def _eval_rewrite_as_sin(self, arg):
381 return 2*sin(x)**2/sin(2*x)
383 def _eval_rewrite_as_cos(self, arg):
384 return -cos(x + S.Pi/2)/cos(x)
386 def _eval_rewrite_as_cot(self, arg):
387 return 1/S.Cot(arg)
389 def _eval_as_leading_term(self, x):
390 arg = self.args[0].as_leading_term(x)
392 if C.Order(1,x).contains(arg):
393 return S.One
394 else:
395 return self.func(arg)
397 def _eval_is_real(self):
398 return self.args[0].is_real
400 def _eval_is_bounded(self):
401 arg = self.args[0]
403 if arg.is_imaginary:
404 return True
406 class cot(Function):
408 nargs = 1
410 def fdiff(self, argindex=1):
411 if argindex == 1:
412 return -S.One - S.Cot**2
413 else:
414 raise ArgumentIndexError(self, argindex)
416 def inverse(self, argindex=1):
417 return S.ACot
419 @classmethod
420 def _eval_apply_subs(self, *args):
421 return
423 @classmethod
424 def canonize(cls, arg):
425 arg = sympify(arg)
427 if isinstance(arg, C.Number):
428 if arg is S.NaN:
429 return S.NaN
430 #elif arg is S.Zero:
431 # return S.ComplexInfinity
432 elif arg.is_negative:
433 return -cls(-arg)
434 else:
435 i_coeff = arg.as_coefficient(S.ImaginaryUnit)
437 if i_coeff is not None:
438 return -S.ImaginaryUnit * C.coth(i_coeff)
439 else:
440 pi_coeff = arg.as_coefficient(S.Pi)
442 if pi_coeff is not None:
443 #if pi_coeff.is_integer:
444 # return S.ComplexInfinity
445 if isinstance(pi_coeff, C.Rational):
446 cst_table = {
447 2 : S.Zero,
448 3 : 1 / sqrt(3),
449 4 : S.One,
450 6 : sqrt(3)
453 try:
454 result = cst_table[pi_coeff.q]
456 if (2*pi_coeff.p // pi_coeff.q) % 4 in (1, 3):
457 return -result
458 else:
459 return result
460 except KeyError:
461 pass
463 coeff, terms = arg.as_coeff_terms()
465 if coeff.is_negative:
466 return -cls(-arg)
469 @staticmethod
470 @cache_it_immutable
471 def taylor_term(n, x, *previous_terms):
472 if n == 0:
473 return 1 / sympify(x)
474 elif n < 0 or n % 2 == 0:
475 return S.Zero
476 else:
477 x = sympify(x)
479 B = S.Bernoulli(n+1)
480 F = C.Factorial(n+1)
482 return (-1)**((n+1)//2) * 2**(n+1) * B/F * x**n
484 def _eval_conjugate(self):
485 assert len(self.args) == 1
486 return self.func(self.args[0].conjugate())
488 def _eval_expand_complex(self, *args):
489 if self.args[0].is_real:
490 return self
491 re, im = self.args[0].as_real_imag()
492 denom = sin(re)**2 + C.sinh(im)**2
493 return (sin(re)*cos(re) - \
494 S.ImaginaryUnit*C.sinh(im)*C.cosh(im))/denom
496 def _eval_rewrite_as_exp(self, arg):
497 exp, I = C.exp, S.ImaginaryUnit
498 neg_exp, pos_exp = exp(-arg*I), exp(arg*I)
499 return I*(pos_exp+neg_exp)/(pos_exp-neg_exp)
501 def _eval_rewrite_as_sin(self, arg):
502 return 2*sin(2*x)/sin(x)**2
504 def _eval_rewrite_as_cos(self, arg):
505 return -cos(x)/cos(x + S.Pi/2)
507 def _eval_rewrite_as_tan(self, arg):
508 return 1/tan(arg)
510 def _eval_as_leading_term(self, x):
511 arg = self.args[0].as_leading_term(x)
513 if C.Order(1,x).contains(arg):
514 return S.One
515 else:
516 return self.func(arg)
518 def _eval_is_real(self):
519 return self.args[0].is_real
521 ###############################################################################
522 ########################### TRIGONOMETRIC INVERSES ############################
523 ###############################################################################
525 class asin(Function):
527 nargs = 1
529 def fdiff(self, argindex=1):
530 if argindex == 1:
531 return (1 - self.args[0]**2)**(-S.Half)
532 else:
533 raise ArgumentIndexError(self, argindex)
535 @classmethod
536 def _eval_apply_subs(self, *args):
537 return
539 @classmethod
540 def canonize(cls, arg):
541 arg = sympify(arg)
543 if isinstance(arg, C.Number):
544 if arg is S.NaN:
545 return S.NaN
546 elif arg is S.Infinity:
547 return S.NegativeInfinity * S.ImaginaryUnit
548 elif arg is S.NegativeInfinity:
549 return S.Infinity * S.ImaginaryUnit
550 elif arg is S.Zero:
551 return S.Zero
552 elif arg is S.One:
553 return S.Pi / 2
554 elif arg is S.NegativeOne:
555 return -S.Pi / 2
556 else:
557 cst_table = {
558 S.Half : 6,
559 -S.Half : -6,
560 sqrt(2)/2 : 4,
561 -sqrt(2)/2 : -4,
562 1/sqrt(2) : 4,
563 -1/sqrt(2) : -4,
564 sqrt(3)/2 : 3,
565 -sqrt(3)/2 : -3,
568 if arg in cst_table:
569 return S.Pi / cst_table[arg]
570 elif arg.is_negative:
571 return -cls(-arg)
572 else:
573 i_coeff = arg.as_coefficient(S.ImaginaryUnit)
575 if i_coeff is not None:
576 return S.ImaginaryUnit * C.asinh(i_coeff)
577 else:
578 coeff, terms = arg.as_coeff_terms()
580 if coeff.is_negative:
581 return -cls(-arg)
584 @staticmethod
585 @cache_it_immutable
586 def taylor_term(n, x, *previous_terms):
587 if n < 0 or n % 2 == 0:
588 return S.Zero
589 else:
590 x = sympify(x)
592 if len(previous_terms) > 2:
593 p = previous_terms[-2]
594 return p * (n-2)**2/(k*(k-1)) * x**2
595 else:
596 k = (n - 1) // 2
598 R = C.RisingFactorial(S.Half, k)
599 F = C.Factorial(k)
601 return R / F * x**n / n
603 def _eval_as_leading_term(self, x):
604 arg = self.args[0].as_leading_term(x)
606 if C.Order(1,x).contains(arg):
607 return arg
608 else:
609 return self.func(arg)
611 def _eval_is_real(self):
612 return self.args[0].is_real and (self.args[0]>=-1 and self.args[0]<=1)
614 class acos(Function):
616 nargs = 1
618 def fdiff(self, argindex=1):
619 if argindex == 1:
620 return -(1 - self.args[0]**2)**(-S.Half)
621 else:
622 raise ArgumentIndexError(self, argindex)
624 @classmethod
625 def _eval_apply_subs(self, *args):
626 return
628 @classmethod
629 def canonize(cls, arg):
630 arg = sympify(arg)
632 if isinstance(arg, C.Number):
633 if arg is S.NaN:
634 return S.NaN
635 elif arg is S.Infinity:
636 return S.Infinity * S.ImaginaryUnit
637 elif arg is S.NegativeInfinity:
638 return S.NegativeInfinity * S.ImaginaryUnit
639 elif arg is S.Zero:
640 return S.Pi / 2
641 elif arg is S.One:
642 return S.Zero
643 elif arg is S.NegativeOne:
644 return S.Pi
645 else:
646 cst_table = {
647 S.Half : S.Pi/3,
648 -S.Half : 2*S.Pi/3,
649 sqrt(2)/2 : S.Pi/4,
650 -sqrt(2)/2 : 3*S.Pi/4,
651 1/sqrt(2) : S.Pi/4,
652 -1/sqrt(2) : 3*S.Pi/4,
653 sqrt(3)/2 : S.Pi/6,
654 -sqrt(3)/2 : 5*S.Pi/6,
657 if arg in cst_table:
658 return cst_table[arg]
661 @staticmethod
662 @cache_it_immutable
663 def taylor_term(n, x, *previous_terms):
664 if n == 0:
665 return S.Pi / 2
666 elif n < 0 or n % 2 == 0:
667 return S.Zero
668 else:
669 x = sympify(x)
671 if len(previous_terms) > 2:
672 p = previous_terms[-2]
673 return p * (n-2)**2/(k*(k-1)) * x**2
674 else:
675 k = (n - 1) // 2
677 R = C.RisingFactorial(S.Half, k)
678 F = C.Factorial(k)
680 return -R / F * x**n / n
682 def _eval_as_leading_term(self, x):
683 arg = self.args[0].as_leading_term(x)
685 if C.Order(1,x).contains(arg):
686 return arg
687 else:
688 return self.func(arg)
690 def _eval_is_real(self):
691 return self.args[0].is_real and (self.args[0]>=-1 and self.args[0]<=1)
693 class atan(Function):
695 nargs = 1
697 def fdiff(self, argindex=1):
698 if argindex == 1:
699 return 1/(1+self.args[0]**2)
700 else:
701 raise ArgumentIndexError(self, argindex)
703 @classmethod
704 def _eval_apply_subs(self, *args):
705 return
707 @classmethod
708 def canonize(cls, arg):
709 arg = sympify(arg)
711 if isinstance(arg, C.Number):
712 if arg is S.NaN:
713 return S.NaN
714 elif arg is S.Infinity:
715 return S.Pi / 2
716 elif arg is S.NegativeInfinity:
717 return -S.Pi / 2
718 elif arg is S.Zero:
719 return S.Zero
720 elif arg is S.One:
721 return S.Pi / 4
722 elif arg is S.NegativeOne:
723 return -S.Pi / 4
724 else:
725 cst_table = {
726 sqrt(3)/3 : 6,
727 -sqrt(3)/3 : -6,
728 1/sqrt(3) : 6,
729 -1/sqrt(3) : -6,
730 sqrt(3) : 3,
731 -sqrt(3) : -3,
734 if arg in cst_table:
735 return S.Pi / cst_table[arg]
736 elif arg.is_negative:
737 return -cls(-arg)
738 else:
739 i_coeff = arg.as_coefficient(S.ImaginaryUnit)
741 if i_coeff is not None:
742 return S.ImaginaryUnit * C.atanh(i_coeff)
743 else:
744 coeff, terms = arg.as_coeff_terms()
746 if coeff.is_negative:
747 return -cls(-arg)
750 @staticmethod
751 @cache_it_immutable
752 def taylor_term(n, x, *previous_terms):
753 if n < 0 or n % 2 == 0:
754 return S.Zero
755 else:
756 x = sympify(x)
757 return (-1)**((n-1)//2) * x**n / n
759 def _eval_as_leading_term(self, x):
760 arg = self.args[0].as_leading_term(x)
762 if C.Order(1,x).contains(arg):
763 return arg
764 else:
765 return self.func(arg)
767 def _eval_is_real(self):
768 return self.args[0].is_real
770 class acot(Function):
772 nargs = 1
774 def fdiff(self, argindex=1):
775 if argindex == 1:
776 return -1 / (1+self.args[0]**2)
777 else:
778 raise ArgumentIndexError(self, argindex)
780 @classmethod
781 def canonize(cls, arg):
782 arg = sympify(arg)
784 if isinstance(arg, C.Number):
785 if arg is S.NaN:
786 return S.NaN
787 elif arg is S.Infinity:
788 return S.Zero
789 elif arg is S.NegativeInfinity:
790 return S.Zero
791 elif arg is S.Zero:
792 return S.Pi/ 2
793 elif arg is S.One:
794 return S.Pi / 4
795 elif arg is S.NegativeOne:
796 return -S.Pi / 4
797 else:
798 cst_table = {
799 sqrt(3)/3 : 3,
800 -sqrt(3)/3 : -3,
801 1/sqrt(3) : 3,
802 -1/sqrt(3) : -3,
803 sqrt(3) : 6,
804 -sqrt(3) : -6,
807 if arg in cst_table:
808 return S.Pi / cst_table[arg]
809 elif arg.is_negative:
810 return -cls(-arg)
811 else:
812 i_coeff = arg.as_coefficient(S.ImaginaryUnit)
814 if i_coeff is not None:
815 return -S.ImaginaryUnit * C.acoth(i_coeff)
816 else:
817 coeff, terms = arg.as_coeff_terms()
819 if coeff.is_negative:
820 return -cls(-arg)
823 @staticmethod
824 @cache_it_immutable
825 def taylor_term(n, x, *previous_terms):
826 if n == 0:
827 return S.Pi / 2 # FIX THIS
828 elif n < 0 or n % 2 == 0:
829 return S.Zero
830 else:
831 x = sympify(x)
832 return (-1)**((n+1)//2) * x**n / n
834 def _eval_as_leading_term(self, x):
835 arg = self.args[0].as_leading_term(x)
837 if C.Order(1,x).contains(arg):
838 return arg
839 else:
840 return self.func(arg)
842 def _eval_is_real(self):
843 return self.args[0].is_real