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