hierarchy and describe the classes of objects that are handled by
@code{ex}.
+@subsection Note: Expressions and STL containers
+
+GiNaC expressions (@code{ex} objects) have value semantics (they can be
+assigned, reassigned and copied like integral types) but the operator
+@code{<} doesn't provide a well-defined ordering on them. In STL-speak,
+expressions are @samp{Assignable} but not @samp{LessThanComparable}.
+
+This implies that in order to use expressions in sorted containers such as
+@code{std::map<>} and @code{std::set<>} you have to supply a suitable
+comparison predicate. GiNaC provides such a predicate, called
+@code{ex_is_less}. For example, a set of expressions should be defined
+as @code{std::set<ex, ex_is_less>}.
+
+Unsorted containers such as @code{std::vector<>} and @code{std::list<>}
+don't pose a problem. A @code{std::vector<ex>} works as expected.
+
+@xref{Information About Expressions}, for more about comparing and ordering
+expressions.
+
@node Automatic evaluation, Error handling, Expressions, Basic Concepts
@c node-name, next, previous, up
@itemize @bullet
@item
-at most of complexity @math{O(n log n)}
+at most of complexity
+@tex
+$O(n\log n)$
+@end tex
+@ifnottex
+@math{O(n log n)}
+@end ifnottex
@item
algebraically correct, possibly except for a set of measure zero (e.g.
@math{x/x} is transformed to @math{1} although this is incorrect for @math{x=0})
@end ifnottex
@dots{}
@item @code{pseries} @tab Power Series, e.g. @math{x-1/6*x^3+1/120*x^5+O(x^7)}
-@item @code{function} @tab A symbolic function like @math{sin(2*x)}
+@item @code{function} @tab A symbolic function like
+@tex
+$\sin 2x$
+@end tex
+@ifnottex
+@math{sin(2*x)}
+@end ifnottex
@item @code{lst} @tab Lists of expressions @{@math{x}, @math{2*y}, @math{3+z}@}
@item @code{matrix} @tab @math{m}x@math{n} matrices of expressions
@item @code{relational} @tab A relation like the identity @math{x}@code{==}@math{y}
@end multitable
@end cartouche
+@subsection Converting numbers
+
+Sometimes it is desirable to convert a @code{numeric} object back to a
+built-in arithmetic type (@code{int}, @code{double}, etc.). The @code{numeric}
+class provides a couple of methods for this purpose:
+
+@cindex @code{to_int()}
+@cindex @code{to_long()}
+@cindex @code{to_double()}
+@cindex @code{to_cl_N()}
+@example
+int numeric::to_int() const;
+long numeric::to_long() const;
+double numeric::to_double() const;
+cln::cl_N numeric::to_cl_N() const;
+@end example
+
+@code{to_int()} and @code{to_long()} only work when the number they are
+applied on is an exact integer. Otherwise the program will halt with a
+message like @samp{Not a 32-bit integer}. @code{to_double()} applied on a
+rational number will return a floating-point approximation. Both
+@code{to_int()/to_long()} and @code{to_double()} discard the imaginary
+part of complex numbers.
+
@node Constants, Fundamental containers, Numbers, Basic Concepts
@c node-name, next, previous, up
The GiNaC class @code{lst} serves for holding a @dfn{list} of arbitrary
expressions. They are not as ubiquitous as in many other computer algebra
packages, but are sometimes used to supply a variable number of arguments of
-the same type to GiNaC methods such as @code{subs()} and @code{to_rational()},
-so you should have a basic understanding of them.
+the same type to GiNaC methods such as @code{subs()} and some @code{matrix}
+constructors, so you should have a basic understanding of them.
-Lists of up to 16 expressions can be directly constructed from single
+Lists can be constructed by assigning a comma-separated sequence of
expressions:
@example
@{
symbol x("x"), y("y");
- lst l(x, 2, y, x+y);
- // now, l is a list holding the expressions 'x', '2', 'y', and 'x+y'
+ lst l;
+ l = x, 2, y, x+y;
+ // now, l is a list holding the expressions 'x', '2', 'y', and 'x+y',
+ // in that order
+ ...
+@end example
+
+There are also constructors that allow direct creation of lists of up to
+16 expressions, which is often more convenient but slightly less efficient:
+
+@example
+ ...
+ // This produces the same list 'l' as above:
+ // lst l(x, 2, y, x+y);
+ // lst l = lst(x, 2, y, x+y);
...
@end example
@example
...
// print the elements of the list (requires #include <iterator>)
- copy(l.begin(), l.end(), ostream_iterator<ex>(cout, "\n"));
+ std::copy(l.begin(), l.end(), ostream_iterator<ex>(cout, "\n"));
// sum up the elements of the list (requires #include <numeric>)
- ex sum = accumulate(l.begin(), l.end(), ex(0));
+ ex sum = std::accumulate(l.begin(), l.end(), ex(0));
cout << sum << endl; // prints '2+2*x+2*y'
...
@end example
@example
...
- lst l1(x, 2, y, x+y);
- lst l2(2, x+y, x, y);
+ lst l1, l2;
+ l1 = x, 2, y, x+y;
+ l2 = 2, x+y, x, y;
l1.sort();
l2.sort();
// l1 and l2 are now equal
@example
...
- lst l3(x, 2, 2, 2, y, x+y, y+x);
+ lst l3;
+ l3 = x, 2, 2, 2, y, x+y, y+x;
l3.unique(); // l3 is now @{x, 2, y, x+y@}
@}
@end example
second one in the range 0@dots{}@math{n-1}.
There are a couple of ways to construct matrices, with or without preset
-elements:
+elements. The constructor
+
+@example
+matrix::matrix(unsigned r, unsigned c);
+@end example
+
+creates a matrix with @samp{r} rows and @samp{c} columns with all elements
+set to zero.
+
+The fastest way to create a matrix with preinitialized elements is to assign
+a list of comma-separated expressions to an empty matrix (see below for an
+example). But you can also specify the elements as a (flat) list with
+
+@example
+matrix::matrix(unsigned r, unsigned c, const lst & l);
+@end example
+
+The function
@cindex @code{lst_to_matrix()}
+@example
+ex lst_to_matrix(const lst & l);
+@end example
+
+constructs a matrix from a list of lists, each list representing a matrix row.
+
+There is also a set of functions for creating some special types of
+matrices:
+
@cindex @code{diag_matrix()}
@cindex @code{unit_matrix()}
@cindex @code{symbolic_matrix()}
@example
-matrix::matrix(unsigned r, unsigned c);
-matrix::matrix(unsigned r, unsigned c, const lst & l);
-ex lst_to_matrix(const lst & l);
ex diag_matrix(const lst & l);
ex unit_matrix(unsigned x);
ex unit_matrix(unsigned r, unsigned c);
ex symbolic_matrix(unsigned r, unsigned c, const string & base_name, const string & tex_base_name);
@end example
-The first two functions are @code{matrix} constructors which create a matrix
-with @samp{r} rows and @samp{c} columns. The matrix elements can be
-initialized from a (flat) list of expressions @samp{l}. Otherwise they are
-all set to zero. The @code{lst_to_matrix()} function constructs a matrix
-from a list of lists, each list representing a matrix row. @code{diag_matrix()}
-constructs a diagonal matrix given the list of diagonal elements.
-@code{unit_matrix()} creates an @samp{x} by @samp{x} (or @samp{r} by @samp{c})
-unit matrix. And finally, @code{symbolic_matrix} constructs a matrix filled
-with newly generated symbols made of the specified base name and the
-position of each element in the matrix.
+@code{diag_matrix()} constructs a diagonal matrix given the list of diagonal
+elements. @code{unit_matrix()} creates an @samp{x} by @samp{x} (or @samp{r}
+by @samp{c}) unit matrix. And finally, @code{symbolic_matrix} constructs a
+matrix filled with newly generated symbols made of the specified base name
+and the position of each element in the matrix.
Matrix elements can be accessed and set using the parenthesis (function call)
operator:
the @code{op()} method. But C++-style subscripting with square brackets
@samp{[]} is not available.
-Here are a couple of examples of constructing matrices:
+Here are a couple of examples for constructing matrices:
@example
@{
symbol a("a"), b("b");
matrix M(2, 2);
- M(0, 0) = a;
- M(1, 1) = b;
+ M = a, 0,
+ 0, b;
cout << M << endl;
// -> [[a,0],[0,b]]
+ matrix M2(2, 2);
+ M2(0, 0) = a;
+ M2(1, 1) = b;
+ cout << M2 << endl;
+ // -> [[a,0],[0,b]]
+
cout << matrix(2, 2, lst(a, 0, 0, b)) << endl;
// -> [[a,0],[0,b]]
@example
@{
- matrix A(2, 2, lst(1, 2, 3, 4));
- matrix B(2, 2, lst(-1, 0, 2, 1));
- matrix C(2, 2, lst(8, 4, 2, 1));
+ matrix A(2, 2), B(2, 2), C(2, 2);
+ A = 1, 2,
+ 3, 4;
+ B = -1, 0,
+ 2, 1;
+ C = 8, 4,
+ 2, 1;
matrix result = A.mul(B).sub(C.mul_scalar(2));
cout << result << endl;
@example
ex matrix::determinant(unsigned algo=determinant_algo::automatic) const;
ex matrix::trace() const;
-ex matrix::charpoly(const symbol & lambda) const;
+ex matrix::charpoly(const ex & lambda) const;
@end example
The @samp{algo} argument of @code{determinant()} allows to select
symbol x("x"), y("y");
// A is a 2x2 matrix, X is a 2x1 vector
- matrix A(2, 2, lst(1, 2, 3, 4)), X(2, 1, lst(x, y));
+ matrix A(2, 2), X(2, 1);
+ A = 1, 2,
+ 3, 4;
+ X = x, y;
cout << indexed(A, i, i) << endl;
// -> 5
@menu
* Information About Expressions::
+* Numerical Evaluation::
* Substituting Expressions::
* Pattern Matching and Advanced Substitutions::
* Applying a Function on Subexpressions::
@end menu
-@node Information About Expressions, Substituting Expressions, Methods and Functions, Methods and Functions
+@node Information About Expressions, Numerical Evaluation, Methods and Functions, Methods and Functions
@c node-name, next, previous, up
@section Getting information about expressions
after @code{other}.
-@node Substituting Expressions, Pattern Matching and Advanced Substitutions, Information About Expressions, Methods and Functions
+@node Numerical Evaluation, Substituting Expressions, Information About Expressions, Methods and Functions
+@c node-name, next, previous, up
+@section Numercial Evaluation
+@cindex @code{evalf()}
+
+GiNaC keeps algebraic expressions, numbers and constants in their exact form.
+To evaluate them using floating-point arithmetic you need to call
+
+@example
+ex ex::evalf(int level = 0) const;
+@end example
+
+@cindex @code{Digits}
+The accuracy of the evaluation is controlled by the global object @code{Digits}
+which can be assigned an integer value. The default value of @code{Digits}
+is 17. @xref{Numbers}, for more information and examples.
+
+To evaluate an expression to a @code{double} floating-point number you can
+call @code{evalf()} followed by @code{numeric::to_double()}, like this:
+
+@example
+@{
+ // Approximate sin(x/Pi)
+ symbol x("x");
+ ex e = series(sin(x/Pi), x == 0, 6);
+
+ // Evaluate numerically at x=0.1
+ ex f = evalf(e.subs(x == 0.1));
+
+ // ex_to<numeric> is an unsafe cast, so check the type first
+ if (is_a<numeric>(f)) @{
+ double d = ex_to<numeric>(f).to_double();
+ cout << d << endl;
+ // -> 0.0318256
+ @} else
+ // error
+@}
+@end example
+
+
+@node Substituting Expressions, Pattern Matching and Advanced Substitutions, Numerical Evaluation, Methods and Functions
@c node-name, next, previous, up
@section Substituting expressions
@cindex @code{subs()}
@example
ex ex::subs(const ex & e, unsigned options = 0);
+ex ex::subs(const exmap & m, unsigned options = 0);
ex ex::subs(const lst & syms, const lst & repls, unsigned options = 0);
@end example
If you specify multiple substitutions, they are performed in parallel, so e.g.
@code{subs(lst(x == y, y == x))} exchanges @samp{x} and @samp{y}.
-The second form of @code{subs()} takes two lists, one for the objects to be
+The second form of @code{subs()} takes an @code{exmap} object which is a
+pair associative container that maps expressions to expressions (currently
+implemented as a @code{std::map}). This is the most efficient one of the
+three @code{subs()} forms and should be used when the number of objects to
+be substituted is large or unknown.
+
+Using this form, the second example from above would look like this:
+
+@example
+@{
+ symbol x("x"), y("y");
+ ex e2 = x*y + x;
+
+ exmap m;
+ m[x] = -2;
+ m[y] = 4;
+ cout << "e2(-2, 4) = " << e2.subs(m) << endl;
+@}
+@end example
+
+The third form of @code{subs()} takes two lists, one for the objects to be
replaced and one for the expressions to be substituted (both lists must
contain the same number of elements). Using this form, you would write
-@code{subs(lst(x, y), lst(y, x))} to exchange @samp{x} and @samp{y}.
+
+@example
+@{
+ symbol x("x"), y("y");
+ ex e2 = x*y + x;
+
+ cout << "e2(-2, 4) = " << e2.subs(lst(x, y), lst(-2, 4)) << endl;
+@}
+@end example
The optional last argument to @code{subs()} is a combination of
@code{subs_options} flags. There are two options available:
The two functions
@example
-ex quo(const ex & a, const ex & b, const symbol & x);
-ex rem(const ex & a, const ex & b, const symbol & x);
+ex quo(const ex & a, const ex & b, const ex & x);
+ex rem(const ex & a, const ex & b, const ex & x);
@end example
compute the quotient and remainder of univariate polynomials in the variable
The additional function
@example
-ex prem(const ex & a, const ex & b, const symbol & x);
+ex prem(const ex & a, const ex & b, const ex & x);
@end example
computes the pseudo-remainder of @samp{a} and @samp{b} which satisfies
The methods
@example
-ex ex::unit(const symbol & x);
-ex ex::content(const symbol & x);
-ex ex::primpart(const symbol & x);
+ex ex::unit(const ex & x);
+ex ex::content(const ex & x);
+ex ex::primpart(const ex & x);
@end example
return the unit part, content part, and primitive polynomial of a multivariate
above. You do this by calling
@example
-ex ex::to_polynomial(lst &l);
+ex ex::to_polynomial(exmap & m);
+ex ex::to_polynomial(lst & l);
@end example
or
@example
-ex ex::to_rational(lst &l);
+ex ex::to_rational(exmap & m);
+ex ex::to_rational(lst & l);
@end example
-on the expression to be converted. The supplied @code{lst} will be filled
-with the generated temporary symbols and their replacement expressions in
-a format that can be used directly for the @code{subs()} method. It can also
-already contain a list of replacements from an earlier application of
-@code{.to_polynomial()} or @code{.to_rational()}, so it's possible to use
-it on multiple expressions and get consistent results.
+on the expression to be converted. The supplied @code{exmap} or @code{lst}
+will be filled with the generated temporary symbols and their replacement
+expressions in a format that can be used directly for the @code{subs()}
+method. It can also already contain a list of replacements from an earlier
+application of @code{.to_polynomial()} or @code{.to_rational()}, so it's
+possible to use it on multiple expressions and get consistent results.
The difference betwerrn @code{.to_polynomial()} and @code{.to_rational()}
is probably best illustrated with an example:
ex a = pow(sin(x), 2) - pow(cos(x), 2);
ex b = sin(x) + cos(x);
ex q;
- lst l;
- divide(a.to_polynomial(l), b.to_polynomial(l), q);
- cout << q.subs(l) << endl;
+ exmap m;
+ divide(a.to_polynomial(m), b.to_polynomial(m), q);
+ cout << q.subs(m) << endl;
@}
@end example
@item @code{Order(x)}
@tab order term function in truncated power series
@cindex @code{Order()}
+@item @code{Li(n, x)}
+@tab polylogarithm
+@cindex @code{Li()}
+@item @code{S(n, p, x)}
+@tab Nielsen's generalized polylogarithm
+@cindex @code{S()}
+@item @code{H(m_lst, x)}
+@tab harmonic polylogarithm
+@cindex @code{H()}
+@item @code{Li(m_lst, x_lst)}
+@tab multiple polylogarithm
+@cindex @code{Li()}
+@item @code{mZeta(m_lst)}
+@tab multiple zeta value
+@cindex @code{mZeta()}
@end multitable
@end cartouche
@example
@{
symbol a("a"), b("b"), x("x"), y("y");
- lst eqns;
- eqns.append(a*x+b*y==3).append(x-y==b);
- lst vars;
- vars.append(x).append(y);
+ lst eqns, vars;
+ eqns = a*x+b*y==3, x-y==b;
+ vars = x, y;
cout << lsolve(eqns, vars) << endl;
- // -> @{x==(3+b^2)/(b+a),y==(3-b*a)/(b+a)@}
+ // -> @{x==(3+b^2)/(b+a),y==(3-b*a)/(b+a)@}
@end example
When the linear equations @code{eqns} are underdetermined, the solution
@example
// ...
- lst syms(x, y);
+ lst syms;
+ syms = x, y;
ex ex1 = a2.unarchive_ex(syms, "foo");
ex ex2 = a2.unarchive_ex(syms, "the second one");