1 /** @file inifcns_trans.cpp
3 * Implementation of transcendental (and trigonometric and hyperbolic)
12 // exponential function
15 ex exp_evalf(ex const & x)
21 return exp(ex_to_numeric(x)); // -> numeric exp(numeric)
24 ex exp_eval(ex const & x)
30 // exp(n*Pi*I/2) -> {+1|+I|-1|-I}
31 ex TwoExOverPiI=(2*x)/(Pi*I);
32 if (TwoExOverPiI.info(info_flags::integer)) {
33 numeric z=mod(ex_to_numeric(TwoExOverPiI),numeric(4));
34 if (z.is_equal(numZERO()))
36 if (z.is_equal(numONE()))
38 if (z.is_equal(numTWO()))
40 if (z.is_equal(numTHREE()))
44 if (is_ex_the_function(x, log))
48 if (x.info(info_flags::numeric) && !x.info(info_flags::rational))
54 ex exp_diff(ex const & x, unsigned diff_param)
56 ASSERT(diff_param==0);
61 REGISTER_FUNCTION(exp, exp_eval, exp_evalf, exp_diff, NULL);
67 ex log_evalf(ex const & x)
73 return log(ex_to_numeric(x)); // -> numeric log(numeric)
76 ex log_eval(ex const & x)
78 if (x.info(info_flags::numeric)) {
80 if (x.is_equal(exONE()))
83 if (x.is_equal(exMINUSONE()))
87 return (I*Pi*numeric(1,2));
90 return (I*Pi*numeric(-1,2));
91 // log(0) -> throw singularity
92 if (x.is_equal(exZERO()))
93 throw(std::domain_error("log_eval(): log(0)"));
95 if (!x.info(info_flags::rational))
102 ex log_diff(ex const & x, unsigned diff_param)
104 ASSERT(diff_param==0);
109 REGISTER_FUNCTION(log, log_eval, log_evalf, log_diff, NULL);
112 // sine (trigonometric function)
115 ex sin_evalf(ex const & x)
119 END_TYPECHECK(sin(x))
121 return sin(ex_to_numeric(x)); // -> numeric sin(numeric)
124 ex sin_eval(ex const & x)
128 if (xOverPi.info(info_flags::integer))
131 // sin((2n+1)*Pi/2) -> {+|-}1
132 ex xOverPiMinusHalf=xOverPi-exHALF();
133 if (xOverPiMinusHalf.info(info_flags::even))
135 else if (xOverPiMinusHalf.info(info_flags::odd))
138 if (is_ex_exactly_of_type(x, function)) {
141 if (is_ex_the_function(x, asin))
143 // sin(acos(x)) -> (1-x^2)^(1/2)
144 if (is_ex_the_function(x, acos))
145 return power(exONE()-power(t,exTWO()),exHALF());
146 // sin(atan(x)) -> x*(1+x^2)^(-1/2)
147 if (is_ex_the_function(x, atan))
148 return t*power(exONE()+power(t,exTWO()),exMINUSHALF());
151 // sin(float) -> float
152 if (x.info(info_flags::numeric) && !x.info(info_flags::rational))
155 return sin(x).hold();
158 ex sin_diff(ex const & x, unsigned diff_param)
160 ASSERT(diff_param==0);
165 REGISTER_FUNCTION(sin, sin_eval, sin_evalf, sin_diff, NULL);
168 // cosine (trigonometric function)
171 ex cos_evalf(ex const & x)
175 END_TYPECHECK(cos(x))
177 return cos(ex_to_numeric(x)); // -> numeric cos(numeric)
180 ex cos_eval(ex const & x)
182 // cos(n*Pi) -> {+|-}1
184 if (xOverPi.info(info_flags::even))
186 else if (xOverPi.info(info_flags::odd))
189 // cos((2n+1)*Pi/2) -> 0
190 ex xOverPiMinusHalf=xOverPi-exHALF();
191 if (xOverPiMinusHalf.info(info_flags::integer))
194 if (is_ex_exactly_of_type(x, function)) {
197 if (is_ex_the_function(x, acos))
199 // cos(asin(x)) -> (1-x^2)^(1/2)
200 if (is_ex_the_function(x, asin))
201 return power(exONE()-power(t,exTWO()),exHALF());
202 // cos(atan(x)) -> (1+x^2)^(-1/2)
203 if (is_ex_the_function(x, atan))
204 return power(exONE()+power(t,exTWO()),exMINUSHALF());
207 // cos(float) -> float
208 if (x.info(info_flags::numeric) && !x.info(info_flags::rational))
211 return cos(x).hold();
214 ex cos_diff(ex const & x, unsigned diff_param)
216 ASSERT(diff_param==0);
218 return numMINUSONE()*sin(x);
221 REGISTER_FUNCTION(cos, cos_eval, cos_evalf, cos_diff, NULL);
224 // tangent (trigonometric function)
227 ex tan_evalf(ex const & x)
231 END_TYPECHECK(tan(x)) // -> numeric tan(numeric)
233 return tan(ex_to_numeric(x));
236 ex tan_eval(ex const & x)
238 // tan(n*Pi/3) -> {0|3^(1/2)|-(3^(1/2))}
239 ex ThreeExOverPi=numTHREE()*x/Pi;
240 if (ThreeExOverPi.info(info_flags::integer)) {
241 numeric z=mod(ex_to_numeric(ThreeExOverPi),numeric(3));
242 if (z.is_equal(numZERO()))
244 if (z.is_equal(numONE()))
245 return power(exTHREE(),exHALF());
246 if (z.is_equal(numTWO()))
247 return -power(exTHREE(),exHALF());
250 // tan((2n+1)*Pi/2) -> throw
251 ex ExOverPiMinusHalf=x/Pi-exHALF();
252 if (ExOverPiMinusHalf.info(info_flags::integer))
253 throw (std::domain_error("tan_eval(): infinity"));
255 if (is_ex_exactly_of_type(x, function)) {
258 if (is_ex_the_function(x, atan))
260 // tan(asin(x)) -> x*(1+x^2)^(-1/2)
261 if (is_ex_the_function(x, asin))
262 return t*power(exONE()-power(t,exTWO()),exMINUSHALF());
263 // tan(acos(x)) -> (1-x^2)^(1/2)/x
264 if (is_ex_the_function(x, acos))
265 return power(t,exMINUSONE())*power(exONE()-power(t,exTWO()),exHALF());
268 // tan(float) -> float
269 if (x.info(info_flags::numeric) && !x.info(info_flags::rational)) {
273 return tan(x).hold();
276 ex tan_diff(ex const & x, unsigned diff_param)
278 ASSERT(diff_param==0);
280 return (1+power(tan(x),exTWO()));
283 REGISTER_FUNCTION(tan, tan_eval, tan_evalf, tan_diff, NULL);
286 // inverse sine (arc sine)
289 ex asin_evalf(ex const & x)
293 END_TYPECHECK(asin(x))
295 return asin(ex_to_numeric(x)); // -> numeric asin(numeric)
298 ex asin_eval(ex const & x)
300 if (x.info(info_flags::numeric)) {
305 if (x.is_equal(exHALF()))
306 return numeric(1,6)*Pi;
308 if (x.is_equal(exONE()))
309 return numeric(1,2)*Pi;
310 // asin(-1/2) -> -Pi/6
311 if (x.is_equal(exMINUSHALF()))
312 return numeric(-1,6)*Pi;
314 if (x.is_equal(exMINUSONE()))
315 return numeric(-1,2)*Pi;
316 // asin(float) -> float
317 if (!x.info(info_flags::rational))
318 return asin_evalf(x);
321 return asin(x).hold();
324 ex asin_diff(ex const & x, unsigned diff_param)
326 ASSERT(diff_param==0);
328 return power(1-power(x,exTWO()),exMINUSHALF());
331 REGISTER_FUNCTION(asin, asin_eval, asin_evalf, asin_diff, NULL);
334 // inverse cosine (arc cosine)
337 ex acos_evalf(ex const & x)
341 END_TYPECHECK(acos(x))
343 return acos(ex_to_numeric(x)); // -> numeric acos(numeric)
346 ex acos_eval(ex const & x)
348 if (x.info(info_flags::numeric)) {
350 if (x.is_equal(exONE()))
353 if (x.is_equal(exHALF()))
354 return numeric(1,3)*Pi;
357 return numeric(1,2)*Pi;
358 // acos(-1/2) -> 2/3*Pi
359 if (x.is_equal(exMINUSHALF()))
360 return numeric(2,3)*Pi;
362 if (x.is_equal(exMINUSONE()))
364 // acos(float) -> float
365 if (!x.info(info_flags::rational))
366 return acos_evalf(x);
369 return acos(x).hold();
372 ex acos_diff(ex const & x, unsigned diff_param)
374 ASSERT(diff_param==0);
376 return numMINUSONE()*power(1-power(x,exTWO()),exMINUSHALF());
379 REGISTER_FUNCTION(acos, acos_eval, acos_evalf, acos_diff, NULL);
382 // inverse tangent (arc tangent)
385 ex atan_evalf(ex const & x)
389 END_TYPECHECK(atan(x))
391 return atan(ex_to_numeric(x)); // -> numeric atan(numeric)
394 ex atan_eval(ex const & x)
396 if (x.info(info_flags::numeric)) {
398 if (x.is_equal(exZERO()))
400 // atan(float) -> float
401 if (!x.info(info_flags::rational))
402 return atan_evalf(x);
405 return atan(x).hold();
408 ex atan_diff(ex const & x, unsigned diff_param)
410 ASSERT(diff_param==0);
412 return power(1+x*x, -1);
415 REGISTER_FUNCTION(atan, atan_eval, atan_evalf, atan_diff, NULL);
418 // inverse tangent (atan2(y,x))
421 ex atan2_evalf(ex const & y, ex const & x)
426 END_TYPECHECK(atan2(y,x))
428 return atan(ex_to_numeric(y),ex_to_numeric(x)); // -> numeric atan(numeric)
431 ex atan2_eval(ex const & y, ex const & x)
433 if (y.info(info_flags::numeric) && !y.info(info_flags::rational) &&
434 x.info(info_flags::numeric) && !x.info(info_flags::rational)) {
435 return atan2_evalf(y,x);
438 return atan2(y,x).hold();
441 ex atan2_diff(ex const & y, ex const & x, unsigned diff_param)
443 ASSERT(diff_param<2);
447 return power(x*(1+y*y/(x*x)),-1);
450 return -y*power(x*x+y*y,-1);
453 REGISTER_FUNCTION(atan2, atan2_eval, atan2_evalf, atan2_diff, NULL);
456 // hyperbolic sine (trigonometric function)
459 ex sinh_evalf(ex const & x)
463 END_TYPECHECK(sinh(x))
465 return sinh(ex_to_numeric(x)); // -> numeric sinh(numeric)
468 ex sinh_eval(ex const & x)
470 if (x.info(info_flags::numeric)) {
474 // sinh(float) -> float
475 if (!x.info(info_flags::rational))
476 return sinh_evalf(x);
479 if (is_ex_exactly_of_type(x, function)) {
481 // sinh(asinh(x)) -> x
482 if (is_ex_the_function(x, asinh))
484 // sinh(acosh(x)) -> (x-1)^(1/2) * (x+1)^(1/2)
485 if (is_ex_the_function(x, acosh))
486 return power(t-exONE(),exHALF())*power(t+exONE(),exHALF());
487 // sinh(atanh(x)) -> x*(1-x^2)^(-1/2)
488 if (is_ex_the_function(x, atanh))
489 return t*power(exONE()-power(t,exTWO()),exMINUSHALF());
492 return sinh(x).hold();
495 ex sinh_diff(ex const & x, unsigned diff_param)
497 ASSERT(diff_param==0);
502 REGISTER_FUNCTION(sinh, sinh_eval, sinh_evalf, sinh_diff, NULL);
505 // hyperbolic cosine (trigonometric function)
508 ex cosh_evalf(ex const & x)
512 END_TYPECHECK(cosh(x))
514 return cosh(ex_to_numeric(x)); // -> numeric cosh(numeric)
517 ex cosh_eval(ex const & x)
519 if (x.info(info_flags::numeric)) {
523 // cosh(float) -> float
524 if (!x.info(info_flags::rational))
525 return cosh_evalf(x);
528 if (is_ex_exactly_of_type(x, function)) {
530 // cosh(acosh(x)) -> x
531 if (is_ex_the_function(x, acosh))
533 // cosh(asinh(x)) -> (1+x^2)^(1/2)
534 if (is_ex_the_function(x, asinh))
535 return power(exONE()+power(t,exTWO()),exHALF());
536 // cosh(atanh(x)) -> (1-x^2)^(-1/2)
537 if (is_ex_the_function(x, atanh))
538 return power(exONE()-power(t,exTWO()),exMINUSHALF());
541 return cosh(x).hold();
544 ex cosh_diff(ex const & x, unsigned diff_param)
546 ASSERT(diff_param==0);
551 REGISTER_FUNCTION(cosh, cosh_eval, cosh_evalf, cosh_diff, NULL);
554 // hyperbolic tangent (trigonometric function)
557 ex tanh_evalf(ex const & x)
561 END_TYPECHECK(tanh(x))
563 return tanh(ex_to_numeric(x)); // -> numeric tanh(numeric)
566 ex tanh_eval(ex const & x)
568 if (x.info(info_flags::numeric)) {
572 // tanh(float) -> float
573 if (!x.info(info_flags::rational))
574 return tanh_evalf(x);
577 if (is_ex_exactly_of_type(x, function)) {
579 // tanh(atanh(x)) -> x
580 if (is_ex_the_function(x, atanh))
582 // tanh(asinh(x)) -> x*(1+x^2)^(-1/2)
583 if (is_ex_the_function(x, asinh))
584 return t*power(exONE()+power(t,exTWO()),exMINUSHALF());
585 // tanh(acosh(x)) -> (x-1)^(1/2)*(x+1)^(1/2)/x
586 if (is_ex_the_function(x, acosh))
587 return power(t-exONE(),exHALF())*power(t+exONE(),exHALF())*power(t,exMINUSONE());
590 return tanh(x).hold();
593 ex tanh_diff(ex const & x, unsigned diff_param)
595 ASSERT(diff_param==0);
597 return exONE()-power(tanh(x),exTWO());
600 REGISTER_FUNCTION(tanh, tanh_eval, tanh_evalf, tanh_diff, NULL);
603 // inverse hyperbolic sine (trigonometric function)
606 ex asinh_evalf(ex const & x)
610 END_TYPECHECK(asinh(x))
612 return asinh(ex_to_numeric(x)); // -> numeric asinh(numeric)
615 ex asinh_eval(ex const & x)
617 if (x.info(info_flags::numeric)) {
621 // asinh(float) -> float
622 if (!x.info(info_flags::rational))
623 return asinh_evalf(x);
626 return asinh(x).hold();
629 ex asinh_diff(ex const & x, unsigned diff_param)
631 ASSERT(diff_param==0);
633 return power(1+power(x,exTWO()),exMINUSHALF());
636 REGISTER_FUNCTION(asinh, asinh_eval, asinh_evalf, asinh_diff, NULL);
639 // inverse hyperbolic cosine (trigonometric function)
642 ex acosh_evalf(ex const & x)
646 END_TYPECHECK(acosh(x))
648 return acosh(ex_to_numeric(x)); // -> numeric acosh(numeric)
651 ex acosh_eval(ex const & x)
653 if (x.info(info_flags::numeric)) {
654 // acosh(0) -> Pi*I/2
656 return Pi*I*numeric(1,2);
658 if (x.is_equal(exONE()))
661 if (x.is_equal(exMINUSONE()))
663 // acosh(float) -> float
664 if (!x.info(info_flags::rational))
665 return acosh_evalf(x);
668 return acosh(x).hold();
671 ex acosh_diff(ex const & x, unsigned diff_param)
673 ASSERT(diff_param==0);
675 return power(x-1,exMINUSHALF())*power(x+1,exMINUSHALF());
678 REGISTER_FUNCTION(acosh, acosh_eval, acosh_evalf, acosh_diff, NULL);
681 // inverse hyperbolic tangent (trigonometric function)
684 ex atanh_evalf(ex const & x)
688 END_TYPECHECK(atanh(x))
690 return atanh(ex_to_numeric(x)); // -> numeric atanh(numeric)
693 ex atanh_eval(ex const & x)
695 if (x.info(info_flags::numeric)) {
699 // atanh({+|-}1) -> throw
700 if (x.is_equal(exONE()) || x.is_equal(exONE()))
701 throw (std::domain_error("atanh_eval(): infinity"));
702 // atanh(float) -> float
703 if (!x.info(info_flags::rational))
704 return atanh_evalf(x);
707 return atanh(x).hold();
710 ex atanh_diff(ex const & x, unsigned diff_param)
712 ASSERT(diff_param==0);
714 return power(exONE()-power(x,exTWO()),exMINUSONE());
717 REGISTER_FUNCTION(atanh, atanh_eval, atanh_evalf, atanh_diff, NULL);