2 from sympy
.core
.basic
import Basic
, S
, cache_it
, cache_it_immutable
3 from sympy
.core
.function
import DefinedFunction
, Apply
, Lambda
5 ###############################################################################
6 ########################### HYPERBOLIC FUNCTIONS ##############################
7 ###############################################################################
9 class Sinh(DefinedFunction
):
13 def fdiff(self
, argindex
=1):
17 raise ArgumentIndexError(self
, argindex
)
19 def inverse(self
, argindex
=1):
22 def _eval_apply(self
, arg
):
23 arg
= Basic
.sympify(arg
)
25 if isinstance(arg
, Basic
.Number
):
26 if isinstance(arg
, Basic
.NaN
):
28 elif isinstance(arg
, Basic
.Infinity
):
30 elif isinstance(arg
, Basic
.NegativeInfinity
):
31 return S
.NegativeInfinity
32 elif isinstance(arg
, Basic
.Zero
):
37 i_coeff
= arg
.as_coefficient(S
.ImaginaryUnit
)
39 if i_coeff
is not None:
40 return S
.ImaginaryUnit
* S
.Sin(i_coeff
)
42 coeff
, terms
= arg
.as_coeff_terms()
47 def _eval_apply_evalf(self
, arg
):
50 if isinstance(arg
, Basic
.Number
):
54 def taylor_term(self
, n
, x
, *previous_terms
):
55 if n
< 0 or n
% 2 == 0:
60 if len(previous_terms
) > 2:
61 p
= previous_terms
[-2]
62 return p
* x
**2 / (n
*(n
-1))
64 return x
**(n
) / S
.Factorial(n
)
66 class ApplySinh(Apply
):
68 def _eval_conjugate(self
):
69 return self
.func(self
[0].conjugate())
71 def _eval_expand_complex(self
, *args
):
74 re
, im
= self
[0].as_real_imag()
75 return S
.Sinh(re
)*S
.Cos(im
) + S
.Cosh(re
)*S
.Sin(im
)*S
.ImaginaryUnit
77 def _eval_rewrite_as_exp(self
, arg
):
78 return (S
.Exp(arg
) - S
.Exp(-arg
)) / 2
80 def _eval_rewrite_as_cosh(self
, arg
):
81 return -S
.ImaginaryUnit
*S
.Cosh(arg
+ S
.Pi
*S
.ImaginaryUnit
/2)
83 def _eval_rewrite_as_tanh(self
, arg
):
84 tanh_half
= S
.Tanh(S
.Half
*arg
)
85 return 2*tanh_half
/(1 - tanh_half
**2)
87 def _eval_rewrite_as_coth(self
, arg
):
88 coth_half
= S
.Coth(S
.Half
*arg
)
89 return 2*coth_half
/(coth_half
**2 - 1)
91 def _eval_as_leading_term(self
, x
):
92 arg
= self
[0].as_leading_term(x
)
94 if Basic
.Order(1,x
).contains(arg
):
99 def _eval_is_real(self
):
100 return self
[0].is_real
101 def _eval_is_bounded(self
):
106 class Cosh(DefinedFunction
):
110 def fdiff(self
, argindex
=1):
114 raise ArgumentIndexError(self
, argindex
)
116 def inverse(self
, argindex
=1):
119 def _eval_apply(self
, arg
):
120 arg
= Basic
.sympify(arg
)
122 if isinstance(arg
, Basic
.Number
):
123 if isinstance(arg
, Basic
.NaN
):
125 elif isinstance(arg
, Basic
.Infinity
):
127 elif isinstance(arg
, Basic
.NegativeInfinity
):
129 elif isinstance(arg
, Basic
.Zero
):
131 elif arg
.is_negative
:
134 i_coeff
= arg
.as_coefficient(S
.ImaginaryUnit
)
136 if i_coeff
is not None:
137 return S
.Cos(i_coeff
)
139 coeff
, terms
= arg
.as_coeff_terms()
141 if coeff
.is_negative
:
144 def _eval_apply_evalf(self
, arg
):
147 if isinstance(arg
, Basic
.Number
):
151 def taylor_term(self
, n
, x
, *previous_terms
):
152 if n
< 0 or n
% 2 == 1:
157 if len(previous_terms
) > 2:
158 p
= previous_terms
[-2]
159 return p
* x
**2 / (n
*(n
-1))
161 return x
**(n
)/S
.Factorial(n
)
163 class ApplyCosh(Apply
):
164 def _eval_conjugate(self
):
165 return self
.func(self
[0].conjugate())
167 def _eval_expand_complex(self
, *args
):
170 re
, im
= self
[0].as_real_imag()
171 return S
.Cosh(re
)*S
.Cos(im
) + S
.Sinh(re
)*S
.Sin(im
)*S
.ImaginaryUnit
173 def _eval_rewrite_as_exp(self
, arg
):
174 return (S
.Exp(arg
) + S
.Exp(-arg
)) / 2
176 def _eval_rewrite_as_sinh(self
, arg
):
177 return -S
.ImaginaryUnit
*S
.Sinh(arg
+ S
.Pi
*S
.ImaginaryUnit
/2)
179 def _eval_rewrite_as_tanh(self
, arg
):
180 tanh_half
= S
.Tanh(S
.Half
*arg
)**2
181 return (1+tanh_half
)/(1-tanh_half
)
183 def _eval_rewrite_as_coth(self
, arg
):
184 coth_half
= S
.Coth(S
.Half
*arg
)**2
185 return (coth_half
+1)/(coth_half
-1)
187 def _eval_as_leading_term(self
, x
):
188 arg
= self
[0].as_leading_term(x
)
190 if Basic
.Order(1,x
).contains(arg
):
193 return self
.func(arg
)
195 def _eval_is_real(self
):
196 return self
[0].is_real
197 def _eval_is_bounded(self
):
202 class Tanh(DefinedFunction
):
206 def fdiff(self
, argindex
=1):
208 return S
.One
- S
.Tanh
**2
210 raise ArgumentIndexError(self
, argindex
)
212 def inverse(self
, argindex
=1):
215 def _eval_apply(self
, arg
):
216 arg
= Basic
.sympify(arg
)
218 if isinstance(arg
, Basic
.Number
):
219 if isinstance(arg
, Basic
.NaN
):
221 elif isinstance(arg
, Basic
.Infinity
):
223 elif isinstance(arg
, Basic
.NegativeInfinity
):
225 elif isinstance(arg
, Basic
.Zero
):
227 elif arg
.is_negative
:
230 i_coeff
= arg
.as_coefficient(S
.ImaginaryUnit
)
232 if i_coeff
is not None:
233 return S
.ImaginaryUnit
* Basic
.tan(i_coeff
)
235 coeff
, terms
= arg
.as_coeff_terms()
237 if coeff
.is_negative
:
240 def _eval_apply_evalf(self
, arg
):
243 if isinstance(arg
, Basic
.Number
):
247 def taylor_term(self
, n
, x
, *previous_terms
):
248 if n
< 0 or n
% 2 == 0:
258 return a
*(a
-1) * B
/F
* x
**n
260 class ApplyTanh(Apply
):
262 def _eval_conjugate(self
):
263 return self
.func(self
[0].conjugate())
265 def _eval_expand_complex(self
, *args
):
268 re
, im
= self
[0].as_real_imag()
269 denom
= S
.Sinh(re
)**2 + S
.Cos(im
)**2
270 return (S
.Sinh(re
)*S
.Cosh(re
) + \
271 S
.ImaginaryUnit
*S
.Sin(im
)*S
.Cos(im
))/denom
273 def _eval_rewrite_as_exp(self
, arg
):
274 neg_exp
, pos_exp
= S
.Exp(-arg
), S
.Exp(arg
)
275 return (pos_exp
-neg_exp
)/(pos_exp
+neg_exp
)
277 def _eval_rewrite_as_sinh(self
, arg
):
278 return S
.ImaginaryUnit
*S
.Sinh(arg
)/S
.Sinh(S
.Pi
*S
.ImaginaryUnit
/2 - arg
)
280 def _eval_rewrite_as_cosh(self
, arg
):
281 return S
.ImaginaryUnit
*S
.Cosh(S
.Pi
*S
.ImaginaryUnit
/2 - arg
)/S
.Cosh(arg
)
283 def _eval_rewrite_as_coth(self
, arg
):
286 def _eval_as_leading_term(self
, x
):
287 arg
= self
[0].as_leading_term(x
)
289 if Basic
.Order(1,x
).contains(arg
):
292 return self
.func(arg
)
294 def _eval_is_real(self
):
295 return self
[0].is_real
296 def _eval_is_bounded(self
):
301 class Coth(DefinedFunction
):
305 def fdiff(self
, argindex
=1):
309 raise ArgumentIndexError(self
, argindex
)
311 def inverse(self
, argindex
=1):
314 def _eval_apply(self
, arg
):
315 arg
= Basic
.sympify(arg
)
317 if isinstance(arg
, Basic
.Number
):
318 if isinstance(arg
, Basic
.NaN
):
320 elif isinstance(arg
, Basic
.Infinity
):
322 elif isinstance(arg
, Basic
.NegativeInfinity
):
324 elif isinstance(arg
, Basic
.Zero
):
326 elif arg
.is_negative
:
329 i_coeff
= arg
.as_coefficient(S
.ImaginaryUnit
)
331 if i_coeff
is not None:
332 return -S
.ImaginaryUnit
* Basic
.cot(i_coeff
)
334 coeff
, terms
= arg
.as_coeff_terms()
336 if coeff
.is_negative
:
339 def _eval_apply_evalf(self
, arg
):
342 if isinstance(arg
, Basic
.Number
):
346 def taylor_term(self
, n
, x
, *previous_terms
):
348 return 1 / Basic
.sympify(x
)
349 elif n
< 0 or n
% 2 == 0:
357 return 2**(n
+1) * B
/F
* x
**n
359 class ApplyCoth(Apply
):
361 def _eval_conjugate(self
):
362 return self
.func(self
[0].conjugate())
364 def _eval_expand_complex(self
, *args
):
367 re
, im
= self
[0].as_real_imag()
368 denom
= S
.Sinh(re
)**2 + S
.Sin(im
)**2
369 return (S
.Sinh(re
)*S
.Cosh(re
) - \
370 S
.ImaginaryUnit
*S
.Sin(im
)*S
.Cos(im
))/denom
372 def _eval_rewrite_as_exp(self
, arg
):
373 neg_exp
, pos_exp
= S
.Exp(-arg
), S
.Exp(arg
)
374 return (pos_exp
+neg_exp
)/(pos_exp
-neg_exp
)
376 def _eval_rewrite_as_sinh(self
, arg
):
377 return -S
.ImaginaryUnit
*S
.Sinh(S
.Pi
*S
.ImaginaryUnit
/2 - arg
)/S
.Sinh(arg
)
379 def _eval_rewrite_as_cosh(self
, arg
):
380 return -S
.ImaginaryUnit
*S
.Cosh(arg
)/S
.Cosh(S
.Pi
*S
.ImaginaryUnit
/2 - arg
)
382 def _eval_rewrite_as_tanh(self
, arg
):
385 def _eval_as_leading_term(self
, x
):
386 arg
= self
[0].as_leading_term(x
)
388 if Basic
.Order(1,x
).contains(arg
):
391 return self
.func(arg
)
393 Basic
.singleton
['sinh'] = Sinh
394 Basic
.singleton
['cosh'] = Cosh
395 Basic
.singleton
['tanh'] = Tanh
396 Basic
.singleton
['coth'] = Coth
398 ###############################################################################
399 ############################# HYPERBOLIC INVERSES #############################
400 ###############################################################################
402 class ASinh(DefinedFunction
):
406 def fdiff(self
, argindex
=1):
408 z
= Basic
.Symbol('z', dummy
=True)
409 return Lambda((1 + z
**2)**(-S
.Half
), z
)
411 raise ArgumentIndexError(self
, argindex
)
413 def _eval_apply(self
, arg
):
414 arg
= Basic
.sympify(arg
)
416 if isinstance(arg
, Basic
.Number
):
417 if isinstance(arg
, Basic
.NaN
):
419 elif isinstance(arg
, Basic
.Infinity
):
421 elif isinstance(arg
, Basic
.NegativeInfinity
):
422 return S
.NegativeInfinity
423 elif isinstance(arg
, Basic
.Zero
):
425 elif isinstance(arg
, Basic
.One
):
426 return S
.Log(S
.Sqrt(2) + 2)
427 elif isinstance(arg
, Basic
.NegativeOne
):
428 return S
.Log(S
.Sqrt(2) - 2)
429 elif arg
.is_negative
:
432 i_coeff
= arg
.as_coefficient(S
.ImaginaryUnit
)
434 if i_coeff
is not None:
435 return S
.ImaginaryUnit
* S
.ASin(i_coeff
)
437 coeff
, terms
= arg
.as_coeff_terms()
439 if coeff
.is_negative
:
442 def _eval_apply_evalf(self
, arg
):
445 if isinstance(arg
, Basic
.Number
):
449 def taylor_term(self
, n
, x
, *previous_terms
):
450 if n
< 0 or n
% 2 == 0:
455 if len(previous_terms
) > 2:
456 p
= previous_terms
[-2]
457 return -p
* (n
-2)**2/(k
*(k
-1)) * x
**2
461 R
= S
.RisingFactorial(S
.Half
, k
)
464 return (-1)**k
* R
/ F
* x
**n
/ n
466 class ApplyASinh(Apply
):
468 def _eval_as_leading_term(self
, x
):
469 arg
= self
[0].as_leading_term(x
)
471 if Basic
.Order(1,x
).contains(arg
):
474 return self
.func(arg
)
476 class ACosh(DefinedFunction
):
480 def fdiff(self
, argindex
=1):
482 z
= Basic
.Symbol('z', dummy
=True)
483 return Lambda(((z
-1)*(z
+1))**(-1), z
)
485 raise ArgumentIndexError(self
, argindex
)
487 def _eval_apply(self
, arg
):
488 arg
= Basic
.sympify(arg
)
490 if isinstance(arg
, Basic
.Number
):
491 if isinstance(arg
, Basic
.NaN
):
493 elif isinstance(arg
, Basic
.Infinity
):
494 return S
.Infinity
* S
.ImaginaryUnit
495 elif isinstance(arg
, Basic
.NegativeInfinity
):
496 return S
.NegativeInfinity
* S
.ImaginaryUnit
497 elif isinstance(arg
, Basic
.Zero
):
498 return S
.Pi
*S
.ImaginaryUnit
/ 2
499 elif isinstance(arg
, Basic
.One
):
501 elif isinstance(arg
, Basic
.NegativeOne
):
502 return S
.Pi
*S
.ImaginaryUnit
507 S
.Sqrt(2)/2 : S
.Pi
/4,
508 -S
.Sqrt(2)/2 : 3*S
.Pi
/4,
509 1/S
.Sqrt(2) : S
.Pi
/4,
510 -1/S
.Sqrt(2) : 3*S
.Pi
/4,
511 S
.Sqrt(3)/2 : S
.Pi
/6,
512 -S
.Sqrt(3)/2 : 5*S
.Pi
/6,
516 return cst_table
[arg
]*S
.ImaginaryUnit
518 def _eval_apply_evalf(self
, arg
):
521 if isinstance(arg
, Basic
.Number
):
525 def taylor_term(self
, n
, x
, *previous_terms
):
527 return S
.Pi
*S
.ImaginaryUnit
/ 2
528 elif n
< 0 or n
% 2 == 0:
533 if len(previous_terms
) > 2:
534 p
= previous_terms
[-2]
535 return p
* (n
-2)**2/(k
*(k
-1)) * x
**2
539 R
= S
.RisingFactorial(S
.Half
, k
)
542 return -R
/ F
* S
.ImaginaryUnit
* x
**n
/ n
544 class ApplyACosh(Apply
):
546 def _eval_as_leading_term(self
, x
):
547 arg
= self
[0].as_leading_term(x
)
549 if Basic
.Order(1,x
).contains(arg
):
552 return self
.func(arg
)
554 class ATanh(DefinedFunction
):
558 def fdiff(self
, argindex
=1):
560 z
= Basic
.Symbol('z', dummy
=True)
561 return Lambda((z
-1)**2, z
)
563 raise ArgumentIndexError(self
, argindex
)
565 def _eval_apply(self
, arg
):
566 arg
= Basic
.sympify(arg
)
568 if isinstance(arg
, Basic
.Number
):
569 if isinstance(arg
, Basic
.NaN
):
571 elif isinstance(arg
, Basic
.Zero
):
573 elif isinstance(arg
, Basic
.One
):
575 elif isinstance(arg
, Basic
.NegativeOne
):
576 return S
.NegativeInfinity
577 elif arg
.is_negative
:
580 i_coeff
= arg
.as_coefficient(S
.ImaginaryUnit
)
582 if i_coeff
is not None:
583 return S
.ImaginaryUnit
* S
.ATan(i_coeff
)
585 coeff
, terms
= arg
.as_coeff_terms()
587 if coeff
.is_negative
:
590 def _eval_apply_evalf(self
, arg
):
593 if isinstance(arg
, Basic
.Number
):
597 def taylor_term(self
, n
, x
, *previous_terms
):
598 if n
< 0 or n
% 2 == 0:
604 class ApplyATanh(Apply
):
606 def _eval_as_leading_term(self
, x
):
607 arg
= self
[0].as_leading_term(x
)
609 if Basic
.Order(1,x
).contains(arg
):
612 return self
.func(arg
)
614 class ACoth(DefinedFunction
):
618 def fdiff(self
, argindex
=1):
620 z
= Basic
.Symbol('z', dummy
=True)
621 return Lambda((z
-1)**2, z
)
623 raise ArgumentIndexError(self
, argindex
)
625 def _eval_apply(self
, arg
):
626 arg
= Basic
.sympify(arg
)
628 if isinstance(arg
, Basic
.Number
):
629 if isinstance(arg
, Basic
.NaN
):
631 elif isinstance(arg
, Basic
.Infinity
):
633 elif isinstance(arg
, Basic
.NegativeInfinity
):
635 elif isinstance(arg
, Basic
.Zero
):
636 return S
.Pi
*S
.ImaginaryUnit
/ 2
637 elif isinstance(arg
, Basic
.One
):
639 elif isinstance(arg
, Basic
.NegativeOne
):
640 return S
.NegativeInfinity
641 elif arg
.is_negative
:
644 i_coeff
= arg
.as_coefficient(S
.ImaginaryUnit
)
646 if i_coeff
is not None:
647 return -S
.ImaginaryUnit
* S
.ACot(i_coeff
)
649 coeff
, terms
= arg
.as_coeff_terms()
651 if coeff
.is_negative
:
654 def _eval_apply_evalf(self
, arg
):
657 if isinstance(arg
, Basic
.Number
):
661 def taylor_term(self
, n
, x
, *previous_terms
):
663 return S
.Pi
*S
.ImaginaryUnit
/ 2
664 elif n
< 0 or n
% 2 == 0:
670 class ApplyACoth(Apply
):
672 def _eval_as_leading_term(self
, x
):
673 arg
= self
[0].as_leading_term(x
)
675 if Basic
.Order(1,x
).contains(arg
):
678 return self
.func(arg
)
680 Basic
.singleton
['asinh'] = ASinh
681 Basic
.singleton
['acosh'] = ACosh
682 Basic
.singleton
['atanh'] = ATanh
683 Basic
.singleton
['acoth'] = ACoth