This is a tutorial that documents GiNaC @value{VERSION}, an open
framework for symbolic computation within the C++ programming language.
-Copyright (C) 1999-2001 Johannes Gutenberg University Mainz, Germany
+Copyright (C) 1999-2002 Johannes Gutenberg University Mainz, Germany
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@page
@vskip 0pt plus 1filll
-Copyright @copyright{} 1999-2001 Johannes Gutenberg University Mainz, Germany
+Copyright @copyright{} 1999-2002 Johannes Gutenberg University Mainz, Germany
@sp 2
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@section License
The GiNaC framework for symbolic computation within the C++ programming
-language is Copyright @copyright{} 1999-2001 Johannes Gutenberg
+language is Copyright @copyright{} 1999-2002 Johannes Gutenberg
University Mainz, Germany.
This program is free software; you can redistribute it and/or
numeric trott("1.0841015122311136151E-2");
std::cout << two*p << std::endl; // floating point 6.283...
+ ...
+@end example
+
+@cindex @code{I}
+@cindex complex numbers
+The imaginary unit in GiNaC is a predefined @code{numeric} object with the
+name @code{I}:
+
+@example
+ ...
+ numeric z1 = 2-3*I; // exact complex number 2-3i
+ numeric z2 = 5.9+1.6*I; // complex floating point number
@}
@end example
-It may be tempting to construct numbers writing @code{numeric r(3/2)}.
+It may be tempting to construct fractions by writing @code{numeric r(3/2)}.
This would, however, call C's built-in operator @code{/} for integers
first and result in a numeric holding a plain integer 1. @strong{Never
use the operator @code{/} on integers} unless you know exactly what you
@example
in 17 digits:
-0.333333333333333333
-3.14159265358979324
+0.33333333333333333334
+3.1415926535897932385
in 60 digits:
-0.333333333333333333333333333333333333333333333333333333333333333333
-3.14159265358979323846264338327950288419716939937510582097494459231
+0.33333333333333333333333333333333333333333333333333333333333333333334
+3.1415926535897932384626433832795028841971693993751058209749445923078
@end example
+@cindex rounding
+Note that the last number is not necessarily rounded as you would
+naively expect it to be rounded in the decimal system. But note also,
+that in both cases you got a couple of extra digits. This is because
+numbers are internally stored by CLN as chunks of binary digits in order
+to match your machine's word size and to not waste precision. Thus, on
+architectures with differnt word size, the above output might even
+differ with regard to actually computed digits.
+
It should be clear that objects of class @code{numeric} should be used
for constructing numbers or for doing arithmetic with them. The objects
one deals with most of the time are the polymorphic expressions @code{ex}.
// -> 2*A.j.i
cout << indexed(B, sy_anti(), i, j)
+ indexed(B, sy_anti(), j, i) << endl;
- // -> -B.j.i
+ // -> 0
cout << indexed(B, sy_anti(), i, j, k)
- + indexed(B, sy_anti(), j, i, k) << endl;
+ - indexed(B, sy_anti(), j, k, i) << endl;
// -> 0
...
@end example
dummy nor free indices.
To be recognized as a dummy index pair, the two indices must be of the same
-class and dimension and their value must be the same single symbol (an index
-like @samp{2*n+1} is never a dummy index). If the indices are of class
+class and their value must be the same single symbol (an index like
+@samp{2*n+1} is never a dummy index). If the indices are of class
@code{varidx} they must also be of opposite variance; if they are of class
@code{spinidx} they must be both dotted or both undotted.
b^3+a^3+(x+y)^3
> subs(a^4+b^4+(x+y)^4,$1^2==$1^3);
b^4+a^4+(x+y)^4
-> subs((a+b+c)^2,a+b=x);
+> subs((a+b+c)^2,a+b==x);
(a+b+c)^2
> subs((a+b+c)^2,a+b+$1==x+$1);
(x+c)^2
-> subs(a+2*b,a+b=x);
+> subs(a+2*b,a+b==x);
a+2*b
> subs(4*x^3-2*x^2+5*x-1,x==a);
-1+5*a-2*a^2+4*a^3
int ex::ldegree(const ex & s);
@end example
-which also work reliably on non-expanded input polynomials (they even work
-on rational functions, returning the asymptotic degree). To extract
-a coefficient with a certain power from an expanded polynomial you use
+These functions only work reliably if the input polynomial is collected in
+terms of the object @samp{s}. Otherwise, they are only guaranteed to return
+the upper/lower bounds of the exponents. If you need accurate results, you
+have to call @code{expand()} and/or @code{collect()} on the input polynomial.
+For example
+
+@example
+> a=(x+1)^2-x^2;
+(1+x)^2-x^2;
+> degree(a,x);
+2
+> degree(expand(a),x);
+1
+@end example
+
+@code{degree()} also works on rational functions, returning the asymptotic
+degree:
+
+@example
+> degree((x+1)/(x^3+1),x);
+-2
+@end example
+
+If the input is not a polynomial or rational function in the variable @samp{s},
+the behavior of @code{degree()} and @code{ldegree()} is undefined.
+
+To extract a coefficient with a certain power from an expanded
+polynomial you use
@example
ex ex::coeff(const ex & s, int n);
factorization is, however, easily implemented by noting that factors
appearing in a polynomial with power two or more also appear in the
derivative and hence can easily be found by computing the GCD of the
-original polynomial and its derivatives. Any system has an interface
-for this so called square-free factorization. So we provide one, too:
+original polynomial and its derivatives. Any decent system has an
+interface for this so called square-free factorization. So we provide
+one, too:
@example
ex sqrfree(const ex & a, const lst & l = lst());
@end example
-Here is an example that by the way illustrates how the result may depend
-on the order of differentiation:
+Here is an example that by the way illustrates how the exact form of the
+result may slightly depend on the order of differentiation, calling for
+some care with subsequent processing of the result:
@example
...
symbol x("x"), y("y");
- ex BiVarPol = expand(pow(x-2*y*x,3) * pow(x+y,2) * (x-y));
+ ex BiVarPol = expand(pow(2-2*y,3) * pow(1+x*y,2) * pow(x-2*y,2) * (x+y));
cout << sqrfree(BiVarPol, lst(x,y)) << endl;
- // -> (y+x)^2*(-1+6*y+8*y^3-12*y^2)*(y-x)*x^3
+ // -> 8*(1-y)^3*(y*x^2-2*y+x*(1-2*y^2))^2*(y+x)
cout << sqrfree(BiVarPol, lst(y,x)) << endl;
- // -> (1-2*y)^3*(y+x)^2*(-y+x)*x^3
+ // -> 8*(1-y)^3*(-y*x^2+2*y+x*(-1+2*y^2))^2*(y+x)
cout << sqrfree(BiVarPol) << endl;
// -> depending on luck, any of the above
...
@end example
+Note also, how factors with the same exponents are not fully factorized
+with this method.
@node Rational Expressions, Symbolic Differentiation, Polynomial Arithmetic, Methods and Functions
@math{1-v^2/c^2+O(v^10)}, without that call we would just have a long
series raised to the power @math{-2}.
-@cindex M@'echain's formula
+@cindex Machin's formula
As another instructive application, let us calculate the numerical
value of Archimedes' constant
@tex
$\pi$
@end tex
(for which there already exists the built-in constant @code{Pi})
-using M@'echain's amazing formula
+using Machin's amazing formula
@tex
$\pi=16$~atan~$\!\left(1 \over 5 \right)-4$~atan~$\!\left(1 \over 239 \right)$.
@end tex
#include <ginac/ginac.h>
using namespace GiNaC;
-ex mechain_pi(int degr)
+ex machin_pi(int degr)
@{
symbol x;
ex pi_expansion = series_to_poly(atan(x).series(x,degr));
using std::endl; // ...dealing with this namespace std.
ex pi_frac;
for (int i=2; i<12; i+=2) @{
- pi_frac = mechain_pi(i);
+ pi_frac = machin_pi(i);
cout << i << ":\t" << pi_frac << endl
<< "\t" << pi_frac.evalf() << endl;
@}
desired symbols to the @code{>>} stream input operator.
Instead, GiNaC lets you construct an expression from a string, specifying the
-list of symbols to be used:
+list of symbols and indices to be used:
@example
@{
- symbol x("x"), y("y");
- ex e("2*x+sin(y)", lst(x, y));
+ symbol x("x"), y("y"), p("p");
+ idx i(symbol("i"), 3);
+ ex e("2*x+sin(y)+p.i", lst(x, y, p, i));
@}
@end example
The input syntax is the same as that used by @command{ginsh} and the stream
-output operator @code{<<}. The symbols in the string are matched by name to
-the symbols in the list and if GiNaC encounters a symbol not specified in
-the list it will throw an exception.
+output operator @code{<<}. The symbols and indices in the string are matched
+by name to the symbols and indices in the list and if GiNaC encounters a
+symbol or index not specified in the list it will throw an exception. Only
+indices whose values are single symbols can be used (i.e. numeric indices
+or compound indices as in "A.(2*n+1)" are not allowed).
With this constructor, it's also easy to implement interactive GiNaC programs: