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 ###############################################################################
15 def fdiff(self
, argindex
=1):
17 return cos(self
.args
[0])
19 raise ArgumentIndexError(self
, argindex
)
21 def inverse(self
, argindex
=1):
25 def _eval_apply_subs(self
, *args
):
29 def canonize(cls
, arg
):
32 if isinstance(arg
, C
.Number
):
40 i_coeff
= arg
.as_coefficient(S
.ImaginaryUnit
)
42 if i_coeff
is not None:
43 return S
.ImaginaryUnit
* C
.sinh(i_coeff
)
45 pi_coeff
= arg
.as_coefficient(S
.Pi
)
47 if pi_coeff
is not None:
48 if pi_coeff
.is_integer
:
50 elif isinstance(pi_coeff
, C
.Rational
):
59 result
= cst_table
[pi_coeff
.q
]
61 if (pi_coeff
.p
// pi_coeff
.q
) % 2 == 1:
68 coeff
, terms
= arg
.as_coeff_terms()
76 def taylor_term(n
, x
, *previous_terms
):
77 if n
< 0 or n
% 2 == 0:
82 if len(previous_terms
) > 2:
83 p
= previous_terms
[-2]
84 return -p
* x
**2 / (n
*(n
-1))
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
:
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()
115 if isinstance(arg
, C
.Add
):
117 y
= C
.Add(*arg
.args
[1:])
119 coeff
, terms
= arg
.as_coeff_terms()
120 if not (coeff
is S
.One
) and isinstance(coeff
, C
.Integer
) and terms
:
124 return (sin(x
)*cos(y
) + sin(y
)*cos(x
)).expand(trig
=True)
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
):
133 return self
.func(arg
)
135 def _eval_is_real(self
):
136 return self
.args
[0].is_real
138 def _eval_is_bounded(self
):
144 import sage
.all
as sage
145 return sage
.sin(self
.args
[0]._sage
_())
151 def fdiff(self
, argindex
=1):
153 return -sin(self
.args
[0])
155 raise ArgumentIndexError(self
, argindex
)
157 def inverse(self
, argindex
=1):
161 def _eval_apply_subs(self
, *args
):
165 def canonize(cls
, arg
):
168 if isinstance(arg
, C
.Number
):
173 elif arg
.is_negative
:
176 i_coeff
= arg
.as_coefficient(S
.ImaginaryUnit
)
178 if i_coeff
is not None:
179 return C
.cosh(i_coeff
)
181 pi_coeff
= arg
.as_coefficient(S
.Pi
)
183 if pi_coeff
is not None:
184 if isinstance(pi_coeff
, C
.Rational
):
194 result
= cst_table
[pi_coeff
.q
]
196 if (2*pi_coeff
.p
// pi_coeff
.q
) % 4 in (1, 2):
203 coeff
, terms
= arg
.as_coeff_terms()
205 if coeff
.is_negative
:
211 def taylor_term(n
, x
, *previous_terms
):
212 if n
< 0 or n
% 2 == 1:
217 if len(previous_terms
) > 2:
218 p
= previous_terms
[-2]
219 return -p
* x
**2 / (n
*(n
-1))
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
:
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()
251 if isinstance(arg
, C
.Add
):
253 y
= C
.Add(*arg
.args
[1:])
254 return (cos(x
)*cos(y
) - sin(y
)*sin(x
)).expand(trig
=True)
256 coeff
, terms
= arg
.as_coeff_terms()
257 if not (coeff
is S
.One
) and isinstance(coeff
, C
.Integer
) and terms
:
259 return C
.chebyshevt(coeff
, cos(x
))
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
):
268 return self
.func(arg
)
270 def _eval_is_real(self
):
271 return self
.args
[0].is_real
273 def _eval_is_bounded(self
):
280 import sage
.all
as sage
281 return sage
.cos(self
.args
[0]._sage
_())
287 def fdiff(self
, argindex
=1):
289 return S
.One
+ self
**2
291 raise ArgumentIndexError(self
, argindex
)
293 def inverse(self
, argindex
=1):
297 def _eval_apply_subs(self
, *args
):
301 def canonize(cls
, arg
):
304 if isinstance(arg
, C
.Number
):
309 elif arg
.is_negative
:
312 i_coeff
= arg
.as_coefficient(S
.ImaginaryUnit
)
314 if i_coeff
is not None:
315 return S
.ImaginaryUnit
* C
.tanh(i_coeff
)
317 pi_coeff
= arg
.as_coefficient(S
.Pi
)
319 if pi_coeff
is not None:
320 if pi_coeff
.is_integer
:
322 elif isinstance(pi_coeff
, C
.Rational
):
324 #2 : S.ComplexInfinity,
331 result
= cst_table
[pi_coeff
.q
]
333 if (2*pi_coeff
.p
// pi_coeff
.q
) % 4 in (1, 3):
340 coeff
, terms
= arg
.as_coeff_terms()
342 if coeff
.is_negative
:
348 def taylor_term(n
, x
, *previous_terms
):
349 if n
< 0 or n
% 2 == 0:
354 a
, b
= ((n
-1)//2), 2**(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
:
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
):
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
):
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
):
395 return self
.func(arg
)
397 def _eval_is_real(self
):
398 return self
.args
[0].is_real
400 def _eval_is_bounded(self
):
410 def fdiff(self
, argindex
=1):
412 return -S
.One
- S
.Cot
**2
414 raise ArgumentIndexError(self
, argindex
)
416 def inverse(self
, argindex
=1):
420 def _eval_apply_subs(self
, *args
):
424 def canonize(cls
, arg
):
427 if isinstance(arg
, C
.Number
):
431 # return S.ComplexInfinity
432 elif arg
.is_negative
:
435 i_coeff
= arg
.as_coefficient(S
.ImaginaryUnit
)
437 if i_coeff
is not None:
438 return -S
.ImaginaryUnit
* C
.coth(i_coeff
)
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
):
454 result
= cst_table
[pi_coeff
.q
]
456 if (2*pi_coeff
.p
// pi_coeff
.q
) % 4 in (1, 3):
463 coeff
, terms
= arg
.as_coeff_terms()
465 if coeff
.is_negative
:
471 def taylor_term(n
, x
, *previous_terms
):
473 return 1 / sympify(x
)
474 elif n
< 0 or n
% 2 == 0:
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
:
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
):
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
):
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
):
529 def fdiff(self
, argindex
=1):
531 return (1 - self
.args
[0]**2)**(-S
.Half
)
533 raise ArgumentIndexError(self
, argindex
)
536 def _eval_apply_subs(self
, *args
):
540 def canonize(cls
, arg
):
543 if isinstance(arg
, C
.Number
):
546 elif arg
is S
.Infinity
:
547 return S
.NegativeInfinity
* S
.ImaginaryUnit
548 elif arg
is S
.NegativeInfinity
:
549 return S
.Infinity
* S
.ImaginaryUnit
554 elif arg
is S
.NegativeOne
:
569 return S
.Pi
/ cst_table
[arg
]
570 elif arg
.is_negative
:
573 i_coeff
= arg
.as_coefficient(S
.ImaginaryUnit
)
575 if i_coeff
is not None:
576 return S
.ImaginaryUnit
* C
.asinh(i_coeff
)
578 coeff
, terms
= arg
.as_coeff_terms()
580 if coeff
.is_negative
:
586 def taylor_term(n
, x
, *previous_terms
):
587 if n
< 0 or n
% 2 == 0:
592 if len(previous_terms
) > 2:
593 p
= previous_terms
[-2]
594 return p
* (n
-2)**2/(k
*(k
-1)) * x
**2
598 R
= C
.RisingFactorial(S
.Half
, 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
):
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
):
618 def fdiff(self
, argindex
=1):
620 return -(1 - self
.args
[0]**2)**(-S
.Half
)
622 raise ArgumentIndexError(self
, argindex
)
625 def _eval_apply_subs(self
, *args
):
629 def canonize(cls
, arg
):
632 if isinstance(arg
, C
.Number
):
635 elif arg
is S
.Infinity
:
636 return S
.Infinity
* S
.ImaginaryUnit
637 elif arg
is S
.NegativeInfinity
:
638 return S
.NegativeInfinity
* S
.ImaginaryUnit
643 elif arg
is S
.NegativeOne
:
650 -sqrt(2)/2 : 3*S
.Pi
/4,
652 -1/sqrt(2) : 3*S
.Pi
/4,
654 -sqrt(3)/2 : 5*S
.Pi
/6,
658 return cst_table
[arg
]
663 def taylor_term(n
, x
, *previous_terms
):
666 elif n
< 0 or n
% 2 == 0:
671 if len(previous_terms
) > 2:
672 p
= previous_terms
[-2]
673 return p
* (n
-2)**2/(k
*(k
-1)) * x
**2
677 R
= C
.RisingFactorial(S
.Half
, 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
):
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
):
697 def fdiff(self
, argindex
=1):
699 return 1/(1+self
.args
[0]**2)
701 raise ArgumentIndexError(self
, argindex
)
704 def _eval_apply_subs(self
, *args
):
708 def canonize(cls
, arg
):
711 if isinstance(arg
, C
.Number
):
714 elif arg
is S
.Infinity
:
716 elif arg
is S
.NegativeInfinity
:
722 elif arg
is S
.NegativeOne
:
735 return S
.Pi
/ cst_table
[arg
]
736 elif arg
.is_negative
:
739 i_coeff
= arg
.as_coefficient(S
.ImaginaryUnit
)
741 if i_coeff
is not None:
742 return S
.ImaginaryUnit
* C
.atanh(i_coeff
)
744 coeff
, terms
= arg
.as_coeff_terms()
746 if coeff
.is_negative
:
752 def taylor_term(n
, x
, *previous_terms
):
753 if n
< 0 or n
% 2 == 0:
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
):
765 return self
.func(arg
)
767 def _eval_is_real(self
):
768 return self
.args
[0].is_real
770 class acot(Function
):
774 def fdiff(self
, argindex
=1):
776 return -1 / (1+self
.args
[0]**2)
778 raise ArgumentIndexError(self
, argindex
)
781 def canonize(cls
, arg
):
784 if isinstance(arg
, C
.Number
):
787 elif arg
is S
.Infinity
:
789 elif arg
is S
.NegativeInfinity
:
795 elif arg
is S
.NegativeOne
:
808 return S
.Pi
/ cst_table
[arg
]
809 elif arg
.is_negative
:
812 i_coeff
= arg
.as_coefficient(S
.ImaginaryUnit
)
814 if i_coeff
is not None:
815 return -S
.ImaginaryUnit
* C
.acoth(i_coeff
)
817 coeff
, terms
= arg
.as_coeff_terms()
819 if coeff
.is_negative
:
825 def taylor_term(n
, x
, *previous_terms
):
827 return S
.Pi
/ 2 # FIX THIS
828 elif n
< 0 or n
% 2 == 0:
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
):
840 return self
.func(arg
)
842 def _eval_is_real(self
):
843 return self
.args
[0].is_real