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