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