moved Tan -> tan
[sympy.git] / sympy / functions / elementary / hyperbolic.py
blob7b93a2ed0b05585c4c063560b2870d9675e1edf6
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):
11 nofargs = 1
13 def fdiff(self, argindex=1):
14 if argindex == 1:
15 return S.Cosh
16 else:
17 raise ArgumentIndexError(self, argindex)
19 def inverse(self, argindex=1):
20 return S.ASinh
22 def _eval_apply(self, arg):
23 arg = Basic.sympify(arg)
25 if isinstance(arg, Basic.Number):
26 if isinstance(arg, Basic.NaN):
27 return S.NaN
28 elif isinstance(arg, Basic.Infinity):
29 return S.Infinity
30 elif isinstance(arg, Basic.NegativeInfinity):
31 return S.NegativeInfinity
32 elif isinstance(arg, Basic.Zero):
33 return S.Zero
34 elif arg.is_negative:
35 return -self(-arg)
36 else:
37 i_coeff = arg.as_coefficient(S.ImaginaryUnit)
39 if i_coeff is not None:
40 return S.ImaginaryUnit * S.Sin(i_coeff)
41 else:
42 coeff, terms = arg.as_coeff_terms()
44 if coeff.is_negative:
45 return -self(-arg)
47 def _eval_apply_evalf(self, arg):
48 arg = arg.evalf()
50 if isinstance(arg, Basic.Number):
51 return arg.sinh()
53 @cache_it_immutable
54 def taylor_term(self, n, x, *previous_terms):
55 if n < 0 or n % 2 == 0:
56 return S.Zero
57 else:
58 x = Basic.sympify(x)
60 if len(previous_terms) > 2:
61 p = previous_terms[-2]
62 return p * x**2 / (n*(n-1))
63 else:
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):
72 if self[0].is_real:
73 return self
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):
95 return S.One
96 else:
97 return self.func(arg)
99 def _eval_is_real(self):
100 return self[0].is_real
101 def _eval_is_bounded(self):
102 arg = self[0]
103 if arg.is_imaginary:
104 return True
106 class Cosh(DefinedFunction):
108 nofargs = 1
110 def fdiff(self, argindex=1):
111 if argindex == 1:
112 return S.Sinh
113 else:
114 raise ArgumentIndexError(self, argindex)
116 def inverse(self, argindex=1):
117 return S.ACosh
119 def _eval_apply(self, arg):
120 arg = Basic.sympify(arg)
122 if isinstance(arg, Basic.Number):
123 if isinstance(arg, Basic.NaN):
124 return S.NaN
125 elif isinstance(arg, Basic.Infinity):
126 return S.Infinity
127 elif isinstance(arg, Basic.NegativeInfinity):
128 return S.Infinity
129 elif isinstance(arg, Basic.Zero):
130 return S.One
131 elif arg.is_negative:
132 return self(-arg)
133 else:
134 i_coeff = arg.as_coefficient(S.ImaginaryUnit)
136 if i_coeff is not None:
137 return S.Cos(i_coeff)
138 else:
139 coeff, terms = arg.as_coeff_terms()
141 if coeff.is_negative:
142 return self(-arg)
144 def _eval_apply_evalf(self, arg):
145 arg = arg.evalf()
147 if isinstance(arg, Basic.Number):
148 return arg.cosh()
150 @cache_it_immutable
151 def taylor_term(self, n, x, *previous_terms):
152 if n < 0 or n % 2 == 1:
153 return S.Zero
154 else:
155 x = Basic.sympify(x)
157 if len(previous_terms) > 2:
158 p = previous_terms[-2]
159 return p * x**2 / (n*(n-1))
160 else:
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):
168 if self[0].is_real:
169 return self
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):
191 return S.One
192 else:
193 return self.func(arg)
195 def _eval_is_real(self):
196 return self[0].is_real
197 def _eval_is_bounded(self):
198 arg = self[0]
199 if arg.is_imaginary:
200 return True
202 class Tanh(DefinedFunction):
204 nofargs = 1
206 def fdiff(self, argindex=1):
207 if argindex == 1:
208 return S.One - S.Tanh**2
209 else:
210 raise ArgumentIndexError(self, argindex)
212 def inverse(self, argindex=1):
213 return S.ATanh
215 def _eval_apply(self, arg):
216 arg = Basic.sympify(arg)
218 if isinstance(arg, Basic.Number):
219 if isinstance(arg, Basic.NaN):
220 return S.NaN
221 elif isinstance(arg, Basic.Infinity):
222 return S.One
223 elif isinstance(arg, Basic.NegativeInfinity):
224 return S.NegativeOne
225 elif isinstance(arg, Basic.Zero):
226 return S.Zero
227 elif arg.is_negative:
228 return -self(-arg)
229 else:
230 i_coeff = arg.as_coefficient(S.ImaginaryUnit)
232 if i_coeff is not None:
233 return S.ImaginaryUnit * Basic.tan(i_coeff)
234 else:
235 coeff, terms = arg.as_coeff_terms()
237 if coeff.is_negative:
238 return -self(-arg)
240 def _eval_apply_evalf(self, arg):
241 arg = arg.evalf()
243 if isinstance(arg, Basic.Number):
244 return arg.tanh()
246 @cache_it_immutable
247 def taylor_term(self, n, x, *previous_terms):
248 if n < 0 or n % 2 == 0:
249 return S.Zero
250 else:
251 x = Basic.sympify(x)
253 a = 2**(n+1)
255 B = S.Bernoulli(n+1)
256 F = S.Factorial(n+1)
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):
266 if self[0].is_real:
267 return self
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):
284 return 1/S.Coth(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):
290 return S.One
291 else:
292 return self.func(arg)
294 def _eval_is_real(self):
295 return self[0].is_real
296 def _eval_is_bounded(self):
297 arg = self[0]
298 if arg.is_real:
299 return True
301 class Coth(DefinedFunction):
303 nofargs = 1
305 def fdiff(self, argindex=1):
306 if argindex == 1:
307 return 1/S.Sinh**2
308 else:
309 raise ArgumentIndexError(self, argindex)
311 def inverse(self, argindex=1):
312 return S.ACoth
314 def _eval_apply(self, arg):
315 arg = Basic.sympify(arg)
317 if isinstance(arg, Basic.Number):
318 if isinstance(arg, Basic.NaN):
319 return S.NaN
320 elif isinstance(arg, Basic.Infinity):
321 return S.One
322 elif isinstance(arg, Basic.NegativeInfinity):
323 return S.NegativeOne
324 elif isinstance(arg, Basic.Zero):
325 return S.Zero
326 elif arg.is_negative:
327 return -self(-arg)
328 else:
329 i_coeff = arg.as_coefficient(S.ImaginaryUnit)
331 if i_coeff is not None:
332 return -S.ImaginaryUnit * Basic.cot(i_coeff)
333 else:
334 coeff, terms = arg.as_coeff_terms()
336 if coeff.is_negative:
337 return -self(-arg)
339 def _eval_apply_evalf(self, arg):
340 arg = arg.evalf()
342 if isinstance(arg, Basic.Number):
343 return arg.coth()
345 @cache_it_immutable
346 def taylor_term(self, n, x, *previous_terms):
347 if n == 0:
348 return 1 / Basic.sympify(x)
349 elif n < 0 or n % 2 == 0:
350 return S.Zero
351 else:
352 x = Basic.sympify(x)
354 B = S.Bernoulli(n+1)
355 F = S.Factorial(n+1)
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):
365 if self[0].is_real:
366 return self
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):
383 return 1/S.Tanh(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):
389 return S.One
390 else:
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):
404 nofargs = 1
406 def fdiff(self, argindex=1):
407 if argindex == 1:
408 z = Basic.Symbol('z', dummy=True)
409 return Lambda((1 + z**2)**(-S.Half), z)
410 else:
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):
418 return S.NaN
419 elif isinstance(arg, Basic.Infinity):
420 return S.Infinity
421 elif isinstance(arg, Basic.NegativeInfinity):
422 return S.NegativeInfinity
423 elif isinstance(arg, Basic.Zero):
424 return S.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:
430 return -self(-arg)
431 else:
432 i_coeff = arg.as_coefficient(S.ImaginaryUnit)
434 if i_coeff is not None:
435 return S.ImaginaryUnit * S.ASin(i_coeff)
436 else:
437 coeff, terms = arg.as_coeff_terms()
439 if coeff.is_negative:
440 return -self(-arg)
442 def _eval_apply_evalf(self, arg):
443 arg = arg.evalf()
445 if isinstance(arg, Basic.Number):
446 return arg.asinh()
448 @cache_it_immutable
449 def taylor_term(self, n, x, *previous_terms):
450 if n < 0 or n % 2 == 0:
451 return S.Zero
452 else:
453 x = Basic.sympify(x)
455 if len(previous_terms) > 2:
456 p = previous_terms[-2]
457 return -p * (n-2)**2/(k*(k-1)) * x**2
458 else:
459 k = (n - 1) // 2
461 R = S.RisingFactorial(S.Half, k)
462 F = S.Factorial(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):
472 return arg
473 else:
474 return self.func(arg)
476 class ACosh(DefinedFunction):
478 nofargs = 1
480 def fdiff(self, argindex=1):
481 if argindex == 1:
482 z = Basic.Symbol('z', dummy=True)
483 return Lambda(((z-1)*(z+1))**(-1), z)
484 else:
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):
492 return S.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):
500 return S.Zero
501 elif isinstance(arg, Basic.NegativeOne):
502 return S.Pi*S.ImaginaryUnit
503 else:
504 cst_table = {
505 S.Half : S.Pi/3,
506 -S.Half : 2*S.Pi/3,
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,
515 if arg in cst_table:
516 return cst_table[arg]*S.ImaginaryUnit
518 def _eval_apply_evalf(self, arg):
519 arg = arg.evalf()
521 if isinstance(arg, Basic.Number):
522 return arg.acosh()
524 @cache_it_immutable
525 def taylor_term(self, n, x, *previous_terms):
526 if n == 0:
527 return S.Pi*S.ImaginaryUnit / 2
528 elif n < 0 or n % 2 == 0:
529 return S.Zero
530 else:
531 x = Basic.sympify(x)
533 if len(previous_terms) > 2:
534 p = previous_terms[-2]
535 return p * (n-2)**2/(k*(k-1)) * x**2
536 else:
537 k = (n - 1) // 2
539 R = S.RisingFactorial(S.Half, k)
540 F = S.Factorial(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):
550 return arg
551 else:
552 return self.func(arg)
554 class ATanh(DefinedFunction):
556 nofargs = 1
558 def fdiff(self, argindex=1):
559 if argindex == 1:
560 z = Basic.Symbol('z', dummy=True)
561 return Lambda((z-1)**2, z)
562 else:
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):
570 return S.NaN
571 elif isinstance(arg, Basic.Zero):
572 return S.Zero
573 elif isinstance(arg, Basic.One):
574 return S.Infinity
575 elif isinstance(arg, Basic.NegativeOne):
576 return S.NegativeInfinity
577 elif arg.is_negative:
578 return -self(-arg)
579 else:
580 i_coeff = arg.as_coefficient(S.ImaginaryUnit)
582 if i_coeff is not None:
583 return S.ImaginaryUnit * S.ATan(i_coeff)
584 else:
585 coeff, terms = arg.as_coeff_terms()
587 if coeff.is_negative:
588 return -self(-arg)
590 def _eval_apply_evalf(self, arg):
591 arg = arg.evalf()
593 if isinstance(arg, Basic.Number):
594 return arg.atanh()
596 @cache_it_immutable
597 def taylor_term(self, n, x, *previous_terms):
598 if n < 0 or n % 2 == 0:
599 return S.Zero
600 else:
601 x = Basic.sympify(x)
602 return x**n / n
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):
610 return arg
611 else:
612 return self.func(arg)
614 class ACoth(DefinedFunction):
616 nofargs = 1
618 def fdiff(self, argindex=1):
619 if argindex == 1:
620 z = Basic.Symbol('z', dummy=True)
621 return Lambda((z-1)**2, z)
622 else:
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):
630 return S.NaN
631 elif isinstance(arg, Basic.Infinity):
632 return S.Zero
633 elif isinstance(arg, Basic.NegativeInfinity):
634 return S.Zero
635 elif isinstance(arg, Basic.Zero):
636 return S.Pi*S.ImaginaryUnit / 2
637 elif isinstance(arg, Basic.One):
638 return S.Infinity
639 elif isinstance(arg, Basic.NegativeOne):
640 return S.NegativeInfinity
641 elif arg.is_negative:
642 return -self(-arg)
643 else:
644 i_coeff = arg.as_coefficient(S.ImaginaryUnit)
646 if i_coeff is not None:
647 return -S.ImaginaryUnit * S.ACot(i_coeff)
648 else:
649 coeff, terms = arg.as_coeff_terms()
651 if coeff.is_negative:
652 return -self(-arg)
654 def _eval_apply_evalf(self, arg):
655 arg = arg.evalf()
657 if isinstance(arg, Basic.Number):
658 return arg.acoth()
660 @cache_it_immutable
661 def taylor_term(self, n, x, *previous_terms):
662 if n == 0:
663 return S.Pi*S.ImaginaryUnit / 2
664 elif n < 0 or n % 2 == 0:
665 return S.Zero
666 else:
667 x = Basic.sympify(x)
668 return x**n / n
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):
676 return arg
677 else:
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