1 /** @file inifcns_trans.cpp
3 * Implementation of transcendental (and trigonometric and hyperbolic)
7 * GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
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.
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.
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
34 // exponential function
37 ex exp_evalf(ex const & x)
43 return exp(ex_to_numeric(x)); // -> numeric exp(numeric)
46 ex exp_eval(ex const & x)
52 // exp(n*Pi*I/2) -> {+1|+I|-1|-I}
53 ex TwoExOverPiI=(2*x)/(Pi*I);
54 if (TwoExOverPiI.info(info_flags::integer)) {
55 numeric z=mod(ex_to_numeric(TwoExOverPiI),numeric(4));
56 if (z.is_equal(numZERO()))
58 if (z.is_equal(numONE()))
60 if (z.is_equal(numTWO()))
62 if (z.is_equal(numTHREE()))
66 if (is_ex_the_function(x, log))
70 if (x.info(info_flags::numeric) && !x.info(info_flags::rational))
76 ex exp_diff(ex const & x, unsigned diff_param)
78 ASSERT(diff_param==0);
83 REGISTER_FUNCTION(exp, exp_eval, exp_evalf, exp_diff, NULL);
89 ex log_evalf(ex const & x)
95 return log(ex_to_numeric(x)); // -> numeric log(numeric)
98 ex log_eval(ex const & x)
100 if (x.info(info_flags::numeric)) {
102 if (x.is_equal(exONE()))
105 if (x.is_equal(exMINUSONE()))
109 return (I*Pi*numeric(1,2));
110 // log(-I) -> -Pi*I/2
112 return (I*Pi*numeric(-1,2));
113 // log(0) -> throw singularity
114 if (x.is_equal(exZERO()))
115 throw(std::domain_error("log_eval(): log(0)"));
117 if (!x.info(info_flags::rational))
121 return log(x).hold();
124 ex log_diff(ex const & x, unsigned diff_param)
126 ASSERT(diff_param==0);
131 REGISTER_FUNCTION(log, log_eval, log_evalf, log_diff, NULL);
134 // sine (trigonometric function)
137 ex sin_evalf(ex const & x)
141 END_TYPECHECK(sin(x))
143 return sin(ex_to_numeric(x)); // -> numeric sin(numeric)
146 ex sin_eval(ex const & x)
150 if (xOverPi.info(info_flags::integer))
153 // sin((2n+1)*Pi/2) -> {+|-}1
154 ex xOverPiMinusHalf=xOverPi-exHALF();
155 if (xOverPiMinusHalf.info(info_flags::even))
157 else if (xOverPiMinusHalf.info(info_flags::odd))
160 if (is_ex_exactly_of_type(x, function)) {
163 if (is_ex_the_function(x, asin))
165 // sin(acos(x)) -> (1-x^2)^(1/2)
166 if (is_ex_the_function(x, acos))
167 return power(exONE()-power(t,exTWO()),exHALF());
168 // sin(atan(x)) -> x*(1+x^2)^(-1/2)
169 if (is_ex_the_function(x, atan))
170 return t*power(exONE()+power(t,exTWO()),exMINUSHALF());
173 // sin(float) -> float
174 if (x.info(info_flags::numeric) && !x.info(info_flags::rational))
177 return sin(x).hold();
180 ex sin_diff(ex const & x, unsigned diff_param)
182 ASSERT(diff_param==0);
187 REGISTER_FUNCTION(sin, sin_eval, sin_evalf, sin_diff, NULL);
190 // cosine (trigonometric function)
193 ex cos_evalf(ex const & x)
197 END_TYPECHECK(cos(x))
199 return cos(ex_to_numeric(x)); // -> numeric cos(numeric)
202 ex cos_eval(ex const & x)
204 // cos(n*Pi) -> {+|-}1
206 if (xOverPi.info(info_flags::even))
208 else if (xOverPi.info(info_flags::odd))
211 // cos((2n+1)*Pi/2) -> 0
212 ex xOverPiMinusHalf=xOverPi-exHALF();
213 if (xOverPiMinusHalf.info(info_flags::integer))
216 if (is_ex_exactly_of_type(x, function)) {
219 if (is_ex_the_function(x, acos))
221 // cos(asin(x)) -> (1-x^2)^(1/2)
222 if (is_ex_the_function(x, asin))
223 return power(exONE()-power(t,exTWO()),exHALF());
224 // cos(atan(x)) -> (1+x^2)^(-1/2)
225 if (is_ex_the_function(x, atan))
226 return power(exONE()+power(t,exTWO()),exMINUSHALF());
229 // cos(float) -> float
230 if (x.info(info_flags::numeric) && !x.info(info_flags::rational))
233 return cos(x).hold();
236 ex cos_diff(ex const & x, unsigned diff_param)
238 ASSERT(diff_param==0);
240 return numMINUSONE()*sin(x);
243 REGISTER_FUNCTION(cos, cos_eval, cos_evalf, cos_diff, NULL);
246 // tangent (trigonometric function)
249 ex tan_evalf(ex const & x)
253 END_TYPECHECK(tan(x)) // -> numeric tan(numeric)
255 return tan(ex_to_numeric(x));
258 ex tan_eval(ex const & x)
260 // tan(n*Pi/3) -> {0|3^(1/2)|-(3^(1/2))}
261 ex ThreeExOverPi=numTHREE()*x/Pi;
262 if (ThreeExOverPi.info(info_flags::integer)) {
263 numeric z=mod(ex_to_numeric(ThreeExOverPi),numeric(3));
264 if (z.is_equal(numZERO()))
266 if (z.is_equal(numONE()))
267 return power(exTHREE(),exHALF());
268 if (z.is_equal(numTWO()))
269 return -power(exTHREE(),exHALF());
272 // tan((2n+1)*Pi/2) -> throw
273 ex ExOverPiMinusHalf=x/Pi-exHALF();
274 if (ExOverPiMinusHalf.info(info_flags::integer))
275 throw (std::domain_error("tan_eval(): infinity"));
277 if (is_ex_exactly_of_type(x, function)) {
280 if (is_ex_the_function(x, atan))
282 // tan(asin(x)) -> x*(1+x^2)^(-1/2)
283 if (is_ex_the_function(x, asin))
284 return t*power(exONE()-power(t,exTWO()),exMINUSHALF());
285 // tan(acos(x)) -> (1-x^2)^(1/2)/x
286 if (is_ex_the_function(x, acos))
287 return power(t,exMINUSONE())*power(exONE()-power(t,exTWO()),exHALF());
290 // tan(float) -> float
291 if (x.info(info_flags::numeric) && !x.info(info_flags::rational)) {
295 return tan(x).hold();
298 ex tan_diff(ex const & x, unsigned diff_param)
300 ASSERT(diff_param==0);
302 return (1+power(tan(x),exTWO()));
305 REGISTER_FUNCTION(tan, tan_eval, tan_evalf, tan_diff, NULL);
308 // inverse sine (arc sine)
311 ex asin_evalf(ex const & x)
315 END_TYPECHECK(asin(x))
317 return asin(ex_to_numeric(x)); // -> numeric asin(numeric)
320 ex asin_eval(ex const & x)
322 if (x.info(info_flags::numeric)) {
327 if (x.is_equal(exHALF()))
328 return numeric(1,6)*Pi;
330 if (x.is_equal(exONE()))
331 return numeric(1,2)*Pi;
332 // asin(-1/2) -> -Pi/6
333 if (x.is_equal(exMINUSHALF()))
334 return numeric(-1,6)*Pi;
336 if (x.is_equal(exMINUSONE()))
337 return numeric(-1,2)*Pi;
338 // asin(float) -> float
339 if (!x.info(info_flags::rational))
340 return asin_evalf(x);
343 return asin(x).hold();
346 ex asin_diff(ex const & x, unsigned diff_param)
348 ASSERT(diff_param==0);
350 return power(1-power(x,exTWO()),exMINUSHALF());
353 REGISTER_FUNCTION(asin, asin_eval, asin_evalf, asin_diff, NULL);
356 // inverse cosine (arc cosine)
359 ex acos_evalf(ex const & x)
363 END_TYPECHECK(acos(x))
365 return acos(ex_to_numeric(x)); // -> numeric acos(numeric)
368 ex acos_eval(ex const & x)
370 if (x.info(info_flags::numeric)) {
372 if (x.is_equal(exONE()))
375 if (x.is_equal(exHALF()))
376 return numeric(1,3)*Pi;
379 return numeric(1,2)*Pi;
380 // acos(-1/2) -> 2/3*Pi
381 if (x.is_equal(exMINUSHALF()))
382 return numeric(2,3)*Pi;
384 if (x.is_equal(exMINUSONE()))
386 // acos(float) -> float
387 if (!x.info(info_flags::rational))
388 return acos_evalf(x);
391 return acos(x).hold();
394 ex acos_diff(ex const & x, unsigned diff_param)
396 ASSERT(diff_param==0);
398 return numMINUSONE()*power(1-power(x,exTWO()),exMINUSHALF());
401 REGISTER_FUNCTION(acos, acos_eval, acos_evalf, acos_diff, NULL);
404 // inverse tangent (arc tangent)
407 ex atan_evalf(ex const & x)
411 END_TYPECHECK(atan(x))
413 return atan(ex_to_numeric(x)); // -> numeric atan(numeric)
416 ex atan_eval(ex const & x)
418 if (x.info(info_flags::numeric)) {
420 if (x.is_equal(exZERO()))
422 // atan(float) -> float
423 if (!x.info(info_flags::rational))
424 return atan_evalf(x);
427 return atan(x).hold();
430 ex atan_diff(ex const & x, unsigned diff_param)
432 ASSERT(diff_param==0);
434 return power(1+x*x, -1);
437 REGISTER_FUNCTION(atan, atan_eval, atan_evalf, atan_diff, NULL);
440 // inverse tangent (atan2(y,x))
443 ex atan2_evalf(ex const & y, ex const & x)
448 END_TYPECHECK(atan2(y,x))
450 return atan(ex_to_numeric(y),ex_to_numeric(x)); // -> numeric atan(numeric)
453 ex atan2_eval(ex const & y, ex const & x)
455 if (y.info(info_flags::numeric) && !y.info(info_flags::rational) &&
456 x.info(info_flags::numeric) && !x.info(info_flags::rational)) {
457 return atan2_evalf(y,x);
460 return atan2(y,x).hold();
463 ex atan2_diff(ex const & y, ex const & x, unsigned diff_param)
465 ASSERT(diff_param<2);
469 return power(x*(1+y*y/(x*x)),-1);
472 return -y*power(x*x+y*y,-1);
475 REGISTER_FUNCTION(atan2, atan2_eval, atan2_evalf, atan2_diff, NULL);
478 // hyperbolic sine (trigonometric function)
481 ex sinh_evalf(ex const & x)
485 END_TYPECHECK(sinh(x))
487 return sinh(ex_to_numeric(x)); // -> numeric sinh(numeric)
490 ex sinh_eval(ex const & x)
492 if (x.info(info_flags::numeric)) {
496 // sinh(float) -> float
497 if (!x.info(info_flags::rational))
498 return sinh_evalf(x);
501 if (is_ex_exactly_of_type(x, function)) {
503 // sinh(asinh(x)) -> x
504 if (is_ex_the_function(x, asinh))
506 // sinh(acosh(x)) -> (x-1)^(1/2) * (x+1)^(1/2)
507 if (is_ex_the_function(x, acosh))
508 return power(t-exONE(),exHALF())*power(t+exONE(),exHALF());
509 // sinh(atanh(x)) -> x*(1-x^2)^(-1/2)
510 if (is_ex_the_function(x, atanh))
511 return t*power(exONE()-power(t,exTWO()),exMINUSHALF());
514 return sinh(x).hold();
517 ex sinh_diff(ex const & x, unsigned diff_param)
519 ASSERT(diff_param==0);
524 REGISTER_FUNCTION(sinh, sinh_eval, sinh_evalf, sinh_diff, NULL);
527 // hyperbolic cosine (trigonometric function)
530 ex cosh_evalf(ex const & x)
534 END_TYPECHECK(cosh(x))
536 return cosh(ex_to_numeric(x)); // -> numeric cosh(numeric)
539 ex cosh_eval(ex const & x)
541 if (x.info(info_flags::numeric)) {
545 // cosh(float) -> float
546 if (!x.info(info_flags::rational))
547 return cosh_evalf(x);
550 if (is_ex_exactly_of_type(x, function)) {
552 // cosh(acosh(x)) -> x
553 if (is_ex_the_function(x, acosh))
555 // cosh(asinh(x)) -> (1+x^2)^(1/2)
556 if (is_ex_the_function(x, asinh))
557 return power(exONE()+power(t,exTWO()),exHALF());
558 // cosh(atanh(x)) -> (1-x^2)^(-1/2)
559 if (is_ex_the_function(x, atanh))
560 return power(exONE()-power(t,exTWO()),exMINUSHALF());
563 return cosh(x).hold();
566 ex cosh_diff(ex const & x, unsigned diff_param)
568 ASSERT(diff_param==0);
573 REGISTER_FUNCTION(cosh, cosh_eval, cosh_evalf, cosh_diff, NULL);
576 // hyperbolic tangent (trigonometric function)
579 ex tanh_evalf(ex const & x)
583 END_TYPECHECK(tanh(x))
585 return tanh(ex_to_numeric(x)); // -> numeric tanh(numeric)
588 ex tanh_eval(ex const & x)
590 if (x.info(info_flags::numeric)) {
594 // tanh(float) -> float
595 if (!x.info(info_flags::rational))
596 return tanh_evalf(x);
599 if (is_ex_exactly_of_type(x, function)) {
601 // tanh(atanh(x)) -> x
602 if (is_ex_the_function(x, atanh))
604 // tanh(asinh(x)) -> x*(1+x^2)^(-1/2)
605 if (is_ex_the_function(x, asinh))
606 return t*power(exONE()+power(t,exTWO()),exMINUSHALF());
607 // tanh(acosh(x)) -> (x-1)^(1/2)*(x+1)^(1/2)/x
608 if (is_ex_the_function(x, acosh))
609 return power(t-exONE(),exHALF())*power(t+exONE(),exHALF())*power(t,exMINUSONE());
612 return tanh(x).hold();
615 ex tanh_diff(ex const & x, unsigned diff_param)
617 ASSERT(diff_param==0);
619 return exONE()-power(tanh(x),exTWO());
622 REGISTER_FUNCTION(tanh, tanh_eval, tanh_evalf, tanh_diff, NULL);
625 // inverse hyperbolic sine (trigonometric function)
628 ex asinh_evalf(ex const & x)
632 END_TYPECHECK(asinh(x))
634 return asinh(ex_to_numeric(x)); // -> numeric asinh(numeric)
637 ex asinh_eval(ex const & x)
639 if (x.info(info_flags::numeric)) {
643 // asinh(float) -> float
644 if (!x.info(info_flags::rational))
645 return asinh_evalf(x);
648 return asinh(x).hold();
651 ex asinh_diff(ex const & x, unsigned diff_param)
653 ASSERT(diff_param==0);
655 return power(1+power(x,exTWO()),exMINUSHALF());
658 REGISTER_FUNCTION(asinh, asinh_eval, asinh_evalf, asinh_diff, NULL);
661 // inverse hyperbolic cosine (trigonometric function)
664 ex acosh_evalf(ex const & x)
668 END_TYPECHECK(acosh(x))
670 return acosh(ex_to_numeric(x)); // -> numeric acosh(numeric)
673 ex acosh_eval(ex const & x)
675 if (x.info(info_flags::numeric)) {
676 // acosh(0) -> Pi*I/2
678 return Pi*I*numeric(1,2);
680 if (x.is_equal(exONE()))
683 if (x.is_equal(exMINUSONE()))
685 // acosh(float) -> float
686 if (!x.info(info_flags::rational))
687 return acosh_evalf(x);
690 return acosh(x).hold();
693 ex acosh_diff(ex const & x, unsigned diff_param)
695 ASSERT(diff_param==0);
697 return power(x-1,exMINUSHALF())*power(x+1,exMINUSHALF());
700 REGISTER_FUNCTION(acosh, acosh_eval, acosh_evalf, acosh_diff, NULL);
703 // inverse hyperbolic tangent (trigonometric function)
706 ex atanh_evalf(ex const & x)
710 END_TYPECHECK(atanh(x))
712 return atanh(ex_to_numeric(x)); // -> numeric atanh(numeric)
715 ex atanh_eval(ex const & x)
717 if (x.info(info_flags::numeric)) {
721 // atanh({+|-}1) -> throw
722 if (x.is_equal(exONE()) || x.is_equal(exONE()))
723 throw (std::domain_error("atanh_eval(): infinity"));
724 // atanh(float) -> float
725 if (!x.info(info_flags::rational))
726 return atanh_evalf(x);
729 return atanh(x).hold();
732 ex atanh_diff(ex const & x, unsigned diff_param)
734 ASSERT(diff_param==0);
736 return power(exONE()-power(x,exTWO()),exMINUSONE());
739 REGISTER_FUNCTION(atanh, atanh_eval, atanh_evalf, atanh_diff, NULL);