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