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
33 // exponential function
36 ex exp_evalf(ex const & x)
42 return exp(ex_to_numeric(x)); // -> numeric exp(numeric)
45 ex exp_eval(ex const & x)
51 // exp(n*Pi*I/2) -> {+1|+I|-1|-I}
52 ex TwoExOverPiI=(2*x)/(Pi*I);
53 if (TwoExOverPiI.info(info_flags::integer)) {
54 numeric z=mod(ex_to_numeric(TwoExOverPiI),numeric(4));
55 if (z.is_equal(numZERO()))
57 if (z.is_equal(numONE()))
59 if (z.is_equal(numTWO()))
61 if (z.is_equal(numTHREE()))
65 if (is_ex_the_function(x, log))
69 if (x.info(info_flags::numeric) && !x.info(info_flags::rational))
75 ex exp_diff(ex const & x, unsigned diff_param)
77 ASSERT(diff_param==0);
82 REGISTER_FUNCTION(exp, exp_eval, exp_evalf, exp_diff, NULL);
88 ex log_evalf(ex const & x)
94 return log(ex_to_numeric(x)); // -> numeric log(numeric)
97 ex log_eval(ex const & x)
99 if (x.info(info_flags::numeric)) {
101 if (x.is_equal(exONE()))
104 if (x.is_equal(exMINUSONE()))
108 return (I*Pi*numeric(1,2));
109 // log(-I) -> -Pi*I/2
111 return (I*Pi*numeric(-1,2));
112 // log(0) -> throw singularity
113 if (x.is_equal(exZERO()))
114 throw(std::domain_error("log_eval(): log(0)"));
116 if (!x.info(info_flags::rational))
120 return log(x).hold();
123 ex log_diff(ex const & x, unsigned diff_param)
125 ASSERT(diff_param==0);
130 REGISTER_FUNCTION(log, log_eval, log_evalf, log_diff, NULL);
133 // sine (trigonometric function)
136 ex sin_evalf(ex const & x)
140 END_TYPECHECK(sin(x))
142 return sin(ex_to_numeric(x)); // -> numeric sin(numeric)
145 ex sin_eval(ex const & x)
149 if (xOverPi.info(info_flags::integer))
152 // sin((2n+1)*Pi/2) -> {+|-}1
153 ex xOverPiMinusHalf=xOverPi-exHALF();
154 if (xOverPiMinusHalf.info(info_flags::even))
156 else if (xOverPiMinusHalf.info(info_flags::odd))
159 if (is_ex_exactly_of_type(x, function)) {
162 if (is_ex_the_function(x, asin))
164 // sin(acos(x)) -> (1-x^2)^(1/2)
165 if (is_ex_the_function(x, acos))
166 return power(exONE()-power(t,exTWO()),exHALF());
167 // sin(atan(x)) -> x*(1+x^2)^(-1/2)
168 if (is_ex_the_function(x, atan))
169 return t*power(exONE()+power(t,exTWO()),exMINUSHALF());
172 // sin(float) -> float
173 if (x.info(info_flags::numeric) && !x.info(info_flags::rational))
176 return sin(x).hold();
179 ex sin_diff(ex const & x, unsigned diff_param)
181 ASSERT(diff_param==0);
186 REGISTER_FUNCTION(sin, sin_eval, sin_evalf, sin_diff, NULL);
189 // cosine (trigonometric function)
192 ex cos_evalf(ex const & x)
196 END_TYPECHECK(cos(x))
198 return cos(ex_to_numeric(x)); // -> numeric cos(numeric)
201 ex cos_eval(ex const & x)
203 // cos(n*Pi) -> {+|-}1
205 if (xOverPi.info(info_flags::even))
207 else if (xOverPi.info(info_flags::odd))
210 // cos((2n+1)*Pi/2) -> 0
211 ex xOverPiMinusHalf=xOverPi-exHALF();
212 if (xOverPiMinusHalf.info(info_flags::integer))
215 if (is_ex_exactly_of_type(x, function)) {
218 if (is_ex_the_function(x, acos))
220 // cos(asin(x)) -> (1-x^2)^(1/2)
221 if (is_ex_the_function(x, asin))
222 return power(exONE()-power(t,exTWO()),exHALF());
223 // cos(atan(x)) -> (1+x^2)^(-1/2)
224 if (is_ex_the_function(x, atan))
225 return power(exONE()+power(t,exTWO()),exMINUSHALF());
228 // cos(float) -> float
229 if (x.info(info_flags::numeric) && !x.info(info_flags::rational))
232 return cos(x).hold();
235 ex cos_diff(ex const & x, unsigned diff_param)
237 ASSERT(diff_param==0);
239 return numMINUSONE()*sin(x);
242 REGISTER_FUNCTION(cos, cos_eval, cos_evalf, cos_diff, NULL);
245 // tangent (trigonometric function)
248 ex tan_evalf(ex const & x)
252 END_TYPECHECK(tan(x)) // -> numeric tan(numeric)
254 return tan(ex_to_numeric(x));
257 ex tan_eval(ex const & x)
259 // tan(n*Pi/3) -> {0|3^(1/2)|-(3^(1/2))}
260 ex ThreeExOverPi=numTHREE()*x/Pi;
261 if (ThreeExOverPi.info(info_flags::integer)) {
262 numeric z=mod(ex_to_numeric(ThreeExOverPi),numeric(3));
263 if (z.is_equal(numZERO()))
265 if (z.is_equal(numONE()))
266 return power(exTHREE(),exHALF());
267 if (z.is_equal(numTWO()))
268 return -power(exTHREE(),exHALF());
271 // tan((2n+1)*Pi/2) -> throw
272 ex ExOverPiMinusHalf=x/Pi-exHALF();
273 if (ExOverPiMinusHalf.info(info_flags::integer))
274 throw (std::domain_error("tan_eval(): infinity"));
276 if (is_ex_exactly_of_type(x, function)) {
279 if (is_ex_the_function(x, atan))
281 // tan(asin(x)) -> x*(1+x^2)^(-1/2)
282 if (is_ex_the_function(x, asin))
283 return t*power(exONE()-power(t,exTWO()),exMINUSHALF());
284 // tan(acos(x)) -> (1-x^2)^(1/2)/x
285 if (is_ex_the_function(x, acos))
286 return power(t,exMINUSONE())*power(exONE()-power(t,exTWO()),exHALF());
289 // tan(float) -> float
290 if (x.info(info_flags::numeric) && !x.info(info_flags::rational)) {
294 return tan(x).hold();
297 ex tan_diff(ex const & x, unsigned diff_param)
299 ASSERT(diff_param==0);
301 return (1+power(tan(x),exTWO()));
304 REGISTER_FUNCTION(tan, tan_eval, tan_evalf, tan_diff, NULL);
307 // inverse sine (arc sine)
310 ex asin_evalf(ex const & x)
314 END_TYPECHECK(asin(x))
316 return asin(ex_to_numeric(x)); // -> numeric asin(numeric)
319 ex asin_eval(ex const & x)
321 if (x.info(info_flags::numeric)) {
326 if (x.is_equal(exHALF()))
327 return numeric(1,6)*Pi;
329 if (x.is_equal(exONE()))
330 return numeric(1,2)*Pi;
331 // asin(-1/2) -> -Pi/6
332 if (x.is_equal(exMINUSHALF()))
333 return numeric(-1,6)*Pi;
335 if (x.is_equal(exMINUSONE()))
336 return numeric(-1,2)*Pi;
337 // asin(float) -> float
338 if (!x.info(info_flags::rational))
339 return asin_evalf(x);
342 return asin(x).hold();
345 ex asin_diff(ex const & x, unsigned diff_param)
347 ASSERT(diff_param==0);
349 return power(1-power(x,exTWO()),exMINUSHALF());
352 REGISTER_FUNCTION(asin, asin_eval, asin_evalf, asin_diff, NULL);
355 // inverse cosine (arc cosine)
358 ex acos_evalf(ex const & x)
362 END_TYPECHECK(acos(x))
364 return acos(ex_to_numeric(x)); // -> numeric acos(numeric)
367 ex acos_eval(ex const & x)
369 if (x.info(info_flags::numeric)) {
371 if (x.is_equal(exONE()))
374 if (x.is_equal(exHALF()))
375 return numeric(1,3)*Pi;
378 return numeric(1,2)*Pi;
379 // acos(-1/2) -> 2/3*Pi
380 if (x.is_equal(exMINUSHALF()))
381 return numeric(2,3)*Pi;
383 if (x.is_equal(exMINUSONE()))
385 // acos(float) -> float
386 if (!x.info(info_flags::rational))
387 return acos_evalf(x);
390 return acos(x).hold();
393 ex acos_diff(ex const & x, unsigned diff_param)
395 ASSERT(diff_param==0);
397 return numMINUSONE()*power(1-power(x,exTWO()),exMINUSHALF());
400 REGISTER_FUNCTION(acos, acos_eval, acos_evalf, acos_diff, NULL);
403 // inverse tangent (arc tangent)
406 ex atan_evalf(ex const & x)
410 END_TYPECHECK(atan(x))
412 return atan(ex_to_numeric(x)); // -> numeric atan(numeric)
415 ex atan_eval(ex const & x)
417 if (x.info(info_flags::numeric)) {
419 if (x.is_equal(exZERO()))
421 // atan(float) -> float
422 if (!x.info(info_flags::rational))
423 return atan_evalf(x);
426 return atan(x).hold();
429 ex atan_diff(ex const & x, unsigned diff_param)
431 ASSERT(diff_param==0);
433 return power(1+x*x, -1);
436 REGISTER_FUNCTION(atan, atan_eval, atan_evalf, atan_diff, NULL);
439 // inverse tangent (atan2(y,x))
442 ex atan2_evalf(ex const & y, ex const & x)
447 END_TYPECHECK(atan2(y,x))
449 return atan(ex_to_numeric(y),ex_to_numeric(x)); // -> numeric atan(numeric)
452 ex atan2_eval(ex const & y, ex const & x)
454 if (y.info(info_flags::numeric) && !y.info(info_flags::rational) &&
455 x.info(info_flags::numeric) && !x.info(info_flags::rational)) {
456 return atan2_evalf(y,x);
459 return atan2(y,x).hold();
462 ex atan2_diff(ex const & y, ex const & x, unsigned diff_param)
464 ASSERT(diff_param<2);
468 return power(x*(1+y*y/(x*x)),-1);
471 return -y*power(x*x+y*y,-1);
474 REGISTER_FUNCTION(atan2, atan2_eval, atan2_evalf, atan2_diff, NULL);
477 // hyperbolic sine (trigonometric function)
480 ex sinh_evalf(ex const & x)
484 END_TYPECHECK(sinh(x))
486 return sinh(ex_to_numeric(x)); // -> numeric sinh(numeric)
489 ex sinh_eval(ex const & x)
491 if (x.info(info_flags::numeric)) {
495 // sinh(float) -> float
496 if (!x.info(info_flags::rational))
497 return sinh_evalf(x);
500 if (is_ex_exactly_of_type(x, function)) {
502 // sinh(asinh(x)) -> x
503 if (is_ex_the_function(x, asinh))
505 // sinh(acosh(x)) -> (x-1)^(1/2) * (x+1)^(1/2)
506 if (is_ex_the_function(x, acosh))
507 return power(t-exONE(),exHALF())*power(t+exONE(),exHALF());
508 // sinh(atanh(x)) -> x*(1-x^2)^(-1/2)
509 if (is_ex_the_function(x, atanh))
510 return t*power(exONE()-power(t,exTWO()),exMINUSHALF());
513 return sinh(x).hold();
516 ex sinh_diff(ex const & x, unsigned diff_param)
518 ASSERT(diff_param==0);
523 REGISTER_FUNCTION(sinh, sinh_eval, sinh_evalf, sinh_diff, NULL);
526 // hyperbolic cosine (trigonometric function)
529 ex cosh_evalf(ex const & x)
533 END_TYPECHECK(cosh(x))
535 return cosh(ex_to_numeric(x)); // -> numeric cosh(numeric)
538 ex cosh_eval(ex const & x)
540 if (x.info(info_flags::numeric)) {
544 // cosh(float) -> float
545 if (!x.info(info_flags::rational))
546 return cosh_evalf(x);
549 if (is_ex_exactly_of_type(x, function)) {
551 // cosh(acosh(x)) -> x
552 if (is_ex_the_function(x, acosh))
554 // cosh(asinh(x)) -> (1+x^2)^(1/2)
555 if (is_ex_the_function(x, asinh))
556 return power(exONE()+power(t,exTWO()),exHALF());
557 // cosh(atanh(x)) -> (1-x^2)^(-1/2)
558 if (is_ex_the_function(x, atanh))
559 return power(exONE()-power(t,exTWO()),exMINUSHALF());
562 return cosh(x).hold();
565 ex cosh_diff(ex const & x, unsigned diff_param)
567 ASSERT(diff_param==0);
572 REGISTER_FUNCTION(cosh, cosh_eval, cosh_evalf, cosh_diff, NULL);
575 // hyperbolic tangent (trigonometric function)
578 ex tanh_evalf(ex const & x)
582 END_TYPECHECK(tanh(x))
584 return tanh(ex_to_numeric(x)); // -> numeric tanh(numeric)
587 ex tanh_eval(ex const & x)
589 if (x.info(info_flags::numeric)) {
593 // tanh(float) -> float
594 if (!x.info(info_flags::rational))
595 return tanh_evalf(x);
598 if (is_ex_exactly_of_type(x, function)) {
600 // tanh(atanh(x)) -> x
601 if (is_ex_the_function(x, atanh))
603 // tanh(asinh(x)) -> x*(1+x^2)^(-1/2)
604 if (is_ex_the_function(x, asinh))
605 return t*power(exONE()+power(t,exTWO()),exMINUSHALF());
606 // tanh(acosh(x)) -> (x-1)^(1/2)*(x+1)^(1/2)/x
607 if (is_ex_the_function(x, acosh))
608 return power(t-exONE(),exHALF())*power(t+exONE(),exHALF())*power(t,exMINUSONE());
611 return tanh(x).hold();
614 ex tanh_diff(ex const & x, unsigned diff_param)
616 ASSERT(diff_param==0);
618 return exONE()-power(tanh(x),exTWO());
621 REGISTER_FUNCTION(tanh, tanh_eval, tanh_evalf, tanh_diff, NULL);
624 // inverse hyperbolic sine (trigonometric function)
627 ex asinh_evalf(ex const & x)
631 END_TYPECHECK(asinh(x))
633 return asinh(ex_to_numeric(x)); // -> numeric asinh(numeric)
636 ex asinh_eval(ex const & x)
638 if (x.info(info_flags::numeric)) {
642 // asinh(float) -> float
643 if (!x.info(info_flags::rational))
644 return asinh_evalf(x);
647 return asinh(x).hold();
650 ex asinh_diff(ex const & x, unsigned diff_param)
652 ASSERT(diff_param==0);
654 return power(1+power(x,exTWO()),exMINUSHALF());
657 REGISTER_FUNCTION(asinh, asinh_eval, asinh_evalf, asinh_diff, NULL);
660 // inverse hyperbolic cosine (trigonometric function)
663 ex acosh_evalf(ex const & x)
667 END_TYPECHECK(acosh(x))
669 return acosh(ex_to_numeric(x)); // -> numeric acosh(numeric)
672 ex acosh_eval(ex const & x)
674 if (x.info(info_flags::numeric)) {
675 // acosh(0) -> Pi*I/2
677 return Pi*I*numeric(1,2);
679 if (x.is_equal(exONE()))
682 if (x.is_equal(exMINUSONE()))
684 // acosh(float) -> float
685 if (!x.info(info_flags::rational))
686 return acosh_evalf(x);
689 return acosh(x).hold();
692 ex acosh_diff(ex const & x, unsigned diff_param)
694 ASSERT(diff_param==0);
696 return power(x-1,exMINUSHALF())*power(x+1,exMINUSHALF());
699 REGISTER_FUNCTION(acosh, acosh_eval, acosh_evalf, acosh_diff, NULL);
702 // inverse hyperbolic tangent (trigonometric function)
705 ex atanh_evalf(ex const & x)
709 END_TYPECHECK(atanh(x))
711 return atanh(ex_to_numeric(x)); // -> numeric atanh(numeric)
714 ex atanh_eval(ex const & x)
716 if (x.info(info_flags::numeric)) {
720 // atanh({+|-}1) -> throw
721 if (x.is_equal(exONE()) || x.is_equal(exONE()))
722 throw (std::domain_error("atanh_eval(): infinity"));
723 // atanh(float) -> float
724 if (!x.info(info_flags::rational))
725 return atanh_evalf(x);
728 return atanh(x).hold();
731 ex atanh_diff(ex const & x, unsigned diff_param)
733 ASSERT(diff_param==0);
735 return power(exONE()-power(x,exTWO()),exMINUSONE());
738 REGISTER_FUNCTION(atanh, atanh_eval, atanh_evalf, atanh_diff, NULL);