- expanded the section on symbols
authorChristian Bauer <Christian.Bauer@uni-mainz.de>
Fri, 11 Jun 2004 21:30:55 +0000 (21:30 +0000)
committerChristian Bauer <Christian.Bauer@uni-mainz.de>
Fri, 11 Jun 2004 21:30:55 +0000 (21:30 +0000)
- added a list of functions of numeric objects

doc/tutorial/ginac.texi

index 9b73ed5c635f6ab37faebd959fa778a6c63919f1..3f98183162437c3a8d7c4bcf03c9cc977c52e2eb 100644 (file)
@@ -953,35 +953,175 @@ $\sin 2x$
 @cindex hierarchy of classes
 
 @cindex atom
 @cindex hierarchy of classes
 
 @cindex atom
-Symbols are for symbolic manipulation what atoms are for chemistry.  You
-can declare objects of class @code{symbol} as any other object simply by
-saying @code{symbol x,y;}.  There is, however, a catch in here having to
-do with the fact that C++ is a compiled language.  The information about
-the symbol's name is thrown away by the compiler but at a later stage
-you may want to print expressions holding your symbols.  In order to
-avoid confusion GiNaC's symbols are able to know their own name.  This
-is accomplished by declaring its name for output at construction time in
-the fashion @code{symbol x("x");}.  If you declare a symbol using the
-default constructor (i.e. without string argument) the system will deal
-out a unique name.  That name may not be suitable for printing but for
-internal routines when no output is desired it is often enough.  We'll
-come across examples of such symbols later in this tutorial.
-
-This implies that the strings passed to symbols at construction time may
-not be used for comparing two of them.  It is perfectly legitimate to
-write @code{symbol x("x"),y("x");} but it is likely to lead into
-trouble.  Here, @code{x} and @code{y} are different symbols and
-statements like @code{x-y} will not be simplified to zero although the
-output @code{x-x} looks funny.  Such output may also occur when there
-are two different symbols in two scopes, for instance when you call a
-function that declares a symbol with a name already existent in a symbol
-in the calling function.  Again, comparing them (using @code{operator==}
-for instance) will always reveal their difference.  Watch out, please.
+Symbolic indeterminates, or @dfn{symbols} for short, are for symbolic
+manipulation what atoms are for chemistry.
+
+A typical symbol definition looks like this:
+@example
+symbol x("x");
+@end example
+
+This definition actually contains three very different things:
+@itemize
+@item a C++ variable named @code{x}
+@item a @code{symbol} object stored in this C++ variable; this object
+  represents the symbol in a GiNaC expression
+@item the string @code{"x"} which is the name of the symbol, used (almost)
+  exclusively for printing expressions holding the symbol
+@end itemize
+
+Symbols have an explicit name, supplied as a string during construction,
+because in C++, variable names can't be used as values, and the C++ compiler
+throws them away during compilation.
+
+It is possible to omit the symbol name in the definition:
+@example
+symbol x;
+@end example
+
+In this case, GiNaC will assign the symbol an internal, unique name of the
+form @code{symbolNNN}. This won't affect the usability of the symbol but
+the output of your calculations will become more readable if you give your
+symbols sensible names (for intermediate expressions that are only used
+internally such anonymous symbols can be quite useful, however).
+
+Now, here is one important property of GiNaC that differentiates it from
+other computer algebra programs you may have used: GiNaC does @emph{not} use
+the names of symbols to tell them apart, but a (hidden) serial number that
+is unique for each newly created @code{symbol} object. In you want to use
+one and the same symbol in different places in your program, you must only
+create one @code{symbol} object and pass that around. If you create another
+symbol, even if it has the same name, GiNaC will treat it as a different
+indeterminate.
+
+Observe:
+@example
+ex f(int n)
+@{
+    symbol x("x");
+    return pow(x, n);
+@}
+
+int main()
+@{
+    symbol x("x");
+    ex e = f(6);
+
+    cout << e << endl;
+     // prints "x^6" which looks right, but...
+
+    cout << e.degree(x) << endl;
+     // ...this doesn't work. The symbol "x" here is different from the one
+     // in f() and in the expression returned by f(). Consequently, it
+     // prints "0".
+@}
+@end example
+
+One possibility to ensure that @code{f()} and @code{main()} use the same
+symbol is to pass the symbol as an argument to @code{f()}:
+@example
+ex f(int n, const ex & x)
+@{
+    return pow(x, n);
+@}
+
+int main()
+@{
+    symbol x("x");
+
+    // Now, f() uses the same symbol.
+    ex e = f(6, x);
+
+    cout << e.degree(x) << endl;
+     // prints "6", as expected
+@}
+@end example
+
+Another possibility would be to define a global symbol @code{x} that is used
+by both @code{f()} and @code{main()}. If you are using global symbols and
+multiple compilation units you must take special care, however. Suppose
+that you have a header file @file{globals.h} in your program that defines
+a @code{symbol x("x");}. In this case, every unit that includes
+@file{globals.h} would also get its own definition of @code{x} (because
+header files are just inlined into the source code by the C++ preprocessor),
+and hence you would again end up with multiple equally-named, but different,
+symbols. Instead, the @file{globals.h} header should only contain a
+@emph{declaration} like @code{extern symbol x;}, with the definition of
+@code{x} moved into a C++ source file such as @file{globals.cpp}.
+
+A different approach to ensuring that symbols used in different parts of
+your program are identical is to create them with a @emph{factory} function
+like this one:
+@example
+const symbol & get_symbol(const string & s)
+@{
+    static map<string, symbol> directory;
+    map<string, symbol>::iterator i = directory.find(s);
+    if (i != directory.end())
+        return i->second;
+    else
+        return directory.insert(make_pair(s, symbol(s))).first->second;
+@}
+@end example
+
+This function returns one newly constructed symbol for each name that is
+passed in, and it returns the same symbol when called multiple times with
+the same name. Using this symbol factory, we can rewrite our example like
+this:
+@example
+ex f(int n)
+@{
+    return pow(get_symbol("x"), n);
+@}
+
+int main()
+@{
+    ex e = f(6);
+
+    // Both calls of get_symbol("x") yield the same symbol.
+    cout << e.degree(get_symbol("x")) << endl;
+     // prints "6"
+@}
+@end example
+
+Instead of creating symbols from strings we could also have
+@code{get_symbol()} take, for example, an integer number as its argument.
+In this case, we would probably want to give the generated symbols names
+that include this number, which can be accomplished with the help of an
+@code{ostringstream}.
+
+In general, if you're getting weird results from GiNaC such as an expression
+@samp{x-x} that is not simplified to zero, you should check your symbol
+definitions.
+
+As we said, the names of symbols primarily serve for purposes of expression
+output. But there are actually two instances where GiNaC uses the names for
+identifying symbols: When constructing an expression from a string, and when
+recreating an expression from an archive (@pxref{Input/Output}).
+
+In addition to its name, a symbol may contain a special string that is used
+in LaTeX output:
+@example
+symbol x("x", "\\Box");
+@end example
+
+This creates a symbol that is printed as "@code{x}" in normal output, but
+as "@code{\Box}" in LaTeX code (@xref{Input/Output}, for more
+information about the different output formats of expressions in GiNaC).
+GiNaC automatically creates proper LaTeX code for symbols having names of
+greek letters (@samp{alpha}, @samp{mu}, etc.).
+
+@cindex @code{subs()}
+Symbols in GiNaC can't be assigned values. If you need to store results of
+calculations and give them a name, use C++ variables of type @code{ex}.
+If you want to replace a symbol in an expression with something else, you
+can invoke the expression's @code{.subs()} method
+(@pxref{Substituting Expressions}).
 
 @cindex @code{realsymbol()}
 
 @cindex @code{realsymbol()}
-Symbols are expected to stand in for complex values by default, i.e. they live
+By default, symbols are expected to stand in for complex values, i.e. they live
 in the complex domain.  As a consequence, operations like complex conjugation,
 in the complex domain.  As a consequence, operations like complex conjugation,
-for example (see @ref{Complex Conjugation}), do @emph{not} evaluate if applied
+for example (@pxref{Complex Conjugation}), do @emph{not} evaluate if applied
 to such symbols. Likewise @code{log(exp(x))} does not evaluate to @code{x},
 because of the unknown imaginary part of @code{x}.
 On the other hand, if you are sure that your symbols will hold only real values, you
 to such symbols. Likewise @code{log(exp(x))} does not evaluate to @code{x},
 because of the unknown imaginary part of @code{x}.
 On the other hand, if you are sure that your symbols will hold only real values, you
@@ -989,12 +1129,6 @@ would like to have such functions evaluated. Therefore GiNaC allows you to speci
 the domain of the symbol. Instead of @code{symbol x("x");} you can write
 @code{realsymbol x("x");} to tell GiNaC that @code{x} stands in for real values.
 
 the domain of the symbol. Instead of @code{symbol x("x");} you can write
 @code{realsymbol x("x");} to tell GiNaC that @code{x} stands in for real values.
 
-@cindex @code{subs()}
-Although symbols can be assigned expressions for internal reasons, you
-should not do it (and we are not going to tell you how it is done).  If
-you want to replace a symbol with something else in an expression, you
-can use the expression's @code{.subs()} method (@pxref{Substituting Expressions}).
-
 
 @node Numbers, Constants, Symbols, Basic Concepts
 @c    node-name, next, previous, up
 
 @node Numbers, Constants, Symbols, Basic Concepts
 @c    node-name, next, previous, up
@@ -1205,6 +1339,120 @@ can be applied is listed in the following table.
 @end multitable
 @end cartouche
 
 @end multitable
 @end cartouche
 
+@subsection Numeric functions
+
+The following functions can be applied to @code{numeric} objects and will be
+evaluated immediately:
+
+@cartouche
+@multitable @columnfractions .30 .70
+@item @strong{Name} @tab @strong{Function}
+@item @code{inverse(z)}
+@tab returns @math{1/z}
+@cindex @code{inverse()} (numeric)
+@item @code{pow(a, b)}
+@tab exponentiation @math{a^b}
+@item @code{abs(z)}
+@tab absolute value
+@item @code{real(z)}
+@tab real part
+@cindex @code{real()}
+@item @code{imag(z)}
+@tab imaginary part
+@cindex @code{imag()}
+@item @code{csgn(z)}
+@tab complex sign (returns an @code{int})
+@item @code{numer(z)}
+@tab numerator of rational or complex rational number
+@item @code{denom(z)}
+@tab denominator of rational or complex rational number
+@item @code{sqrt(z)}
+@tab square root
+@item @code{isqrt(n)}
+@tab integer square root
+@cindex @code{isqrt()}
+@item @code{sin(z)}
+@tab sine
+@item @code{cos(z)}
+@tab cosine
+@item @code{tan(z)}
+@tab tangent
+@item @code{asin(z)}
+@tab inverse sine
+@item @code{acos(z)}
+@tab inverse cosine
+@item @code{atan(z)}
+@tab inverse tangent
+@item @code{atan(y, x)}
+@tab inverse tangent with two arguments
+@item @code{sinh(z)}
+@tab hyperbolic sine
+@item @code{cosh(z)}
+@tab hyperbolic cosine
+@item @code{tanh(z)}
+@tab hyperbolic tangent
+@item @code{asinh(z)}
+@tab inverse hyperbolic sine
+@item @code{acosh(z)}
+@tab inverse hyperbolic cosine
+@item @code{atanh(z)}
+@tab inverse hyperbolic tangent
+@item @code{exp(z)}
+@tab exponential function
+@item @code{log(z)}
+@tab natural logarithm
+@item @code{Li2(z)}
+@tab dilogarithm
+@item @code{zeta(z)}
+@tab Riemann's zeta function
+@item @code{tgamma(z)}
+@tab gamma function
+@item @code{lgamma(z)}
+@tab logarithm of gamma function
+@item @code{psi(z)}
+@tab psi (digamma) function
+@item @code{psi(n, z)}
+@tab derivatives of psi function (polygamma functions)
+@item @code{factorial(n)}
+@tab factorial function @math{n!}
+@item @code{doublefactorial(n)}
+@tab double factorial function @math{n!!}
+@cindex @code{doublefactorial()}
+@item @code{binomial(n, k)}
+@tab binomial coefficients
+@item @code{bernoulli(n)}
+@tab Bernoulli numbers
+@cindex @code{bernoulli()}
+@item @code{fibonacci(n)}
+@tab Fibonacci numbers
+@cindex @code{fibonacci()}
+@item @code{mod(a, b)}
+@tab modulus in positive representation (in the range @code{[0, abs(b)-1]} with the sign of b, or zero)
+@cindex @code{mod()}
+@item @code{smod(a, b)}
+@tab modulus in symmetric representation (in the range @code{[-iquo(abs(b)-1, 2), iquo(abs(b), 2)]})
+@cindex @code{smod()}
+@item @code{irem(a, b)}
+@tab integer remainder (has the sign of @math{a}, or is zero)
+@cindex @code{irem()}
+@item @code{irem(a, b, q)}
+@tab integer remainder and quotient, @code{irem(a, b, q) == a-q*b}
+@item @code{iquo(a, b)}
+@tab integer quotient
+@cindex @code{iquo()}
+@item @code{iquo(a, b, r)}
+@tab integer quotient and remainder, @code{r == a-iquo(a, b)*b}
+@item @code{gcd(a, b)}
+@tab greatest common divisor
+@item @code{lcm(a, b)}
+@tab least common multiple
+@end multitable
+@end cartouche
+
+Most of these functions are also available as symbolic functions that can be
+used in expressions (@pxref{Mathematical functions}) or, like @code{gcd()},
+as polynomial algorithms.
+
 @subsection Converting numbers
 
 Sometimes it is desirable to convert a @code{numeric} object back to a
 @subsection Converting numbers
 
 Sometimes it is desirable to convert a @code{numeric} object back to a
@@ -1785,7 +2033,7 @@ file.  By default, GiNaC uses a heuristic to automatically select an
 algorithm that is likely (but not guaranteed) to give the result most
 quickly.
 
 algorithm that is likely (but not guaranteed) to give the result most
 quickly.
 
-@cindex @code{inverse()}
+@cindex @code{inverse()} (matrix)
 @cindex @code{solve()}
 Matrices may also be inverted using the @code{ex matrix::inverse()}
 method and linear systems may be solved with:
 @cindex @code{solve()}
 Matrices may also be inverted using the @code{ex matrix::inverse()}
 method and linear systems may be solved with:
@@ -3115,7 +3363,7 @@ table:
 @multitable @columnfractions .30 .70
 @item @strong{Flag} @tab @strong{Returns true if the object is@dots{}}
 @item @code{numeric}
 @multitable @columnfractions .30 .70
 @item @strong{Flag} @tab @strong{Returns true if the object is@dots{}}
 @item @code{numeric}
-@tab @dots{}a number (same as @code{is_<numeric>(...)})
+@tab @dots{}a number (same as @code{is_a<numeric>(...)})
 @item @code{real}
 @tab @dots{}a real integer, rational or float (i.e. is not complex)
 @item @code{rational}
 @item @code{real}
 @tab @dots{}a real integer, rational or float (i.e. is not complex)
 @item @code{rational}
@@ -4395,7 +4643,7 @@ constants, functions and indexed objects as well:
 
 @example
 @{
 
 @example
 @{
-    symbol a("a"), b("b"), c("c");
+    symbol a("a"), b("b"), c("c"), x("x");
     idx i(symbol("i"), 3);
 
     ex e = pow(sin(x) - cos(x), 4);
     idx i(symbol("i"), 3);
 
     ex e = pow(sin(x) - cos(x), 4);
@@ -5002,9 +5250,9 @@ GiNaC contains the following predefined mathematical functions:
 @item @code{psi(n, x)}
 @tab derivatives of psi function (polygamma functions)
 @item @code{factorial(n)}
 @item @code{psi(n, x)}
 @tab derivatives of psi function (polygamma functions)
 @item @code{factorial(n)}
-@tab factorial function
+@tab factorial function @math{n!}
 @cindex @code{factorial()}
 @cindex @code{factorial()}
-@item @code{binomial(n, m)}
+@item @code{binomial(n, k)}
 @tab binomial coefficients
 @cindex @code{binomial()}
 @item @code{Order(x)}
 @tab binomial coefficients
 @cindex @code{binomial()}
 @item @code{Order(x)}