]> www.ginac.de Git - ginac.git/blob - ginac/inifcns_trans.cpp
d4ec2d67343f6906275a44fbc0cded506a1e0f54
[ginac.git] / ginac / inifcns_trans.cpp
1 /** @file inifcns_trans.cpp
2  *
3  *  Implementation of transcendental (and trigonometric and hyperbolic)
4  *  functions. */
5
6 /*
7  *  GiNaC Copyright (C) 1999-2020 Johannes Gutenberg University Mainz, Germany
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  */
23
24 #include "inifcns.h"
25 #include "ex.h"
26 #include "constant.h"
27 #include "add.h"
28 #include "mul.h"
29 #include "numeric.h"
30 #include "power.h"
31 #include "operators.h"
32 #include "relational.h"
33 #include "symbol.h"
34 #include "pseries.h"
35 #include "utils.h"
36
37 #include <stdexcept>
38 #include <vector>
39
40 namespace GiNaC {
41
42 //////////
43 // exponential function
44 //////////
45
46 static ex exp_evalf(const ex & x)
47 {
48         if (is_exactly_a<numeric>(x))
49                 return exp(ex_to<numeric>(x));
50         
51         return exp(x).hold();
52 }
53
54 static ex exp_eval(const ex & x)
55 {
56         // exp(0) -> 1
57         if (x.is_zero()) {
58                 return _ex1;
59         }
60
61         // exp(n*Pi*I/2) -> {+1|+I|-1|-I}
62         const ex TwoExOverPiI=(_ex2*x)/(Pi*I);
63         if (TwoExOverPiI.info(info_flags::integer)) {
64                 const numeric z = mod(ex_to<numeric>(TwoExOverPiI),*_num4_p);
65                 if (z.is_equal(*_num0_p))
66                         return _ex1;
67                 if (z.is_equal(*_num1_p))
68                         return ex(I);
69                 if (z.is_equal(*_num2_p))
70                         return _ex_1;
71                 if (z.is_equal(*_num3_p))
72                         return ex(-I);
73         }
74
75         // exp(log(x)) -> x
76         if (is_ex_the_function(x, log))
77                 return x.op(0);
78         
79         // exp(float) -> float
80         if (x.info(info_flags::numeric) && !x.info(info_flags::crational))
81                 return exp(ex_to<numeric>(x));
82         
83         return exp(x).hold();
84 }
85
86 static ex exp_expand(const ex & arg, unsigned options)
87 {
88         ex exp_arg;
89         if (options & expand_options::expand_function_args)
90                 exp_arg = arg.expand(options);
91         else
92                 exp_arg=arg;
93
94         if ((options & expand_options::expand_transcendental)
95                 && is_exactly_a<add>(exp_arg)) {
96                 exvector prodseq;
97                 prodseq.reserve(exp_arg.nops());
98                 for (const_iterator i = exp_arg.begin(); i != exp_arg.end(); ++i)
99                         prodseq.push_back(exp(*i));
100
101                 return dynallocate<mul>(prodseq).setflag(status_flags::expanded);
102         }
103
104         return exp(exp_arg).hold();
105 }
106
107 static ex exp_deriv(const ex & x, unsigned deriv_param)
108 {
109         GINAC_ASSERT(deriv_param==0);
110
111         // d/dx exp(x) -> exp(x)
112         return exp(x);
113 }
114
115 static ex exp_real_part(const ex & x)
116 {
117         return exp(GiNaC::real_part(x))*cos(GiNaC::imag_part(x));
118 }
119
120 static ex exp_imag_part(const ex & x)
121 {
122         return exp(GiNaC::real_part(x))*sin(GiNaC::imag_part(x));
123 }
124
125 static ex exp_conjugate(const ex & x)
126 {
127         // conjugate(exp(x))==exp(conjugate(x))
128         return exp(x.conjugate());
129 }
130
131 REGISTER_FUNCTION(exp, eval_func(exp_eval).
132                        evalf_func(exp_evalf).
133                        expand_func(exp_expand).
134                        derivative_func(exp_deriv).
135                        real_part_func(exp_real_part).
136                        imag_part_func(exp_imag_part).
137                        conjugate_func(exp_conjugate).
138                        latex_name("\\exp"));
139
140 //////////
141 // natural logarithm
142 //////////
143
144 static ex log_evalf(const ex & x)
145 {
146         if (is_exactly_a<numeric>(x))
147                 return log(ex_to<numeric>(x));
148         
149         return log(x).hold();
150 }
151
152 static ex log_eval(const ex & x)
153 {
154         if (x.info(info_flags::numeric)) {
155                 if (x.is_zero())         // log(0) -> infinity
156                         throw(pole_error("log_eval(): log(0)",0));
157                 if (x.info(info_flags::rational) && x.info(info_flags::negative))
158                         return (log(-x)+I*Pi);
159                 if (x.is_equal(_ex1))  // log(1) -> 0
160                         return _ex0;
161                 if (x.is_equal(I))       // log(I) -> Pi*I/2
162                         return (Pi*I*_ex1_2);
163                 if (x.is_equal(-I))      // log(-I) -> -Pi*I/2
164                         return (Pi*I*_ex_1_2);
165
166                 // log(float) -> float
167                 if (!x.info(info_flags::crational))
168                         return log(ex_to<numeric>(x));
169         }
170
171         // log(exp(t)) -> t (if -Pi < t.imag() <= Pi):
172         if (is_ex_the_function(x, exp)) {
173                 const ex &t = x.op(0);
174                 if (t.info(info_flags::real))
175                         return t;
176         }
177
178         return log(x).hold();
179 }
180
181 static ex log_deriv(const ex & x, unsigned deriv_param)
182 {
183         GINAC_ASSERT(deriv_param==0);
184         
185         // d/dx log(x) -> 1/x
186         return power(x, _ex_1);
187 }
188
189 static ex log_series(const ex &arg,
190                      const relational &rel,
191                      int order,
192                      unsigned options)
193 {
194         GINAC_ASSERT(is_a<symbol>(rel.lhs()));
195         ex arg_pt;
196         bool must_expand_arg = false;
197         // maybe substitution of rel into arg fails because of a pole
198         try {
199                 arg_pt = arg.subs(rel, subs_options::no_pattern);
200         } catch (pole_error) {
201                 must_expand_arg = true;
202         }
203         // or we are at the branch point anyways
204         if (arg_pt.is_zero())
205                 must_expand_arg = true;
206         
207         if (arg.diff(ex_to<symbol>(rel.lhs())).is_zero()) {
208                 throw do_taylor();
209         }
210
211         if (must_expand_arg) {
212                 // method:
213                 // This is the branch point: Series expand the argument first, then
214                 // trivially factorize it to isolate that part which has constant
215                 // leading coefficient in this fashion:
216                 //   x^n + x^(n+1) +...+ Order(x^(n+m))  ->  x^n * (1 + x +...+ Order(x^m)).
217                 // Return a plain n*log(x) for the x^n part and series expand the
218                 // other part.  Add them together and reexpand again in order to have
219                 // one unnested pseries object.  All this also works for negative n.
220                 pseries argser;          // series expansion of log's argument
221                 unsigned extra_ord = 0;  // extra expansion order
222                 do {
223                         // oops, the argument expanded to a pure Order(x^something)...
224                         argser = ex_to<pseries>(arg.series(rel, order+extra_ord, options));
225                         ++extra_ord;
226                 } while (!argser.is_terminating() && argser.nops()==1);
227
228                 const symbol &s = ex_to<symbol>(rel.lhs());
229                 const ex &point = rel.rhs();
230                 const int n = argser.ldegree(s);
231                 epvector seq;
232                 // construct what we carelessly called the n*log(x) term above
233                 const ex coeff = argser.coeff(s, n);
234                 // expand the log, but only if coeff is real and > 0, since otherwise
235                 // it would make the branch cut run into the wrong direction
236                 if (coeff.info(info_flags::positive))
237                         seq.push_back(expair(n*log(s-point)+log(coeff), _ex0));
238                 else
239                         seq.push_back(expair(log(coeff*pow(s-point, n)), _ex0));
240
241                 if (!argser.is_terminating() || argser.nops()!=1) {
242                         // in this case n more (or less) terms are needed
243                         // (sadly, to generate them, we have to start from the beginning)
244                         if (n == 0 && coeff == 1) {
245                                 ex rest = pseries(rel, epvector{expair(-1, _ex0), expair(Order(_ex1), order)}).add_series(argser);
246                                 ex acc = dynallocate<pseries>(rel, epvector());
247                                 for (int i = order-1; i>0; --i) {
248                                         epvector cterm { expair(i%2 ? _ex1/i : _ex_1/i, _ex0) };
249                                         acc = pseries(rel, std::move(cterm)).add_series(ex_to<pseries>(acc));
250                                         acc = (ex_to<pseries>(rest)).mul_series(ex_to<pseries>(acc));
251                                 }
252                                 return acc;
253                         }
254                         const ex newarg = ex_to<pseries>((arg/coeff).series(rel, order+n, options)).shift_exponents(-n).convert_to_poly(true);
255                         return pseries(rel, std::move(seq)).add_series(ex_to<pseries>(log(newarg).series(rel, order, options)));
256                 } else  // it was a monomial
257                         return pseries(rel, std::move(seq));
258         }
259         if (!(options & series_options::suppress_branchcut) &&
260              arg_pt.info(info_flags::negative)) {
261                 // method:
262                 // This is the branch cut: assemble the primitive series manually and
263                 // then add the corresponding complex step function.
264                 const symbol &s = ex_to<symbol>(rel.lhs());
265                 const ex &point = rel.rhs();
266                 const symbol foo;
267                 const ex replarg = series(log(arg), s==foo, order).subs(foo==point, subs_options::no_pattern);
268                 epvector seq;
269                 if (order > 0) {
270                         seq.reserve(2);
271                         seq.push_back(expair(-I*csgn(arg*I)*Pi, _ex0));
272                 }
273                 seq.push_back(expair(Order(_ex1), order));
274                 return series(replarg - I*Pi + pseries(rel, std::move(seq)), rel, order);
275         }
276         throw do_taylor();  // caught by function::series()
277 }
278
279 static ex log_real_part(const ex & x)
280 {
281         if (x.info(info_flags::nonnegative))
282                 return log(x).hold();
283         return log(abs(x));
284 }
285
286 static ex log_imag_part(const ex & x)
287 {
288         if (x.info(info_flags::nonnegative))
289                 return 0;
290         return atan2(GiNaC::imag_part(x), GiNaC::real_part(x));
291 }
292
293 static ex log_expand(const ex & arg, unsigned options)
294 {
295         if ((options & expand_options::expand_transcendental)
296                 && is_exactly_a<mul>(arg) && !arg.info(info_flags::indefinite)) {
297                 exvector sumseq;
298                 exvector prodseq;
299                 sumseq.reserve(arg.nops());
300                 prodseq.reserve(arg.nops());
301                 bool possign=true;
302
303                 // searching for positive/negative factors
304                 for (const_iterator i = arg.begin(); i != arg.end(); ++i) {
305                         ex e;
306                         if (options & expand_options::expand_function_args)
307                                 e=i->expand(options);
308                         else
309                                 e=*i;
310                         if (e.info(info_flags::positive))
311                                 sumseq.push_back(log(e));
312                         else if (e.info(info_flags::negative)) {
313                                 sumseq.push_back(log(-e));
314                                 possign = !possign;
315                         } else
316                                 prodseq.push_back(e);
317                 }
318
319                 if (sumseq.size() > 0) {
320                         ex newarg;
321                         if (options & expand_options::expand_function_args)
322                                 newarg=((possign?_ex1:_ex_1)*mul(prodseq)).expand(options);
323                         else {
324                                 newarg=(possign?_ex1:_ex_1)*mul(prodseq);
325                                 ex_to<basic>(newarg).setflag(status_flags::purely_indefinite);
326                         }
327                         return add(sumseq)+log(newarg);
328                 } else {
329                         if (!(options & expand_options::expand_function_args))
330                                 ex_to<basic>(arg).setflag(status_flags::purely_indefinite);
331                 }
332         }
333
334         if (options & expand_options::expand_function_args)
335                 return log(arg.expand(options)).hold();
336         else
337                 return log(arg).hold();
338 }
339
340 static ex log_conjugate(const ex & x)
341 {
342         // conjugate(log(x))==log(conjugate(x)) unless on the branch cut which
343         // runs along the negative real axis.
344         if (x.info(info_flags::positive)) {
345                 return log(x);
346         }
347         if (is_exactly_a<numeric>(x) &&
348             !x.imag_part().is_zero()) {
349                 return log(x.conjugate());
350         }
351         return conjugate_function(log(x)).hold();
352 }
353
354 REGISTER_FUNCTION(log, eval_func(log_eval).
355                        evalf_func(log_evalf).
356                        expand_func(log_expand).
357                        derivative_func(log_deriv).
358                        series_func(log_series).
359                        real_part_func(log_real_part).
360                        imag_part_func(log_imag_part).
361                        conjugate_func(log_conjugate).
362                        latex_name("\\ln"));
363
364 //////////
365 // sine (trigonometric function)
366 //////////
367
368 static ex sin_evalf(const ex & x)
369 {
370         if (is_exactly_a<numeric>(x))
371                 return sin(ex_to<numeric>(x));
372         
373         return sin(x).hold();
374 }
375
376 static ex sin_eval(const ex & x)
377 {
378         // sin(n/d*Pi) -> { all known non-nested radicals }
379         const ex SixtyExOverPi = _ex60*x/Pi;
380         ex sign = _ex1;
381         if (SixtyExOverPi.info(info_flags::integer)) {
382                 numeric z = mod(ex_to<numeric>(SixtyExOverPi),*_num120_p);
383                 if (z>=*_num60_p) {
384                         // wrap to interval [0, Pi)
385                         z -= *_num60_p;
386                         sign = _ex_1;
387                 }
388                 if (z>*_num30_p) {
389                         // wrap to interval [0, Pi/2)
390                         z = *_num60_p-z;
391                 }
392                 if (z.is_equal(*_num0_p))  // sin(0)       -> 0
393                         return _ex0;
394                 if (z.is_equal(*_num5_p))  // sin(Pi/12)   -> sqrt(6)/4*(1-sqrt(3)/3)
395                         return sign*_ex1_4*sqrt(_ex6)*(_ex1+_ex_1_3*sqrt(_ex3));
396                 if (z.is_equal(*_num6_p))  // sin(Pi/10)   -> sqrt(5)/4-1/4
397                         return sign*(_ex1_4*sqrt(_ex5)+_ex_1_4);
398                 if (z.is_equal(*_num10_p)) // sin(Pi/6)    -> 1/2
399                         return sign*_ex1_2;
400                 if (z.is_equal(*_num15_p)) // sin(Pi/4)    -> sqrt(2)/2
401                         return sign*_ex1_2*sqrt(_ex2);
402                 if (z.is_equal(*_num18_p)) // sin(3/10*Pi) -> sqrt(5)/4+1/4
403                         return sign*(_ex1_4*sqrt(_ex5)+_ex1_4);
404                 if (z.is_equal(*_num20_p)) // sin(Pi/3)    -> sqrt(3)/2
405                         return sign*_ex1_2*sqrt(_ex3);
406                 if (z.is_equal(*_num25_p)) // sin(5/12*Pi) -> sqrt(6)/4*(1+sqrt(3)/3)
407                         return sign*_ex1_4*sqrt(_ex6)*(_ex1+_ex1_3*sqrt(_ex3));
408                 if (z.is_equal(*_num30_p)) // sin(Pi/2)    -> 1
409                         return sign;
410         }
411
412         if (is_exactly_a<function>(x)) {
413                 const ex &t = x.op(0);
414
415                 // sin(asin(x)) -> x
416                 if (is_ex_the_function(x, asin))
417                         return t;
418
419                 // sin(acos(x)) -> sqrt(1-x^2)
420                 if (is_ex_the_function(x, acos))
421                         return sqrt(_ex1-power(t,_ex2));
422
423                 // sin(atan(x)) -> x/sqrt(1+x^2)
424                 if (is_ex_the_function(x, atan))
425                         return t*power(_ex1+power(t,_ex2),_ex_1_2);
426         }
427         
428         // sin(float) -> float
429         if (x.info(info_flags::numeric) && !x.info(info_flags::crational))
430                 return sin(ex_to<numeric>(x));
431
432         // sin() is odd
433         if (x.info(info_flags::negative))
434                 return -sin(-x);
435         
436         return sin(x).hold();
437 }
438
439 static ex sin_deriv(const ex & x, unsigned deriv_param)
440 {
441         GINAC_ASSERT(deriv_param==0);
442         
443         // d/dx sin(x) -> cos(x)
444         return cos(x);
445 }
446
447 static ex sin_real_part(const ex & x)
448 {
449         return cosh(GiNaC::imag_part(x))*sin(GiNaC::real_part(x));
450 }
451
452 static ex sin_imag_part(const ex & x)
453 {
454         return sinh(GiNaC::imag_part(x))*cos(GiNaC::real_part(x));
455 }
456
457 static ex sin_conjugate(const ex & x)
458 {
459         // conjugate(sin(x))==sin(conjugate(x))
460         return sin(x.conjugate());
461 }
462
463 REGISTER_FUNCTION(sin, eval_func(sin_eval).
464                        evalf_func(sin_evalf).
465                        derivative_func(sin_deriv).
466                        real_part_func(sin_real_part).
467                        imag_part_func(sin_imag_part).
468                        conjugate_func(sin_conjugate).
469                        latex_name("\\sin"));
470
471 //////////
472 // cosine (trigonometric function)
473 //////////
474
475 static ex cos_evalf(const ex & x)
476 {
477         if (is_exactly_a<numeric>(x))
478                 return cos(ex_to<numeric>(x));
479         
480         return cos(x).hold();
481 }
482
483 static ex cos_eval(const ex & x)
484 {
485         // cos(n/d*Pi) -> { all known non-nested radicals }
486         const ex SixtyExOverPi = _ex60*x/Pi;
487         ex sign = _ex1;
488         if (SixtyExOverPi.info(info_flags::integer)) {
489                 numeric z = mod(ex_to<numeric>(SixtyExOverPi),*_num120_p);
490                 if (z>=*_num60_p) {
491                         // wrap to interval [0, Pi)
492                         z = *_num120_p-z;
493                 }
494                 if (z>=*_num30_p) {
495                         // wrap to interval [0, Pi/2)
496                         z = *_num60_p-z;
497                         sign = _ex_1;
498                 }
499                 if (z.is_equal(*_num0_p))  // cos(0)       -> 1
500                         return sign;
501                 if (z.is_equal(*_num5_p))  // cos(Pi/12)   -> sqrt(6)/4*(1+sqrt(3)/3)
502                         return sign*_ex1_4*sqrt(_ex6)*(_ex1+_ex1_3*sqrt(_ex3));
503                 if (z.is_equal(*_num10_p)) // cos(Pi/6)    -> sqrt(3)/2
504                         return sign*_ex1_2*sqrt(_ex3);
505                 if (z.is_equal(*_num12_p)) // cos(Pi/5)    -> sqrt(5)/4+1/4
506                         return sign*(_ex1_4*sqrt(_ex5)+_ex1_4);
507                 if (z.is_equal(*_num15_p)) // cos(Pi/4)    -> sqrt(2)/2
508                         return sign*_ex1_2*sqrt(_ex2);
509                 if (z.is_equal(*_num20_p)) // cos(Pi/3)    -> 1/2
510                         return sign*_ex1_2;
511                 if (z.is_equal(*_num24_p)) // cos(2/5*Pi)  -> sqrt(5)/4-1/4x
512                         return sign*(_ex1_4*sqrt(_ex5)+_ex_1_4);
513                 if (z.is_equal(*_num25_p)) // cos(5/12*Pi) -> sqrt(6)/4*(1-sqrt(3)/3)
514                         return sign*_ex1_4*sqrt(_ex6)*(_ex1+_ex_1_3*sqrt(_ex3));
515                 if (z.is_equal(*_num30_p)) // cos(Pi/2)    -> 0
516                         return _ex0;
517         }
518
519         if (is_exactly_a<function>(x)) {
520                 const ex &t = x.op(0);
521
522                 // cos(acos(x)) -> x
523                 if (is_ex_the_function(x, acos))
524                         return t;
525
526                 // cos(asin(x)) -> sqrt(1-x^2)
527                 if (is_ex_the_function(x, asin))
528                         return sqrt(_ex1-power(t,_ex2));
529
530                 // cos(atan(x)) -> 1/sqrt(1+x^2)
531                 if (is_ex_the_function(x, atan))
532                         return power(_ex1+power(t,_ex2),_ex_1_2);
533         }
534         
535         // cos(float) -> float
536         if (x.info(info_flags::numeric) && !x.info(info_flags::crational))
537                 return cos(ex_to<numeric>(x));
538         
539         // cos() is even
540         if (x.info(info_flags::negative))
541                 return cos(-x);
542         
543         return cos(x).hold();
544 }
545
546 static ex cos_deriv(const ex & x, unsigned deriv_param)
547 {
548         GINAC_ASSERT(deriv_param==0);
549
550         // d/dx cos(x) -> -sin(x)
551         return -sin(x);
552 }
553
554 static ex cos_real_part(const ex & x)
555 {
556         return cosh(GiNaC::imag_part(x))*cos(GiNaC::real_part(x));
557 }
558
559 static ex cos_imag_part(const ex & x)
560 {
561         return -sinh(GiNaC::imag_part(x))*sin(GiNaC::real_part(x));
562 }
563
564 static ex cos_conjugate(const ex & x)
565 {
566         // conjugate(cos(x))==cos(conjugate(x))
567         return cos(x.conjugate());
568 }
569
570 REGISTER_FUNCTION(cos, eval_func(cos_eval).
571                        evalf_func(cos_evalf).
572                        derivative_func(cos_deriv).
573                        real_part_func(cos_real_part).
574                        imag_part_func(cos_imag_part).
575                        conjugate_func(cos_conjugate).
576                        latex_name("\\cos"));
577
578 //////////
579 // tangent (trigonometric function)
580 //////////
581
582 static ex tan_evalf(const ex & x)
583 {
584         if (is_exactly_a<numeric>(x))
585                 return tan(ex_to<numeric>(x));
586         
587         return tan(x).hold();
588 }
589
590 static ex tan_eval(const ex & x)
591 {
592         // tan(n/d*Pi) -> { all known non-nested radicals }
593         const ex SixtyExOverPi = _ex60*x/Pi;
594         ex sign = _ex1;
595         if (SixtyExOverPi.info(info_flags::integer)) {
596                 numeric z = mod(ex_to<numeric>(SixtyExOverPi),*_num60_p);
597                 if (z>=*_num60_p) {
598                         // wrap to interval [0, Pi)
599                         z -= *_num60_p;
600                 }
601                 if (z>=*_num30_p) {
602                         // wrap to interval [0, Pi/2)
603                         z = *_num60_p-z;
604                         sign = _ex_1;
605                 }
606                 if (z.is_equal(*_num0_p))  // tan(0)       -> 0
607                         return _ex0;
608                 if (z.is_equal(*_num5_p))  // tan(Pi/12)   -> 2-sqrt(3)
609                         return sign*(_ex2-sqrt(_ex3));
610                 if (z.is_equal(*_num10_p)) // tan(Pi/6)    -> sqrt(3)/3
611                         return sign*_ex1_3*sqrt(_ex3);
612                 if (z.is_equal(*_num15_p)) // tan(Pi/4)    -> 1
613                         return sign;
614                 if (z.is_equal(*_num20_p)) // tan(Pi/3)    -> sqrt(3)
615                         return sign*sqrt(_ex3);
616                 if (z.is_equal(*_num25_p)) // tan(5/12*Pi) -> 2+sqrt(3)
617                         return sign*(sqrt(_ex3)+_ex2);
618                 if (z.is_equal(*_num30_p)) // tan(Pi/2)    -> infinity
619                         throw (pole_error("tan_eval(): simple pole",1));
620         }
621
622         if (is_exactly_a<function>(x)) {
623                 const ex &t = x.op(0);
624
625                 // tan(atan(x)) -> x
626                 if (is_ex_the_function(x, atan))
627                         return t;
628
629                 // tan(asin(x)) -> x/sqrt(1+x^2)
630                 if (is_ex_the_function(x, asin))
631                         return t*power(_ex1-power(t,_ex2),_ex_1_2);
632
633                 // tan(acos(x)) -> sqrt(1-x^2)/x
634                 if (is_ex_the_function(x, acos))
635                         return power(t,_ex_1)*sqrt(_ex1-power(t,_ex2));
636         }
637         
638         // tan(float) -> float
639         if (x.info(info_flags::numeric) && !x.info(info_flags::crational)) {
640                 return tan(ex_to<numeric>(x));
641         }
642         
643         // tan() is odd
644         if (x.info(info_flags::negative))
645                 return -tan(-x);
646         
647         return tan(x).hold();
648 }
649
650 static ex tan_deriv(const ex & x, unsigned deriv_param)
651 {
652         GINAC_ASSERT(deriv_param==0);
653         
654         // d/dx tan(x) -> 1+tan(x)^2;
655         return (_ex1+power(tan(x),_ex2));
656 }
657
658 static ex tan_real_part(const ex & x)
659 {
660         ex a = GiNaC::real_part(x);
661         ex b = GiNaC::imag_part(x);
662         return tan(a)/(1+power(tan(a),2)*power(tan(b),2));
663 }
664
665 static ex tan_imag_part(const ex & x)
666 {
667         ex a = GiNaC::real_part(x);
668         ex b = GiNaC::imag_part(x);
669         return tanh(b)/(1+power(tan(a),2)*power(tan(b),2));
670 }
671
672 static ex tan_series(const ex &x,
673                      const relational &rel,
674                      int order,
675                      unsigned options)
676 {
677         GINAC_ASSERT(is_a<symbol>(rel.lhs()));
678         // method:
679         // Taylor series where there is no pole falls back to tan_deriv.
680         // On a pole simply expand sin(x)/cos(x).
681         const ex x_pt = x.subs(rel, subs_options::no_pattern);
682         if (!(2*x_pt/Pi).info(info_flags::odd))
683                 throw do_taylor();  // caught by function::series()
684         // if we got here we have to care for a simple pole
685         return (sin(x)/cos(x)).series(rel, order, options);
686 }
687
688 static ex tan_conjugate(const ex & x)
689 {
690         // conjugate(tan(x))==tan(conjugate(x))
691         return tan(x.conjugate());
692 }
693
694 REGISTER_FUNCTION(tan, eval_func(tan_eval).
695                        evalf_func(tan_evalf).
696                        derivative_func(tan_deriv).
697                        series_func(tan_series).
698                        real_part_func(tan_real_part).
699                        imag_part_func(tan_imag_part).
700                        conjugate_func(tan_conjugate).
701                        latex_name("\\tan"));
702
703 //////////
704 // inverse sine (arc sine)
705 //////////
706
707 static ex asin_evalf(const ex & x)
708 {
709         if (is_exactly_a<numeric>(x))
710                 return asin(ex_to<numeric>(x));
711         
712         return asin(x).hold();
713 }
714
715 static ex asin_eval(const ex & x)
716 {
717         if (x.info(info_flags::numeric)) {
718
719                 // asin(0) -> 0
720                 if (x.is_zero())
721                         return x;
722
723                 // asin(1/2) -> Pi/6
724                 if (x.is_equal(_ex1_2))
725                         return numeric(1,6)*Pi;
726
727                 // asin(1) -> Pi/2
728                 if (x.is_equal(_ex1))
729                         return _ex1_2*Pi;
730
731                 // asin(-1/2) -> -Pi/6
732                 if (x.is_equal(_ex_1_2))
733                         return numeric(-1,6)*Pi;
734
735                 // asin(-1) -> -Pi/2
736                 if (x.is_equal(_ex_1))
737                         return _ex_1_2*Pi;
738
739                 // asin(float) -> float
740                 if (!x.info(info_flags::crational))
741                         return asin(ex_to<numeric>(x));
742
743                 // asin() is odd
744                 if (x.info(info_flags::negative))
745                         return -asin(-x);
746         }
747         
748         return asin(x).hold();
749 }
750
751 static ex asin_deriv(const ex & x, unsigned deriv_param)
752 {
753         GINAC_ASSERT(deriv_param==0);
754         
755         // d/dx asin(x) -> 1/sqrt(1-x^2)
756         return power(1-power(x,_ex2),_ex_1_2);
757 }
758
759 static ex asin_conjugate(const ex & x)
760 {
761         // conjugate(asin(x))==asin(conjugate(x)) unless on the branch cuts which
762         // run along the real axis outside the interval [-1, +1].
763         if (is_exactly_a<numeric>(x) &&
764             (!x.imag_part().is_zero() || (x > *_num_1_p && x < *_num1_p))) {
765                 return asin(x.conjugate());
766         }
767         return conjugate_function(asin(x)).hold();
768 }
769
770 REGISTER_FUNCTION(asin, eval_func(asin_eval).
771                         evalf_func(asin_evalf).
772                         derivative_func(asin_deriv).
773                         conjugate_func(asin_conjugate).
774                         latex_name("\\arcsin"));
775
776 //////////
777 // inverse cosine (arc cosine)
778 //////////
779
780 static ex acos_evalf(const ex & x)
781 {
782         if (is_exactly_a<numeric>(x))
783                 return acos(ex_to<numeric>(x));
784         
785         return acos(x).hold();
786 }
787
788 static ex acos_eval(const ex & x)
789 {
790         if (x.info(info_flags::numeric)) {
791
792                 // acos(1) -> 0
793                 if (x.is_equal(_ex1))
794                         return _ex0;
795
796                 // acos(1/2) -> Pi/3
797                 if (x.is_equal(_ex1_2))
798                         return _ex1_3*Pi;
799
800                 // acos(0) -> Pi/2
801                 if (x.is_zero())
802                         return _ex1_2*Pi;
803
804                 // acos(-1/2) -> 2/3*Pi
805                 if (x.is_equal(_ex_1_2))
806                         return numeric(2,3)*Pi;
807
808                 // acos(-1) -> Pi
809                 if (x.is_equal(_ex_1))
810                         return Pi;
811
812                 // acos(float) -> float
813                 if (!x.info(info_flags::crational))
814                         return acos(ex_to<numeric>(x));
815
816                 // acos(-x) -> Pi-acos(x)
817                 if (x.info(info_flags::negative))
818                         return Pi-acos(-x);
819         }
820         
821         return acos(x).hold();
822 }
823
824 static ex acos_deriv(const ex & x, unsigned deriv_param)
825 {
826         GINAC_ASSERT(deriv_param==0);
827         
828         // d/dx acos(x) -> -1/sqrt(1-x^2)
829         return -power(1-power(x,_ex2),_ex_1_2);
830 }
831
832 static ex acos_conjugate(const ex & x)
833 {
834         // conjugate(acos(x))==acos(conjugate(x)) unless on the branch cuts which
835         // run along the real axis outside the interval [-1, +1].
836         if (is_exactly_a<numeric>(x) &&
837             (!x.imag_part().is_zero() || (x > *_num_1_p && x < *_num1_p))) {
838                 return acos(x.conjugate());
839         }
840         return conjugate_function(acos(x)).hold();
841 }
842
843 REGISTER_FUNCTION(acos, eval_func(acos_eval).
844                         evalf_func(acos_evalf).
845                         derivative_func(acos_deriv).
846                         conjugate_func(acos_conjugate).
847                         latex_name("\\arccos"));
848
849 //////////
850 // inverse tangent (arc tangent)
851 //////////
852
853 static ex atan_evalf(const ex & x)
854 {
855         if (is_exactly_a<numeric>(x))
856                 return atan(ex_to<numeric>(x));
857         
858         return atan(x).hold();
859 }
860
861 static ex atan_eval(const ex & x)
862 {
863         if (x.info(info_flags::numeric)) {
864
865                 // atan(0) -> 0
866                 if (x.is_zero())
867                         return _ex0;
868
869                 // atan(1) -> Pi/4
870                 if (x.is_equal(_ex1))
871                         return _ex1_4*Pi;
872
873                 // atan(-1) -> -Pi/4
874                 if (x.is_equal(_ex_1))
875                         return _ex_1_4*Pi;
876
877                 if (x.is_equal(I) || x.is_equal(-I))
878                         throw (pole_error("atan_eval(): logarithmic pole",0));
879
880                 // atan(float) -> float
881                 if (!x.info(info_flags::crational))
882                         return atan(ex_to<numeric>(x));
883
884                 // atan() is odd
885                 if (x.info(info_flags::negative))
886                         return -atan(-x);
887         }
888         
889         return atan(x).hold();
890 }
891
892 static ex atan_deriv(const ex & x, unsigned deriv_param)
893 {
894         GINAC_ASSERT(deriv_param==0);
895
896         // d/dx atan(x) -> 1/(1+x^2)
897         return power(_ex1+power(x,_ex2), _ex_1);
898 }
899
900 static ex atan_series(const ex &arg,
901                       const relational &rel,
902                       int order,
903                       unsigned options)
904 {
905         GINAC_ASSERT(is_a<symbol>(rel.lhs()));
906         // method:
907         // Taylor series where there is no pole or cut falls back to atan_deriv.
908         // There are two branch cuts, one runnig from I up the imaginary axis and
909         // one running from -I down the imaginary axis.  The points I and -I are
910         // poles.
911         // On the branch cuts and the poles series expand
912         //     (log(1+I*x)-log(1-I*x))/(2*I)
913         // instead.
914         const ex arg_pt = arg.subs(rel, subs_options::no_pattern);
915         if (!(I*arg_pt).info(info_flags::real))
916                 throw do_taylor();     // Re(x) != 0
917         if ((I*arg_pt).info(info_flags::real) && abs(I*arg_pt)<_ex1)
918                 throw do_taylor();     // Re(x) == 0, but abs(x)<1
919         // care for the poles, using the defining formula for atan()...
920         if (arg_pt.is_equal(I) || arg_pt.is_equal(-I))
921                 return ((log(1+I*arg)-log(1-I*arg))/(2*I)).series(rel, order, options);
922         if (!(options & series_options::suppress_branchcut)) {
923                 // method:
924                 // This is the branch cut: assemble the primitive series manually and
925                 // then add the corresponding complex step function.
926                 const symbol &s = ex_to<symbol>(rel.lhs());
927                 const ex &point = rel.rhs();
928                 const symbol foo;
929                 const ex replarg = series(atan(arg), s==foo, order).subs(foo==point, subs_options::no_pattern);
930                 ex Order0correction = replarg.op(0)+csgn(arg)*Pi*_ex_1_2;
931                 if ((I*arg_pt)<_ex0)
932                         Order0correction += log((I*arg_pt+_ex_1)/(I*arg_pt+_ex1))*I*_ex_1_2;
933                 else
934                         Order0correction += log((I*arg_pt+_ex1)/(I*arg_pt+_ex_1))*I*_ex1_2;
935                 epvector seq;
936                 if (order > 0) {
937                         seq.reserve(2);
938                         seq.push_back(expair(Order0correction, _ex0));
939                 }
940                 seq.push_back(expair(Order(_ex1), order));
941                 return series(replarg - pseries(rel, std::move(seq)), rel, order);
942         }
943         throw do_taylor();
944 }
945
946 static ex atan_conjugate(const ex & x)
947 {
948         // conjugate(atan(x))==atan(conjugate(x)) unless on the branch cuts which
949         // run along the imaginary axis outside the interval [-I, +I].
950         if (x.info(info_flags::real))
951                 return atan(x);
952         if (is_exactly_a<numeric>(x)) {
953                 const numeric x_re = ex_to<numeric>(x.real_part());
954                 const numeric x_im = ex_to<numeric>(x.imag_part());
955                 if (!x_re.is_zero() ||
956                     (x_im > *_num_1_p && x_im < *_num1_p))
957                         return atan(x.conjugate());
958         }
959         return conjugate_function(atan(x)).hold();
960 }
961
962 REGISTER_FUNCTION(atan, eval_func(atan_eval).
963                         evalf_func(atan_evalf).
964                         derivative_func(atan_deriv).
965                         series_func(atan_series).
966                         conjugate_func(atan_conjugate).
967                         latex_name("\\arctan"));
968
969 //////////
970 // inverse tangent (atan2(y,x))
971 //////////
972
973 static ex atan2_evalf(const ex &y, const ex &x)
974 {
975         if (is_exactly_a<numeric>(y) && is_exactly_a<numeric>(x))
976                 return atan(ex_to<numeric>(y), ex_to<numeric>(x));
977         
978         return atan2(y, x).hold();
979 }
980
981 static ex atan2_eval(const ex & y, const ex & x)
982 {
983         if (y.is_zero()) {
984
985                 // atan2(0, 0) -> 0
986                 if (x.is_zero())
987                         return _ex0;
988
989                 // atan2(0, x), x real and positive -> 0
990                 if (x.info(info_flags::positive))
991                         return _ex0;
992
993                 // atan2(0, x), x real and negative -> Pi
994                 if (x.info(info_flags::negative))
995                         return Pi;
996         }
997
998         if (x.is_zero()) {
999
1000                 // atan2(y, 0), y real and positive -> Pi/2
1001                 if (y.info(info_flags::positive))
1002                         return _ex1_2*Pi;
1003
1004                 // atan2(y, 0), y real and negative -> -Pi/2
1005                 if (y.info(info_flags::negative))
1006                         return _ex_1_2*Pi;
1007         }
1008
1009         if (y.is_equal(x)) {
1010
1011                 // atan2(y, y), y real and positive -> Pi/4
1012                 if (y.info(info_flags::positive))
1013                         return _ex1_4*Pi;
1014
1015                 // atan2(y, y), y real and negative -> -3/4*Pi
1016                 if (y.info(info_flags::negative))
1017                         return numeric(-3, 4)*Pi;
1018         }
1019
1020         if (y.is_equal(-x)) {
1021
1022                 // atan2(y, -y), y real and positive -> 3*Pi/4
1023                 if (y.info(info_flags::positive))
1024                         return numeric(3, 4)*Pi;
1025
1026                 // atan2(y, -y), y real and negative -> -Pi/4
1027                 if (y.info(info_flags::negative))
1028                         return _ex_1_4*Pi;
1029         }
1030
1031         // atan2(float, float) -> float
1032         if (is_a<numeric>(y) && !y.info(info_flags::crational) &&
1033             is_a<numeric>(x) && !x.info(info_flags::crational))
1034                 return atan(ex_to<numeric>(y), ex_to<numeric>(x));
1035
1036         // atan2(real, real) -> atan(y/x) +/- Pi
1037         if (y.info(info_flags::real) && x.info(info_flags::real)) {
1038                 if (x.info(info_flags::positive))
1039                         return atan(y/x);
1040
1041                 if (x.info(info_flags::negative)) {
1042                         if (y.info(info_flags::positive))
1043                                 return atan(y/x)+Pi;
1044                         if (y.info(info_flags::negative))
1045                                 return atan(y/x)-Pi;
1046                 }
1047         }
1048
1049         return atan2(y, x).hold();
1050 }    
1051
1052 static ex atan2_deriv(const ex & y, const ex & x, unsigned deriv_param)
1053 {
1054         GINAC_ASSERT(deriv_param<2);
1055         
1056         if (deriv_param==0) {
1057                 // d/dy atan2(y,x)
1058                 return x*power(power(x,_ex2)+power(y,_ex2),_ex_1);
1059         }
1060         // d/dx atan2(y,x)
1061         return -y*power(power(x,_ex2)+power(y,_ex2),_ex_1);
1062 }
1063
1064 REGISTER_FUNCTION(atan2, eval_func(atan2_eval).
1065                          evalf_func(atan2_evalf).
1066                          derivative_func(atan2_deriv));
1067
1068 //////////
1069 // hyperbolic sine (trigonometric function)
1070 //////////
1071
1072 static ex sinh_evalf(const ex & x)
1073 {
1074         if (is_exactly_a<numeric>(x))
1075                 return sinh(ex_to<numeric>(x));
1076         
1077         return sinh(x).hold();
1078 }
1079
1080 static ex sinh_eval(const ex & x)
1081 {
1082         if (x.info(info_flags::numeric)) {
1083
1084                 // sinh(0) -> 0
1085                 if (x.is_zero())
1086                         return _ex0;        
1087
1088                 // sinh(float) -> float
1089                 if (!x.info(info_flags::crational))
1090                         return sinh(ex_to<numeric>(x));
1091
1092                 // sinh() is odd
1093                 if (x.info(info_flags::negative))
1094                         return -sinh(-x);
1095         }
1096         
1097         if ((x/Pi).info(info_flags::numeric) &&
1098                 ex_to<numeric>(x/Pi).real().is_zero())  // sinh(I*x) -> I*sin(x)
1099                 return I*sin(x/I);
1100         
1101         if (is_exactly_a<function>(x)) {
1102                 const ex &t = x.op(0);
1103
1104                 // sinh(asinh(x)) -> x
1105                 if (is_ex_the_function(x, asinh))
1106                         return t;
1107
1108                 // sinh(acosh(x)) -> sqrt(x-1) * sqrt(x+1)
1109                 if (is_ex_the_function(x, acosh))
1110                         return sqrt(t-_ex1)*sqrt(t+_ex1);
1111
1112                 // sinh(atanh(x)) -> x/sqrt(1-x^2)
1113                 if (is_ex_the_function(x, atanh))
1114                         return t*power(_ex1-power(t,_ex2),_ex_1_2);
1115         }
1116         
1117         return sinh(x).hold();
1118 }
1119
1120 static ex sinh_deriv(const ex & x, unsigned deriv_param)
1121 {
1122         GINAC_ASSERT(deriv_param==0);
1123         
1124         // d/dx sinh(x) -> cosh(x)
1125         return cosh(x);
1126 }
1127
1128 static ex sinh_real_part(const ex & x)
1129 {
1130         return sinh(GiNaC::real_part(x))*cos(GiNaC::imag_part(x));
1131 }
1132
1133 static ex sinh_imag_part(const ex & x)
1134 {
1135         return cosh(GiNaC::real_part(x))*sin(GiNaC::imag_part(x));
1136 }
1137
1138 static ex sinh_conjugate(const ex & x)
1139 {
1140         // conjugate(sinh(x))==sinh(conjugate(x))
1141         return sinh(x.conjugate());
1142 }
1143
1144 REGISTER_FUNCTION(sinh, eval_func(sinh_eval).
1145                         evalf_func(sinh_evalf).
1146                         derivative_func(sinh_deriv).
1147                         real_part_func(sinh_real_part).
1148                         imag_part_func(sinh_imag_part).
1149                         conjugate_func(sinh_conjugate).
1150                         latex_name("\\sinh"));
1151
1152 //////////
1153 // hyperbolic cosine (trigonometric function)
1154 //////////
1155
1156 static ex cosh_evalf(const ex & x)
1157 {
1158         if (is_exactly_a<numeric>(x))
1159                 return cosh(ex_to<numeric>(x));
1160         
1161         return cosh(x).hold();
1162 }
1163
1164 static ex cosh_eval(const ex & x)
1165 {
1166         if (x.info(info_flags::numeric)) {
1167
1168                 // cosh(0) -> 1
1169                 if (x.is_zero())
1170                         return _ex1;
1171
1172                 // cosh(float) -> float
1173                 if (!x.info(info_flags::crational))
1174                         return cosh(ex_to<numeric>(x));
1175
1176                 // cosh() is even
1177                 if (x.info(info_flags::negative))
1178                         return cosh(-x);
1179         }
1180         
1181         if ((x/Pi).info(info_flags::numeric) &&
1182                 ex_to<numeric>(x/Pi).real().is_zero())  // cosh(I*x) -> cos(x)
1183                 return cos(x/I);
1184         
1185         if (is_exactly_a<function>(x)) {
1186                 const ex &t = x.op(0);
1187
1188                 // cosh(acosh(x)) -> x
1189                 if (is_ex_the_function(x, acosh))
1190                         return t;
1191
1192                 // cosh(asinh(x)) -> sqrt(1+x^2)
1193                 if (is_ex_the_function(x, asinh))
1194                         return sqrt(_ex1+power(t,_ex2));
1195
1196                 // cosh(atanh(x)) -> 1/sqrt(1-x^2)
1197                 if (is_ex_the_function(x, atanh))
1198                         return power(_ex1-power(t,_ex2),_ex_1_2);
1199         }
1200         
1201         return cosh(x).hold();
1202 }
1203
1204 static ex cosh_deriv(const ex & x, unsigned deriv_param)
1205 {
1206         GINAC_ASSERT(deriv_param==0);
1207         
1208         // d/dx cosh(x) -> sinh(x)
1209         return sinh(x);
1210 }
1211
1212 static ex cosh_real_part(const ex & x)
1213 {
1214         return cosh(GiNaC::real_part(x))*cos(GiNaC::imag_part(x));
1215 }
1216
1217 static ex cosh_imag_part(const ex & x)
1218 {
1219         return sinh(GiNaC::real_part(x))*sin(GiNaC::imag_part(x));
1220 }
1221
1222 static ex cosh_conjugate(const ex & x)
1223 {
1224         // conjugate(cosh(x))==cosh(conjugate(x))
1225         return cosh(x.conjugate());
1226 }
1227
1228 REGISTER_FUNCTION(cosh, eval_func(cosh_eval).
1229                         evalf_func(cosh_evalf).
1230                         derivative_func(cosh_deriv).
1231                         real_part_func(cosh_real_part).
1232                         imag_part_func(cosh_imag_part).
1233                         conjugate_func(cosh_conjugate).
1234                         latex_name("\\cosh"));
1235
1236 //////////
1237 // hyperbolic tangent (trigonometric function)
1238 //////////
1239
1240 static ex tanh_evalf(const ex & x)
1241 {
1242         if (is_exactly_a<numeric>(x))
1243                 return tanh(ex_to<numeric>(x));
1244         
1245         return tanh(x).hold();
1246 }
1247
1248 static ex tanh_eval(const ex & x)
1249 {
1250         if (x.info(info_flags::numeric)) {
1251
1252                 // tanh(0) -> 0
1253                 if (x.is_zero())
1254                         return _ex0;
1255
1256                 // tanh(float) -> float
1257                 if (!x.info(info_flags::crational))
1258                         return tanh(ex_to<numeric>(x));
1259
1260                 // tanh() is odd
1261                 if (x.info(info_flags::negative))
1262                         return -tanh(-x);
1263         }
1264         
1265         if ((x/Pi).info(info_flags::numeric) &&
1266                 ex_to<numeric>(x/Pi).real().is_zero())  // tanh(I*x) -> I*tan(x);
1267                 return I*tan(x/I);
1268         
1269         if (is_exactly_a<function>(x)) {
1270                 const ex &t = x.op(0);
1271
1272                 // tanh(atanh(x)) -> x
1273                 if (is_ex_the_function(x, atanh))
1274                         return t;
1275
1276                 // tanh(asinh(x)) -> x/sqrt(1+x^2)
1277                 if (is_ex_the_function(x, asinh))
1278                         return t*power(_ex1+power(t,_ex2),_ex_1_2);
1279
1280                 // tanh(acosh(x)) -> sqrt(x-1)*sqrt(x+1)/x
1281                 if (is_ex_the_function(x, acosh))
1282                         return sqrt(t-_ex1)*sqrt(t+_ex1)*power(t,_ex_1);
1283         }
1284         
1285         return tanh(x).hold();
1286 }
1287
1288 static ex tanh_deriv(const ex & x, unsigned deriv_param)
1289 {
1290         GINAC_ASSERT(deriv_param==0);
1291         
1292         // d/dx tanh(x) -> 1-tanh(x)^2
1293         return _ex1-power(tanh(x),_ex2);
1294 }
1295
1296 static ex tanh_series(const ex &x,
1297                       const relational &rel,
1298                       int order,
1299                       unsigned options)
1300 {
1301         GINAC_ASSERT(is_a<symbol>(rel.lhs()));
1302         // method:
1303         // Taylor series where there is no pole falls back to tanh_deriv.
1304         // On a pole simply expand sinh(x)/cosh(x).
1305         const ex x_pt = x.subs(rel, subs_options::no_pattern);
1306         if (!(2*I*x_pt/Pi).info(info_flags::odd))
1307                 throw do_taylor();  // caught by function::series()
1308         // if we got here we have to care for a simple pole
1309         return (sinh(x)/cosh(x)).series(rel, order, options);
1310 }
1311
1312 static ex tanh_real_part(const ex & x)
1313 {
1314         ex a = GiNaC::real_part(x);
1315         ex b = GiNaC::imag_part(x);
1316         return tanh(a)/(1+power(tanh(a),2)*power(tan(b),2));
1317 }
1318
1319 static ex tanh_imag_part(const ex & x)
1320 {
1321         ex a = GiNaC::real_part(x);
1322         ex b = GiNaC::imag_part(x);
1323         return tan(b)/(1+power(tanh(a),2)*power(tan(b),2));
1324 }
1325
1326 static ex tanh_conjugate(const ex & x)
1327 {
1328         // conjugate(tanh(x))==tanh(conjugate(x))
1329         return tanh(x.conjugate());
1330 }
1331
1332 REGISTER_FUNCTION(tanh, eval_func(tanh_eval).
1333                         evalf_func(tanh_evalf).
1334                         derivative_func(tanh_deriv).
1335                         series_func(tanh_series).
1336                         real_part_func(tanh_real_part).
1337                         imag_part_func(tanh_imag_part).
1338                         conjugate_func(tanh_conjugate).
1339                         latex_name("\\tanh"));
1340
1341 //////////
1342 // inverse hyperbolic sine (trigonometric function)
1343 //////////
1344
1345 static ex asinh_evalf(const ex & x)
1346 {
1347         if (is_exactly_a<numeric>(x))
1348                 return asinh(ex_to<numeric>(x));
1349         
1350         return asinh(x).hold();
1351 }
1352
1353 static ex asinh_eval(const ex & x)
1354 {
1355         if (x.info(info_flags::numeric)) {
1356
1357                 // asinh(0) -> 0
1358                 if (x.is_zero())
1359                         return _ex0;
1360
1361                 // asinh(float) -> float
1362                 if (!x.info(info_flags::crational))
1363                         return asinh(ex_to<numeric>(x));
1364
1365                 // asinh() is odd
1366                 if (x.info(info_flags::negative))
1367                         return -asinh(-x);
1368         }
1369         
1370         return asinh(x).hold();
1371 }
1372
1373 static ex asinh_deriv(const ex & x, unsigned deriv_param)
1374 {
1375         GINAC_ASSERT(deriv_param==0);
1376         
1377         // d/dx asinh(x) -> 1/sqrt(1+x^2)
1378         return power(_ex1+power(x,_ex2),_ex_1_2);
1379 }
1380
1381 static ex asinh_conjugate(const ex & x)
1382 {
1383         // conjugate(asinh(x))==asinh(conjugate(x)) unless on the branch cuts which
1384         // run along the imaginary axis outside the interval [-I, +I].
1385         if (x.info(info_flags::real))
1386                 return asinh(x);
1387         if (is_exactly_a<numeric>(x)) {
1388                 const numeric x_re = ex_to<numeric>(x.real_part());
1389                 const numeric x_im = ex_to<numeric>(x.imag_part());
1390                 if (!x_re.is_zero() ||
1391                     (x_im > *_num_1_p && x_im < *_num1_p))
1392                         return asinh(x.conjugate());
1393         }
1394         return conjugate_function(asinh(x)).hold();
1395 }
1396
1397 REGISTER_FUNCTION(asinh, eval_func(asinh_eval).
1398                          evalf_func(asinh_evalf).
1399                          derivative_func(asinh_deriv).
1400                          conjugate_func(asinh_conjugate));
1401
1402 //////////
1403 // inverse hyperbolic cosine (trigonometric function)
1404 //////////
1405
1406 static ex acosh_evalf(const ex & x)
1407 {
1408         if (is_exactly_a<numeric>(x))
1409                 return acosh(ex_to<numeric>(x));
1410         
1411         return acosh(x).hold();
1412 }
1413
1414 static ex acosh_eval(const ex & x)
1415 {
1416         if (x.info(info_flags::numeric)) {
1417
1418                 // acosh(0) -> Pi*I/2
1419                 if (x.is_zero())
1420                         return Pi*I*numeric(1,2);
1421
1422                 // acosh(1) -> 0
1423                 if (x.is_equal(_ex1))
1424                         return _ex0;
1425
1426                 // acosh(-1) -> Pi*I
1427                 if (x.is_equal(_ex_1))
1428                         return Pi*I;
1429
1430                 // acosh(float) -> float
1431                 if (!x.info(info_flags::crational))
1432                         return acosh(ex_to<numeric>(x));
1433
1434                 // acosh(-x) -> Pi*I-acosh(x)
1435                 if (x.info(info_flags::negative))
1436                         return Pi*I-acosh(-x);
1437         }
1438         
1439         return acosh(x).hold();
1440 }
1441
1442 static ex acosh_deriv(const ex & x, unsigned deriv_param)
1443 {
1444         GINAC_ASSERT(deriv_param==0);
1445         
1446         // d/dx acosh(x) -> 1/(sqrt(x-1)*sqrt(x+1))
1447         return power(x+_ex_1,_ex_1_2)*power(x+_ex1,_ex_1_2);
1448 }
1449
1450 static ex acosh_conjugate(const ex & x)
1451 {
1452         // conjugate(acosh(x))==acosh(conjugate(x)) unless on the branch cut
1453         // which runs along the real axis from +1 to -inf.
1454         if (is_exactly_a<numeric>(x) &&
1455             (!x.imag_part().is_zero() || x > *_num1_p)) {
1456                 return acosh(x.conjugate());
1457         }
1458         return conjugate_function(acosh(x)).hold();
1459 }
1460
1461 REGISTER_FUNCTION(acosh, eval_func(acosh_eval).
1462                          evalf_func(acosh_evalf).
1463                          derivative_func(acosh_deriv).
1464                          conjugate_func(acosh_conjugate));
1465
1466 //////////
1467 // inverse hyperbolic tangent (trigonometric function)
1468 //////////
1469
1470 static ex atanh_evalf(const ex & x)
1471 {
1472         if (is_exactly_a<numeric>(x))
1473                 return atanh(ex_to<numeric>(x));
1474         
1475         return atanh(x).hold();
1476 }
1477
1478 static ex atanh_eval(const ex & x)
1479 {
1480         if (x.info(info_flags::numeric)) {
1481
1482                 // atanh(0) -> 0
1483                 if (x.is_zero())
1484                         return _ex0;
1485
1486                 // atanh({+|-}1) -> throw
1487                 if (x.is_equal(_ex1) || x.is_equal(_ex_1))
1488                         throw (pole_error("atanh_eval(): logarithmic pole",0));
1489
1490                 // atanh(float) -> float
1491                 if (!x.info(info_flags::crational))
1492                         return atanh(ex_to<numeric>(x));
1493
1494                 // atanh() is odd
1495                 if (x.info(info_flags::negative))
1496                         return -atanh(-x);
1497         }
1498         
1499         return atanh(x).hold();
1500 }
1501
1502 static ex atanh_deriv(const ex & x, unsigned deriv_param)
1503 {
1504         GINAC_ASSERT(deriv_param==0);
1505         
1506         // d/dx atanh(x) -> 1/(1-x^2)
1507         return power(_ex1-power(x,_ex2),_ex_1);
1508 }
1509
1510 static ex atanh_series(const ex &arg,
1511                        const relational &rel,
1512                        int order,
1513                        unsigned options)
1514 {
1515         GINAC_ASSERT(is_a<symbol>(rel.lhs()));
1516         // method:
1517         // Taylor series where there is no pole or cut falls back to atanh_deriv.
1518         // There are two branch cuts, one runnig from 1 up the real axis and one
1519         // one running from -1 down the real axis.  The points 1 and -1 are poles
1520         // On the branch cuts and the poles series expand
1521         //     (log(1+x)-log(1-x))/2
1522         // instead.
1523         const ex arg_pt = arg.subs(rel, subs_options::no_pattern);
1524         if (!(arg_pt).info(info_flags::real))
1525                 throw do_taylor();     // Im(x) != 0
1526         if ((arg_pt).info(info_flags::real) && abs(arg_pt)<_ex1)
1527                 throw do_taylor();     // Im(x) == 0, but abs(x)<1
1528         // care for the poles, using the defining formula for atanh()...
1529         if (arg_pt.is_equal(_ex1) || arg_pt.is_equal(_ex_1))
1530                 return ((log(_ex1+arg)-log(_ex1-arg))*_ex1_2).series(rel, order, options);
1531         // ...and the branch cuts (the discontinuity at the cut being just I*Pi)
1532         if (!(options & series_options::suppress_branchcut)) {
1533                 // method:
1534                 // This is the branch cut: assemble the primitive series manually and
1535                 // then add the corresponding complex step function.
1536                 const symbol &s = ex_to<symbol>(rel.lhs());
1537                 const ex &point = rel.rhs();
1538                 const symbol foo;
1539                 const ex replarg = series(atanh(arg), s==foo, order).subs(foo==point, subs_options::no_pattern);
1540                 ex Order0correction = replarg.op(0)+csgn(I*arg)*Pi*I*_ex1_2;
1541                 if (arg_pt<_ex0)
1542                         Order0correction += log((arg_pt+_ex_1)/(arg_pt+_ex1))*_ex1_2;
1543                 else
1544                         Order0correction += log((arg_pt+_ex1)/(arg_pt+_ex_1))*_ex_1_2;
1545                 epvector seq;
1546                 if (order > 0) {
1547                         seq.reserve(2);
1548                         seq.push_back(expair(Order0correction, _ex0));
1549                 }
1550                 seq.push_back(expair(Order(_ex1), order));
1551                 return series(replarg - pseries(rel, std::move(seq)), rel, order);
1552         }
1553         throw do_taylor();
1554 }
1555
1556 static ex atanh_conjugate(const ex & x)
1557 {
1558         // conjugate(atanh(x))==atanh(conjugate(x)) unless on the branch cuts which
1559         // run along the real axis outside the interval [-1, +1].
1560         if (is_exactly_a<numeric>(x) &&
1561             (!x.imag_part().is_zero() || (x > *_num_1_p && x < *_num1_p))) {
1562                 return atanh(x.conjugate());
1563         }
1564         return conjugate_function(atanh(x)).hold();
1565 }
1566
1567 REGISTER_FUNCTION(atanh, eval_func(atanh_eval).
1568                          evalf_func(atanh_evalf).
1569                          derivative_func(atanh_deriv).
1570                          series_func(atanh_series).
1571                          conjugate_func(atanh_conjugate));
1572
1573
1574 } // namespace GiNaC