Update copyright statements.
[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-2014 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 (new mul(prodseq))->setflag(status_flags::dynallocated | 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                                 epvector epv;
246                                 ex acc = (new pseries(rel, epv))->setflag(status_flags::dynallocated);
247                                 epv.reserve(2);
248                                 epv.push_back(expair(-1, _ex0));
249                                 epv.push_back(expair(Order(_ex1), order));
250                                 ex rest = pseries(rel, epv).add_series(argser);
251                                 for (int i = order-1; i>0; --i) {
252                                         epvector cterm;
253                                         cterm.reserve(1);
254                                         cterm.push_back(expair(i%2 ? _ex1/i : _ex_1/i, _ex0));
255                                         acc = pseries(rel, cterm).add_series(ex_to<pseries>(acc));
256                                         acc = (ex_to<pseries>(rest)).mul_series(ex_to<pseries>(acc));
257                                 }
258                                 return acc;
259                         }
260                         const ex newarg = ex_to<pseries>((arg/coeff).series(rel, order+n, options)).shift_exponents(-n).convert_to_poly(true);
261                         return pseries(rel, seq).add_series(ex_to<pseries>(log(newarg).series(rel, order, options)));
262                 } else  // it was a monomial
263                         return pseries(rel, seq);
264         }
265         if (!(options & series_options::suppress_branchcut) &&
266              arg_pt.info(info_flags::negative)) {
267                 // method:
268                 // This is the branch cut: assemble the primitive series manually and
269                 // then add the corresponding complex step function.
270                 const symbol &s = ex_to<symbol>(rel.lhs());
271                 const ex &point = rel.rhs();
272                 const symbol foo;
273                 const ex replarg = series(log(arg), s==foo, order).subs(foo==point, subs_options::no_pattern);
274                 epvector seq;
275                 seq.push_back(expair(-I*csgn(arg*I)*Pi, _ex0));
276                 seq.push_back(expair(Order(_ex1), order));
277                 return series(replarg - I*Pi + pseries(rel, seq), rel, order);
278         }
279         throw do_taylor();  // caught by function::series()
280 }
281
282 static ex log_real_part(const ex & x)
283 {
284         if (x.info(info_flags::nonnegative))
285                 return log(x).hold();
286         return log(abs(x));
287 }
288
289 static ex log_imag_part(const ex & x)
290 {
291         if (x.info(info_flags::nonnegative))
292                 return 0;
293         return atan2(GiNaC::imag_part(x), GiNaC::real_part(x));
294 }
295
296 static ex log_expand(const ex & arg, unsigned options)
297 {
298         if ((options & expand_options::expand_transcendental)
299                 && is_exactly_a<mul>(arg) && !arg.info(info_flags::indefinite)) {
300                 exvector sumseq;
301                 exvector prodseq;
302                 sumseq.reserve(arg.nops());
303                 prodseq.reserve(arg.nops());
304                 bool possign=true;
305
306                 // searching for positive/negative factors
307                 for (const_iterator i = arg.begin(); i != arg.end(); ++i) {
308                         ex e;
309                         if (options & expand_options::expand_function_args)
310                                 e=i->expand(options);
311                         else
312                                 e=*i;
313                         if (e.info(info_flags::positive))
314                                 sumseq.push_back(log(e));
315                         else if (e.info(info_flags::negative)) {
316                                 sumseq.push_back(log(-e));
317                                 possign = !possign;
318                         } else
319                                 prodseq.push_back(e);
320                 }
321
322                 if (sumseq.size() > 0) {
323                         ex newarg;
324                         if (options & expand_options::expand_function_args)
325                                 newarg=((possign?_ex1:_ex_1)*mul(prodseq)).expand(options);
326                         else {
327                                 newarg=(possign?_ex1:_ex_1)*mul(prodseq);
328                                 ex_to<basic>(newarg).setflag(status_flags::purely_indefinite);
329                         }
330                         return add(sumseq)+log(newarg);
331                 } else {
332                         if (!(options & expand_options::expand_function_args))
333                                 ex_to<basic>(arg).setflag(status_flags::purely_indefinite);
334                 }
335         }
336
337         if (options & expand_options::expand_function_args)
338                 return log(arg.expand(options)).hold();
339         else
340                 return log(arg).hold();
341 }
342
343 static ex log_conjugate(const ex & x)
344 {
345         // conjugate(log(x))==log(conjugate(x)) unless on the branch cut which
346         // runs along the negative real axis.
347         if (x.info(info_flags::positive)) {
348                 return log(x);
349         }
350         if (is_exactly_a<numeric>(x) &&
351             !x.imag_part().is_zero()) {
352                 return log(x.conjugate());
353         }
354         return conjugate_function(log(x)).hold();
355 }
356
357 REGISTER_FUNCTION(log, eval_func(log_eval).
358                        evalf_func(log_evalf).
359                        expand_func(log_expand).
360                        derivative_func(log_deriv).
361                        series_func(log_series).
362                        real_part_func(log_real_part).
363                        imag_part_func(log_imag_part).
364                        conjugate_func(log_conjugate).
365                        latex_name("\\ln"));
366
367 //////////
368 // sine (trigonometric function)
369 //////////
370
371 static ex sin_evalf(const ex & x)
372 {
373         if (is_exactly_a<numeric>(x))
374                 return sin(ex_to<numeric>(x));
375         
376         return sin(x).hold();
377 }
378
379 static ex sin_eval(const ex & x)
380 {
381         // sin(n/d*Pi) -> { all known non-nested radicals }
382         const ex SixtyExOverPi = _ex60*x/Pi;
383         ex sign = _ex1;
384         if (SixtyExOverPi.info(info_flags::integer)) {
385                 numeric z = mod(ex_to<numeric>(SixtyExOverPi),*_num120_p);
386                 if (z>=*_num60_p) {
387                         // wrap to interval [0, Pi)
388                         z -= *_num60_p;
389                         sign = _ex_1;
390                 }
391                 if (z>*_num30_p) {
392                         // wrap to interval [0, Pi/2)
393                         z = *_num60_p-z;
394                 }
395                 if (z.is_equal(*_num0_p))  // sin(0)       -> 0
396                         return _ex0;
397                 if (z.is_equal(*_num5_p))  // sin(Pi/12)   -> sqrt(6)/4*(1-sqrt(3)/3)
398                         return sign*_ex1_4*sqrt(_ex6)*(_ex1+_ex_1_3*sqrt(_ex3));
399                 if (z.is_equal(*_num6_p))  // sin(Pi/10)   -> sqrt(5)/4-1/4
400                         return sign*(_ex1_4*sqrt(_ex5)+_ex_1_4);
401                 if (z.is_equal(*_num10_p)) // sin(Pi/6)    -> 1/2
402                         return sign*_ex1_2;
403                 if (z.is_equal(*_num15_p)) // sin(Pi/4)    -> sqrt(2)/2
404                         return sign*_ex1_2*sqrt(_ex2);
405                 if (z.is_equal(*_num18_p)) // sin(3/10*Pi) -> sqrt(5)/4+1/4
406                         return sign*(_ex1_4*sqrt(_ex5)+_ex1_4);
407                 if (z.is_equal(*_num20_p)) // sin(Pi/3)    -> sqrt(3)/2
408                         return sign*_ex1_2*sqrt(_ex3);
409                 if (z.is_equal(*_num25_p)) // sin(5/12*Pi) -> sqrt(6)/4*(1+sqrt(3)/3)
410                         return sign*_ex1_4*sqrt(_ex6)*(_ex1+_ex1_3*sqrt(_ex3));
411                 if (z.is_equal(*_num30_p)) // sin(Pi/2)    -> 1
412                         return sign;
413         }
414
415         if (is_exactly_a<function>(x)) {
416                 const ex &t = x.op(0);
417
418                 // sin(asin(x)) -> x
419                 if (is_ex_the_function(x, asin))
420                         return t;
421
422                 // sin(acos(x)) -> sqrt(1-x^2)
423                 if (is_ex_the_function(x, acos))
424                         return sqrt(_ex1-power(t,_ex2));
425
426                 // sin(atan(x)) -> x/sqrt(1+x^2)
427                 if (is_ex_the_function(x, atan))
428                         return t*power(_ex1+power(t,_ex2),_ex_1_2);
429         }
430         
431         // sin(float) -> float
432         if (x.info(info_flags::numeric) && !x.info(info_flags::crational))
433                 return sin(ex_to<numeric>(x));
434
435         // sin() is odd
436         if (x.info(info_flags::negative))
437                 return -sin(-x);
438         
439         return sin(x).hold();
440 }
441
442 static ex sin_deriv(const ex & x, unsigned deriv_param)
443 {
444         GINAC_ASSERT(deriv_param==0);
445         
446         // d/dx sin(x) -> cos(x)
447         return cos(x);
448 }
449
450 static ex sin_real_part(const ex & x)
451 {
452         return cosh(GiNaC::imag_part(x))*sin(GiNaC::real_part(x));
453 }
454
455 static ex sin_imag_part(const ex & x)
456 {
457         return sinh(GiNaC::imag_part(x))*cos(GiNaC::real_part(x));
458 }
459
460 static ex sin_conjugate(const ex & x)
461 {
462         // conjugate(sin(x))==sin(conjugate(x))
463         return sin(x.conjugate());
464 }
465
466 REGISTER_FUNCTION(sin, eval_func(sin_eval).
467                        evalf_func(sin_evalf).
468                        derivative_func(sin_deriv).
469                        real_part_func(sin_real_part).
470                        imag_part_func(sin_imag_part).
471                        conjugate_func(sin_conjugate).
472                        latex_name("\\sin"));
473
474 //////////
475 // cosine (trigonometric function)
476 //////////
477
478 static ex cos_evalf(const ex & x)
479 {
480         if (is_exactly_a<numeric>(x))
481                 return cos(ex_to<numeric>(x));
482         
483         return cos(x).hold();
484 }
485
486 static ex cos_eval(const ex & x)
487 {
488         // cos(n/d*Pi) -> { all known non-nested radicals }
489         const ex SixtyExOverPi = _ex60*x/Pi;
490         ex sign = _ex1;
491         if (SixtyExOverPi.info(info_flags::integer)) {
492                 numeric z = mod(ex_to<numeric>(SixtyExOverPi),*_num120_p);
493                 if (z>=*_num60_p) {
494                         // wrap to interval [0, Pi)
495                         z = *_num120_p-z;
496                 }
497                 if (z>=*_num30_p) {
498                         // wrap to interval [0, Pi/2)
499                         z = *_num60_p-z;
500                         sign = _ex_1;
501                 }
502                 if (z.is_equal(*_num0_p))  // cos(0)       -> 1
503                         return sign;
504                 if (z.is_equal(*_num5_p))  // cos(Pi/12)   -> sqrt(6)/4*(1+sqrt(3)/3)
505                         return sign*_ex1_4*sqrt(_ex6)*(_ex1+_ex1_3*sqrt(_ex3));
506                 if (z.is_equal(*_num10_p)) // cos(Pi/6)    -> sqrt(3)/2
507                         return sign*_ex1_2*sqrt(_ex3);
508                 if (z.is_equal(*_num12_p)) // cos(Pi/5)    -> sqrt(5)/4+1/4
509                         return sign*(_ex1_4*sqrt(_ex5)+_ex1_4);
510                 if (z.is_equal(*_num15_p)) // cos(Pi/4)    -> sqrt(2)/2
511                         return sign*_ex1_2*sqrt(_ex2);
512                 if (z.is_equal(*_num20_p)) // cos(Pi/3)    -> 1/2
513                         return sign*_ex1_2;
514                 if (z.is_equal(*_num24_p)) // cos(2/5*Pi)  -> sqrt(5)/4-1/4x
515                         return sign*(_ex1_4*sqrt(_ex5)+_ex_1_4);
516                 if (z.is_equal(*_num25_p)) // cos(5/12*Pi) -> sqrt(6)/4*(1-sqrt(3)/3)
517                         return sign*_ex1_4*sqrt(_ex6)*(_ex1+_ex_1_3*sqrt(_ex3));
518                 if (z.is_equal(*_num30_p)) // cos(Pi/2)    -> 0
519                         return _ex0;
520         }
521
522         if (is_exactly_a<function>(x)) {
523                 const ex &t = x.op(0);
524
525                 // cos(acos(x)) -> x
526                 if (is_ex_the_function(x, acos))
527                         return t;
528
529                 // cos(asin(x)) -> sqrt(1-x^2)
530                 if (is_ex_the_function(x, asin))
531                         return sqrt(_ex1-power(t,_ex2));
532
533                 // cos(atan(x)) -> 1/sqrt(1+x^2)
534                 if (is_ex_the_function(x, atan))
535                         return power(_ex1+power(t,_ex2),_ex_1_2);
536         }
537         
538         // cos(float) -> float
539         if (x.info(info_flags::numeric) && !x.info(info_flags::crational))
540                 return cos(ex_to<numeric>(x));
541         
542         // cos() is even
543         if (x.info(info_flags::negative))
544                 return cos(-x);
545         
546         return cos(x).hold();
547 }
548
549 static ex cos_deriv(const ex & x, unsigned deriv_param)
550 {
551         GINAC_ASSERT(deriv_param==0);
552
553         // d/dx cos(x) -> -sin(x)
554         return -sin(x);
555 }
556
557 static ex cos_real_part(const ex & x)
558 {
559         return cosh(GiNaC::imag_part(x))*cos(GiNaC::real_part(x));
560 }
561
562 static ex cos_imag_part(const ex & x)
563 {
564         return -sinh(GiNaC::imag_part(x))*sin(GiNaC::real_part(x));
565 }
566
567 static ex cos_conjugate(const ex & x)
568 {
569         // conjugate(cos(x))==cos(conjugate(x))
570         return cos(x.conjugate());
571 }
572
573 REGISTER_FUNCTION(cos, eval_func(cos_eval).
574                        evalf_func(cos_evalf).
575                        derivative_func(cos_deriv).
576                        real_part_func(cos_real_part).
577                        imag_part_func(cos_imag_part).
578                        conjugate_func(cos_conjugate).
579                        latex_name("\\cos"));
580
581 //////////
582 // tangent (trigonometric function)
583 //////////
584
585 static ex tan_evalf(const ex & x)
586 {
587         if (is_exactly_a<numeric>(x))
588                 return tan(ex_to<numeric>(x));
589         
590         return tan(x).hold();
591 }
592
593 static ex tan_eval(const ex & x)
594 {
595         // tan(n/d*Pi) -> { all known non-nested radicals }
596         const ex SixtyExOverPi = _ex60*x/Pi;
597         ex sign = _ex1;
598         if (SixtyExOverPi.info(info_flags::integer)) {
599                 numeric z = mod(ex_to<numeric>(SixtyExOverPi),*_num60_p);
600                 if (z>=*_num60_p) {
601                         // wrap to interval [0, Pi)
602                         z -= *_num60_p;
603                 }
604                 if (z>=*_num30_p) {
605                         // wrap to interval [0, Pi/2)
606                         z = *_num60_p-z;
607                         sign = _ex_1;
608                 }
609                 if (z.is_equal(*_num0_p))  // tan(0)       -> 0
610                         return _ex0;
611                 if (z.is_equal(*_num5_p))  // tan(Pi/12)   -> 2-sqrt(3)
612                         return sign*(_ex2-sqrt(_ex3));
613                 if (z.is_equal(*_num10_p)) // tan(Pi/6)    -> sqrt(3)/3
614                         return sign*_ex1_3*sqrt(_ex3);
615                 if (z.is_equal(*_num15_p)) // tan(Pi/4)    -> 1
616                         return sign;
617                 if (z.is_equal(*_num20_p)) // tan(Pi/3)    -> sqrt(3)
618                         return sign*sqrt(_ex3);
619                 if (z.is_equal(*_num25_p)) // tan(5/12*Pi) -> 2+sqrt(3)
620                         return sign*(sqrt(_ex3)+_ex2);
621                 if (z.is_equal(*_num30_p)) // tan(Pi/2)    -> infinity
622                         throw (pole_error("tan_eval(): simple pole",1));
623         }
624
625         if (is_exactly_a<function>(x)) {
626                 const ex &t = x.op(0);
627
628                 // tan(atan(x)) -> x
629                 if (is_ex_the_function(x, atan))
630                         return t;
631
632                 // tan(asin(x)) -> x/sqrt(1+x^2)
633                 if (is_ex_the_function(x, asin))
634                         return t*power(_ex1-power(t,_ex2),_ex_1_2);
635
636                 // tan(acos(x)) -> sqrt(1-x^2)/x
637                 if (is_ex_the_function(x, acos))
638                         return power(t,_ex_1)*sqrt(_ex1-power(t,_ex2));
639         }
640         
641         // tan(float) -> float
642         if (x.info(info_flags::numeric) && !x.info(info_flags::crational)) {
643                 return tan(ex_to<numeric>(x));
644         }
645         
646         // tan() is odd
647         if (x.info(info_flags::negative))
648                 return -tan(-x);
649         
650         return tan(x).hold();
651 }
652
653 static ex tan_deriv(const ex & x, unsigned deriv_param)
654 {
655         GINAC_ASSERT(deriv_param==0);
656         
657         // d/dx tan(x) -> 1+tan(x)^2;
658         return (_ex1+power(tan(x),_ex2));
659 }
660
661 static ex tan_real_part(const ex & x)
662 {
663         ex a = GiNaC::real_part(x);
664         ex b = GiNaC::imag_part(x);
665         return tan(a)/(1+power(tan(a),2)*power(tan(b),2));
666 }
667
668 static ex tan_imag_part(const ex & x)
669 {
670         ex a = GiNaC::real_part(x);
671         ex b = GiNaC::imag_part(x);
672         return tanh(b)/(1+power(tan(a),2)*power(tan(b),2));
673 }
674
675 static ex tan_series(const ex &x,
676                      const relational &rel,
677                      int order,
678                      unsigned options)
679 {
680         GINAC_ASSERT(is_a<symbol>(rel.lhs()));
681         // method:
682         // Taylor series where there is no pole falls back to tan_deriv.
683         // On a pole simply expand sin(x)/cos(x).
684         const ex x_pt = x.subs(rel, subs_options::no_pattern);
685         if (!(2*x_pt/Pi).info(info_flags::odd))
686                 throw do_taylor();  // caught by function::series()
687         // if we got here we have to care for a simple pole
688         return (sin(x)/cos(x)).series(rel, order, options);
689 }
690
691 static ex tan_conjugate(const ex & x)
692 {
693         // conjugate(tan(x))==tan(conjugate(x))
694         return tan(x.conjugate());
695 }
696
697 REGISTER_FUNCTION(tan, eval_func(tan_eval).
698                        evalf_func(tan_evalf).
699                        derivative_func(tan_deriv).
700                        series_func(tan_series).
701                        real_part_func(tan_real_part).
702                        imag_part_func(tan_imag_part).
703                        conjugate_func(tan_conjugate).
704                        latex_name("\\tan"));
705
706 //////////
707 // inverse sine (arc sine)
708 //////////
709
710 static ex asin_evalf(const ex & x)
711 {
712         if (is_exactly_a<numeric>(x))
713                 return asin(ex_to<numeric>(x));
714         
715         return asin(x).hold();
716 }
717
718 static ex asin_eval(const ex & x)
719 {
720         if (x.info(info_flags::numeric)) {
721
722                 // asin(0) -> 0
723                 if (x.is_zero())
724                         return x;
725
726                 // asin(1/2) -> Pi/6
727                 if (x.is_equal(_ex1_2))
728                         return numeric(1,6)*Pi;
729
730                 // asin(1) -> Pi/2
731                 if (x.is_equal(_ex1))
732                         return _ex1_2*Pi;
733
734                 // asin(-1/2) -> -Pi/6
735                 if (x.is_equal(_ex_1_2))
736                         return numeric(-1,6)*Pi;
737
738                 // asin(-1) -> -Pi/2
739                 if (x.is_equal(_ex_1))
740                         return _ex_1_2*Pi;
741
742                 // asin(float) -> float
743                 if (!x.info(info_flags::crational))
744                         return asin(ex_to<numeric>(x));
745
746                 // asin() is odd
747                 if (x.info(info_flags::negative))
748                         return -asin(-x);
749         }
750         
751         return asin(x).hold();
752 }
753
754 static ex asin_deriv(const ex & x, unsigned deriv_param)
755 {
756         GINAC_ASSERT(deriv_param==0);
757         
758         // d/dx asin(x) -> 1/sqrt(1-x^2)
759         return power(1-power(x,_ex2),_ex_1_2);
760 }
761
762 static ex asin_conjugate(const ex & x)
763 {
764         // conjugate(asin(x))==asin(conjugate(x)) unless on the branch cuts which
765         // run along the real axis outside the interval [-1, +1].
766         if (is_exactly_a<numeric>(x) &&
767             (!x.imag_part().is_zero() || (x > *_num_1_p && x < *_num1_p))) {
768                 return asin(x.conjugate());
769         }
770         return conjugate_function(asin(x)).hold();
771 }
772
773 REGISTER_FUNCTION(asin, eval_func(asin_eval).
774                         evalf_func(asin_evalf).
775                         derivative_func(asin_deriv).
776                         conjugate_func(asin_conjugate).
777                         latex_name("\\arcsin"));
778
779 //////////
780 // inverse cosine (arc cosine)
781 //////////
782
783 static ex acos_evalf(const ex & x)
784 {
785         if (is_exactly_a<numeric>(x))
786                 return acos(ex_to<numeric>(x));
787         
788         return acos(x).hold();
789 }
790
791 static ex acos_eval(const ex & x)
792 {
793         if (x.info(info_flags::numeric)) {
794
795                 // acos(1) -> 0
796                 if (x.is_equal(_ex1))
797                         return _ex0;
798
799                 // acos(1/2) -> Pi/3
800                 if (x.is_equal(_ex1_2))
801                         return _ex1_3*Pi;
802
803                 // acos(0) -> Pi/2
804                 if (x.is_zero())
805                         return _ex1_2*Pi;
806
807                 // acos(-1/2) -> 2/3*Pi
808                 if (x.is_equal(_ex_1_2))
809                         return numeric(2,3)*Pi;
810
811                 // acos(-1) -> Pi
812                 if (x.is_equal(_ex_1))
813                         return Pi;
814
815                 // acos(float) -> float
816                 if (!x.info(info_flags::crational))
817                         return acos(ex_to<numeric>(x));
818
819                 // acos(-x) -> Pi-acos(x)
820                 if (x.info(info_flags::negative))
821                         return Pi-acos(-x);
822         }
823         
824         return acos(x).hold();
825 }
826
827 static ex acos_deriv(const ex & x, unsigned deriv_param)
828 {
829         GINAC_ASSERT(deriv_param==0);
830         
831         // d/dx acos(x) -> -1/sqrt(1-x^2)
832         return -power(1-power(x,_ex2),_ex_1_2);
833 }
834
835 static ex acos_conjugate(const ex & x)
836 {
837         // conjugate(acos(x))==acos(conjugate(x)) unless on the branch cuts which
838         // run along the real axis outside the interval [-1, +1].
839         if (is_exactly_a<numeric>(x) &&
840             (!x.imag_part().is_zero() || (x > *_num_1_p && x < *_num1_p))) {
841                 return acos(x.conjugate());
842         }
843         return conjugate_function(acos(x)).hold();
844 }
845
846 REGISTER_FUNCTION(acos, eval_func(acos_eval).
847                         evalf_func(acos_evalf).
848                         derivative_func(acos_deriv).
849                         conjugate_func(acos_conjugate).
850                         latex_name("\\arccos"));
851
852 //////////
853 // inverse tangent (arc tangent)
854 //////////
855
856 static ex atan_evalf(const ex & x)
857 {
858         if (is_exactly_a<numeric>(x))
859                 return atan(ex_to<numeric>(x));
860         
861         return atan(x).hold();
862 }
863
864 static ex atan_eval(const ex & x)
865 {
866         if (x.info(info_flags::numeric)) {
867
868                 // atan(0) -> 0
869                 if (x.is_zero())
870                         return _ex0;
871
872                 // atan(1) -> Pi/4
873                 if (x.is_equal(_ex1))
874                         return _ex1_4*Pi;
875
876                 // atan(-1) -> -Pi/4
877                 if (x.is_equal(_ex_1))
878                         return _ex_1_4*Pi;
879
880                 if (x.is_equal(I) || x.is_equal(-I))
881                         throw (pole_error("atan_eval(): logarithmic pole",0));
882
883                 // atan(float) -> float
884                 if (!x.info(info_flags::crational))
885                         return atan(ex_to<numeric>(x));
886
887                 // atan() is odd
888                 if (x.info(info_flags::negative))
889                         return -atan(-x);
890         }
891         
892         return atan(x).hold();
893 }
894
895 static ex atan_deriv(const ex & x, unsigned deriv_param)
896 {
897         GINAC_ASSERT(deriv_param==0);
898
899         // d/dx atan(x) -> 1/(1+x^2)
900         return power(_ex1+power(x,_ex2), _ex_1);
901 }
902
903 static ex atan_series(const ex &arg,
904                       const relational &rel,
905                       int order,
906                       unsigned options)
907 {
908         GINAC_ASSERT(is_a<symbol>(rel.lhs()));
909         // method:
910         // Taylor series where there is no pole or cut falls back to atan_deriv.
911         // There are two branch cuts, one runnig from I up the imaginary axis and
912         // one running from -I down the imaginary axis.  The points I and -I are
913         // poles.
914         // On the branch cuts and the poles series expand
915         //     (log(1+I*x)-log(1-I*x))/(2*I)
916         // instead.
917         const ex arg_pt = arg.subs(rel, subs_options::no_pattern);
918         if (!(I*arg_pt).info(info_flags::real))
919                 throw do_taylor();     // Re(x) != 0
920         if ((I*arg_pt).info(info_flags::real) && abs(I*arg_pt)<_ex1)
921                 throw do_taylor();     // Re(x) == 0, but abs(x)<1
922         // care for the poles, using the defining formula for atan()...
923         if (arg_pt.is_equal(I) || arg_pt.is_equal(-I))
924                 return ((log(1+I*arg)-log(1-I*arg))/(2*I)).series(rel, order, options);
925         if (!(options & series_options::suppress_branchcut)) {
926                 // method:
927                 // This is the branch cut: assemble the primitive series manually and
928                 // then add the corresponding complex step function.
929                 const symbol &s = ex_to<symbol>(rel.lhs());
930                 const ex &point = rel.rhs();
931                 const symbol foo;
932                 const ex replarg = series(atan(arg), s==foo, order).subs(foo==point, subs_options::no_pattern);
933                 ex Order0correction = replarg.op(0)+csgn(arg)*Pi*_ex_1_2;
934                 if ((I*arg_pt)<_ex0)
935                         Order0correction += log((I*arg_pt+_ex_1)/(I*arg_pt+_ex1))*I*_ex_1_2;
936                 else
937                         Order0correction += log((I*arg_pt+_ex1)/(I*arg_pt+_ex_1))*I*_ex1_2;
938                 epvector seq;
939                 seq.push_back(expair(Order0correction, _ex0));
940                 seq.push_back(expair(Order(_ex1), order));
941                 return series(replarg - pseries(rel, 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                 seq.push_back(expair(Order0correction, _ex0));
1547                 seq.push_back(expair(Order(_ex1), order));
1548                 return series(replarg - pseries(rel, seq), rel, order);
1549         }
1550         throw do_taylor();
1551 }
1552
1553 static ex atanh_conjugate(const ex & x)
1554 {
1555         // conjugate(atanh(x))==atanh(conjugate(x)) unless on the branch cuts which
1556         // run along the real axis outside the interval [-1, +1].
1557         if (is_exactly_a<numeric>(x) &&
1558             (!x.imag_part().is_zero() || (x > *_num_1_p && x < *_num1_p))) {
1559                 return atanh(x.conjugate());
1560         }
1561         return conjugate_function(atanh(x)).hold();
1562 }
1563
1564 REGISTER_FUNCTION(atanh, eval_func(atanh_eval).
1565                          evalf_func(atanh_evalf).
1566                          derivative_func(atanh_deriv).
1567                          series_func(atanh_series).
1568                          conjugate_func(atanh_conjugate));
1569
1570
1571 } // namespace GiNaC