1 /** @file inifcns_trans.cpp
3 * Implementation of transcendental (and trigonometric and hyperbolic)
6 * GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 // exponential function
32 ex exp_evalf(ex const & x)
38 return exp(ex_to_numeric(x)); // -> numeric exp(numeric)
41 ex exp_eval(ex const & x)
47 // exp(n*Pi*I/2) -> {+1|+I|-1|-I}
48 ex TwoExOverPiI=(2*x)/(Pi*I);
49 if (TwoExOverPiI.info(info_flags::integer)) {
50 numeric z=mod(ex_to_numeric(TwoExOverPiI),numeric(4));
51 if (z.is_equal(numZERO()))
53 if (z.is_equal(numONE()))
55 if (z.is_equal(numTWO()))
57 if (z.is_equal(numTHREE()))
61 if (is_ex_the_function(x, log))
65 if (x.info(info_flags::numeric) && !x.info(info_flags::rational))
71 ex exp_diff(ex const & x, unsigned diff_param)
73 ASSERT(diff_param==0);
78 REGISTER_FUNCTION(exp, exp_eval, exp_evalf, exp_diff, NULL);
84 ex log_evalf(ex const & x)
90 return log(ex_to_numeric(x)); // -> numeric log(numeric)
93 ex log_eval(ex const & x)
95 if (x.info(info_flags::numeric)) {
97 if (x.is_equal(exONE()))
100 if (x.is_equal(exMINUSONE()))
104 return (I*Pi*numeric(1,2));
105 // log(-I) -> -Pi*I/2
107 return (I*Pi*numeric(-1,2));
108 // log(0) -> throw singularity
109 if (x.is_equal(exZERO()))
110 throw(std::domain_error("log_eval(): log(0)"));
112 if (!x.info(info_flags::rational))
116 return log(x).hold();
119 ex log_diff(ex const & x, unsigned diff_param)
121 ASSERT(diff_param==0);
126 REGISTER_FUNCTION(log, log_eval, log_evalf, log_diff, NULL);
129 // sine (trigonometric function)
132 ex sin_evalf(ex const & x)
136 END_TYPECHECK(sin(x))
138 return sin(ex_to_numeric(x)); // -> numeric sin(numeric)
141 ex sin_eval(ex const & x)
145 if (xOverPi.info(info_flags::integer))
148 // sin((2n+1)*Pi/2) -> {+|-}1
149 ex xOverPiMinusHalf=xOverPi-exHALF();
150 if (xOverPiMinusHalf.info(info_flags::even))
152 else if (xOverPiMinusHalf.info(info_flags::odd))
155 if (is_ex_exactly_of_type(x, function)) {
158 if (is_ex_the_function(x, asin))
160 // sin(acos(x)) -> (1-x^2)^(1/2)
161 if (is_ex_the_function(x, acos))
162 return power(exONE()-power(t,exTWO()),exHALF());
163 // sin(atan(x)) -> x*(1+x^2)^(-1/2)
164 if (is_ex_the_function(x, atan))
165 return t*power(exONE()+power(t,exTWO()),exMINUSHALF());
168 // sin(float) -> float
169 if (x.info(info_flags::numeric) && !x.info(info_flags::rational))
172 return sin(x).hold();
175 ex sin_diff(ex const & x, unsigned diff_param)
177 ASSERT(diff_param==0);
182 REGISTER_FUNCTION(sin, sin_eval, sin_evalf, sin_diff, NULL);
185 // cosine (trigonometric function)
188 ex cos_evalf(ex const & x)
192 END_TYPECHECK(cos(x))
194 return cos(ex_to_numeric(x)); // -> numeric cos(numeric)
197 ex cos_eval(ex const & x)
199 // cos(n*Pi) -> {+|-}1
201 if (xOverPi.info(info_flags::even))
203 else if (xOverPi.info(info_flags::odd))
206 // cos((2n+1)*Pi/2) -> 0
207 ex xOverPiMinusHalf=xOverPi-exHALF();
208 if (xOverPiMinusHalf.info(info_flags::integer))
211 if (is_ex_exactly_of_type(x, function)) {
214 if (is_ex_the_function(x, acos))
216 // cos(asin(x)) -> (1-x^2)^(1/2)
217 if (is_ex_the_function(x, asin))
218 return power(exONE()-power(t,exTWO()),exHALF());
219 // cos(atan(x)) -> (1+x^2)^(-1/2)
220 if (is_ex_the_function(x, atan))
221 return power(exONE()+power(t,exTWO()),exMINUSHALF());
224 // cos(float) -> float
225 if (x.info(info_flags::numeric) && !x.info(info_flags::rational))
228 return cos(x).hold();
231 ex cos_diff(ex const & x, unsigned diff_param)
233 ASSERT(diff_param==0);
235 return numMINUSONE()*sin(x);
238 REGISTER_FUNCTION(cos, cos_eval, cos_evalf, cos_diff, NULL);
241 // tangent (trigonometric function)
244 ex tan_evalf(ex const & x)
248 END_TYPECHECK(tan(x)) // -> numeric tan(numeric)
250 return tan(ex_to_numeric(x));
253 ex tan_eval(ex const & x)
255 // tan(n*Pi/3) -> {0|3^(1/2)|-(3^(1/2))}
256 ex ThreeExOverPi=numTHREE()*x/Pi;
257 if (ThreeExOverPi.info(info_flags::integer)) {
258 numeric z=mod(ex_to_numeric(ThreeExOverPi),numeric(3));
259 if (z.is_equal(numZERO()))
261 if (z.is_equal(numONE()))
262 return power(exTHREE(),exHALF());
263 if (z.is_equal(numTWO()))
264 return -power(exTHREE(),exHALF());
267 // tan((2n+1)*Pi/2) -> throw
268 ex ExOverPiMinusHalf=x/Pi-exHALF();
269 if (ExOverPiMinusHalf.info(info_flags::integer))
270 throw (std::domain_error("tan_eval(): infinity"));
272 if (is_ex_exactly_of_type(x, function)) {
275 if (is_ex_the_function(x, atan))
277 // tan(asin(x)) -> x*(1+x^2)^(-1/2)
278 if (is_ex_the_function(x, asin))
279 return t*power(exONE()-power(t,exTWO()),exMINUSHALF());
280 // tan(acos(x)) -> (1-x^2)^(1/2)/x
281 if (is_ex_the_function(x, acos))
282 return power(t,exMINUSONE())*power(exONE()-power(t,exTWO()),exHALF());
285 // tan(float) -> float
286 if (x.info(info_flags::numeric) && !x.info(info_flags::rational)) {
290 return tan(x).hold();
293 ex tan_diff(ex const & x, unsigned diff_param)
295 ASSERT(diff_param==0);
297 return (1+power(tan(x),exTWO()));
300 REGISTER_FUNCTION(tan, tan_eval, tan_evalf, tan_diff, NULL);
303 // inverse sine (arc sine)
306 ex asin_evalf(ex const & x)
310 END_TYPECHECK(asin(x))
312 return asin(ex_to_numeric(x)); // -> numeric asin(numeric)
315 ex asin_eval(ex const & x)
317 if (x.info(info_flags::numeric)) {
322 if (x.is_equal(exHALF()))
323 return numeric(1,6)*Pi;
325 if (x.is_equal(exONE()))
326 return numeric(1,2)*Pi;
327 // asin(-1/2) -> -Pi/6
328 if (x.is_equal(exMINUSHALF()))
329 return numeric(-1,6)*Pi;
331 if (x.is_equal(exMINUSONE()))
332 return numeric(-1,2)*Pi;
333 // asin(float) -> float
334 if (!x.info(info_flags::rational))
335 return asin_evalf(x);
338 return asin(x).hold();
341 ex asin_diff(ex const & x, unsigned diff_param)
343 ASSERT(diff_param==0);
345 return power(1-power(x,exTWO()),exMINUSHALF());
348 REGISTER_FUNCTION(asin, asin_eval, asin_evalf, asin_diff, NULL);
351 // inverse cosine (arc cosine)
354 ex acos_evalf(ex const & x)
358 END_TYPECHECK(acos(x))
360 return acos(ex_to_numeric(x)); // -> numeric acos(numeric)
363 ex acos_eval(ex const & x)
365 if (x.info(info_flags::numeric)) {
367 if (x.is_equal(exONE()))
370 if (x.is_equal(exHALF()))
371 return numeric(1,3)*Pi;
374 return numeric(1,2)*Pi;
375 // acos(-1/2) -> 2/3*Pi
376 if (x.is_equal(exMINUSHALF()))
377 return numeric(2,3)*Pi;
379 if (x.is_equal(exMINUSONE()))
381 // acos(float) -> float
382 if (!x.info(info_flags::rational))
383 return acos_evalf(x);
386 return acos(x).hold();
389 ex acos_diff(ex const & x, unsigned diff_param)
391 ASSERT(diff_param==0);
393 return numMINUSONE()*power(1-power(x,exTWO()),exMINUSHALF());
396 REGISTER_FUNCTION(acos, acos_eval, acos_evalf, acos_diff, NULL);
399 // inverse tangent (arc tangent)
402 ex atan_evalf(ex const & x)
406 END_TYPECHECK(atan(x))
408 return atan(ex_to_numeric(x)); // -> numeric atan(numeric)
411 ex atan_eval(ex const & x)
413 if (x.info(info_flags::numeric)) {
415 if (x.is_equal(exZERO()))
417 // atan(float) -> float
418 if (!x.info(info_flags::rational))
419 return atan_evalf(x);
422 return atan(x).hold();
425 ex atan_diff(ex const & x, unsigned diff_param)
427 ASSERT(diff_param==0);
429 return power(1+x*x, -1);
432 REGISTER_FUNCTION(atan, atan_eval, atan_evalf, atan_diff, NULL);
435 // inverse tangent (atan2(y,x))
438 ex atan2_evalf(ex const & y, ex const & x)
443 END_TYPECHECK(atan2(y,x))
445 return atan(ex_to_numeric(y),ex_to_numeric(x)); // -> numeric atan(numeric)
448 ex atan2_eval(ex const & y, ex const & x)
450 if (y.info(info_flags::numeric) && !y.info(info_flags::rational) &&
451 x.info(info_flags::numeric) && !x.info(info_flags::rational)) {
452 return atan2_evalf(y,x);
455 return atan2(y,x).hold();
458 ex atan2_diff(ex const & y, ex const & x, unsigned diff_param)
460 ASSERT(diff_param<2);
464 return power(x*(1+y*y/(x*x)),-1);
467 return -y*power(x*x+y*y,-1);
470 REGISTER_FUNCTION(atan2, atan2_eval, atan2_evalf, atan2_diff, NULL);
473 // hyperbolic sine (trigonometric function)
476 ex sinh_evalf(ex const & x)
480 END_TYPECHECK(sinh(x))
482 return sinh(ex_to_numeric(x)); // -> numeric sinh(numeric)
485 ex sinh_eval(ex const & x)
487 if (x.info(info_flags::numeric)) {
491 // sinh(float) -> float
492 if (!x.info(info_flags::rational))
493 return sinh_evalf(x);
496 if (is_ex_exactly_of_type(x, function)) {
498 // sinh(asinh(x)) -> x
499 if (is_ex_the_function(x, asinh))
501 // sinh(acosh(x)) -> (x-1)^(1/2) * (x+1)^(1/2)
502 if (is_ex_the_function(x, acosh))
503 return power(t-exONE(),exHALF())*power(t+exONE(),exHALF());
504 // sinh(atanh(x)) -> x*(1-x^2)^(-1/2)
505 if (is_ex_the_function(x, atanh))
506 return t*power(exONE()-power(t,exTWO()),exMINUSHALF());
509 return sinh(x).hold();
512 ex sinh_diff(ex const & x, unsigned diff_param)
514 ASSERT(diff_param==0);
519 REGISTER_FUNCTION(sinh, sinh_eval, sinh_evalf, sinh_diff, NULL);
522 // hyperbolic cosine (trigonometric function)
525 ex cosh_evalf(ex const & x)
529 END_TYPECHECK(cosh(x))
531 return cosh(ex_to_numeric(x)); // -> numeric cosh(numeric)
534 ex cosh_eval(ex const & x)
536 if (x.info(info_flags::numeric)) {
540 // cosh(float) -> float
541 if (!x.info(info_flags::rational))
542 return cosh_evalf(x);
545 if (is_ex_exactly_of_type(x, function)) {
547 // cosh(acosh(x)) -> x
548 if (is_ex_the_function(x, acosh))
550 // cosh(asinh(x)) -> (1+x^2)^(1/2)
551 if (is_ex_the_function(x, asinh))
552 return power(exONE()+power(t,exTWO()),exHALF());
553 // cosh(atanh(x)) -> (1-x^2)^(-1/2)
554 if (is_ex_the_function(x, atanh))
555 return power(exONE()-power(t,exTWO()),exMINUSHALF());
558 return cosh(x).hold();
561 ex cosh_diff(ex const & x, unsigned diff_param)
563 ASSERT(diff_param==0);
568 REGISTER_FUNCTION(cosh, cosh_eval, cosh_evalf, cosh_diff, NULL);
571 // hyperbolic tangent (trigonometric function)
574 ex tanh_evalf(ex const & x)
578 END_TYPECHECK(tanh(x))
580 return tanh(ex_to_numeric(x)); // -> numeric tanh(numeric)
583 ex tanh_eval(ex const & x)
585 if (x.info(info_flags::numeric)) {
589 // tanh(float) -> float
590 if (!x.info(info_flags::rational))
591 return tanh_evalf(x);
594 if (is_ex_exactly_of_type(x, function)) {
596 // tanh(atanh(x)) -> x
597 if (is_ex_the_function(x, atanh))
599 // tanh(asinh(x)) -> x*(1+x^2)^(-1/2)
600 if (is_ex_the_function(x, asinh))
601 return t*power(exONE()+power(t,exTWO()),exMINUSHALF());
602 // tanh(acosh(x)) -> (x-1)^(1/2)*(x+1)^(1/2)/x
603 if (is_ex_the_function(x, acosh))
604 return power(t-exONE(),exHALF())*power(t+exONE(),exHALF())*power(t,exMINUSONE());
607 return tanh(x).hold();
610 ex tanh_diff(ex const & x, unsigned diff_param)
612 ASSERT(diff_param==0);
614 return exONE()-power(tanh(x),exTWO());
617 REGISTER_FUNCTION(tanh, tanh_eval, tanh_evalf, tanh_diff, NULL);
620 // inverse hyperbolic sine (trigonometric function)
623 ex asinh_evalf(ex const & x)
627 END_TYPECHECK(asinh(x))
629 return asinh(ex_to_numeric(x)); // -> numeric asinh(numeric)
632 ex asinh_eval(ex const & x)
634 if (x.info(info_flags::numeric)) {
638 // asinh(float) -> float
639 if (!x.info(info_flags::rational))
640 return asinh_evalf(x);
643 return asinh(x).hold();
646 ex asinh_diff(ex const & x, unsigned diff_param)
648 ASSERT(diff_param==0);
650 return power(1+power(x,exTWO()),exMINUSHALF());
653 REGISTER_FUNCTION(asinh, asinh_eval, asinh_evalf, asinh_diff, NULL);
656 // inverse hyperbolic cosine (trigonometric function)
659 ex acosh_evalf(ex const & x)
663 END_TYPECHECK(acosh(x))
665 return acosh(ex_to_numeric(x)); // -> numeric acosh(numeric)
668 ex acosh_eval(ex const & x)
670 if (x.info(info_flags::numeric)) {
671 // acosh(0) -> Pi*I/2
673 return Pi*I*numeric(1,2);
675 if (x.is_equal(exONE()))
678 if (x.is_equal(exMINUSONE()))
680 // acosh(float) -> float
681 if (!x.info(info_flags::rational))
682 return acosh_evalf(x);
685 return acosh(x).hold();
688 ex acosh_diff(ex const & x, unsigned diff_param)
690 ASSERT(diff_param==0);
692 return power(x-1,exMINUSHALF())*power(x+1,exMINUSHALF());
695 REGISTER_FUNCTION(acosh, acosh_eval, acosh_evalf, acosh_diff, NULL);
698 // inverse hyperbolic tangent (trigonometric function)
701 ex atanh_evalf(ex const & x)
705 END_TYPECHECK(atanh(x))
707 return atanh(ex_to_numeric(x)); // -> numeric atanh(numeric)
710 ex atanh_eval(ex const & x)
712 if (x.info(info_flags::numeric)) {
716 // atanh({+|-}1) -> throw
717 if (x.is_equal(exONE()) || x.is_equal(exONE()))
718 throw (std::domain_error("atanh_eval(): infinity"));
719 // atanh(float) -> float
720 if (!x.info(info_flags::rational))
721 return atanh_evalf(x);
724 return atanh(x).hold();
727 ex atanh_diff(ex const & x, unsigned diff_param)
729 ASSERT(diff_param==0);
731 return power(exONE()-power(x,exTWO()),exMINUSONE());
734 REGISTER_FUNCTION(atanh, atanh_eval, atanh_evalf, atanh_diff, NULL);