82cln::cl_N arithmetic_geometric_mean(
const cln::cl_N & a_0,
const cln::cl_N & b_0)
84 cln::cl_N a_old = a_0 * cln::cl_float(1, cln::float_format(
Digits));
85 cln::cl_N b_old = b_0 * cln::cl_float(1, cln::float_format(
Digits));
88 cln::cl_N res = a_old;
93 a_new = (a_old+b_old)/2;
94 b_new =
sqrt(a_old*b_old);
96 if ( (
abs(a_new-b_new) >
abs(a_new+b_new) )
98 ( (
abs(a_new-b_new) ==
abs(a_new+b_new)) && (imagpart(b_new/a_new) <= 0) ) ) {
106 }
while (res != resbuf);
117cln::cl_N agm_helper_second_kind(
const cln::cl_N & a_0,
const cln::cl_N & b_0,
const cln::cl_N & c_0)
119 cln::cl_N a_old = a_0 * cln::cl_float(1, cln::float_format(
Digits));
120 cln::cl_N b_old = b_0 * cln::cl_float(1, cln::float_format(
Digits));
121 cln::cl_N c_old = c_0 * cln::cl_float(1, cln::float_format(
Digits));
125 cln::cl_N res = square(a_old)-square(c_old)/2;
127 cln::cl_N pre = cln::cl_float(1, cln::float_format(
Digits));
131 a_new = (a_old+b_old)/2;
132 b_new =
sqrt(a_old*b_old);
134 if ( (
abs(a_new-b_new) >
abs(a_new+b_new) )
136 ( (
abs(a_new-b_new) ==
abs(a_new+b_new)) && (imagpart(b_new/a_new) <= 0) ) ) {
140 c_new = square(c_old)/4/a_new;
142 res -= pre*square(c_new);
149 }
while (res != resbuf);
168 return EllipticK(
k).hold();
171 cln::cl_N kbar =
sqrt(1-square(ex_to<numeric>(
k).to_cl_N()));
173 ex result =
Pi/2/
numeric(arithmetic_geometric_mean(1,kbar));
175 return result.
evalf();
186 return EllipticK(
k).
evalf();
189 return EllipticK(
k).hold();
195 return -EllipticK(
k)/
k + EllipticE(
k)/
k/(1-
k*
k);
207 for (
int i=0; i<(
order+1)/2; ++i)
209 ser +=
Pi/2 *
numeric(cln::square(cln::binomial(2*i,i))) *
pow(s/4,2*i);
215 ser +=
pseries(rel, std::move(nseq));
220 if ( (k_pt ==
_ex1) || (k_pt ==
_ex_1) ) {
221 throw std::runtime_error(
"EllipticK_series: don't know how to do the series expansion at this point!");
230 c.s <<
"\\mathrm{K}(";
242 do_not_evalf_params());
248 return EllipticE(
k).hold();
251 cln::cl_N kbar =
sqrt(1-square(ex_to<numeric>(
k).to_cl_N()));
253 ex result =
Pi/2 *
numeric( agm_helper_second_kind(1,kbar,ex_to<numeric>(
k).to_cl_N()) / arithmetic_geometric_mean(1,kbar) );
255 return result.
evalf();
270 return EllipticE(
k).
evalf();
273 return EllipticE(
k).hold();
279 return -EllipticK(
k)/
k + EllipticE(
k)/
k;
291 for (
int i=0; i<(
order+1)/2; ++i)
293 ser -=
Pi/2 *
numeric(cln::square(cln::binomial(2*i,i)))/(2*i-1) *
pow(s/4,2*i);
299 ser +=
pseries(rel, std::move(nseq));
304 if ( (k_pt ==
_ex1) || (k_pt ==
_ex_1) ) {
305 throw std::runtime_error(
"EllipticE_series: don't know how to do the series expansion at this point!");
314 c.s <<
"\\mathrm{K}(";
326 do_not_evalf_params());
341cln::cl_N iterated_integral_do_sum(
const std::vector<int> &
m,
const std::vector<const integration_kernel *> & kernel,
const cln::cl_N & lambda,
int N_trunc)
343 if ( cln::zerop(lambda) ) {
347 cln::cl_F
one = cln::cl_float(1, cln::float_format(
Digits));
349 const int depth =
m.size();
355 if ( N_trunc == 0 ) {
357 bool flag_accidental_zero =
false;
366 multi_iterator_ordered_eq<int> i_multi(1,N+1,depth-1);
367 for( i_multi.init(); !i_multi.overflow(); i_multi++) {
369 for (
int j=1; j<depth; j++) {
371 tt = tt * kernel[0]->series_coeff(N-i_multi[depth-2]) / cln::expt(cln::cl_I(i_multi[depth-2]),
m[1]);
374 tt = tt * kernel[j-1]->series_coeff(i_multi[depth-j]-i_multi[depth-j-1]) / cln::expt(cln::cl_I(i_multi[depth-j-1]),
m[j]);
377 tt = tt * kernel[depth-1]->series_coeff(i_multi[0]);
383 subexpr = kernel[0]->series_coeff(N) *
one;
385 flag_accidental_zero = cln::zerop(subexpr);
386 res += cln::expt(lambda, N) / cln::expt(cln::cl_I(N),
m[0]) * subexpr;
389 }
while ( (res != resbuf) || flag_accidental_zero );
393 for (
int N=1; N<=N_trunc; N++) {
396 multi_iterator_ordered_eq<int> i_multi(1,N+1,depth-1);
397 for( i_multi.init(); !i_multi.overflow(); i_multi++) {
399 for (
int j=1; j<depth; j++) {
401 tt = tt * kernel[0]->series_coeff(N-i_multi[depth-2]) / cln::expt(cln::cl_I(i_multi[depth-2]),
m[1]);
404 tt = tt * kernel[j-1]->series_coeff(i_multi[depth-j]-i_multi[depth-j-1]) / cln::expt(cln::cl_I(i_multi[depth-j-1]),
m[j]);
407 tt = tt * kernel[depth-1]->series_coeff(i_multi[0]);
413 subexpr = kernel[0]->series_coeff(N) *
one;
415 res += cln::expt(lambda, N) / cln::expt(cln::cl_I(N),
m[0]) * subexpr;
423cln::cl_N iterated_integral_prepare_m_lst(
const std::vector<const integration_kernel *> & kernel_in,
const cln::cl_N & lambda,
int N_trunc)
425 size_t depth = kernel_in.size();
430 std::vector<const integration_kernel *> kernel;
431 kernel.reserve(depth);
435 for (
const auto & it : kernel_in) {
436 if ( is_a<basic_log_kernel>(*it) ) {
441 kernel.push_back( &ex_to<integration_kernel>(*it) );
446 cln::cl_N result = iterated_integral_do_sum(
m, kernel, lambda, N_trunc);
453cln::cl_N iterated_integral_shuffle(
const std::vector<const integration_kernel *> & kernel,
const cln::cl_N & lambda,
int N_trunc)
455 cln::cl_F
one = cln::cl_float(1, cln::float_format(
Digits));
457 const size_t depth = kernel.size();
459 size_t i_trailing = 0;
460 for (
size_t i=0; i<depth; i++) {
461 if ( !(is_a<basic_log_kernel>(*(kernel[i]))) ) {
466 if ( i_trailing == 0 ) {
467 return cln::expt(cln::log(lambda), depth) / cln::factorial(depth) *
one;
470 if ( i_trailing == depth ) {
471 return iterated_integral_prepare_m_lst(kernel, lambda, N_trunc);
475 std::vector<const integration_kernel *> a,b;
476 for (
size_t i=0; i<i_trailing; i++) {
477 a.push_back(kernel[i]);
479 for (
size_t i=i_trailing; i<depth; i++) {
480 b.push_back(kernel[i]);
483 cln::cl_N result = iterated_integral_prepare_m_lst(a, lambda, N_trunc) * cln::expt(cln::log(lambda), depth-i_trailing) / cln::factorial(depth-i_trailing);
484 multi_iterator_shuffle_prime<const integration_kernel *> i_shuffle(a,b);
485 for( i_shuffle.init(); !i_shuffle.overflow(); i_shuffle++) {
486 std::vector<const integration_kernel *> new_kernel;
487 new_kernel.reserve(depth);
488 for (
size_t i=0; i<depth; i++) {
489 new_kernel.push_back(i_shuffle[i]);
492 result -= iterated_integral_shuffle(new_kernel, lambda, N_trunc);
515 lst k_lst = ex_to<lst>(kernel_lst);
517 bool flag_not_numeric =
false;
518 for (
const auto & it : k_lst) {
519 if ( !is_a<integration_kernel>(it) ) {
520 flag_not_numeric =
true;
523 if ( flag_not_numeric) {
527 for (
const auto & it : k_lst) {
528 if ( !(ex_to<integration_kernel>(it).is_numeric()) ) {
529 flag_not_numeric =
true;
532 if ( flag_not_numeric) {
538 int N_trunc_int = ex_to<numeric>(N_trunc).to_int();
541 const size_t depth = k_lst.
nops();
543 std::vector<const integration_kernel *> kernel_vec;
544 kernel_vec.reserve(depth);
546 for (
const auto & it : k_lst) {
547 kernel_vec.push_back( &ex_to<integration_kernel>(it) );
550 size_t i_trailing = 0;
551 for (
size_t i=0; i<depth; i++) {
552 if ( !(kernel_vec[i]->has_trailing_zero()) ) {
559 cln::cl_F
one = cln::cl_float(1, cln::float_format(
Digits));
560 cln::cl_N lambda_cln = ex_to<numeric>(lambda.
evalf()).to_cl_N();
564 if ( is_a<basic_log_kernel>(*(kernel_vec[depth-1])) ) {
568 result = iterated_integral_shuffle(kernel_vec, lambda_cln, N_trunc_int);
572 for (
size_t i_plus=depth; i_plus>i_trailing; i_plus--) {
573 coeff =
coeff * kernel_vec[i_plus-1]->series_coeff(0);
574 kernel_vec[i_plus-1] = &L0;
575 if ( i_plus==i_trailing+1 ) {
576 result +=
coeff * iterated_integral_shuffle(kernel_vec, lambda_cln, N_trunc_int);
579 if ( !(is_a<basic_log_kernel>(*(kernel_vec[i_plus-2]))) ) {
580 result +=
coeff * iterated_integral_shuffle(kernel_vec, lambda_cln, N_trunc_int);
620 do_not_evalf_params().
627 do_not_evalf_params().
Interface to GiNaC's sums of expressions.
The basic integration kernel with a logarithmic singularity at the origin.
const basic & hold() const
Stop further evaluation.
ex evalf() const override
Evaluate object numerically.
Wrapper template for making GiNaC classes out of STL containers.
size_t nops() const override
Number of operands/members.
Exception class thrown by classes which provide their own series expansion to signal that ordinary Ta...
Lightweight wrapper for GiNaC's symbolic objects.
ex series(const ex &r, int order, unsigned options=0) const
Compute the truncated series expansion of an expression.
ex subs(const exmap &m, unsigned options=0) const
bool info(unsigned inf) const
ex evalf() const override
Evaluate object numerically.
static unsigned register_new(function_options const &opt)
This class is a wrapper around CLN-numbers within the GiNaC class hierarchy.
Base class for print_contexts.
This class holds a extended truncated power series (positive and negative integer powers).
This class holds a relation consisting of two expressions and a logical relation between them.
@ no_pattern
disable pattern matching
ex series(const relational &s, int order, unsigned options=0) const override
Implementation of ex::series() for symbols.
Interface to GiNaC's constant types and some special constants.
#define REGISTER_FUNCTION(NAME, OPT)
Interface to GiNaC's initially known functions.
Interface to GiNaC's integration kernels for iterated integrals.
Definition of GiNaC's lst.
Interface to GiNaC's products of expressions.
static ex iterated_integral3_evalf(const ex &kernel_lst, const ex &lambda, const ex &N_trunc)
static ex iterated_integral2_eval(const ex &kernel_lst, const ex &lambda)
const numeric pow(const numeric &x, const numeric &y)
static ex EllipticE_evalf(const ex &k)
static void EllipticK_print_latex(const ex &k, const print_context &c)
static ex EllipticE_series(const ex &k, const relational &rel, int order, unsigned options)
static ex iterated_integral3_eval(const ex &kernel_lst, const ex &lambda, const ex &N_trunc)
static ex EllipticK_series(const ex &k, const relational &rel, int order, unsigned options)
std::vector< expair > epvector
expair-vector
const numeric abs(const numeric &x)
Absolute value.
function iterated_integral(const T1 &kernel_lst, const T2 &lambda)
const numeric sqrt(const numeric &x)
Numeric square root.
static ex iterated_integral_evalf_impl(const ex &kernel_lst, const ex &lambda, const ex &N_trunc)
static void EllipticE_print_latex(const ex &k, const print_context &c)
static ex EllipticE_eval(const ex &k)
const constant Pi("Pi", PiEvalf, "\\pi", domain::positive)
Pi.
static ex EllipticK_eval(const ex &k)
static ex EllipticE_deriv(const ex &k, unsigned deriv_param)
static ex EllipticK_evalf(const ex &k)
static ex EllipticK_deriv(const ex &k, unsigned deriv_param)
_numeric_digits Digits
Accuracy in decimal digits.
ex coeff(const ex &thisex, const ex &s, int n=1)
static ex iterated_integral2_evalf(const ex &kernel_lst, const ex &lambda)
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 several small and furry utilities needed within GiNaC but not of any interest to the use...
Utilities for summing over multiple indices.
Interface to GiNaC's wildcard objects.