]> www.ginac.de Git - ginac.git/blob - ginac/inifcns_trans.cpp
a37f7163ce9647c48969fdb2434a55c7d5a25d71
[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-2001 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include <vector>
25 #include <stdexcept>
26
27 #include "inifcns.h"
28 #include "ex.h"
29 #include "constant.h"
30 #include "numeric.h"
31 #include "power.h"
32 #include "relational.h"
33 #include "symbol.h"
34 #include "pseries.h"
35 #include "utils.h"
36
37 namespace GiNaC {
38
39 //////////
40 // exponential function
41 //////////
42
43 static ex exp_evalf(const ex & x)
44 {
45         BEGIN_TYPECHECK
46                 TYPECHECK(x,numeric)
47         END_TYPECHECK(exp(x))
48         
49         return exp(ex_to<numeric>(x)); // -> numeric exp(numeric)
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         // exp(n*Pi*I/2) -> {+1|+I|-1|-I}
59         ex TwoExOverPiI=(_ex2()*x)/(Pi*I);
60         if (TwoExOverPiI.info(info_flags::integer)) {
61                 numeric z=mod(ex_to<numeric>(TwoExOverPiI),_num4());
62                 if (z.is_equal(_num0()))
63                         return _ex1();
64                 if (z.is_equal(_num1()))
65                         return ex(I);
66                 if (z.is_equal(_num2()))
67                         return _ex_1();
68                 if (z.is_equal(_num3()))
69                         return ex(-I);
70         }
71         // exp(log(x)) -> x
72         if (is_ex_the_function(x, log))
73                 return x.op(0);
74         
75         // exp(float)
76         if (x.info(info_flags::numeric) && !x.info(info_flags::crational))
77                 return exp_evalf(x);
78         
79         return exp(x).hold();
80 }
81
82 static ex exp_deriv(const ex & x, unsigned deriv_param)
83 {
84         GINAC_ASSERT(deriv_param==0);
85
86         // d/dx exp(x) -> exp(x)
87         return exp(x);
88 }
89
90 REGISTER_FUNCTION(exp, eval_func(exp_eval).
91                        evalf_func(exp_evalf).
92                        derivative_func(exp_deriv).
93                        latex_name("\\exp"));
94
95 //////////
96 // natural logarithm
97 //////////
98
99 static ex log_evalf(const ex & x)
100 {
101         BEGIN_TYPECHECK
102                 TYPECHECK(x,numeric)
103         END_TYPECHECK(log(x))
104         
105         return log(ex_to<numeric>(x)); // -> numeric log(numeric)
106 }
107
108 static ex log_eval(const ex & x)
109 {
110         if (x.info(info_flags::numeric)) {
111                 if (x.is_equal(_ex0()))  // log(0) -> infinity
112                         throw(pole_error("log_eval(): log(0)",0));
113                 if (x.info(info_flags::real) && x.info(info_flags::negative))
114                         return (log(-x)+I*Pi);
115                 if (x.is_equal(_ex1()))  // log(1) -> 0
116                         return _ex0();
117                 if (x.is_equal(I))       // log(I) -> Pi*I/2
118                         return (Pi*I*_num1_2());
119                 if (x.is_equal(-I))      // log(-I) -> -Pi*I/2
120                         return (Pi*I*_num_1_2());
121                 // log(float)
122                 if (!x.info(info_flags::crational))
123                         return log_evalf(x);
124         }
125         // log(exp(t)) -> t (if -Pi < t.imag() <= Pi):
126         if (is_ex_the_function(x, exp)) {
127                 ex t = x.op(0);
128                 if (t.info(info_flags::numeric)) {
129                         numeric nt = ex_to<numeric>(t);
130                         if (nt.is_real())
131                                 return t;
132                 }
133         }
134         
135         return log(x).hold();
136 }
137
138 static ex log_deriv(const ex & x, unsigned deriv_param)
139 {
140         GINAC_ASSERT(deriv_param==0);
141         
142         // d/dx log(x) -> 1/x
143         return power(x, _ex_1());
144 }
145
146 static ex log_series(const ex &arg,
147                      const relational &rel,
148                      int order,
149                      unsigned options)
150 {
151         GINAC_ASSERT(is_ex_exactly_of_type(rel.lhs(),symbol));
152         ex arg_pt;
153         bool must_expand_arg = false;
154         // maybe substitution of rel into arg fails because of a pole
155         try {
156                 arg_pt = arg.subs(rel);
157         } catch (pole_error) {
158                 must_expand_arg = true;
159         }
160         // or we are at the branch point anyways
161         if (arg_pt.is_zero())
162                 must_expand_arg = true;
163         
164         if (must_expand_arg) {
165                 // method:
166                 // This is the branch point: Series expand the argument first, then
167                 // trivially factorize it to isolate that part which has constant
168                 // leading coefficient in this fashion:
169                 //   x^n + Order(x^(n+m))  ->  x^n * (1 + Order(x^m)).
170                 // Return a plain n*log(x) for the x^n part and series expand the
171                 // other part.  Add them together and reexpand again in order to have
172                 // one unnested pseries object.  All this also works for negative n.
173                 const pseries argser = ex_to<pseries>(arg.series(rel, order, options));
174                 const symbol *s = static_cast<symbol *>(rel.lhs().bp);
175                 const ex point = rel.rhs();
176                 const int n = argser.ldegree(*s);
177                 epvector seq;
178                 // construct what we carelessly called the n*log(x) term above
179                 ex coeff = argser.coeff(*s, n);
180                 // expand the log, but only if coeff is real and > 0, since otherwise
181                 // it would make the branch cut run into the wrong direction
182                 if (coeff.info(info_flags::positive))
183                         seq.push_back(expair(n*log(*s-point)+log(coeff), _ex0()));
184                 else
185                         seq.push_back(expair(log(coeff*pow(*s-point, n)), _ex0()));
186                 if (!argser.is_terminating() || argser.nops()!=1) {
187                         // in this case n more terms are needed
188                         // (sadly, to generate them, we have to start from the beginning)
189                         ex newarg = ex_to<pseries>((arg/coeff).series(rel, order+n, options)).shift_exponents(-n).convert_to_poly(true);
190                         return pseries(rel, seq).add_series(ex_to<pseries>(log(newarg).series(rel, order, options)));
191                 } else  // it was a monomial
192                         return pseries(rel, seq);
193         }
194         if (!(options & series_options::suppress_branchcut) &&
195              arg_pt.info(info_flags::negative)) {
196                 // method:
197                 // This is the branch cut: assemble the primitive series manually and
198                 // then add the corresponding complex step function.
199                 const symbol *s = static_cast<symbol *>(rel.lhs().bp);
200                 const ex point = rel.rhs();
201                 const symbol foo;
202                 ex replarg = series(log(arg), *s==foo, order).subs(foo==point);
203                 epvector seq;
204                 seq.push_back(expair(-I*csgn(arg*I)*Pi, _ex0()));
205                 seq.push_back(expair(Order(_ex1()), order));
206                 return series(replarg - I*Pi + pseries(rel, seq), rel, order);
207         }
208         throw do_taylor();  // caught by function::series()
209 }
210
211 REGISTER_FUNCTION(log, eval_func(log_eval).
212                        evalf_func(log_evalf).
213                        derivative_func(log_deriv).
214                        series_func(log_series).
215                        latex_name("\\ln"));
216
217 //////////
218 // sine (trigonometric function)
219 //////////
220
221 static ex sin_evalf(const ex & x)
222 {
223         BEGIN_TYPECHECK
224            TYPECHECK(x,numeric)
225         END_TYPECHECK(sin(x))
226         
227         return sin(ex_to<numeric>(x)); // -> numeric sin(numeric)
228 }
229
230 static ex sin_eval(const ex & x)
231 {
232         // sin(n/d*Pi) -> { all known non-nested radicals }
233         ex SixtyExOverPi = _ex60()*x/Pi;
234         ex sign = _ex1();
235         if (SixtyExOverPi.info(info_flags::integer)) {
236                 numeric z = mod(ex_to<numeric>(SixtyExOverPi),_num120());
237                 if (z>=_num60()) {
238                         // wrap to interval [0, Pi)
239                         z -= _num60();
240                         sign = _ex_1();
241                 }
242                 if (z>_num30()) {
243                         // wrap to interval [0, Pi/2)
244                         z = _num60()-z;
245                 }
246                 if (z.is_equal(_num0()))  // sin(0)       -> 0
247                         return _ex0();
248                 if (z.is_equal(_num5()))  // sin(Pi/12)   -> sqrt(6)/4*(1-sqrt(3)/3)
249                         return sign*_ex1_4()*power(_ex6(),_ex1_2())*(_ex1()+_ex_1_3()*power(_ex3(),_ex1_2()));
250                 if (z.is_equal(_num6()))  // sin(Pi/10)   -> sqrt(5)/4-1/4
251                         return sign*(_ex1_4()*power(_ex5(),_ex1_2())+_ex_1_4());
252                 if (z.is_equal(_num10())) // sin(Pi/6)    -> 1/2
253                         return sign*_ex1_2();
254                 if (z.is_equal(_num15())) // sin(Pi/4)    -> sqrt(2)/2
255                         return sign*_ex1_2()*power(_ex2(),_ex1_2());
256                 if (z.is_equal(_num18())) // sin(3/10*Pi) -> sqrt(5)/4+1/4
257                         return sign*(_ex1_4()*power(_ex5(),_ex1_2())+_ex1_4());
258                 if (z.is_equal(_num20())) // sin(Pi/3)    -> sqrt(3)/2
259                         return sign*_ex1_2()*power(_ex3(),_ex1_2());
260                 if (z.is_equal(_num25())) // sin(5/12*Pi) -> sqrt(6)/4*(1+sqrt(3)/3)
261                         return sign*_ex1_4()*power(_ex6(),_ex1_2())*(_ex1()+_ex1_3()*power(_ex3(),_ex1_2()));
262                 if (z.is_equal(_num30())) // sin(Pi/2)    -> 1
263                         return sign*_ex1();
264         }
265         
266         if (is_ex_exactly_of_type(x, function)) {
267                 ex t = x.op(0);
268                 // sin(asin(x)) -> x
269                 if (is_ex_the_function(x, asin))
270                         return t;
271                 // sin(acos(x)) -> sqrt(1-x^2)
272                 if (is_ex_the_function(x, acos))
273                         return power(_ex1()-power(t,_ex2()),_ex1_2());
274                 // sin(atan(x)) -> x*(1+x^2)^(-1/2)
275                 if (is_ex_the_function(x, atan))
276                         return t*power(_ex1()+power(t,_ex2()),_ex_1_2());
277         }
278         
279         // sin(float) -> float
280         if (x.info(info_flags::numeric) && !x.info(info_flags::crational))
281                 return sin_evalf(x);
282         
283         return sin(x).hold();
284 }
285
286 static ex sin_deriv(const ex & x, unsigned deriv_param)
287 {
288         GINAC_ASSERT(deriv_param==0);
289         
290         // d/dx sin(x) -> cos(x)
291         return cos(x);
292 }
293
294 REGISTER_FUNCTION(sin, eval_func(sin_eval).
295                        evalf_func(sin_evalf).
296                        derivative_func(sin_deriv).
297                        latex_name("\\sin"));
298
299 //////////
300 // cosine (trigonometric function)
301 //////////
302
303 static ex cos_evalf(const ex & x)
304 {
305         BEGIN_TYPECHECK
306                 TYPECHECK(x,numeric)
307         END_TYPECHECK(cos(x))
308         
309         return cos(ex_to<numeric>(x)); // -> numeric cos(numeric)
310 }
311
312 static ex cos_eval(const ex & x)
313 {
314         // cos(n/d*Pi) -> { all known non-nested radicals }
315         ex SixtyExOverPi = _ex60()*x/Pi;
316         ex sign = _ex1();
317         if (SixtyExOverPi.info(info_flags::integer)) {
318                 numeric z = mod(ex_to<numeric>(SixtyExOverPi),_num120());
319                 if (z>=_num60()) {
320                         // wrap to interval [0, Pi)
321                         z = _num120()-z;
322                 }
323                 if (z>=_num30()) {
324                         // wrap to interval [0, Pi/2)
325                         z = _num60()-z;
326                         sign = _ex_1();
327                 }
328                 if (z.is_equal(_num0()))  // cos(0)       -> 1
329                         return sign*_ex1();
330                 if (z.is_equal(_num5()))  // cos(Pi/12)   -> sqrt(6)/4*(1+sqrt(3)/3)
331                         return sign*_ex1_4()*power(_ex6(),_ex1_2())*(_ex1()+_ex1_3()*power(_ex3(),_ex1_2()));
332                 if (z.is_equal(_num10())) // cos(Pi/6)    -> sqrt(3)/2
333                         return sign*_ex1_2()*power(_ex3(),_ex1_2());
334                 if (z.is_equal(_num12())) // cos(Pi/5)    -> sqrt(5)/4+1/4
335                         return sign*(_ex1_4()*power(_ex5(),_ex1_2())+_ex1_4());
336                 if (z.is_equal(_num15())) // cos(Pi/4)    -> sqrt(2)/2
337                         return sign*_ex1_2()*power(_ex2(),_ex1_2());
338                 if (z.is_equal(_num20())) // cos(Pi/3)    -> 1/2
339                         return sign*_ex1_2();
340                 if (z.is_equal(_num24())) // cos(2/5*Pi)  -> sqrt(5)/4-1/4x
341                         return sign*(_ex1_4()*power(_ex5(),_ex1_2())+_ex_1_4());
342                 if (z.is_equal(_num25())) // cos(5/12*Pi) -> sqrt(6)/4*(1-sqrt(3)/3)
343                         return sign*_ex1_4()*power(_ex6(),_ex1_2())*(_ex1()+_ex_1_3()*power(_ex3(),_ex1_2()));
344                 if (z.is_equal(_num30())) // cos(Pi/2)    -> 0
345                         return sign*_ex0();
346         }
347         
348         if (is_ex_exactly_of_type(x, function)) {
349                 ex t = x.op(0);
350                 // cos(acos(x)) -> x
351                 if (is_ex_the_function(x, acos))
352                         return t;
353                 // cos(asin(x)) -> (1-x^2)^(1/2)
354                 if (is_ex_the_function(x, asin))
355                         return power(_ex1()-power(t,_ex2()),_ex1_2());
356                 // cos(atan(x)) -> (1+x^2)^(-1/2)
357                 if (is_ex_the_function(x, atan))
358                         return power(_ex1()+power(t,_ex2()),_ex_1_2());
359         }
360         
361         // cos(float) -> float
362         if (x.info(info_flags::numeric) && !x.info(info_flags::crational))
363                 return cos_evalf(x);
364         
365         return cos(x).hold();
366 }
367
368 static ex cos_deriv(const ex & x, unsigned deriv_param)
369 {
370         GINAC_ASSERT(deriv_param==0);
371
372         // d/dx cos(x) -> -sin(x)
373         return _ex_1()*sin(x);
374 }
375
376 REGISTER_FUNCTION(cos, eval_func(cos_eval).
377                        evalf_func(cos_evalf).
378                        derivative_func(cos_deriv).
379                        latex_name("\\cos"));
380
381 //////////
382 // tangent (trigonometric function)
383 //////////
384
385 static ex tan_evalf(const ex & x)
386 {
387         BEGIN_TYPECHECK
388            TYPECHECK(x,numeric)
389         END_TYPECHECK(tan(x)) // -> numeric tan(numeric)
390         
391         return tan(ex_to<numeric>(x));
392 }
393
394 static ex tan_eval(const ex & x)
395 {
396         // tan(n/d*Pi) -> { all known non-nested radicals }
397         ex SixtyExOverPi = _ex60()*x/Pi;
398         ex sign = _ex1();
399         if (SixtyExOverPi.info(info_flags::integer)) {
400                 numeric z = mod(ex_to<numeric>(SixtyExOverPi),_num60());
401                 if (z>=_num60()) {
402                         // wrap to interval [0, Pi)
403                         z -= _num60();
404                 }
405                 if (z>=_num30()) {
406                         // wrap to interval [0, Pi/2)
407                         z = _num60()-z;
408                         sign = _ex_1();
409                 }
410                 if (z.is_equal(_num0()))  // tan(0)       -> 0
411                         return _ex0();
412                 if (z.is_equal(_num5()))  // tan(Pi/12)   -> 2-sqrt(3)
413                         return sign*(_ex2()-power(_ex3(),_ex1_2()));
414                 if (z.is_equal(_num10())) // tan(Pi/6)    -> sqrt(3)/3
415                         return sign*_ex1_3()*power(_ex3(),_ex1_2());
416                 if (z.is_equal(_num15())) // tan(Pi/4)    -> 1
417                         return sign*_ex1();
418                 if (z.is_equal(_num20())) // tan(Pi/3)    -> sqrt(3)
419                         return sign*power(_ex3(),_ex1_2());
420                 if (z.is_equal(_num25())) // tan(5/12*Pi) -> 2+sqrt(3)
421                         return sign*(power(_ex3(),_ex1_2())+_ex2());
422                 if (z.is_equal(_num30())) // tan(Pi/2)    -> infinity
423                         throw (pole_error("tan_eval(): simple pole",1));
424         }
425         
426         if (is_ex_exactly_of_type(x, function)) {
427                 ex t = x.op(0);
428                 // tan(atan(x)) -> x
429                 if (is_ex_the_function(x, atan))
430                         return t;
431                 // tan(asin(x)) -> x*(1+x^2)^(-1/2)
432                 if (is_ex_the_function(x, asin))
433                         return t*power(_ex1()-power(t,_ex2()),_ex_1_2());
434                 // tan(acos(x)) -> (1-x^2)^(1/2)/x
435                 if (is_ex_the_function(x, acos))
436                         return power(t,_ex_1())*power(_ex1()-power(t,_ex2()),_ex1_2());
437         }
438         
439         // tan(float) -> float
440         if (x.info(info_flags::numeric) && !x.info(info_flags::crational)) {
441                 return tan_evalf(x);
442         }
443         
444         return tan(x).hold();
445 }
446
447 static ex tan_deriv(const ex & x, unsigned deriv_param)
448 {
449         GINAC_ASSERT(deriv_param==0);
450         
451         // d/dx tan(x) -> 1+tan(x)^2;
452         return (_ex1()+power(tan(x),_ex2()));
453 }
454
455 static ex tan_series(const ex &x,
456                      const relational &rel,
457                      int order,
458                      unsigned options)
459 {
460         GINAC_ASSERT(is_ex_exactly_of_type(rel.lhs(),symbol));
461         // method:
462         // Taylor series where there is no pole falls back to tan_deriv.
463         // On a pole simply expand sin(x)/cos(x).
464         const ex x_pt = x.subs(rel);
465         if (!(2*x_pt/Pi).info(info_flags::odd))
466                 throw do_taylor();  // caught by function::series()
467         // if we got here we have to care for a simple pole
468         return (sin(x)/cos(x)).series(rel, order+2, options);
469 }
470
471 REGISTER_FUNCTION(tan, eval_func(tan_eval).
472                        evalf_func(tan_evalf).
473                        derivative_func(tan_deriv).
474                        series_func(tan_series).
475                        latex_name("\\tan"));
476
477 //////////
478 // inverse sine (arc sine)
479 //////////
480
481 static ex asin_evalf(const ex & x)
482 {
483         BEGIN_TYPECHECK
484            TYPECHECK(x,numeric)
485         END_TYPECHECK(asin(x))
486         
487         return asin(ex_to<numeric>(x)); // -> numeric asin(numeric)
488 }
489
490 static ex asin_eval(const ex & x)
491 {
492         if (x.info(info_flags::numeric)) {
493                 // asin(0) -> 0
494                 if (x.is_zero())
495                         return x;
496                 // asin(1/2) -> Pi/6
497                 if (x.is_equal(_ex1_2()))
498                         return numeric(1,6)*Pi;
499                 // asin(1) -> Pi/2
500                 if (x.is_equal(_ex1()))
501                         return _num1_2()*Pi;
502                 // asin(-1/2) -> -Pi/6
503                 if (x.is_equal(_ex_1_2()))
504                         return numeric(-1,6)*Pi;
505                 // asin(-1) -> -Pi/2
506                 if (x.is_equal(_ex_1()))
507                         return _num_1_2()*Pi;
508                 // asin(float) -> float
509                 if (!x.info(info_flags::crational))
510                         return asin_evalf(x);
511         }
512         
513         return asin(x).hold();
514 }
515
516 static ex asin_deriv(const ex & x, unsigned deriv_param)
517 {
518         GINAC_ASSERT(deriv_param==0);
519         
520         // d/dx asin(x) -> 1/sqrt(1-x^2)
521         return power(1-power(x,_ex2()),_ex_1_2());
522 }
523
524 REGISTER_FUNCTION(asin, eval_func(asin_eval).
525                         evalf_func(asin_evalf).
526                         derivative_func(asin_deriv).
527                         latex_name("\\arcsin"));
528
529 //////////
530 // inverse cosine (arc cosine)
531 //////////
532
533 static ex acos_evalf(const ex & x)
534 {
535         BEGIN_TYPECHECK
536            TYPECHECK(x,numeric)
537         END_TYPECHECK(acos(x))
538         
539         return acos(ex_to<numeric>(x)); // -> numeric acos(numeric)
540 }
541
542 static ex acos_eval(const ex & x)
543 {
544         if (x.info(info_flags::numeric)) {
545                 // acos(1) -> 0
546                 if (x.is_equal(_ex1()))
547                         return _ex0();
548                 // acos(1/2) -> Pi/3
549                 if (x.is_equal(_ex1_2()))
550                         return _ex1_3()*Pi;
551                 // acos(0) -> Pi/2
552                 if (x.is_zero())
553                         return _ex1_2()*Pi;
554                 // acos(-1/2) -> 2/3*Pi
555                 if (x.is_equal(_ex_1_2()))
556                         return numeric(2,3)*Pi;
557                 // acos(-1) -> Pi
558                 if (x.is_equal(_ex_1()))
559                         return Pi;
560                 // acos(float) -> float
561                 if (!x.info(info_flags::crational))
562                         return acos_evalf(x);
563         }
564         
565         return acos(x).hold();
566 }
567
568 static ex acos_deriv(const ex & x, unsigned deriv_param)
569 {
570         GINAC_ASSERT(deriv_param==0);
571         
572         // d/dx acos(x) -> -1/sqrt(1-x^2)
573         return _ex_1()*power(1-power(x,_ex2()),_ex_1_2());
574 }
575
576 REGISTER_FUNCTION(acos, eval_func(acos_eval).
577                         evalf_func(acos_evalf).
578                         derivative_func(acos_deriv).
579                         latex_name("\\arccos"));
580
581 //////////
582 // inverse tangent (arc tangent)
583 //////////
584
585 static ex atan_evalf(const ex & x)
586 {
587         BEGIN_TYPECHECK
588                 TYPECHECK(x,numeric)
589         END_TYPECHECK(atan(x))
590         
591         return atan(ex_to<numeric>(x)); // -> numeric atan(numeric)
592 }
593
594 static ex atan_eval(const ex & x)
595 {
596         if (x.info(info_flags::numeric)) {
597                 // atan(0) -> 0
598                 if (x.is_equal(_ex0()))
599                         return _ex0();
600                 // atan(1) -> Pi/4
601                 if (x.is_equal(_ex1()))
602                         return _ex1_4()*Pi;
603                 // atan(-1) -> -Pi/4
604                 if (x.is_equal(_ex_1()))
605                         return _ex_1_4()*Pi;
606                 if (x.is_equal(I) || x.is_equal(-I))
607                         throw (pole_error("atan_eval(): logarithmic pole",0));
608                 // atan(float) -> float
609                 if (!x.info(info_flags::crational))
610                         return atan_evalf(x);
611         }
612         
613         return atan(x).hold();
614 }
615
616 static ex atan_deriv(const ex & x, unsigned deriv_param)
617 {
618         GINAC_ASSERT(deriv_param==0);
619
620         // d/dx atan(x) -> 1/(1+x^2)
621         return power(_ex1()+power(x,_ex2()), _ex_1());
622 }
623
624 static ex atan_series(const ex &arg,
625                       const relational &rel,
626                       int order,
627                       unsigned options)
628 {
629         GINAC_ASSERT(is_ex_exactly_of_type(rel.lhs(),symbol));
630         // method:
631         // Taylor series where there is no pole or cut falls back to atan_deriv.
632         // There are two branch cuts, one runnig from I up the imaginary axis and
633         // one running from -I down the imaginary axis.  The points I and -I are
634         // poles.
635         // On the branch cuts and the poles series expand
636         //     (log(1+I*x)-log(1-I*x))/(2*I)
637         // instead.
638         const ex arg_pt = arg.subs(rel);
639         if (!(I*arg_pt).info(info_flags::real))
640                 throw do_taylor();     // Re(x) != 0
641         if ((I*arg_pt).info(info_flags::real) && abs(I*arg_pt)<_ex1())
642                 throw do_taylor();     // Re(x) == 0, but abs(x)<1
643         // care for the poles, using the defining formula for atan()...
644         if (arg_pt.is_equal(I) || arg_pt.is_equal(-I))
645                 return ((log(1+I*arg)-log(1-I*arg))/(2*I)).series(rel, order, options);
646         if (!(options & series_options::suppress_branchcut)) {
647                 // method:
648                 // This is the branch cut: assemble the primitive series manually and
649                 // then add the corresponding complex step function.
650                 const symbol *s = static_cast<symbol *>(rel.lhs().bp);
651                 const ex point = rel.rhs();
652                 const symbol foo;
653                 ex replarg = series(atan(arg), *s==foo, order).subs(foo==point);
654                 ex Order0correction = replarg.op(0)+csgn(arg)*Pi*_ex_1_2();
655                 if ((I*arg_pt)<_ex0())
656                         Order0correction += log((I*arg_pt+_ex_1())/(I*arg_pt+_ex1()))*I*_ex_1_2();
657                 else
658                         Order0correction += log((I*arg_pt+_ex1())/(I*arg_pt+_ex_1()))*I*_ex1_2();
659                 epvector seq;
660                 seq.push_back(expair(Order0correction, _ex0()));
661                 seq.push_back(expair(Order(_ex1()), order));
662                 return series(replarg - pseries(rel, seq), rel, order);
663         }
664         throw do_taylor();
665 }
666
667 REGISTER_FUNCTION(atan, eval_func(atan_eval).
668                         evalf_func(atan_evalf).
669                         derivative_func(atan_deriv).
670                         series_func(atan_series).
671                         latex_name("\\arctan"));
672
673 //////////
674 // inverse tangent (atan2(y,x))
675 //////////
676
677 static ex atan2_evalf(const ex & y, const ex & x)
678 {
679         BEGIN_TYPECHECK
680                 TYPECHECK(y,numeric)
681                 TYPECHECK(x,numeric)
682         END_TYPECHECK(atan2(y,x))
683         
684         return atan(ex_to<numeric>(y),ex_to<numeric>(x)); // -> numeric atan(numeric)
685 }
686
687 static ex atan2_eval(const ex & y, const ex & x)
688 {
689         if (y.info(info_flags::numeric) && !y.info(info_flags::crational) &&
690                 x.info(info_flags::numeric) && !x.info(info_flags::crational)) {
691                 return atan2_evalf(y,x);
692         }
693         
694         return atan2(y,x).hold();
695 }    
696
697 static ex atan2_deriv(const ex & y, const ex & x, unsigned deriv_param)
698 {
699         GINAC_ASSERT(deriv_param<2);
700         
701         if (deriv_param==0) {
702                 // d/dy atan(y,x)
703                 return x*power(power(x,_ex2())+power(y,_ex2()),_ex_1());
704         }
705         // d/dx atan(y,x)
706         return -y*power(power(x,_ex2())+power(y,_ex2()),_ex_1());
707 }
708
709 REGISTER_FUNCTION(atan2, eval_func(atan2_eval).
710                          evalf_func(atan2_evalf).
711                          derivative_func(atan2_deriv));
712
713 //////////
714 // hyperbolic sine (trigonometric function)
715 //////////
716
717 static ex sinh_evalf(const ex & x)
718 {
719         BEGIN_TYPECHECK
720            TYPECHECK(x,numeric)
721         END_TYPECHECK(sinh(x))
722         
723         return sinh(ex_to<numeric>(x)); // -> numeric sinh(numeric)
724 }
725
726 static ex sinh_eval(const ex & x)
727 {
728         if (x.info(info_flags::numeric)) {
729                 if (x.is_zero())  // sinh(0) -> 0
730                         return _ex0();        
731                 if (!x.info(info_flags::crational))  // sinh(float) -> float
732                         return sinh_evalf(x);
733         }
734         
735         if ((x/Pi).info(info_flags::numeric) &&
736                 ex_to<numeric>(x/Pi).real().is_zero())  // sinh(I*x) -> I*sin(x)
737                 return I*sin(x/I);
738         
739         if (is_ex_exactly_of_type(x, function)) {
740                 ex t = x.op(0);
741                 // sinh(asinh(x)) -> x
742                 if (is_ex_the_function(x, asinh))
743                         return t;
744                 // sinh(acosh(x)) -> (x-1)^(1/2) * (x+1)^(1/2)
745                 if (is_ex_the_function(x, acosh))
746                         return power(t-_ex1(),_ex1_2())*power(t+_ex1(),_ex1_2());
747                 // sinh(atanh(x)) -> x*(1-x^2)^(-1/2)
748                 if (is_ex_the_function(x, atanh))
749                         return t*power(_ex1()-power(t,_ex2()),_ex_1_2());
750         }
751         
752         return sinh(x).hold();
753 }
754
755 static ex sinh_deriv(const ex & x, unsigned deriv_param)
756 {
757         GINAC_ASSERT(deriv_param==0);
758         
759         // d/dx sinh(x) -> cosh(x)
760         return cosh(x);
761 }
762
763 REGISTER_FUNCTION(sinh, eval_func(sinh_eval).
764                         evalf_func(sinh_evalf).
765                         derivative_func(sinh_deriv).
766                         latex_name("\\sinh"));
767
768 //////////
769 // hyperbolic cosine (trigonometric function)
770 //////////
771
772 static ex cosh_evalf(const ex & x)
773 {
774         BEGIN_TYPECHECK
775            TYPECHECK(x,numeric)
776         END_TYPECHECK(cosh(x))
777         
778         return cosh(ex_to<numeric>(x)); // -> numeric cosh(numeric)
779 }
780
781 static ex cosh_eval(const ex & x)
782 {
783         if (x.info(info_flags::numeric)) {
784                 if (x.is_zero())  // cosh(0) -> 1
785                         return _ex1();
786                 if (!x.info(info_flags::crational))  // cosh(float) -> float
787                         return cosh_evalf(x);
788         }
789         
790         if ((x/Pi).info(info_flags::numeric) &&
791                 ex_to<numeric>(x/Pi).real().is_zero())  // cosh(I*x) -> cos(x)
792                 return cos(x/I);
793         
794         if (is_ex_exactly_of_type(x, function)) {
795                 ex t = x.op(0);
796                 // cosh(acosh(x)) -> x
797                 if (is_ex_the_function(x, acosh))
798                         return t;
799                 // cosh(asinh(x)) -> (1+x^2)^(1/2)
800                 if (is_ex_the_function(x, asinh))
801                         return power(_ex1()+power(t,_ex2()),_ex1_2());
802                 // cosh(atanh(x)) -> (1-x^2)^(-1/2)
803                 if (is_ex_the_function(x, atanh))
804                         return power(_ex1()-power(t,_ex2()),_ex_1_2());
805         }
806         
807         return cosh(x).hold();
808 }
809
810 static ex cosh_deriv(const ex & x, unsigned deriv_param)
811 {
812         GINAC_ASSERT(deriv_param==0);
813         
814         // d/dx cosh(x) -> sinh(x)
815         return sinh(x);
816 }
817
818 REGISTER_FUNCTION(cosh, eval_func(cosh_eval).
819                         evalf_func(cosh_evalf).
820                         derivative_func(cosh_deriv).
821                         latex_name("\\cosh"));
822
823 //////////
824 // hyperbolic tangent (trigonometric function)
825 //////////
826
827 static ex tanh_evalf(const ex & x)
828 {
829         BEGIN_TYPECHECK
830            TYPECHECK(x,numeric)
831         END_TYPECHECK(tanh(x))
832         
833         return tanh(ex_to<numeric>(x)); // -> numeric tanh(numeric)
834 }
835
836 static ex tanh_eval(const ex & x)
837 {
838         if (x.info(info_flags::numeric)) {
839                 if (x.is_zero())  // tanh(0) -> 0
840                         return _ex0();
841                 if (!x.info(info_flags::crational))  // tanh(float) -> float
842                         return tanh_evalf(x);
843         }
844         
845         if ((x/Pi).info(info_flags::numeric) &&
846                 ex_to<numeric>(x/Pi).real().is_zero())  // tanh(I*x) -> I*tan(x);
847                 return I*tan(x/I);
848         
849         if (is_ex_exactly_of_type(x, function)) {
850                 ex t = x.op(0);
851                 // tanh(atanh(x)) -> x
852                 if (is_ex_the_function(x, atanh))
853                         return t;
854                 // tanh(asinh(x)) -> x*(1+x^2)^(-1/2)
855                 if (is_ex_the_function(x, asinh))
856                         return t*power(_ex1()+power(t,_ex2()),_ex_1_2());
857                 // tanh(acosh(x)) -> (x-1)^(1/2)*(x+1)^(1/2)/x
858                 if (is_ex_the_function(x, acosh))
859                         return power(t-_ex1(),_ex1_2())*power(t+_ex1(),_ex1_2())*power(t,_ex_1());
860         }
861         
862         return tanh(x).hold();
863 }
864
865 static ex tanh_deriv(const ex & x, unsigned deriv_param)
866 {
867         GINAC_ASSERT(deriv_param==0);
868         
869         // d/dx tanh(x) -> 1-tanh(x)^2
870         return _ex1()-power(tanh(x),_ex2());
871 }
872
873 static ex tanh_series(const ex &x,
874                       const relational &rel,
875                       int order,
876                       unsigned options)
877 {
878         GINAC_ASSERT(is_ex_exactly_of_type(rel.lhs(),symbol));
879         // method:
880         // Taylor series where there is no pole falls back to tanh_deriv.
881         // On a pole simply expand sinh(x)/cosh(x).
882         const ex x_pt = x.subs(rel);
883         if (!(2*I*x_pt/Pi).info(info_flags::odd))
884                 throw do_taylor();  // caught by function::series()
885         // if we got here we have to care for a simple pole
886         return (sinh(x)/cosh(x)).series(rel, order+2, options);
887 }
888
889 REGISTER_FUNCTION(tanh, eval_func(tanh_eval).
890                         evalf_func(tanh_evalf).
891                         derivative_func(tanh_deriv).
892                         series_func(tanh_series).
893                         latex_name("\\tanh"));
894
895 //////////
896 // inverse hyperbolic sine (trigonometric function)
897 //////////
898
899 static ex asinh_evalf(const ex & x)
900 {
901         BEGIN_TYPECHECK
902            TYPECHECK(x,numeric)
903         END_TYPECHECK(asinh(x))
904         
905         return asinh(ex_to<numeric>(x)); // -> numeric asinh(numeric)
906 }
907
908 static ex asinh_eval(const ex & x)
909 {
910         if (x.info(info_flags::numeric)) {
911                 // asinh(0) -> 0
912                 if (x.is_zero())
913                         return _ex0();
914                 // asinh(float) -> float
915                 if (!x.info(info_flags::crational))
916                         return asinh_evalf(x);
917         }
918         
919         return asinh(x).hold();
920 }
921
922 static ex asinh_deriv(const ex & x, unsigned deriv_param)
923 {
924         GINAC_ASSERT(deriv_param==0);
925         
926         // d/dx asinh(x) -> 1/sqrt(1+x^2)
927         return power(_ex1()+power(x,_ex2()),_ex_1_2());
928 }
929
930 REGISTER_FUNCTION(asinh, eval_func(asinh_eval).
931                          evalf_func(asinh_evalf).
932                          derivative_func(asinh_deriv));
933
934 //////////
935 // inverse hyperbolic cosine (trigonometric function)
936 //////////
937
938 static ex acosh_evalf(const ex & x)
939 {
940         BEGIN_TYPECHECK
941            TYPECHECK(x,numeric)
942         END_TYPECHECK(acosh(x))
943         
944         return acosh(ex_to<numeric>(x)); // -> numeric acosh(numeric)
945 }
946
947 static ex acosh_eval(const ex & x)
948 {
949         if (x.info(info_flags::numeric)) {
950                 // acosh(0) -> Pi*I/2
951                 if (x.is_zero())
952                         return Pi*I*numeric(1,2);
953                 // acosh(1) -> 0
954                 if (x.is_equal(_ex1()))
955                         return _ex0();
956                 // acosh(-1) -> Pi*I
957                 if (x.is_equal(_ex_1()))
958                         return Pi*I;
959                 // acosh(float) -> float
960                 if (!x.info(info_flags::crational))
961                         return acosh_evalf(x);
962         }
963         
964         return acosh(x).hold();
965 }
966
967 static ex acosh_deriv(const ex & x, unsigned deriv_param)
968 {
969         GINAC_ASSERT(deriv_param==0);
970         
971         // d/dx acosh(x) -> 1/(sqrt(x-1)*sqrt(x+1))
972         return power(x+_ex_1(),_ex_1_2())*power(x+_ex1(),_ex_1_2());
973 }
974
975 REGISTER_FUNCTION(acosh, eval_func(acosh_eval).
976                          evalf_func(acosh_evalf).
977                          derivative_func(acosh_deriv));
978
979 //////////
980 // inverse hyperbolic tangent (trigonometric function)
981 //////////
982
983 static ex atanh_evalf(const ex & x)
984 {
985         BEGIN_TYPECHECK
986            TYPECHECK(x,numeric)
987         END_TYPECHECK(atanh(x))
988         
989         return atanh(ex_to<numeric>(x)); // -> numeric atanh(numeric)
990 }
991
992 static ex atanh_eval(const ex & x)
993 {
994         if (x.info(info_flags::numeric)) {
995                 // atanh(0) -> 0
996                 if (x.is_zero())
997                         return _ex0();
998                 // atanh({+|-}1) -> throw
999                 if (x.is_equal(_ex1()) || x.is_equal(_ex_1()))
1000                         throw (pole_error("atanh_eval(): logarithmic pole",0));
1001                 // atanh(float) -> float
1002                 if (!x.info(info_flags::crational))
1003                         return atanh_evalf(x);
1004         }
1005         
1006         return atanh(x).hold();
1007 }
1008
1009 static ex atanh_deriv(const ex & x, unsigned deriv_param)
1010 {
1011         GINAC_ASSERT(deriv_param==0);
1012         
1013         // d/dx atanh(x) -> 1/(1-x^2)
1014         return power(_ex1()-power(x,_ex2()),_ex_1());
1015 }
1016
1017 static ex atanh_series(const ex &arg,
1018                        const relational &rel,
1019                        int order,
1020                        unsigned options)
1021 {
1022         GINAC_ASSERT(is_ex_exactly_of_type(rel.lhs(),symbol));
1023         // method:
1024         // Taylor series where there is no pole or cut falls back to atanh_deriv.
1025         // There are two branch cuts, one runnig from 1 up the real axis and one
1026         // one running from -1 down the real axis.  The points 1 and -1 are poles
1027         // On the branch cuts and the poles series expand
1028         //     (log(1+x)-log(1-x))/2
1029         // instead.
1030         const ex arg_pt = arg.subs(rel);
1031         if (!(arg_pt).info(info_flags::real))
1032                 throw do_taylor();     // Im(x) != 0
1033         if ((arg_pt).info(info_flags::real) && abs(arg_pt)<_ex1())
1034                 throw do_taylor();     // Im(x) == 0, but abs(x)<1
1035         // care for the poles, using the defining formula for atanh()...
1036         if (arg_pt.is_equal(_ex1()) || arg_pt.is_equal(_ex_1()))
1037                 return ((log(_ex1()+arg)-log(_ex1()-arg))*_ex1_2()).series(rel, order, options);
1038         // ...and the branch cuts (the discontinuity at the cut being just I*Pi)
1039         if (!(options & series_options::suppress_branchcut)) {
1040                 // method:
1041                 // This is the branch cut: assemble the primitive series manually and
1042                 // then add the corresponding complex step function.
1043                 const symbol *s = static_cast<symbol *>(rel.lhs().bp);
1044                 const ex point = rel.rhs();
1045                 const symbol foo;
1046                 ex replarg = series(atanh(arg), *s==foo, order).subs(foo==point);
1047                 ex Order0correction = replarg.op(0)+csgn(I*arg)*Pi*I*_ex1_2();
1048                 if (arg_pt<_ex0())
1049                         Order0correction += log((arg_pt+_ex_1())/(arg_pt+_ex1()))*_ex1_2();
1050                 else
1051                         Order0correction += log((arg_pt+_ex1())/(arg_pt+_ex_1()))*_ex_1_2();
1052                 epvector seq;
1053                 seq.push_back(expair(Order0correction, _ex0()));
1054                 seq.push_back(expair(Order(_ex1()), order));
1055                 return series(replarg - pseries(rel, seq), rel, order);
1056         }
1057         throw do_taylor();
1058 }
1059
1060 REGISTER_FUNCTION(atanh, eval_func(atanh_eval).
1061                          evalf_func(atanh_evalf).
1062                          derivative_func(atanh_deriv).
1063                          series_func(atanh_series));
1064
1065
1066 } // namespace GiNaC