GiNaC 1.8.7
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_power(const ex & x, const ex & e)
1025{
1026 // Order(x)^e -> Order(x^e) for positive integer e
1027 if (is_exactly_a<numeric>(e) && e.info(info_flags::posint))
1028 return Order(pow(x, e));
1029 // NB: For negative exponents, the above could be wrong.
1030 // This is because series() produces Order(x^n) to denote the order where
1031 // it gave up. So, Order(x^n) can also be an x^(n+1) term if the x^n term
1032 // vanishes. In this situation, 1/Order(x^n) can also be a x^(-n-1) term.
1033 // Transforming it to Order(x^-n) would miss that.
1034
1035 return power(Order(x), e).hold();
1036}
1037
1038static ex Order_expl_derivative(const ex & arg, const symbol & s)
1039{
1040 return Order(arg.diff(s));
1041}
1042
1044 series_func(Order_series).
1045 latex_name("\\mathcal{O}").
1046 expl_derivative_func(Order_expl_derivative).
1047 conjugate_func(Order_conjugate).
1048 real_part_func(Order_real_part).
1049 imag_part_func(Order_imag_part).
1050 power_func(Order_power));
1051
1053// Solve linear system
1055
1058 void insert_symbols(const ex &e)
1059 {
1060 if (is_a<symbol>(e)) {
1061 s.insert(e);
1062 } else {
1063 for (const ex &sube : e) {
1064 insert_symbols(sube);
1065 }
1066 }
1067 }
1068public:
1069 explicit symbolset(const ex &e)
1070 {
1071 insert_symbols(e);
1072 }
1073 bool has(const ex &e) const
1074 {
1075 return s.find(e) != s.end();
1076 }
1077};
1078
1079ex lsolve(const ex &eqns, const ex &symbols, unsigned options)
1080{
1081 // solve a system of linear equations
1082 if (eqns.info(info_flags::relation_equal)) {
1083 if (!symbols.info(info_flags::symbol))
1084 throw(std::invalid_argument("lsolve(): 2nd argument must be a symbol"));
1085 const ex sol = lsolve(lst{eqns}, lst{symbols});
1086
1087 GINAC_ASSERT(sol.nops()==1);
1088 GINAC_ASSERT(is_exactly_a<relational>(sol.op(0)));
1089
1090 return sol.op(0).op(1); // return rhs of first solution
1091 }
1092
1093 // syntax checks
1094 if (!(eqns.info(info_flags::list) || eqns.info(info_flags::exprseq))) {
1095 throw(std::invalid_argument("lsolve(): 1st argument must be a list, a sequence, or an equation"));
1096 }
1097 for (size_t i=0; i<eqns.nops(); i++) {
1098 if (!eqns.op(i).info(info_flags::relation_equal)) {
1099 throw(std::invalid_argument("lsolve(): 1st argument must be a list of equations"));
1100 }
1101 }
1102 if (!(symbols.info(info_flags::list) || symbols.info(info_flags::exprseq))) {
1103 throw(std::invalid_argument("lsolve(): 2nd argument must be a list, a sequence, or a symbol"));
1104 }
1105 for (size_t i=0; i<symbols.nops(); i++) {
1106 if (!symbols.op(i).info(info_flags::symbol)) {
1107 throw(std::invalid_argument("lsolve(): 2nd argument must be a list or a sequence of symbols"));
1108 }
1109 }
1110
1111 // build matrix from equation system
1112 matrix sys(eqns.nops(),symbols.nops());
1113 matrix rhs(eqns.nops(),1);
1114 matrix vars(symbols.nops(),1);
1115
1116 for (size_t r=0; r<eqns.nops(); r++) {
1117 const ex eq = eqns.op(r).op(0)-eqns.op(r).op(1); // lhs-rhs==0
1118 const symbolset syms(eq);
1119 ex linpart = eq;
1120 for (size_t c=0; c<symbols.nops(); c++) {
1121 if (!syms.has(symbols.op(c)))
1122 continue;
1123 const ex co = eq.coeff(ex_to<symbol>(symbols.op(c)),1);
1124 linpart -= co*symbols.op(c);
1125 sys(r,c) = co;
1126 }
1127 linpart = linpart.expand();
1128 rhs(r,0) = -linpart;
1129 }
1130
1131 // test if system is linear and fill vars matrix
1132 const symbolset sys_syms(sys);
1133 const symbolset rhs_syms(rhs);
1134 for (size_t i=0; i<symbols.nops(); i++) {
1135 vars(i,0) = symbols.op(i);
1136 if (sys_syms.has(symbols.op(i)))
1137 throw(std::logic_error("lsolve: system is not linear"));
1138 if (rhs_syms.has(symbols.op(i)))
1139 throw(std::logic_error("lsolve: system is not linear"));
1140 }
1141
1142 matrix solution;
1143 try {
1144 solution = sys.solve(vars,rhs,options);
1145 } catch (const std::runtime_error & e) {
1146 // Probably singular matrix or otherwise overdetermined system:
1147 // It is consistent to return an empty list
1148 return lst{};
1149 }
1150 GINAC_ASSERT(solution.cols()==1);
1151 GINAC_ASSERT(solution.rows()==symbols.nops());
1152
1153 // return list of equations of the form lst{var1==sol1,var2==sol2,...}
1154 lst sollist;
1155 for (size_t i=0; i<symbols.nops(); i++)
1156 sollist.append(symbols.op(i)==solution(i,0));
1157
1158 return sollist;
1159}
1160
1162// Find real root of f(x) numerically
1164
1165const numeric
1166fsolve(const ex& f_in, const symbol& x, const numeric& x1, const numeric& x2)
1167{
1168 if (!x1.is_real() || !x2.is_real()) {
1169 throw std::runtime_error("fsolve(): interval not bounded by real numbers");
1170 }
1171 if (x1==x2) {
1172 throw std::runtime_error("fsolve(): vanishing interval");
1173 }
1174 // xx[0] == left interval limit, xx[1] == right interval limit.
1175 // fx[0] == f(xx[0]), fx[1] == f(xx[1]).
1176 // We keep the root bracketed: xx[0]<xx[1] and fx[0]*fx[1]<0.
1177 numeric xx[2] = { x1<x2 ? x1 : x2,
1178 x1<x2 ? x2 : x1 };
1179 ex f;
1180 if (is_a<relational>(f_in)) {
1181 f = f_in.lhs()-f_in.rhs();
1182 } else {
1183 f = f_in;
1184 }
1185 const ex fx_[2] = { f.subs(x==xx[0]).evalf(),
1186 f.subs(x==xx[1]).evalf() };
1187 if (!is_a<numeric>(fx_[0]) || !is_a<numeric>(fx_[1])) {
1188 throw std::runtime_error("fsolve(): function does not evaluate numerically");
1189 }
1190 numeric fx[2] = { ex_to<numeric>(fx_[0]),
1191 ex_to<numeric>(fx_[1]) };
1192 if (!fx[0].is_real() || !fx[1].is_real()) {
1193 throw std::runtime_error("fsolve(): function evaluates to complex values at interval boundaries");
1194 }
1195 if (fx[0]*fx[1]>=0) {
1196 throw std::runtime_error("fsolve(): function does not change sign at interval boundaries");
1197 }
1198
1199 // The Newton-Raphson method has quadratic convergence! Simply put, it
1200 // replaces x with x-f(x)/f'(x) at each step. -f/f' is the delta:
1201 const ex ff = normal(-f/f.diff(x));
1202 int side = 0; // Start at left interval limit.
1203 numeric xxprev;
1204 numeric fxprev;
1205 do {
1206 xxprev = xx[side];
1207 fxprev = fx[side];
1208 ex dx_ = ff.subs(x == xx[side]).evalf();
1209 if (!is_a<numeric>(dx_))
1210 throw std::runtime_error("fsolve(): function derivative does not evaluate numerically");
1211 xx[side] += ex_to<numeric>(dx_);
1212 // Now check if Newton-Raphson method shot out of the interval
1213 bool bad_shot = (side == 0 && xx[0] < xxprev) ||
1214 (side == 1 && xx[1] > xxprev) || xx[0] > xx[1];
1215 if (!bad_shot) {
1216 // Compute f(x) only if new x is inside the interval.
1217 // The function might be difficult to compute numerically
1218 // or even ill defined outside the interval. Also it's
1219 // a small optimization.
1220 ex f_x = f.subs(x == xx[side]).evalf();
1221 if (!is_a<numeric>(f_x))
1222 throw std::runtime_error("fsolve(): function does not evaluate numerically");
1223 fx[side] = ex_to<numeric>(f_x);
1224 }
1225 if (bad_shot) {
1226 // Oops, Newton-Raphson method shot out of the interval.
1227 // Restore, and try again with the other side instead!
1228 xx[side] = xxprev;
1229 fx[side] = fxprev;
1230 side = !side;
1231 xxprev = xx[side];
1232 fxprev = fx[side];
1233
1234 ex dx_ = ff.subs(x == xx[side]).evalf();
1235 if (!is_a<numeric>(dx_))
1236 throw std::runtime_error("fsolve(): function derivative does not evaluate numerically [2]");
1237 xx[side] += ex_to<numeric>(dx_);
1238
1239 ex f_x = f.subs(x==xx[side]).evalf();
1240 if (!is_a<numeric>(f_x))
1241 throw std::runtime_error("fsolve(): function does not evaluate numerically [2]");
1242 fx[side] = ex_to<numeric>(f_x);
1243 }
1244 if ((fx[side]<0 && fx[!side]<0) || (fx[side]>0 && fx[!side]>0)) {
1245 // Oops, the root isn't bracketed any more.
1246 // Restore, and perform a bisection!
1247 xx[side] = xxprev;
1248 fx[side] = fxprev;
1249
1250 // Ah, the bisection! Bisections converge linearly. Unfortunately,
1251 // they occur pretty often when Newton-Raphson arrives at an x too
1252 // close to the result on one side of the interval and
1253 // f(x-f(x)/f'(x)) turns out to have the same sign as f(x) due to
1254 // precision errors! Recall that this function does not have a
1255 // precision goal as one of its arguments but instead relies on
1256 // x converging to a fixed point. We speed up the (safe but slow)
1257 // bisection method by mixing in a dash of the (unsafer but faster)
1258 // secant method: Instead of splitting the interval at the
1259 // arithmetic mean (bisection), we split it nearer to the root as
1260 // determined by the secant between the values xx[0] and xx[1].
1261 // Don't set the secant_weight to one because that could disturb
1262 // the convergence in some corner cases!
1263 constexpr double secant_weight = 0.984375; // == 63/64 < 1
1264 numeric xxmid = (1-secant_weight)*0.5*(xx[0]+xx[1])
1265 + secant_weight*(xx[0]+fx[0]*(xx[0]-xx[1])/(fx[1]-fx[0]));
1266 ex fxmid_ = f.subs(x == xxmid).evalf();
1267 if (!is_a<numeric>(fxmid_))
1268 throw std::runtime_error("fsolve(): function does not evaluate numerically [3]");
1269 numeric fxmid = ex_to<numeric>(fxmid_);
1270 if (fxmid.is_zero()) {
1271 // Luck strikes...
1272 return xxmid;
1273 }
1274 if ((fxmid<0 && fx[side]>0) || (fxmid>0 && fx[side]<0)) {
1275 side = !side;
1276 }
1277 xxprev = xx[side];
1278 fxprev = fx[side];
1279 xx[side] = xxmid;
1280 fx[side] = fxmid;
1281 }
1282 } while (xxprev!=xx[side]);
1283 return xxprev;
1284}
1285
1286
1287/* Force inclusion of functions from inifcns_gamma and inifcns_zeta
1288 * for static lib (so ginsh will see them). */
1289unsigned force_include_tgamma = tgamma_SERIAL::serial;
1291
1292} // 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:88
ex expand(unsigned options=0) const
Expand an expression.
Definition: ex.cpp:75
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:1272
ex imag_part() const
Definition: ex.h:148
ex subs(const exmap &m, unsigned options=0) const
Definition: ex.h:841
bool info(unsigned inf) const
Definition: ex.h:132
ex lhs() const
Left hand side of relational expression.
Definition: ex.cpp:227
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:235
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:1069
bool has(const ex &e) const
Definition: inifcns.cpp:1073
void insert_symbols(const ex &e)
Definition: inifcns.cpp:1058
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:1289
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:1079
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 Order_power(const ex &x, const ex &e)
Definition: inifcns.cpp:1024
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:1166
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:1290
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:1038
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.