GiNaC 1.8.7
inifcns_gamma.cpp
Go to the documentation of this file.
1
6/*
7 * GiNaC Copyright (C) 1999-2023 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include "inifcns.h"
25#include "constant.h"
26#include "pseries.h"
27#include "numeric.h"
28#include "power.h"
29#include "relational.h"
30#include "operators.h"
31#include "symbol.h"
32#include "symmetry.h"
33#include "utils.h"
34
35#include <stdexcept>
36#include <vector>
37
38namespace GiNaC {
39
41// Logarithm of Gamma function
43
44static ex lgamma_evalf(const ex & x)
45{
46 if (is_exactly_a<numeric>(x)) {
47 try {
48 return lgamma(ex_to<numeric>(x));
49 } catch (const dunno &e) { }
50 }
51
52 return lgamma(x).hold();
53}
54
55
60static ex lgamma_eval(const ex & x)
61{
63 // trap integer arguments:
65 // lgamma(n) -> log((n-1)!) for postitive n
67 return log(factorial(x + _ex_1));
68 else
69 throw (pole_error("lgamma_eval(): logarithmic pole",0));
70 }
71 if (!ex_to<numeric>(x).is_rational())
72 return lgamma(ex_to<numeric>(x));
73 }
74
75 return lgamma(x).hold();
76}
77
78
79static ex lgamma_deriv(const ex & x, unsigned deriv_param)
80{
81 GINAC_ASSERT(deriv_param==0);
82
83 // d/dx lgamma(x) -> psi(x)
84 return psi(x);
85}
86
87
88static ex lgamma_series(const ex & arg,
89 const relational & rel,
90 int order,
91 unsigned options)
92{
93 // method:
94 // Taylor series where there is no pole falls back to psi function
95 // evaluation.
96 // On a pole at -m we could use the recurrence relation
97 // lgamma(x) == lgamma(x+1)-log(x)
98 // from which follows
99 // series(lgamma(x),x==-m,order) ==
100 // series(lgamma(x+m+1)-log(x)...-log(x+m)),x==-m,order);
101 const ex arg_pt = arg.subs(rel, subs_options::no_pattern);
102 if (!arg_pt.info(info_flags::integer) || arg_pt.info(info_flags::positive))
103 throw do_taylor(); // caught by function::series()
104 // if we got here we have to care for a simple pole of tgamma(-m):
105 numeric m = -ex_to<numeric>(arg_pt);
106 ex recur;
107 for (numeric p = 0; p<=m; ++p)
108 recur += log(arg+p);
109 return (lgamma(arg+m+_ex1)-recur).series(rel, order, options);
110}
111
112
113static ex lgamma_conjugate(const ex & x)
114{
115 // conjugate(lgamma(x))==lgamma(conjugate(x)) unless on the branch cut
116 // which runs along the negative real axis.
118 return lgamma(x);
119 }
120 if (is_exactly_a<numeric>(x) &&
121 !x.imag_part().is_zero()) {
122 return lgamma(x.conjugate());
123 }
124 return conjugate_function(lgamma(x)).hold();
125}
126
127
129 evalf_func(lgamma_evalf).
130 derivative_func(lgamma_deriv).
131 series_func(lgamma_series).
132 conjugate_func(lgamma_conjugate).
133 latex_name("\\log \\Gamma"));
134
135
137// true Gamma function
139
140static ex tgamma_evalf(const ex & x)
141{
142 if (is_exactly_a<numeric>(x)) {
143 try {
144 return tgamma(ex_to<numeric>(x));
145 } catch (const dunno &e) { }
146 }
147
148 return tgamma(x).hold();
149}
150
151
157static ex tgamma_eval(const ex & x)
158{
160 // trap integer arguments:
161 const numeric two_x = (*_num2_p)*ex_to<numeric>(x);
162 if (two_x.is_even()) {
163 // tgamma(n) -> (n-1)! for postitive n
164 if (two_x.is_positive()) {
165 return factorial(ex_to<numeric>(x).sub(*_num1_p));
166 } else {
167 throw (pole_error("tgamma_eval(): simple pole",1));
168 }
169 }
170 // trap half integer arguments:
171 if (two_x.is_integer()) {
172 // trap positive x==(n+1/2)
173 // tgamma(n+1/2) -> Pi^(1/2)*(1*3*..*(2*n-1))/(2^n)
174 if (two_x.is_positive()) {
175 const numeric n = ex_to<numeric>(x).sub(*_num1_2_p);
176 return (doublefactorial(n.mul(*_num2_p).sub(*_num1_p)).div(pow(*_num2_p,n))) * sqrt(Pi);
177 } else {
178 // trap negative x==(-n+1/2)
179 // tgamma(-n+1/2) -> Pi^(1/2)*(-2)^n/(1*3*..*(2*n-1))
180 const numeric n = abs(ex_to<numeric>(x).sub(*_num1_2_p));
181 return (pow(*_num_2_p, n).div(doublefactorial(n.mul(*_num2_p).sub(*_num1_p))))*sqrt(Pi);
182 }
183 }
184 if (!ex_to<numeric>(x).is_rational())
185 return tgamma(ex_to<numeric>(x));
186 }
187
188 return tgamma(x).hold();
189}
190
191
192static ex tgamma_deriv(const ex & x, unsigned deriv_param)
193{
194 GINAC_ASSERT(deriv_param==0);
195
196 // d/dx tgamma(x) -> psi(x)*tgamma(x)
197 return psi(x)*tgamma(x);
198}
199
200
201static ex tgamma_series(const ex & arg,
202 const relational & rel,
203 int order,
204 unsigned options)
205{
206 // method:
207 // Taylor series where there is no pole falls back to psi function
208 // evaluation.
209 // On a pole at -m use the recurrence relation
210 // tgamma(x) == tgamma(x+1) / x
211 // from which follows
212 // series(tgamma(x),x==-m,order) ==
213 // series(tgamma(x+m+1)/(x*(x+1)*...*(x+m)),x==-m,order);
214 const ex arg_pt = arg.subs(rel, subs_options::no_pattern);
215 if (!arg_pt.info(info_flags::integer) || arg_pt.info(info_flags::positive))
216 throw do_taylor(); // caught by function::series()
217 // if we got here we have to care for a simple pole at -m:
218 const numeric m = -ex_to<numeric>(arg_pt);
219 ex ser_denom = _ex1;
220 for (numeric p; p<=m; ++p)
221 ser_denom *= arg+p;
222 return (tgamma(arg+m+_ex1)/ser_denom).series(rel, order, options);
223}
224
225
226static ex tgamma_conjugate(const ex & x)
227{
228 // conjugate(tgamma(x))==tgamma(conjugate(x))
229 return tgamma(x.conjugate());
230}
231
232
234 evalf_func(tgamma_evalf).
235 derivative_func(tgamma_deriv).
236 series_func(tgamma_series).
237 conjugate_func(tgamma_conjugate).
238 latex_name("\\Gamma"));
239
240
242// beta-function
244
245static ex beta_evalf(const ex & x, const ex & y)
246{
247 if (is_exactly_a<numeric>(x) && is_exactly_a<numeric>(y)) {
248 try {
249 return exp(lgamma(ex_to<numeric>(x))+lgamma(ex_to<numeric>(y))-lgamma(ex_to<numeric>(x+y)));
250 } catch (const dunno &e) { }
251 }
252
253 return beta(x,y).hold();
254}
255
256
257static ex beta_eval(const ex & x, const ex & y)
258{
259 if (x.is_equal(_ex1))
260 return 1/y;
261 if (y.is_equal(_ex1))
262 return 1/x;
264 // treat all problematic x and y that may not be passed into tgamma,
265 // because they would throw there although beta(x,y) is well-defined
266 // using the formula beta(x,y) == (-1)^y * beta(1-x-y, y)
267 const numeric &nx = ex_to<numeric>(x);
268 const numeric &ny = ex_to<numeric>(y);
269 if (nx.is_real() && nx.is_integer() &&
270 ny.is_real() && ny.is_integer()) {
271 if (nx.is_negative()) {
272 if (nx<=-ny)
273 return pow(*_num_1_p, ny)*beta(1-x-y, y);
274 else
275 throw (pole_error("beta_eval(): simple pole",1));
276 }
277 if (ny.is_negative()) {
278 if (ny<=-nx)
279 return pow(*_num_1_p, nx)*beta(1-y-x, x);
280 else
281 throw (pole_error("beta_eval(): simple pole",1));
282 }
283 return tgamma(x)*tgamma(y)/tgamma(x+y);
284 }
285 // no problem in numerator, but denominator has pole:
286 if ((nx+ny).is_real() &&
287 (nx+ny).is_integer() &&
288 !(nx+ny).is_positive())
289 return _ex0;
290 if (!ex_to<numeric>(x).is_rational() || !ex_to<numeric>(x).is_rational())
291 return evalf(beta(x, y).hold());
292 }
293
294 return beta(x,y).hold();
295}
296
297
298static ex beta_deriv(const ex & x, const ex & y, unsigned deriv_param)
299{
300 GINAC_ASSERT(deriv_param<2);
301 ex retval;
302
303 // d/dx beta(x,y) -> (psi(x)-psi(x+y)) * beta(x,y)
304 if (deriv_param==0)
305 retval = (psi(x)-psi(x+y))*beta(x,y);
306 // d/dy beta(x,y) -> (psi(y)-psi(x+y)) * beta(x,y)
307 if (deriv_param==1)
308 retval = (psi(y)-psi(x+y))*beta(x,y);
309 return retval;
310}
311
312
313static ex beta_series(const ex & arg1,
314 const ex & arg2,
315 const relational & rel,
316 int order,
317 unsigned options)
318{
319 // method:
320 // Taylor series where there is no pole of one of the tgamma functions
321 // falls back to beta function evaluation. Otherwise, fall back to
322 // tgamma series directly.
323 const ex arg1_pt = arg1.subs(rel, subs_options::no_pattern);
324 const ex arg2_pt = arg2.subs(rel, subs_options::no_pattern);
325 GINAC_ASSERT(is_a<symbol>(rel.lhs()));
326 const symbol &s = ex_to<symbol>(rel.lhs());
327 ex arg1_ser, arg2_ser, arg1arg2_ser;
328 if ((!arg1_pt.info(info_flags::integer) || arg1_pt.info(info_flags::positive)) &&
329 (!arg2_pt.info(info_flags::integer) || arg2_pt.info(info_flags::positive)))
330 throw do_taylor(); // caught by function::series()
331 // trap the case where arg1 is on a pole:
333 arg1_ser = tgamma(arg1+s);
334 else
335 arg1_ser = tgamma(arg1);
336 // trap the case where arg2 is on a pole:
338 arg2_ser = tgamma(arg2+s);
339 else
340 arg2_ser = tgamma(arg2);
341 // trap the case where arg1+arg2 is on a pole:
342 if ((arg1+arg2).info(info_flags::integer) && !(arg1+arg2).info(info_flags::positive))
343 arg1arg2_ser = tgamma(arg2+arg1+s);
344 else
345 arg1arg2_ser = tgamma(arg2+arg1);
346 // compose the result (expanding all the terms):
347 return (arg1_ser*arg2_ser/arg1arg2_ser).series(rel, order, options).expand();
348}
349
350
352 evalf_func(beta_evalf).
353 derivative_func(beta_deriv).
354 series_func(beta_series).
355 latex_name("\\mathrm{B}").
356 set_symmetry(sy_symm(0, 1)));
357
358
360// Psi-function (aka digamma-function)
362
363static ex psi1_evalf(const ex & x)
364{
365 if (is_exactly_a<numeric>(x)) {
366 try {
367 return psi(ex_to<numeric>(x));
368 } catch (const dunno &e) { }
369 }
370
371 return psi(x).hold();
372}
373
376static ex psi1_eval(const ex & x)
377{
379 const numeric &nx = ex_to<numeric>(x);
380 if (nx.is_integer()) {
381 // integer case
382 if (nx.is_positive()) {
383 // psi(n) -> 1 + 1/2 +...+ 1/(n-1) - Euler
384 numeric rat = 0;
385 for (numeric i(nx+(*_num_1_p)); i>0; --i)
386 rat += i.inverse();
387 return rat-Euler;
388 } else {
389 // for non-positive integers there is a pole:
390 throw (pole_error("psi_eval(): simple pole",1));
391 }
392 }
393 if (((*_num2_p)*nx).is_integer()) {
394 // half integer case
395 if (nx.is_positive()) {
396 // psi((2m+1)/2) -> 2/(2m+1) + 2/2m +...+ 2/1 - Euler - 2log(2)
397 numeric rat = 0;
398 for (numeric i = (nx+(*_num_1_p))*(*_num2_p); i>0; i-=(*_num2_p))
399 rat += (*_num2_p)*i.inverse();
400 return rat-Euler-_ex2*log(_ex2);
401 } else {
402 // use the recurrence relation
403 // psi(-m-1/2) == psi(-m-1/2+1) - 1 / (-m-1/2)
404 // to relate psi(-m-1/2) to psi(1/2):
405 // psi(-m-1/2) == psi(1/2) + r
406 // where r == ((-1/2)^(-1) + ... + (-m-1/2)^(-1))
407 numeric recur = 0;
408 for (numeric p = nx; p<0; ++p)
409 recur -= pow(p, *_num_1_p);
410 return recur+psi(_ex1_2);
411 }
412 }
413 // psi1_evalf should be called here once it becomes available
414 }
415
416 return psi(x).hold();
417}
418
419static ex psi1_deriv(const ex & x, unsigned deriv_param)
420{
421 GINAC_ASSERT(deriv_param==0);
422
423 // d/dx psi(x) -> psi(1,x)
424 return psi(_ex1, x);
425}
426
427static ex psi1_series(const ex & arg,
428 const relational & rel,
429 int order,
430 unsigned options)
431{
432 // method:
433 // Taylor series where there is no pole falls back to polygamma function
434 // evaluation.
435 // On a pole at -m use the recurrence relation
436 // psi(x) == psi(x+1) - 1/z
437 // from which follows
438 // series(psi(x),x==-m,order) ==
439 // series(psi(x+m+1) - 1/x - 1/(x+1) - 1/(x+m)),x==-m,order);
440 const ex arg_pt = arg.subs(rel, subs_options::no_pattern);
441 if (!arg_pt.info(info_flags::integer) || arg_pt.info(info_flags::positive))
442 throw do_taylor(); // caught by function::series()
443 // if we got here we have to care for a simple pole at -m:
444 const numeric m = -ex_to<numeric>(arg_pt);
445 ex recur;
446 for (numeric p; p<=m; ++p)
447 recur += power(arg+p,_ex_1);
448 return (psi(arg+m+_ex1)-recur).series(rel, order, options);
449}
450
451unsigned psi1_SERIAL::serial =
452 function::register_new(function_options("psi", 1).
453 eval_func(psi1_eval).
454 evalf_func(psi1_evalf).
455 derivative_func(psi1_deriv).
456 series_func(psi1_series).
457 latex_name("\\psi").
458 overloaded(2));
459
461// Psi-functions (aka polygamma-functions) psi(0,x)==psi(x)
463
464static ex psi2_evalf(const ex & n, const ex & x)
465{
466 if (is_exactly_a<numeric>(n) && is_exactly_a<numeric>(x)) {
467 try {
468 return psi(ex_to<numeric>(n),ex_to<numeric>(x));
469 } catch (const dunno &e) { }
470 }
471
472 return psi(n,x).hold();
473}
474
477static ex psi2_eval(const ex & n, const ex & x)
478{
479 // psi(0,x) -> psi(x)
480 if (n.is_zero())
481 return psi(x);
482 // psi(-1,x) -> log(tgamma(x))
483 if (n.is_equal(_ex_1))
484 return log(tgamma(x));
485 if (n.info(info_flags::numeric) && n.info(info_flags::posint) &&
487 const numeric &nn = ex_to<numeric>(n);
488 const numeric &nx = ex_to<numeric>(x);
489 if (nx.is_integer()) {
490 // integer case
491 if (nx.is_equal(*_num1_p))
492 // use psi(n,1) == (-)^(n+1) * n! * zeta(n+1)
493 return pow(*_num_1_p,nn+(*_num1_p))*factorial(nn)*zeta(ex(nn+(*_num1_p)));
494 if (nx.is_positive()) {
495 // use the recurrence relation
496 // psi(n,m) == psi(n,m+1) - (-)^n * n! / m^(n+1)
497 // to relate psi(n,m) to psi(n,1):
498 // psi(n,m) == psi(n,1) + r
499 // where r == (-)^n * n! * (1^(-n-1) + ... + (m-1)^(-n-1))
500 numeric recur = 0;
501 for (numeric p = 1; p<nx; ++p)
502 recur += pow(p, -nn+(*_num_1_p));
503 recur *= factorial(nn)*pow((*_num_1_p), nn);
504 return recur+psi(n,_ex1);
505 } else {
506 // for non-positive integers there is a pole:
507 throw (pole_error("psi2_eval(): pole",1));
508 }
509 }
510 if (((*_num2_p)*nx).is_integer()) {
511 // half integer case
512 if (nx.is_equal(*_num1_2_p))
513 // use psi(n,1/2) == (-)^(n+1) * n! * (2^(n+1)-1) * zeta(n+1)
514 return pow(*_num_1_p,nn+(*_num1_p))*factorial(nn)*(pow(*_num2_p,nn+(*_num1_p)) + (*_num_1_p))*zeta(ex(nn+(*_num1_p)));
515 if (nx.is_positive()) {
516 const numeric m = nx - (*_num1_2_p);
517 // use the multiplication formula
518 // psi(n,2*m) == (psi(n,m) + psi(n,m+1/2)) / 2^(n+1)
519 // to revert to positive integer case
520 return psi(n,(*_num2_p)*m)*pow((*_num2_p),nn+(*_num1_p))-psi(n,m);
521 } else {
522 // use the recurrence relation
523 // psi(n,-m-1/2) == psi(n,-m-1/2+1) - (-)^n * n! / (-m-1/2)^(n+1)
524 // to relate psi(n,-m-1/2) to psi(n,1/2):
525 // psi(n,-m-1/2) == psi(n,1/2) + r
526 // where r == (-)^(n+1) * n! * ((-1/2)^(-n-1) + ... + (-m-1/2)^(-n-1))
527 numeric recur = 0;
528 for (numeric p = nx; p<0; ++p)
529 recur += pow(p, -nn+(*_num_1_p));
530 recur *= factorial(nn)*pow(*_num_1_p, nn+(*_num_1_p));
531 return recur+psi(n,_ex1_2);
532 }
533 }
534 // psi2_evalf should be called here once it becomes available
535 }
536
537 return psi(n, x).hold();
538}
539
540static ex psi2_deriv(const ex & n, const ex & x, unsigned deriv_param)
541{
542 GINAC_ASSERT(deriv_param<2);
543
544 if (deriv_param==0) {
545 // d/dn psi(n,x)
546 throw(std::logic_error("cannot diff psi(n,x) with respect to n"));
547 }
548 // d/dx psi(n,x) -> psi(n+1,x)
549 return psi(n+_ex1, x);
550}
551
552static ex psi2_series(const ex & n,
553 const ex & arg,
554 const relational & rel,
555 int order,
556 unsigned options)
557{
558 // method:
559 // Taylor series where there is no pole falls back to polygamma function
560 // evaluation.
561 // On a pole at -m use the recurrence relation
562 // psi(n,x) == psi(n,x+1) - (-)^n * n! / x^(n+1)
563 // from which follows
564 // series(psi(x),x==-m,order) ==
565 // series(psi(x+m+1) - (-1)^n * n! * ((x)^(-n-1) + (x+1)^(-n-1) + ...
566 // ... + (x+m)^(-n-1))),x==-m,order);
567 const ex arg_pt = arg.subs(rel, subs_options::no_pattern);
568 if (!arg_pt.info(info_flags::integer) || arg_pt.info(info_flags::positive))
569 throw do_taylor(); // caught by function::series()
570 // if we got here we have to care for a pole of order n+1 at -m:
571 const numeric m = -ex_to<numeric>(arg_pt);
572 ex recur;
573 for (numeric p; p<=m; ++p)
574 recur += power(arg+p,-n+_ex_1);
575 recur *= factorial(n)*power(_ex_1,n);
576 return (psi(n, arg+m+_ex1)-recur).series(rel, order, options);
577}
578
579unsigned psi2_SERIAL::serial =
580 function::register_new(function_options("psi", 2).
581 eval_func(psi2_eval).
582 evalf_func(psi2_evalf).
583 derivative_func(psi2_deriv).
584 series_func(psi2_series).
585 latex_name("\\psi").
586 overloaded(2));
587
588
589} // namespace GiNaC
#define GINAC_ASSERT(X)
Assertion macro for checking invariances.
Definition: assertion.h:33
const basic & hold() const
Stop further evaluation.
Definition: basic.cpp:887
virtual ex series(const relational &r, int order, unsigned options=0) const
Default implementation of ex::series().
Definition: pseries.cpp:611
Exception class thrown by classes which provide their own series expansion to signal that ordinary Ta...
Definition: function.h:668
Exception class thrown by functions to signal unimplemented functionality so the expression may just ...
Definition: utils.h:37
Lightweight wrapper for GiNaC's symbolic objects.
Definition: ex.h:72
bool is_equal(const ex &other) const
Definition: ex.h:345
ex conjugate() const
Definition: ex.h:146
ex series(const ex &r, int order, unsigned options=0) const
Compute the truncated series expansion of an expression.
Definition: pseries.cpp:1272
ex imag_part() const
Definition: ex.h:148
ex subs(const exmap &m, unsigned options=0) const
Definition: ex.h:841
bool info(unsigned inf) const
Definition: ex.h:132
bool is_zero() const
Definition: ex.h:213
static unsigned register_new(function_options const &opt)
Definition: function.cpp:2243
This class is a wrapper around CLN-numbers within the GiNaC class hierarchy.
Definition: numeric.h:82
bool is_positive() const
True if object is not complex and greater than zero.
Definition: numeric.cpp:1136
bool is_real() const
True if object is a real integer, rational or float (but not complex).
Definition: numeric.cpp:1208
bool is_integer() const
True if object is a non-complex integer.
Definition: numeric.cpp:1154
bool is_negative() const
True if object is not complex and less than zero.
Definition: numeric.cpp:1145
bool is_even() const
True if object is an exact even integer.
Definition: numeric.cpp:1175
bool is_equal(const numeric &other) const
Definition: numeric.cpp:1122
const numeric inverse() const
Inverse of a number.
Definition: numeric.cpp:1053
const numeric div(const numeric &other) const
Numerical division method.
Definition: numeric.cpp:890
Exception class thrown when a singularity is encountered.
Definition: numeric.h:70
This class holds a two-component object, a basis and and exponent representing exponentiation.
Definition: power.h:39
ex series(const relational &s, int order, unsigned options=0) const override
Implementation of ex::series() for powers.
Definition: pseries.cpp:1085
static unsigned serial
Definition: inifcns.h:163
static unsigned serial
Definition: inifcns.h:169
This class holds a relation consisting of two expressions and a logical relation between them.
Definition: relational.h:35
ex lhs() const
Definition: relational.h:81
@ no_pattern
disable pattern matching
Definition: flags.h:51
Basic CAS symbol.
Definition: symbol.h:39
Interface to GiNaC's constant types and some special constants.
unsigned options
Definition: factor.cpp:2475
size_t n
Definition: factor.cpp:1432
ex x
Definition: factor.cpp:1610
mvec m
Definition: factor.cpp:758
Interface to GiNaC's initially known functions.
int order
Definition: add.cpp:38
static ex lgamma_deriv(const ex &x, unsigned deriv_param)
const numeric * _num_1_p
Definition: utils.cpp:351
const ex _ex2
Definition: utils.cpp:389
const numeric pow(const numeric &x, const numeric &y)
Definition: numeric.h:251
const ex _ex1_2
Definition: utils.cpp:381
static ex beta_series(const ex &arg1, const ex &arg2, const relational &rel, int order, unsigned options)
symmetry sy_symm()
Definition: symmetry.h:121
const numeric abs(const numeric &x)
Absolute value.
Definition: numeric.cpp:2320
const constant Euler("Euler", EulerEvalf, "\\gamma_E", domain::positive)
Euler's constant.
Definition: constant.h:84
const numeric * _num1_2_p
Definition: utils.cpp:380
function zeta(const T1 &p1)
Definition: inifcns.h:111
const ex _ex1
Definition: utils.cpp:385
const numeric doublefactorial(const numeric &n)
The double factorial combinatorial function.
Definition: numeric.cpp:2127
static ex lgamma_eval(const ex &x)
Evaluation of lgamma(x), the natural logarithm of the Gamma function.
bool is_rational(const numeric &x)
Definition: numeric.h:290
static ex psi2_eval(const ex &n, const ex &x)
Evaluation of polygamma-function psi(n,x).
static ex beta_deriv(const ex &x, const ex &y, unsigned deriv_param)
function psi(const T1 &p1)
Definition: inifcns.h:165
const numeric sqrt(const numeric &x)
Numeric square root.
Definition: numeric.cpp:2480
const cln::cl_N tgamma(const cln::cl_N &x)
Definition: numeric.cpp:2067
static ex psi1_eval(const ex &x)
Evaluation of digamma-function psi(x).
const numeric * _num_2_p
Definition: utils.cpp:347
const numeric * _num2_p
Definition: utils.cpp:388
static ex tgamma_deriv(const ex &x, unsigned deriv_param)
const numeric exp(const numeric &x)
Exponential function.
Definition: numeric.cpp:1439
const numeric factorial(const numeric &n)
Factorial combinatorial function.
Definition: numeric.cpp:2113
const ex _ex_1
Definition: utils.cpp:352
static ex beta_eval(const ex &x, const ex &y)
const constant Pi("Pi", PiEvalf, "\\pi", domain::positive)
Pi.
Definition: constant.h:82
static ex tgamma_evalf(const ex &x)
static ex psi2_deriv(const ex &n, const ex &x, unsigned deriv_param)
const numeric log(const numeric &x)
Natural logarithm.
Definition: numeric.cpp:1450
ex evalf(const ex &thisex)
Definition: ex.h:784
static ex tgamma_eval(const ex &x)
Evaluation of tgamma(x), the true Gamma function.
bool is_real(const numeric &x)
Definition: numeric.h:293
const numeric * _num1_p
Definition: utils.cpp:384
static ex lgamma_series(const ex &arg, const relational &rel, int order, unsigned options)
static ex lgamma_conjugate(const ex &x)
static ex tgamma_conjugate(const ex &x)
static ex psi1_deriv(const ex &x, unsigned deriv_param)
bool is_integer(const numeric &x)
Definition: numeric.h:272
static ex psi2_series(const ex &n, const ex &arg, const relational &rel, int order, unsigned options)
static ex psi2_evalf(const ex &n, const ex &x)
static ex psi1_evalf(const ex &x)
REGISTER_FUNCTION(conjugate_function, eval_func(conjugate_eval). evalf_func(conjugate_evalf). expl_derivative_func(conjugate_expl_derivative). info_func(conjugate_info). print_func< print_latex >(conjugate_print_latex). conjugate_func(conjugate_conjugate). real_part_func(conjugate_real_part). imag_part_func(conjugate_imag_part). set_name("conjugate","conjugate"))
static ex beta_evalf(const ex &x, const ex &y)
const cln::cl_N lgamma(const cln::cl_N &x)
The Gamma function.
Definition: numeric.cpp:2039
static ex lgamma_evalf(const ex &x)
bool is_positive(const numeric &x)
Definition: numeric.h:266
const ex _ex0
Definition: utils.cpp:369
static ex tgamma_series(const ex &arg, const relational &rel, int order, unsigned options)
static ex psi1_series(const ex &arg, const relational &rel, int order, unsigned options)
Makes the interface to the underlying bignum package available.
Interface to GiNaC's overloaded operators.
Interface to GiNaC's symbolic exponentiation (basis^exponent).
Interface to class for extended truncated power series.
Interface to relations between expressions.
Interface to GiNaC's symbolic objects.
Interface to GiNaC's symmetry definitions.
Interface to several small and furry utilities needed within GiNaC but not of any interest to the use...

This page is part of the GiNaC developer's reference. It was generated automatically by doxygen. For an introduction, see the tutorial.