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