GiNaC 1.8.6
inifcns.cpp
Go to the documentation of this file.
1
5/*
6 * GiNaC Copyright (C) 1999-2023 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
41namespace GiNaC {
42
44// complex conjugate
46
47static 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
55static ex conjugate_eval(const ex & arg)
56{
57 return arg.conjugate();
58}
59
60static void conjugate_print_latex(const ex & arg, const print_context & c)
61{
62 c.s << "\\bar{"; arg.print(c); c.s << "}";
63}
64
65static 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))
72static ex conjugate_expl_derivative(const ex & arg, const symbol & s)
73{
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
83static ex conjugate_real_part(const ex & arg)
84{
85 return arg.real_part();
86}
87
88static ex conjugate_imag_part(const ex & arg)
89{
90 return -arg.imag_part();
91}
92
93static 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:
107 case info_flags::even:
108 case info_flags::odd:
119 return arg.info(inf);
120 }
121 return false;
122}
123
124static bool conjugate_info(const ex & arg, unsigned inf)
125{
126 return func_arg_info(arg, inf);
127}
128
129REGISTER_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
143static 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
151static ex real_part_eval(const ex & arg)
152{
153 return arg.real_part();
154}
155
156static void real_part_print_latex(const ex & arg, const print_context & c)
157{
158 c.s << "\\Re"; arg.print(c); c.s << "";
159}
160
161static ex real_part_conjugate(const ex & arg)
162{
163 return real_part_function(arg).hold();
164}
165
166static ex real_part_real_part(const ex & arg)
167{
168 return real_part_function(arg).hold();
169}
170
171static 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))
177static 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
188REGISTER_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
201static 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
209static ex imag_part_eval(const ex & arg)
210{
211 return arg.imag_part();
212}
213
214static void imag_part_print_latex(const ex & arg, const print_context & c)
215{
216 c.s << "\\Im"; arg.print(c); c.s << "";
217}
218
219static ex imag_part_conjugate(const ex & arg)
220{
221 return imag_part_function(arg).hold();
222}
223
224static ex imag_part_real_part(const ex & arg)
225{
226 return imag_part_function(arg).hold();
227}
228
229static 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))
235static 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
246REGISTER_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
259static 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
267static ex abs_eval(const ex & arg)
268{
269 if (is_exactly_a<numeric>(arg))
270 return abs(ex_to<numeric>(arg));
271
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
300static 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
321static 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
327static void abs_print_latex(const ex & arg, const print_context & c)
328{
329 c.s << "{|"; arg.print(c); c.s << "|}";
330}
331
332static void abs_print_csrc_float(const ex & arg, const print_context & c)
333{
334 c.s << "fabs("; arg.print(c); c.s << ")";
335}
336
337static ex abs_conjugate(const ex & arg)
338{
339 return abs(arg).hold();
340}
341
342static ex abs_real_part(const ex & arg)
343{
344 return abs(arg).hold();
345}
346
347static ex abs_imag_part(const ex& arg)
348{
349 return 0;
350}
351
352static 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
363bool abs_info(const ex & arg, unsigned inf)
364{
365 switch (inf) {
367 case info_flags::even:
368 case info_flags::odd:
370 return arg.info(inf);
372 return arg.info(info_flags::integer);
374 case info_flags::real:
375 return true;
377 return false;
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
407static 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
415static 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
444static 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
459static ex step_conjugate(const ex& arg)
460{
461 return step(arg).hold();
462}
463
464static ex step_real_part(const ex& arg)
465{
466 return step(arg).hold();
467}
468
469static 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
485static 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
493static 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
522static 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
537static ex csgn_conjugate(const ex& arg)
538{
539 return csgn(arg).hold();
540}
541
542static ex csgn_real_part(const ex& arg)
543{
544 return csgn(arg).hold();
545}
546
547static ex csgn_imag_part(const ex& arg)
548{
549 return 0;
550}
551
552static 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
579static 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
604static 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
629static 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
644static ex eta_conjugate(const ex & x, const ex & y)
645{
646 return -eta(x, y).hold();
647}
648
649static ex eta_real_part(const ex & x, const ex & y)
650{
651 return 0;
652}
653
654static ex eta_imag_part(const ex & x, const ex & y)
655{
656 return -I*eta(x, y).hold();
657}
658
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
673static 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
681static ex Li2_eval(const ex & x)
682{
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
710static 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
718static 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
798static 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.
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
823static ex Li3_eval(const ex & x)
824{
825 if (x.is_zero())
826 return x;
827 return Li3(x).hold();
828}
829
831 latex_name("\\mathrm{Li}_3"));
832
834// Derivatives of Riemann's Zeta-function zetaderiv(0,x)==zeta(x)
836
837static 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
848static 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
860REGISTER_FUNCTION(zetaderiv, eval_func(zetaderiv_eval).
861 derivative_func(zetaderiv_deriv).
862 latex_name("\\zeta^\\prime"));
863
865// factorial
867
868static ex factorial_evalf(const ex & x)
869{
870 return factorial(x).hold();
871}
872
873static 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
881static 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
892static ex factorial_conjugate(const ex & x)
893{
894 return factorial(x).hold();
895}
896
897static ex factorial_real_part(const ex & x)
898{
899 return factorial(x).hold();
900}
901
902static 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
919static ex binomial_evalf(const ex & x, const ex & y)
920{
921 return binomial(x, y).hold();
922}
923
924static 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
942static 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).
956static ex binomial_conjugate(const ex & x, const ex & y)
957{
958 return binomial(x,y).hold();
959}
960
961static ex binomial_real_part(const ex & x, const ex & y)
962{
963 return binomial(x,y).hold();
964}
965
966static 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
981static 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
998static 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
1007static ex Order_conjugate(const ex & x)
1008{
1009 return Order(x).hold();
1010}
1011
1012static ex Order_real_part(const ex & x)
1013{
1014 return Order(x).hold();
1015}
1016
1017static ex Order_imag_part(const ex & x)
1018{
1020 return 0;
1021 return Order(x).hold();
1022}
1023
1024static ex Order_expl_derivative(const ex & arg, const symbol & s)
1025{
1026 return Order(arg.diff(s));
1027}
1028
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
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 }
1053public:
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
1064ex 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
1150const numeric
1151fsolve(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). */
1274unsigned 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: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
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:1259
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: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:2475
size_t n
Definition: factor.cpp:1432
size_t c
Definition: factor.cpp:757
ex x
Definition: factor.cpp:1610
size_t r
Definition: factor.cpp:757
exset syms
Definition: factor.cpp:2429
mvec m
Definition: factor.cpp:758
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:736
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:2320
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:832
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:796
ex conjugate(const ex &thisex)
Definition: ex.h:733
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:2145
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:846
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:784
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:769
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:826
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:48
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:739
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.