GiNaC  1.8.3
inifcns.cpp
Go to the documentation of this file.
1 
5 /*
6  * GiNaC Copyright (C) 1999-2022 Johannes Gutenberg University Mainz, Germany
7  *
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.
12  *
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.
17  *
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include "inifcns.h"
24 #include "ex.h"
25 #include "constant.h"
26 #include "lst.h"
27 #include "fderivative.h"
28 #include "matrix.h"
29 #include "mul.h"
30 #include "power.h"
31 #include "operators.h"
32 #include "relational.h"
33 #include "pseries.h"
34 #include "symbol.h"
35 #include "symmetry.h"
36 #include "utils.h"
37 
38 #include <stdexcept>
39 #include <vector>
40 
41 namespace GiNaC {
42 
44 // complex conjugate
46 
47 static ex conjugate_evalf(const ex & arg)
48 {
49  if (is_exactly_a<numeric>(arg)) {
50  return ex_to<numeric>(arg).conjugate();
51  }
52  return conjugate_function(arg).hold();
53 }
54 
55 static ex conjugate_eval(const ex & arg)
56 {
57  return arg.conjugate();
58 }
59 
60 static void conjugate_print_latex(const ex & arg, const print_context & c)
61 {
62  c.s << "\\bar{"; arg.print(c); c.s << "}";
63 }
64 
65 static ex conjugate_conjugate(const ex & arg)
66 {
67  return arg;
68 }
69 
70 // If x is real then U.diff(x)-I*V.diff(x) represents both conjugate(U+I*V).diff(x)
71 // and conjugate((U+I*V).diff(x))
72 static ex conjugate_expl_derivative(const ex & arg, const symbol & s)
73 {
74  if (s.info(info_flags::real))
75  return conjugate(arg.diff(s));
76  else {
77  exvector vec_arg;
78  vec_arg.push_back(arg);
79  return fderivative(ex_to<function>(conjugate(arg)).get_serial(),0,vec_arg).hold()*arg.diff(s);
80  }
81 }
82 
83 static ex conjugate_real_part(const ex & arg)
84 {
85  return arg.real_part();
86 }
87 
88 static ex conjugate_imag_part(const ex & arg)
89 {
90  return -arg.imag_part();
91 }
92 
93 static bool func_arg_info(const ex & arg, unsigned inf)
94 {
95  // for some functions we can return the info() of its argument
96  // (think of conjugate())
97  switch (inf) {
102  case info_flags::real:
104  case info_flags::integer:
107  case info_flags::even:
108  case info_flags::odd:
109  case info_flags::prime:
115  case info_flags::posint:
116  case info_flags::negint:
119  return arg.info(inf);
120  }
121  return false;
122 }
123 
124 static bool conjugate_info(const ex & arg, unsigned inf)
125 {
126  return func_arg_info(arg, inf);
127 }
128 
129 REGISTER_FUNCTION(conjugate_function, eval_func(conjugate_eval).
130  evalf_func(conjugate_evalf).
131  expl_derivative_func(conjugate_expl_derivative).
132  info_func(conjugate_info).
133  print_func<print_latex>(conjugate_print_latex).
134  conjugate_func(conjugate_conjugate).
135  real_part_func(conjugate_real_part).
136  imag_part_func(conjugate_imag_part).
137  set_name("conjugate","conjugate"));
138 
140 // real part
142 
143 static ex real_part_evalf(const ex & arg)
144 {
145  if (is_exactly_a<numeric>(arg)) {
146  return ex_to<numeric>(arg).real();
147  }
148  return real_part_function(arg).hold();
149 }
150 
151 static ex real_part_eval(const ex & arg)
152 {
153  return arg.real_part();
154 }
155 
156 static void real_part_print_latex(const ex & arg, const print_context & c)
157 {
158  c.s << "\\Re"; arg.print(c); c.s << "";
159 }
160 
161 static ex real_part_conjugate(const ex & arg)
162 {
163  return real_part_function(arg).hold();
164 }
165 
166 static ex real_part_real_part(const ex & arg)
167 {
168  return real_part_function(arg).hold();
169 }
170 
171 static ex real_part_imag_part(const ex & arg)
172 {
173  return 0;
174 }
175 
176 // If x is real then Re(e).diff(x) is equal to Re(e.diff(x))
177 static ex real_part_expl_derivative(const ex & arg, const symbol & s)
178 {
179  if (s.info(info_flags::real))
180  return real_part_function(arg.diff(s));
181  else {
182  exvector vec_arg;
183  vec_arg.push_back(arg);
184  return fderivative(ex_to<function>(real_part(arg)).get_serial(),0,vec_arg).hold()*arg.diff(s);
185  }
186 }
187 
188 REGISTER_FUNCTION(real_part_function, eval_func(real_part_eval).
189  evalf_func(real_part_evalf).
190  expl_derivative_func(real_part_expl_derivative).
191  print_func<print_latex>(real_part_print_latex).
192  conjugate_func(real_part_conjugate).
193  real_part_func(real_part_real_part).
194  imag_part_func(real_part_imag_part).
195  set_name("real_part","real_part"));
196 
198 // imag part
200 
201 static ex imag_part_evalf(const ex & arg)
202 {
203  if (is_exactly_a<numeric>(arg)) {
204  return ex_to<numeric>(arg).imag();
205  }
206  return imag_part_function(arg).hold();
207 }
208 
209 static ex imag_part_eval(const ex & arg)
210 {
211  return arg.imag_part();
212 }
213 
214 static void imag_part_print_latex(const ex & arg, const print_context & c)
215 {
216  c.s << "\\Im"; arg.print(c); c.s << "";
217 }
218 
219 static ex imag_part_conjugate(const ex & arg)
220 {
221  return imag_part_function(arg).hold();
222 }
223 
224 static ex imag_part_real_part(const ex & arg)
225 {
226  return imag_part_function(arg).hold();
227 }
228 
229 static ex imag_part_imag_part(const ex & arg)
230 {
231  return 0;
232 }
233 
234 // If x is real then Im(e).diff(x) is equal to Im(e.diff(x))
235 static ex imag_part_expl_derivative(const ex & arg, const symbol & s)
236 {
237  if (s.info(info_flags::real))
238  return imag_part_function(arg.diff(s));
239  else {
240  exvector vec_arg;
241  vec_arg.push_back(arg);
242  return fderivative(ex_to<function>(imag_part(arg)).get_serial(),0,vec_arg).hold()*arg.diff(s);
243  }
244 }
245 
246 REGISTER_FUNCTION(imag_part_function, eval_func(imag_part_eval).
247  evalf_func(imag_part_evalf).
248  expl_derivative_func(imag_part_expl_derivative).
249  print_func<print_latex>(imag_part_print_latex).
250  conjugate_func(imag_part_conjugate).
251  real_part_func(imag_part_real_part).
252  imag_part_func(imag_part_imag_part).
253  set_name("imag_part","imag_part"));
254 
256 // absolute value
258 
259 static ex abs_evalf(const ex & arg)
260 {
261  if (is_exactly_a<numeric>(arg))
262  return abs(ex_to<numeric>(arg));
263 
264  return abs(arg).hold();
265 }
266 
267 static ex abs_eval(const ex & arg)
268 {
269  if (is_exactly_a<numeric>(arg))
270  return abs(ex_to<numeric>(arg));
271 
272  if (arg.info(info_flags::nonnegative))
273  return arg;
274 
275  if (arg.info(info_flags::negative) || (-arg).info(info_flags::nonnegative))
276  return -arg;
277 
278  if (is_ex_the_function(arg, abs))
279  return arg;
280 
281  if (is_ex_the_function(arg, exp))
282  return exp(arg.op(0).real_part());
283 
284  if (is_exactly_a<power>(arg)) {
285  const ex& base = arg.op(0);
286  const ex& exponent = arg.op(1);
287  if (base.info(info_flags::positive) || exponent.info(info_flags::real))
288  return pow(abs(base), exponent.real_part());
289  }
290 
291  if (is_ex_the_function(arg, conjugate_function))
292  return abs(arg.op(0));
293 
294  if (is_ex_the_function(arg, step))
295  return arg;
296 
297  return abs(arg).hold();
298 }
299 
300 static ex abs_expand(const ex & arg, unsigned options)
301 {
303  && is_exactly_a<mul>(arg)) {
304  exvector prodseq;
305  prodseq.reserve(arg.nops());
306  for (const_iterator i = arg.begin(); i != arg.end(); ++i) {
308  prodseq.push_back(abs(i->expand(options)));
309  else
310  prodseq.push_back(abs(*i));
311  }
312  return dynallocate<mul>(prodseq).setflag(status_flags::expanded);
313  }
314 
316  return abs(arg.expand(options)).hold();
317  else
318  return abs(arg).hold();
319 }
320 
321 static ex abs_expl_derivative(const ex & arg, const symbol & s)
322 {
323  ex diff_arg = arg.diff(s);
324  return (diff_arg*arg.conjugate()+arg*diff_arg.conjugate())/2/abs(arg);
325 }
326 
327 static void abs_print_latex(const ex & arg, const print_context & c)
328 {
329  c.s << "{|"; arg.print(c); c.s << "|}";
330 }
331 
332 static void abs_print_csrc_float(const ex & arg, const print_context & c)
333 {
334  c.s << "fabs("; arg.print(c); c.s << ")";
335 }
336 
337 static ex abs_conjugate(const ex & arg)
338 {
339  return abs(arg).hold();
340 }
341 
342 static ex abs_real_part(const ex & arg)
343 {
344  return abs(arg).hold();
345 }
346 
347 static ex abs_imag_part(const ex& arg)
348 {
349  return 0;
350 }
351 
352 static ex abs_power(const ex & arg, const ex & exp)
353 {
354  if ((is_a<numeric>(exp) && ex_to<numeric>(exp).is_even()) || exp.info(info_flags::even)) {
355  if (arg.info(info_flags::real) || arg.is_equal(arg.conjugate()))
356  return pow(arg, exp);
357  else
358  return pow(arg, exp/2) * pow(arg.conjugate(), exp/2);
359  } else
360  return power(abs(arg), exp).hold();
361 }
362 
363 bool abs_info(const ex & arg, unsigned inf)
364 {
365  switch (inf) {
366  case info_flags::integer:
367  case info_flags::even:
368  case info_flags::odd:
369  case info_flags::prime:
370  return arg.info(inf);
372  return arg.info(info_flags::integer);
374  case info_flags::real:
375  return true;
377  return false;
381  if (arg.info(info_flags::has_indices))
382  return true;
383  else
384  return false;
385  }
386  }
387  return false;
388 }
389 
391  evalf_func(abs_evalf).
392  expand_func(abs_expand).
393  expl_derivative_func(abs_expl_derivative).
394  info_func(abs_info).
395  print_func<print_latex>(abs_print_latex).
396  print_func<print_csrc_float>(abs_print_csrc_float).
397  print_func<print_csrc_double>(abs_print_csrc_float).
398  conjugate_func(abs_conjugate).
399  real_part_func(abs_real_part).
400  imag_part_func(abs_imag_part).
401  power_func(abs_power));
402 
404 // Step function
406 
407 static ex step_evalf(const ex & arg)
408 {
409  if (is_exactly_a<numeric>(arg))
410  return step(ex_to<numeric>(arg));
411 
412  return step(arg).hold();
413 }
414 
415 static ex step_eval(const ex & arg)
416 {
417  if (is_exactly_a<numeric>(arg))
418  return step(ex_to<numeric>(arg));
419 
420  else if (is_exactly_a<mul>(arg) &&
421  is_exactly_a<numeric>(arg.op(arg.nops()-1))) {
422  numeric oc = ex_to<numeric>(arg.op(arg.nops()-1));
423  if (oc.is_real()) {
424  if (oc > 0)
425  // step(42*x) -> step(x)
426  return step(arg/oc).hold();
427  else
428  // step(-42*x) -> step(-x)
429  return step(-arg/oc).hold();
430  }
431  if (oc.real().is_zero()) {
432  if (oc.imag() > 0)
433  // step(42*I*x) -> step(I*x)
434  return step(I*arg/oc).hold();
435  else
436  // step(-42*I*x) -> step(-I*x)
437  return step(-I*arg/oc).hold();
438  }
439  }
440 
441  return step(arg).hold();
442 }
443 
444 static ex step_series(const ex & arg,
445  const relational & rel,
446  int order,
447  unsigned options)
448 {
449  const ex arg_pt = arg.subs(rel, subs_options::no_pattern);
450  if (arg_pt.info(info_flags::numeric)
451  && ex_to<numeric>(arg_pt).real().is_zero()
453  throw (std::domain_error("step_series(): on imaginary axis"));
454 
455  epvector seq { expair(step(arg_pt), _ex0) };
456  return pseries(rel, std::move(seq));
457 }
458 
459 static ex step_conjugate(const ex& arg)
460 {
461  return step(arg).hold();
462 }
463 
464 static ex step_real_part(const ex& arg)
465 {
466  return step(arg).hold();
467 }
468 
469 static ex step_imag_part(const ex& arg)
470 {
471  return 0;
472 }
473 
475  evalf_func(step_evalf).
476  series_func(step_series).
477  conjugate_func(step_conjugate).
478  real_part_func(step_real_part).
479  imag_part_func(step_imag_part));
480 
482 // Complex sign
484 
485 static ex csgn_evalf(const ex & arg)
486 {
487  if (is_exactly_a<numeric>(arg))
488  return csgn(ex_to<numeric>(arg));
489 
490  return csgn(arg).hold();
491 }
492 
493 static ex csgn_eval(const ex & arg)
494 {
495  if (is_exactly_a<numeric>(arg))
496  return csgn(ex_to<numeric>(arg));
497 
498  else if (is_exactly_a<mul>(arg) &&
499  is_exactly_a<numeric>(arg.op(arg.nops()-1))) {
500  numeric oc = ex_to<numeric>(arg.op(arg.nops()-1));
501  if (oc.is_real()) {
502  if (oc > 0)
503  // csgn(42*x) -> csgn(x)
504  return csgn(arg/oc).hold();
505  else
506  // csgn(-42*x) -> -csgn(x)
507  return -csgn(arg/oc).hold();
508  }
509  if (oc.real().is_zero()) {
510  if (oc.imag() > 0)
511  // csgn(42*I*x) -> csgn(I*x)
512  return csgn(I*arg/oc).hold();
513  else
514  // csgn(-42*I*x) -> -csgn(I*x)
515  return -csgn(I*arg/oc).hold();
516  }
517  }
518 
519  return csgn(arg).hold();
520 }
521 
522 static ex csgn_series(const ex & arg,
523  const relational & rel,
524  int order,
525  unsigned options)
526 {
527  const ex arg_pt = arg.subs(rel, subs_options::no_pattern);
528  if (arg_pt.info(info_flags::numeric)
529  && ex_to<numeric>(arg_pt).real().is_zero()
531  throw (std::domain_error("csgn_series(): on imaginary axis"));
532 
533  epvector seq { expair(csgn(arg_pt), _ex0) };
534  return pseries(rel, std::move(seq));
535 }
536 
537 static ex csgn_conjugate(const ex& arg)
538 {
539  return csgn(arg).hold();
540 }
541 
542 static ex csgn_real_part(const ex& arg)
543 {
544  return csgn(arg).hold();
545 }
546 
547 static ex csgn_imag_part(const ex& arg)
548 {
549  return 0;
550 }
551 
552 static ex csgn_power(const ex & arg, const ex & exp)
553 {
554  if (is_a<numeric>(exp) && exp.info(info_flags::positive) && ex_to<numeric>(exp).is_integer()) {
555  if (ex_to<numeric>(exp).is_odd())
556  return csgn(arg).hold();
557  else
558  return power(csgn(arg), _ex2).hold();
559  } else
560  return power(csgn(arg), exp).hold();
561 }
562 
563 
565  evalf_func(csgn_evalf).
566  series_func(csgn_series).
567  conjugate_func(csgn_conjugate).
568  real_part_func(csgn_real_part).
569  imag_part_func(csgn_imag_part).
570  power_func(csgn_power));
571 
572 
574 // Eta function: eta(x,y) == log(x*y) - log(x) - log(y).
575 // This function is closely related to the unwinding number K, sometimes found
576 // in modern literature: K(z) == (z-log(exp(z)))/(2*Pi*I).
578 
579 static ex eta_evalf(const ex &x, const ex &y)
580 {
581  // It seems like we basically have to replicate the eval function here,
582  // since the expression might not be fully evaluated yet.
584  return _ex0;
585 
587  const numeric nx = ex_to<numeric>(x);
588  const numeric ny = ex_to<numeric>(y);
589  const numeric nxy = ex_to<numeric>(x*y);
590  int cut = 0;
591  if (nx.is_real() && nx.is_negative())
592  cut -= 4;
593  if (ny.is_real() && ny.is_negative())
594  cut -= 4;
595  if (nxy.is_real() && nxy.is_negative())
596  cut += 4;
597  return evalf(I/4*Pi)*((csgn(-imag(nx))+1)*(csgn(-imag(ny))+1)*(csgn(imag(nxy))+1)-
598  (csgn(imag(nx))+1)*(csgn(imag(ny))+1)*(csgn(-imag(nxy))+1)+cut);
599  }
600 
601  return eta(x,y).hold();
602 }
603 
604 static ex eta_eval(const ex &x, const ex &y)
605 {
606  // trivial: eta(x,c) -> 0 if c is real and positive
608  return _ex0;
609 
611  // don't call eta_evalf here because it would call Pi.evalf()!
612  const numeric nx = ex_to<numeric>(x);
613  const numeric ny = ex_to<numeric>(y);
614  const numeric nxy = ex_to<numeric>(x*y);
615  int cut = 0;
616  if (nx.is_real() && nx.is_negative())
617  cut -= 4;
618  if (ny.is_real() && ny.is_negative())
619  cut -= 4;
620  if (nxy.is_real() && nxy.is_negative())
621  cut += 4;
622  return (I/4)*Pi*((csgn(-imag(nx))+1)*(csgn(-imag(ny))+1)*(csgn(imag(nxy))+1)-
623  (csgn(imag(nx))+1)*(csgn(imag(ny))+1)*(csgn(-imag(nxy))+1)+cut);
624  }
625 
626  return eta(x,y).hold();
627 }
628 
629 static ex eta_series(const ex & x, const ex & y,
630  const relational & rel,
631  int order,
632  unsigned options)
633 {
634  const ex x_pt = x.subs(rel, subs_options::no_pattern);
635  const ex y_pt = y.subs(rel, subs_options::no_pattern);
636  if ((x_pt.info(info_flags::numeric) && x_pt.info(info_flags::negative)) ||
638  ((x_pt*y_pt).info(info_flags::numeric) && (x_pt*y_pt).info(info_flags::negative)))
639  throw (std::domain_error("eta_series(): on discontinuity"));
640  epvector seq { expair(eta(x_pt,y_pt), _ex0) };
641  return pseries(rel, std::move(seq));
642 }
643 
644 static ex eta_conjugate(const ex & x, const ex & y)
645 {
646  return -eta(x, y).hold();
647 }
648 
649 static ex eta_real_part(const ex & x, const ex & y)
650 {
651  return 0;
652 }
653 
654 static ex eta_imag_part(const ex & x, const ex & y)
655 {
656  return -I*eta(x, y).hold();
657 }
658 
659 REGISTER_FUNCTION(eta, eval_func(eta_eval).
660  evalf_func(eta_evalf).
661  series_func(eta_series).
662  latex_name("\\eta").
663  set_symmetry(sy_symm(0, 1)).
664  conjugate_func(eta_conjugate).
665  real_part_func(eta_real_part).
666  imag_part_func(eta_imag_part));
667 
668 
670 // dilogarithm
672 
673 static ex Li2_evalf(const ex & x)
674 {
675  if (is_exactly_a<numeric>(x))
676  return Li2(ex_to<numeric>(x));
677 
678  return Li2(x).hold();
679 }
680 
681 static ex Li2_eval(const ex & x)
682 {
683  if (x.info(info_flags::numeric)) {
684  // Li2(0) -> 0
685  if (x.is_zero())
686  return _ex0;
687  // Li2(1) -> Pi^2/6
688  if (x.is_equal(_ex1))
689  return power(Pi,_ex2)/_ex6;
690  // Li2(1/2) -> Pi^2/12 - log(2)^2/2
691  if (x.is_equal(_ex1_2))
692  return power(Pi,_ex2)/_ex12 + power(log(_ex2),_ex2)*_ex_1_2;
693  // Li2(-1) -> -Pi^2/12
694  if (x.is_equal(_ex_1))
695  return -power(Pi,_ex2)/_ex12;
696  // Li2(I) -> -Pi^2/48+Catalan*I
697  if (x.is_equal(I))
698  return power(Pi,_ex2)/_ex_48 + Catalan*I;
699  // Li2(-I) -> -Pi^2/48-Catalan*I
700  if (x.is_equal(-I))
701  return power(Pi,_ex2)/_ex_48 - Catalan*I;
702  // Li2(float)
704  return Li2(ex_to<numeric>(x));
705  }
706 
707  return Li2(x).hold();
708 }
709 
710 static ex Li2_deriv(const ex & x, unsigned deriv_param)
711 {
712  GINAC_ASSERT(deriv_param==0);
713 
714  // d/dx Li2(x) -> -log(1-x)/x
715  return -log(_ex1-x)/x;
716 }
717 
718 static ex Li2_series(const ex &x, const relational &rel, int order, unsigned options)
719 {
720  const ex x_pt = x.subs(rel, subs_options::no_pattern);
721  if (x_pt.info(info_flags::numeric)) {
722  // First special case: x==0 (derivatives have poles)
723  if (x_pt.is_zero()) {
724  // method:
725  // The problem is that in d/dx Li2(x==0) == -log(1-x)/x we cannot
726  // simply substitute x==0. The limit, however, exists: it is 1.
727  // We also know all higher derivatives' limits:
728  // (d/dx)^n Li2(x) == n!/n^2.
729  // So the primitive series expansion is
730  // Li2(x==0) == x + x^2/4 + x^3/9 + ...
731  // and so on.
732  // We first construct such a primitive series expansion manually in
733  // a dummy symbol s and then insert the argument's series expansion
734  // for s. Reexpanding the resulting series returns the desired
735  // result.
736  const symbol s;
737  ex ser;
738  // manually construct the primitive expansion
739  for (int i=1; i<order; ++i)
740  ser += pow(s,i) / pow(numeric(i), *_num2_p);
741  // substitute the argument's series expansion
742  ser = ser.subs(s==x.series(rel, order), subs_options::no_pattern);
743  // maybe that was terminating, so add a proper order term
744  epvector nseq { expair(Order(_ex1), order) };
745  ser += pseries(rel, std::move(nseq));
746  // reexpanding it will collapse the series again
747  return ser.series(rel, order);
748  // NB: Of course, this still does not allow us to compute anything
749  // like sin(Li2(x)).series(x==0,2), since then this code here is
750  // not reached and the derivative of sin(Li2(x)) doesn't allow the
751  // substitution x==0. Probably limits *are* needed for the general
752  // cases. In case L'Hospital's rule is implemented for limits and
753  // basic::series() takes care of this, this whole block is probably
754  // obsolete!
755  }
756  // second special case: x==1 (branch point)
757  if (x_pt.is_equal(_ex1)) {
758  // method:
759  // construct series manually in a dummy symbol s
760  const symbol s;
761  ex ser = zeta(_ex2);
762  // manually construct the primitive expansion
763  for (int i=1; i<order; ++i)
764  ser += pow(1-s,i) * (numeric(1,i)*(I*Pi+log(s-1)) - numeric(1,i*i));
765  // substitute the argument's series expansion
766  ser = ser.subs(s==x.series(rel, order), subs_options::no_pattern);
767  // maybe that was terminating, so add a proper order term
768  epvector nseq { expair(Order(_ex1), order) };
769  ser += pseries(rel, std::move(nseq));
770  // reexpanding it will collapse the series again
771  return ser.series(rel, order);
772  }
773  // third special case: x real, >=1 (branch cut)
775  ex_to<numeric>(x_pt).is_real() && ex_to<numeric>(x_pt)>1) {
776  // method:
777  // This is the branch cut: assemble the primitive series manually
778  // and then add the corresponding complex step function.
779  const symbol &s = ex_to<symbol>(rel.lhs());
780  const ex point = rel.rhs();
781  const symbol foo;
782  epvector seq;
783  // zeroth order term:
784  seq.push_back(expair(Li2(x_pt), _ex0));
785  // compute the intermediate terms:
786  ex replarg = series(Li2(x), s==foo, order);
787  for (size_t i=1; i<replarg.nops()-1; ++i)
788  seq.push_back(expair((replarg.op(i)/power(s-foo,i)).series(foo==point,1,options).op(0).subs(foo==s, subs_options::no_pattern),i));
789  // append an order term:
790  seq.push_back(expair(Order(_ex1), replarg.nops()-1));
791  return pseries(rel, std::move(seq));
792  }
793  }
794  // all other cases should be safe, by now:
795  throw do_taylor(); // caught by function::series()
796 }
797 
798 static ex Li2_conjugate(const ex & x)
799 {
800  // conjugate(Li2(x))==Li2(conjugate(x)) unless on the branch cuts which
801  // run along the positive real axis beginning at 1.
802  if (x.info(info_flags::negative)) {
803  return Li2(x).hold();
804  }
805  if (is_exactly_a<numeric>(x) &&
806  (!x.imag_part().is_zero() || x < *_num1_p)) {
807  return Li2(x.conjugate());
808  }
809  return conjugate_function(Li2(x)).hold();
810 }
811 
813  evalf_func(Li2_evalf).
814  derivative_func(Li2_deriv).
815  series_func(Li2_series).
816  conjugate_func(Li2_conjugate).
817  latex_name("\\mathrm{Li}_2"));
818 
820 // trilogarithm
822 
823 static ex Li3_eval(const ex & x)
824 {
825  if (x.is_zero())
826  return x;
827  return Li3(x).hold();
828 }
829 
830 REGISTER_FUNCTION(Li3, eval_func(Li3_eval).
831  latex_name("\\mathrm{Li}_3"));
832 
834 // Derivatives of Riemann's Zeta-function zetaderiv(0,x)==zeta(x)
836 
837 static ex zetaderiv_eval(const ex & n, const ex & x)
838 {
839  if (n.info(info_flags::numeric)) {
840  // zetaderiv(0,x) -> zeta(x)
841  if (n.is_zero())
842  return zeta(x).hold();
843  }
844 
845  return zetaderiv(n, x).hold();
846 }
847 
848 static ex zetaderiv_deriv(const ex & n, const ex & x, unsigned deriv_param)
849 {
850  GINAC_ASSERT(deriv_param<2);
851 
852  if (deriv_param==0) {
853  // d/dn zeta(n,x)
854  throw(std::logic_error("cannot diff zetaderiv(n,x) with respect to n"));
855  }
856  // d/dx psi(n,x)
857  return zetaderiv(n+1,x);
858 }
859 
860 REGISTER_FUNCTION(zetaderiv, eval_func(zetaderiv_eval).
861  derivative_func(zetaderiv_deriv).
862  latex_name("\\zeta^\\prime"));
863 
865 // factorial
867 
868 static ex factorial_evalf(const ex & x)
869 {
870  return factorial(x).hold();
871 }
872 
873 static ex factorial_eval(const ex & x)
874 {
875  if (is_exactly_a<numeric>(x))
876  return factorial(ex_to<numeric>(x));
877  else
878  return factorial(x).hold();
879 }
880 
881 static void factorial_print_dflt_latex(const ex & x, const print_context & c)
882 {
883  if (is_exactly_a<symbol>(x) ||
884  is_exactly_a<constant>(x) ||
885  is_exactly_a<function>(x)) {
886  x.print(c); c.s << "!";
887  } else {
888  c.s << "("; x.print(c); c.s << ")!";
889  }
890 }
891 
892 static ex factorial_conjugate(const ex & x)
893 {
894  return factorial(x).hold();
895 }
896 
897 static ex factorial_real_part(const ex & x)
898 {
899  return factorial(x).hold();
900 }
901 
902 static ex factorial_imag_part(const ex & x)
903 {
904  return 0;
905 }
906 
908  evalf_func(factorial_evalf).
910  print_func<print_latex>(factorial_print_dflt_latex).
911  conjugate_func(factorial_conjugate).
912  real_part_func(factorial_real_part).
913  imag_part_func(factorial_imag_part));
914 
916 // binomial
918 
919 static ex binomial_evalf(const ex & x, const ex & y)
920 {
921  return binomial(x, y).hold();
922 }
923 
924 static ex binomial_sym(const ex & x, const numeric & y)
925 {
926  if (y.is_integer()) {
927  if (y.is_nonneg_integer()) {
928  const unsigned N = y.to_int();
929  if (N == 0) return _ex1;
930  if (N == 1) return x;
931  ex t = x.expand();
932  for (unsigned i = 2; i <= N; ++i)
933  t = (t * (x + i - y - 1)).expand() / i;
934  return t;
935  } else
936  return _ex0;
937  }
938 
939  return binomial(x, y).hold();
940 }
941 
942 static ex binomial_eval(const ex & x, const ex &y)
943 {
944  if (is_exactly_a<numeric>(y)) {
945  if (is_exactly_a<numeric>(x) && ex_to<numeric>(x).is_integer())
946  return binomial(ex_to<numeric>(x), ex_to<numeric>(y));
947  else
948  return binomial_sym(x, ex_to<numeric>(y));
949  } else
950  return binomial(x, y).hold();
951 }
952 
953 // At the moment the numeric evaluation of a binomial function always
954 // gives a real number, but if this would be implemented using the gamma
955 // function, also complex conjugation should be changed (or rather, deleted).
956 static ex binomial_conjugate(const ex & x, const ex & y)
957 {
958  return binomial(x,y).hold();
959 }
960 
961 static ex binomial_real_part(const ex & x, const ex & y)
962 {
963  return binomial(x,y).hold();
964 }
965 
966 static ex binomial_imag_part(const ex & x, const ex & y)
967 {
968  return 0;
969 }
970 
972  evalf_func(binomial_evalf).
973  conjugate_func(binomial_conjugate).
974  real_part_func(binomial_real_part).
975  imag_part_func(binomial_imag_part));
976 
978 // Order term function (for truncated power series)
980 
981 static ex Order_eval(const ex & x)
982 {
983  if (is_exactly_a<numeric>(x)) {
984  // O(c) -> O(1) or 0
985  if (!x.is_zero())
986  return Order(_ex1).hold();
987  else
988  return _ex0;
989  } else if (is_exactly_a<mul>(x)) {
990  const mul &m = ex_to<mul>(x);
991  // O(c*expr) -> O(expr)
992  if (is_exactly_a<numeric>(m.op(m.nops() - 1)))
993  return Order(x / m.op(m.nops() - 1)).hold();
994  }
995  return Order(x).hold();
996 }
997 
998 static ex Order_series(const ex & x, const relational & r, int order, unsigned options)
999 {
1000  // Just wrap the function into a pseries object
1001  GINAC_ASSERT(is_a<symbol>(r.lhs()));
1002  const symbol &s = ex_to<symbol>(r.lhs());
1003  epvector new_seq { expair(Order(_ex1), numeric(std::min(x.ldegree(s), order))) };
1004  return pseries(r, std::move(new_seq));
1005 }
1006 
1007 static ex Order_conjugate(const ex & x)
1008 {
1009  return Order(x).hold();
1010 }
1011 
1012 static ex Order_real_part(const ex & x)
1013 {
1014  return Order(x).hold();
1015 }
1016 
1017 static ex Order_imag_part(const ex & x)
1018 {
1019  if(x.info(info_flags::real))
1020  return 0;
1021  return Order(x).hold();
1022 }
1023 
1024 static ex Order_expl_derivative(const ex & arg, const symbol & s)
1025 {
1026  return Order(arg.diff(s));
1027 }
1028 
1029 REGISTER_FUNCTION(Order, eval_func(Order_eval).
1030  series_func(Order_series).
1031  latex_name("\\mathcal{O}").
1032  expl_derivative_func(Order_expl_derivative).
1033  conjugate_func(Order_conjugate).
1034  real_part_func(Order_real_part).
1035  imag_part_func(Order_imag_part));
1036 
1038 // Solve linear system
1040 
1041 class symbolset {
1043  void insert_symbols(const ex &e)
1044  {
1045  if (is_a<symbol>(e)) {
1046  s.insert(e);
1047  } else {
1048  for (const ex &sube : e) {
1049  insert_symbols(sube);
1050  }
1051  }
1052  }
1053 public:
1054  explicit symbolset(const ex &e)
1055  {
1056  insert_symbols(e);
1057  }
1058  bool has(const ex &e) const
1059  {
1060  return s.find(e) != s.end();
1061  }
1062 };
1063 
1064 ex lsolve(const ex &eqns, const ex &symbols, unsigned options)
1065 {
1066  // solve a system of linear equations
1067  if (eqns.info(info_flags::relation_equal)) {
1068  if (!symbols.info(info_flags::symbol))
1069  throw(std::invalid_argument("lsolve(): 2nd argument must be a symbol"));
1070  const ex sol = lsolve(lst{eqns}, lst{symbols});
1071 
1072  GINAC_ASSERT(sol.nops()==1);
1073  GINAC_ASSERT(is_exactly_a<relational>(sol.op(0)));
1074 
1075  return sol.op(0).op(1); // return rhs of first solution
1076  }
1077 
1078  // syntax checks
1079  if (!(eqns.info(info_flags::list) || eqns.info(info_flags::exprseq))) {
1080  throw(std::invalid_argument("lsolve(): 1st argument must be a list, a sequence, or an equation"));
1081  }
1082  for (size_t i=0; i<eqns.nops(); i++) {
1083  if (!eqns.op(i).info(info_flags::relation_equal)) {
1084  throw(std::invalid_argument("lsolve(): 1st argument must be a list of equations"));
1085  }
1086  }
1087  if (!(symbols.info(info_flags::list) || symbols.info(info_flags::exprseq))) {
1088  throw(std::invalid_argument("lsolve(): 2nd argument must be a list, a sequence, or a symbol"));
1089  }
1090  for (size_t i=0; i<symbols.nops(); i++) {
1091  if (!symbols.op(i).info(info_flags::symbol)) {
1092  throw(std::invalid_argument("lsolve(): 2nd argument must be a list or a sequence of symbols"));
1093  }
1094  }
1095 
1096  // build matrix from equation system
1097  matrix sys(eqns.nops(),symbols.nops());
1098  matrix rhs(eqns.nops(),1);
1099  matrix vars(symbols.nops(),1);
1100 
1101  for (size_t r=0; r<eqns.nops(); r++) {
1102  const ex eq = eqns.op(r).op(0)-eqns.op(r).op(1); // lhs-rhs==0
1103  const symbolset syms(eq);
1104  ex linpart = eq;
1105  for (size_t c=0; c<symbols.nops(); c++) {
1106  if (!syms.has(symbols.op(c)))
1107  continue;
1108  const ex co = eq.coeff(ex_to<symbol>(symbols.op(c)),1);
1109  linpart -= co*symbols.op(c);
1110  sys(r,c) = co;
1111  }
1112  linpart = linpart.expand();
1113  rhs(r,0) = -linpart;
1114  }
1115 
1116  // test if system is linear and fill vars matrix
1117  const symbolset sys_syms(sys);
1118  const symbolset rhs_syms(rhs);
1119  for (size_t i=0; i<symbols.nops(); i++) {
1120  vars(i,0) = symbols.op(i);
1121  if (sys_syms.has(symbols.op(i)))
1122  throw(std::logic_error("lsolve: system is not linear"));
1123  if (rhs_syms.has(symbols.op(i)))
1124  throw(std::logic_error("lsolve: system is not linear"));
1125  }
1126 
1127  matrix solution;
1128  try {
1129  solution = sys.solve(vars,rhs,options);
1130  } catch (const std::runtime_error & e) {
1131  // Probably singular matrix or otherwise overdetermined system:
1132  // It is consistent to return an empty list
1133  return lst{};
1134  }
1135  GINAC_ASSERT(solution.cols()==1);
1136  GINAC_ASSERT(solution.rows()==symbols.nops());
1137 
1138  // return list of equations of the form lst{var1==sol1,var2==sol2,...}
1139  lst sollist;
1140  for (size_t i=0; i<symbols.nops(); i++)
1141  sollist.append(symbols.op(i)==solution(i,0));
1142 
1143  return sollist;
1144 }
1145 
1147 // Find real root of f(x) numerically
1149 
1150 const numeric
1151 fsolve(const ex& f_in, const symbol& x, const numeric& x1, const numeric& x2)
1152 {
1153  if (!x1.is_real() || !x2.is_real()) {
1154  throw std::runtime_error("fsolve(): interval not bounded by real numbers");
1155  }
1156  if (x1==x2) {
1157  throw std::runtime_error("fsolve(): vanishing interval");
1158  }
1159  // xx[0] == left interval limit, xx[1] == right interval limit.
1160  // fx[0] == f(xx[0]), fx[1] == f(xx[1]).
1161  // We keep the root bracketed: xx[0]<xx[1] and fx[0]*fx[1]<0.
1162  numeric xx[2] = { x1<x2 ? x1 : x2,
1163  x1<x2 ? x2 : x1 };
1164  ex f;
1165  if (is_a<relational>(f_in)) {
1166  f = f_in.lhs()-f_in.rhs();
1167  } else {
1168  f = f_in;
1169  }
1170  const ex fx_[2] = { f.subs(x==xx[0]).evalf(),
1171  f.subs(x==xx[1]).evalf() };
1172  if (!is_a<numeric>(fx_[0]) || !is_a<numeric>(fx_[1])) {
1173  throw std::runtime_error("fsolve(): function does not evaluate numerically");
1174  }
1175  numeric fx[2] = { ex_to<numeric>(fx_[0]),
1176  ex_to<numeric>(fx_[1]) };
1177  if (!fx[0].is_real() || !fx[1].is_real()) {
1178  throw std::runtime_error("fsolve(): function evaluates to complex values at interval boundaries");
1179  }
1180  if (fx[0]*fx[1]>=0) {
1181  throw std::runtime_error("fsolve(): function does not change sign at interval boundaries");
1182  }
1183 
1184  // The Newton-Raphson method has quadratic convergence! Simply put, it
1185  // replaces x with x-f(x)/f'(x) at each step. -f/f' is the delta:
1186  const ex ff = normal(-f/f.diff(x));
1187  int side = 0; // Start at left interval limit.
1188  numeric xxprev;
1189  numeric fxprev;
1190  do {
1191  xxprev = xx[side];
1192  fxprev = fx[side];
1193  ex dx_ = ff.subs(x == xx[side]).evalf();
1194  if (!is_a<numeric>(dx_))
1195  throw std::runtime_error("fsolve(): function derivative does not evaluate numerically");
1196  xx[side] += ex_to<numeric>(dx_);
1197  // Now check if Newton-Raphson method shot out of the interval
1198  bool bad_shot = (side == 0 && xx[0] < xxprev) ||
1199  (side == 1 && xx[1] > xxprev) || xx[0] > xx[1];
1200  if (!bad_shot) {
1201  // Compute f(x) only if new x is inside the interval.
1202  // The function might be difficult to compute numerically
1203  // or even ill defined outside the interval. Also it's
1204  // a small optimization.
1205  ex f_x = f.subs(x == xx[side]).evalf();
1206  if (!is_a<numeric>(f_x))
1207  throw std::runtime_error("fsolve(): function does not evaluate numerically");
1208  fx[side] = ex_to<numeric>(f_x);
1209  }
1210  if (bad_shot) {
1211  // Oops, Newton-Raphson method shot out of the interval.
1212  // Restore, and try again with the other side instead!
1213  xx[side] = xxprev;
1214  fx[side] = fxprev;
1215  side = !side;
1216  xxprev = xx[side];
1217  fxprev = fx[side];
1218 
1219  ex dx_ = ff.subs(x == xx[side]).evalf();
1220  if (!is_a<numeric>(dx_))
1221  throw std::runtime_error("fsolve(): function derivative does not evaluate numerically [2]");
1222  xx[side] += ex_to<numeric>(dx_);
1223 
1224  ex f_x = f.subs(x==xx[side]).evalf();
1225  if (!is_a<numeric>(f_x))
1226  throw std::runtime_error("fsolve(): function does not evaluate numerically [2]");
1227  fx[side] = ex_to<numeric>(f_x);
1228  }
1229  if ((fx[side]<0 && fx[!side]<0) || (fx[side]>0 && fx[!side]>0)) {
1230  // Oops, the root isn't bracketed any more.
1231  // Restore, and perform a bisection!
1232  xx[side] = xxprev;
1233  fx[side] = fxprev;
1234 
1235  // Ah, the bisection! Bisections converge linearly. Unfortunately,
1236  // they occur pretty often when Newton-Raphson arrives at an x too
1237  // close to the result on one side of the interval and
1238  // f(x-f(x)/f'(x)) turns out to have the same sign as f(x) due to
1239  // precision errors! Recall that this function does not have a
1240  // precision goal as one of its arguments but instead relies on
1241  // x converging to a fixed point. We speed up the (safe but slow)
1242  // bisection method by mixing in a dash of the (unsafer but faster)
1243  // secant method: Instead of splitting the interval at the
1244  // arithmetic mean (bisection), we split it nearer to the root as
1245  // determined by the secant between the values xx[0] and xx[1].
1246  // Don't set the secant_weight to one because that could disturb
1247  // the convergence in some corner cases!
1248  constexpr double secant_weight = 0.984375; // == 63/64 < 1
1249  numeric xxmid = (1-secant_weight)*0.5*(xx[0]+xx[1])
1250  + secant_weight*(xx[0]+fx[0]*(xx[0]-xx[1])/(fx[1]-fx[0]));
1251  ex fxmid_ = f.subs(x == xxmid).evalf();
1252  if (!is_a<numeric>(fxmid_))
1253  throw std::runtime_error("fsolve(): function does not evaluate numerically [3]");
1254  numeric fxmid = ex_to<numeric>(fxmid_);
1255  if (fxmid.is_zero()) {
1256  // Luck strikes...
1257  return xxmid;
1258  }
1259  if ((fxmid<0 && fx[side]>0) || (fxmid>0 && fx[side]<0)) {
1260  side = !side;
1261  }
1262  xxprev = xx[side];
1263  fxprev = fx[side];
1264  xx[side] = xxmid;
1265  fx[side] = fxmid;
1266  }
1267  } while (xxprev!=xx[side]);
1268  return xxprev;
1269 }
1270 
1271 
1272 /* Force inclusion of functions from inifcns_gamma and inifcns_zeta
1273  * for static lib (so ginsh will see them). */
1274 unsigned force_include_tgamma = tgamma_SERIAL::serial;
1276 
1277 } // 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
Wrapper template for making GiNaC classes out of STL containers.
Definition: container.h:73
container & append(const ex &b)
Add element at back.
Definition: container.h:391
Exception class thrown by classes which provide their own series expansion to signal that ordinary Ta...
Definition: function.h:668
Lightweight wrapper for GiNaC's symbolic objects.
Definition: ex.h:72
const_iterator begin() const noexcept
Definition: ex.h:647
ex diff(const symbol &s, unsigned nth=1) const
Compute partial derivative of an expression.
Definition: ex.cpp:86
ex expand(unsigned options=0) const
Definition: ex.cpp:73
bool is_equal(const ex &other) const
Definition: ex.h:345
ex evalf() const
Definition: ex.h:121
ex conjugate() const
Definition: ex.h:146
const_iterator end() const noexcept
Definition: ex.h:652
size_t nops() const
Definition: ex.h:135
ex series(const ex &r, int order, unsigned options=0) const
Compute the truncated series expansion of an expression.
Definition: pseries.cpp:1259
ex imag_part() const
Definition: ex.h:148
ex subs(const exmap &m, unsigned options=0) const
Definition: ex.h:826
bool info(unsigned inf) const
Definition: ex.h:132
ex lhs() const
Left hand side of relational expression.
Definition: ex.cpp:225
bool is_zero() const
Definition: ex.h:213
void print(const print_context &c, unsigned level=0) const
Print expression to stream.
Definition: ex.cpp:56
ex op(size_t i) const
Definition: ex.h:136
int ldegree(const ex &s) const
Definition: ex.h:174
ex rhs() const
Right hand side of relational expression.
Definition: ex.cpp:233
ex real_part() const
Definition: ex.h:147
ex coeff(const ex &s, int n=1) const
Definition: ex.h:175
A pair of expressions.
Definition: expair.h:38
@ expand_transcendental
expands transcendental functions like log and exp
Definition: flags.h:35
@ expand_function_args
expands the arguments of functions
Definition: flags.h:33
This class represents the (abstract) derivative of a symbolic function.
Definition: fderivative.h:38
@ integer_polynomial
Definition: flags.h:256
@ cinteger_polynomial
Definition: flags.h:257
@ crational_polynomial
Definition: flags.h:259
@ rational_polynomial
Definition: flags.h:258
Symbolic matrices.
Definition: matrix.h:38
unsigned cols() const
Get number of columns.
Definition: matrix.h:77
matrix solve(const matrix &vars, const matrix &rhs, unsigned algo=solve_algo::automatic) const
Solve a linear system consisting of a m x n matrix and a m x p right hand side by applying an elimina...
Definition: matrix.cpp:995
unsigned rows() const
Get number of rows.
Definition: matrix.h:75
Product of expressions.
Definition: mul.h:32
This class is a wrapper around CLN-numbers within the GiNaC class hierarchy.
Definition: numeric.h:82
bool info(unsigned inf) const override
Information about the object.
Definition: numeric.cpp:684
const numeric real() const
Real part of a number.
Definition: numeric.cpp:1339
bool is_nonneg_integer() const
True if object is an exact integer greater or equal zero.
Definition: numeric.cpp:1168
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
const numeric imag() const
Imaginary part of a number.
Definition: numeric.cpp:1346
int to_int() const
Converts numeric types to machine's int.
Definition: numeric.cpp:1303
bool is_zero() const
True if object is zero.
Definition: numeric.cpp:1129
This class holds a two-component object, a basis and and exponent representing exponentiation.
Definition: power.h:39
Base class for print_contexts.
Definition: print.h:103
This class holds a extended truncated power series (positive and negative integer powers).
Definition: pseries.h:36
This class holds a relation consisting of two expressions and a logical relation between them.
Definition: relational.h:35
ex rhs() const
Definition: relational.h:82
ex lhs() const
Definition: relational.h:81
@ suppress_branchcut
Suppress branch cuts in series expansion.
Definition: flags.h:83
@ expanded
.expand(0) has already done its job (other expand() options ignore this flag)
Definition: flags.h:204
@ no_pattern
disable pattern matching
Definition: flags.h:51
Basic CAS symbol.
Definition: symbol.h:39
bool info(unsigned inf) const override
Information about the object.
Definition: symbol.cpp:206
symbolset(const ex &e)
Definition: inifcns.cpp:1054
bool has(const ex &e) const
Definition: inifcns.cpp:1058
void insert_symbols(const ex &e)
Definition: inifcns.cpp:1043
static unsigned serial
Definition: inifcns.h:109
Interface to GiNaC's constant types and some special constants.
Interface to GiNaC's light-weight expression handles.
unsigned options
Definition: factor.cpp:2480
ex x
Definition: factor.cpp:1641
size_t n
Definition: factor.cpp:1463
size_t c
Definition: factor.cpp:770
size_t r
Definition: factor.cpp:770
exset syms
Definition: factor.cpp:2434
mvec m
Definition: factor.cpp:771
Interface to abstract derivatives of functions.
#define is_ex_the_function(OBJ, FUNCNAME)
Definition: function.h:765
Interface to GiNaC's initially known functions.
int order
Definition of GiNaC's lst.
Interface to symbolic matrices.
Interface to GiNaC's products of expressions.
Definition: add.cpp:38
static ex csgn_imag_part(const ex &arg)
Definition: inifcns.cpp:547
unsigned force_include_tgamma
Definition: inifcns.cpp:1274
const numeric I
Imaginary unit.
Definition: numeric.cpp:1433
static ex step_imag_part(const ex &arg)
Definition: inifcns.cpp:469
static ex imag_part_evalf(const ex &arg)
Definition: inifcns.cpp:201
ex real_part(const ex &thisex)
Definition: ex.h:721
static ex Order_eval(const ex &x)
Definition: inifcns.cpp:981
const ex _ex2
Definition: utils.cpp:389
const numeric pow(const numeric &x, const numeric &y)
Definition: numeric.h:251
ex lsolve(const ex &eqns, const ex &symbols, unsigned options)
Factorial function.
Definition: inifcns.cpp:1064
static ex conjugate_real_part(const ex &arg)
Definition: inifcns.cpp:83
const ex _ex_1_2
Definition: utils.cpp:356
static ex eta_imag_part(const ex &x, const ex &y)
Definition: inifcns.cpp:654
const ex _ex1_2
Definition: utils.cpp:381
static ex eta_real_part(const ex &x, const ex &y)
Definition: inifcns.cpp:649
symmetry sy_symm()
Definition: symmetry.h:121
static void imag_part_print_latex(const ex &arg, const print_context &c)
Definition: inifcns.cpp:214
static ex abs_eval(const ex &arg)
Definition: inifcns.cpp:267
std::set< ex, ex_is_less > exset
Definition: basic.h:49
std::vector< expair > epvector
expair-vector
Definition: expairseq.h:33
static ex conjugate_eval(const ex &arg)
Definition: inifcns.cpp:55
static bool func_arg_info(const ex &arg, unsigned inf)
Definition: inifcns.cpp:93
static ex step_conjugate(const ex &arg)
Definition: inifcns.cpp:459
const numeric abs(const numeric &x)
Absolute value.
Definition: numeric.cpp:2315
function zeta(const T1 &p1)
Definition: inifcns.h:111
static ex abs_power(const ex &arg, const ex &exp)
Definition: inifcns.cpp:352
const ex _ex12
Definition: utils.cpp:429
const ex _ex1
Definition: utils.cpp:385
static ex eta_eval(const ex &x, const ex &y)
Definition: inifcns.cpp:604
static ex abs_expand(const ex &arg, unsigned options)
Definition: inifcns.cpp:300
static ex imag_part_eval(const ex &arg)
Definition: inifcns.cpp:209
const numeric Li2(const numeric &x)
Definition: numeric.cpp:1705
int csgn(const numeric &x)
Definition: numeric.h:260
static void abs_print_csrc_float(const ex &arg, const print_context &c)
Definition: inifcns.cpp:332
static ex binomial_sym(const ex &x, const numeric &y)
Definition: inifcns.cpp:924
static void conjugate_print_latex(const ex &arg, const print_context &c)
Definition: inifcns.cpp:60
static ex imag_part_real_part(const ex &arg)
Definition: inifcns.cpp:224
ex rhs(const ex &thisex)
Definition: ex.h:817
static ex Order_real_part(const ex &x)
Definition: inifcns.cpp:1012
static ex factorial_evalf(const ex &x)
Definition: inifcns.cpp:868
static ex Li2_conjugate(const ex &x)
Definition: inifcns.cpp:798
ex series(const ex &thisex, const ex &r, int order, unsigned options=0)
Definition: ex.h:781
ex conjugate(const ex &thisex)
Definition: ex.h:718
static ex abs_real_part(const ex &arg)
Definition: inifcns.cpp:342
const ex _ex6
Definition: utils.cpp:405
const numeric imag(const numeric &x)
Definition: numeric.h:314
const numeric binomial(const numeric &n, const numeric &k)
The Binomial coefficients.
Definition: numeric.cpp:2143
bool abs_info(const ex &arg, unsigned inf)
Definition: inifcns.cpp:363
print_func< print_dflt >(&diracone::do_print). print_func< print_latex >(&diracone
Definition: clifford.cpp:51
const numeric * _num2_p
Definition: utils.cpp:388
const numeric exp(const numeric &x)
Exponential function.
Definition: numeric.cpp:1439
static ex csgn_power(const ex &arg, const ex &exp)
Definition: inifcns.cpp:552
static ex eta_conjugate(const ex &x, const ex &y)
Definition: inifcns.cpp:644
static ex Li3_eval(const ex &x)
Definition: inifcns.cpp:823
static ex conjugate_expl_derivative(const ex &arg, const symbol &s)
Definition: inifcns.cpp:72
static bool conjugate_info(const ex &arg, unsigned inf)
Definition: inifcns.cpp:124
const numeric factorial(const numeric &n)
Factorial combinatorial function.
Definition: numeric.cpp:2113
ex subs(const ex &thisex, const exmap &m, unsigned options=0)
Definition: ex.h:831
const ex _ex_1
Definition: utils.cpp:352
bool is_even(const numeric &x)
Definition: numeric.h:281
const numeric fsolve(const ex &f_in, const symbol &x, const numeric &x1, const numeric &x2)
Find a real root of real-valued function f(x) numerically within a given interval.
Definition: inifcns.cpp:1151
static ex conjugate_conjugate(const ex &arg)
Definition: inifcns.cpp:65
const constant Pi("Pi", PiEvalf, "\\pi", domain::positive)
Pi.
Definition: constant.h:82
static ex imag_part_expl_derivative(const ex &arg, const symbol &s)
Definition: inifcns.cpp:235
static ex real_part_expl_derivative(const ex &arg, const symbol &s)
Definition: inifcns.cpp:177
static ex csgn_evalf(const ex &arg)
Definition: inifcns.cpp:485
static ex csgn_eval(const ex &arg)
Definition: inifcns.cpp:493
static ex step_real_part(const ex &arg)
Definition: inifcns.cpp:464
static ex factorial_imag_part(const ex &x)
Definition: inifcns.cpp:902
static ex factorial_real_part(const ex &x)
Definition: inifcns.cpp:897
static ex abs_imag_part(const ex &arg)
Definition: inifcns.cpp:347
static ex step_eval(const ex &arg)
Definition: inifcns.cpp:415
static ex zetaderiv_eval(const ex &n, const ex &x)
Definition: inifcns.cpp:837
const numeric log(const numeric &x)
Natural logarithm.
Definition: numeric.cpp:1450
ex evalf(const ex &thisex)
Definition: ex.h:769
static ex binomial_real_part(const ex &x, const ex &y)
Definition: inifcns.cpp:961
bool is_real(const numeric &x)
Definition: numeric.h:293
static ex Order_series(const ex &x, const relational &r, int order, unsigned options)
Definition: inifcns.cpp:998
static ex Li2_eval(const ex &x)
Definition: inifcns.cpp:681
ex normal(const ex &thisex)
Definition: ex.h:754
static ex zetaderiv_deriv(const ex &n, const ex &x, unsigned deriv_param)
Definition: inifcns.cpp:848
ex op(const ex &thisex, size_t i)
Definition: ex.h:811
static void abs_print_latex(const ex &arg, const print_context &c)
Definition: inifcns.cpp:327
static ex imag_part_conjugate(const ex &arg)
Definition: inifcns.cpp:219
const numeric * _num1_p
Definition: utils.cpp:384
static ex real_part_imag_part(const ex &arg)
Definition: inifcns.cpp:171
const constant Catalan("Catalan", CatalanEvalf, "G", domain::positive)
Catalan's constant.
Definition: constant.h:83
static ex Order_conjugate(const ex &x)
Definition: inifcns.cpp:1007
static ex imag_part_imag_part(const ex &arg)
Definition: inifcns.cpp:229
static ex csgn_conjugate(const ex &arg)
Definition: inifcns.cpp:537
static ex real_part_eval(const ex &arg)
Definition: inifcns.cpp:151
static ex real_part_evalf(const ex &arg)
Definition: inifcns.cpp:143
static ex real_part_real_part(const ex &arg)
Definition: inifcns.cpp:166
static ex csgn_real_part(const ex &arg)
Definition: inifcns.cpp:542
static ex binomial_imag_part(const ex &x, const ex &y)
Definition: inifcns.cpp:966
static ex abs_conjugate(const ex &arg)
Definition: inifcns.cpp:337
static ex Li2_evalf(const ex &x)
Definition: inifcns.cpp:673
static ex step_evalf(const ex &arg)
Definition: inifcns.cpp:407
static ex eta_series(const ex &x, const ex &y, const relational &rel, int order, unsigned options)
Definition: inifcns.cpp:629
bool is_integer(const numeric &x)
Definition: numeric.h:272
static ex step_series(const ex &arg, const relational &rel, int order, unsigned options)
Definition: inifcns.cpp:444
bool is_odd(const numeric &x)
Definition: numeric.h:284
static ex factorial_conjugate(const ex &x)
Definition: inifcns.cpp:892
static ex abs_expl_derivative(const ex &arg, const symbol &s)
Definition: inifcns.cpp:321
const ex _ex_48
Definition: utils.cpp:280
static ex Order_imag_part(const ex &x)
Definition: inifcns.cpp:1017
static ex binomial_evalf(const ex &x, const ex &y)
Definition: inifcns.cpp:919
unsigned force_include_zeta1
Definition: inifcns.cpp:1275
static ex Li2_deriv(const ex &x, unsigned deriv_param)
Definition: inifcns.cpp:710
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 void factorial_print_dflt_latex(const ex &x, const print_context &c)
Definition: inifcns.cpp:881
static ex binomial_eval(const ex &x, const ex &y)
Definition: inifcns.cpp:942
static void real_part_print_latex(const ex &arg, const print_context &c)
Definition: inifcns.cpp:156
const ex _ex0
Definition: utils.cpp:369
std::vector< ex > exvector
Definition: basic.h:46
static ex binomial_conjugate(const ex &x, const ex &y)
Definition: inifcns.cpp:956
static ex Li2_series(const ex &x, const relational &rel, int order, unsigned options)
Definition: inifcns.cpp:718
static ex csgn_series(const ex &arg, const relational &rel, int order, unsigned options)
Definition: inifcns.cpp:522
static ex factorial_eval(const ex &x)
Definition: inifcns.cpp:873
ex imag_part(const ex &thisex)
Definition: ex.h:724
static ex Order_expl_derivative(const ex &arg, const symbol &s)
Definition: inifcns.cpp:1024
static ex real_part_conjugate(const ex &arg)
Definition: inifcns.cpp:161
static ex conjugate_imag_part(const ex &arg)
Definition: inifcns.cpp:88
static ex eta_evalf(const ex &x, const ex &y)
Definition: inifcns.cpp:579
numeric step(const numeric &x)
Definition: numeric.h:257
static ex conjugate_evalf(const ex &arg)
Definition: inifcns.cpp:47
static ex abs_evalf(const ex &arg)
Definition: inifcns.cpp:259
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.