This is a tutorial that documents GiNaC @value{VERSION}, an open
framework for symbolic computation within the C++ programming language.
-Copyright (C) 1999-2004 Johannes Gutenberg University Mainz, Germany
+Copyright (C) 1999-2005 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-2004 Johannes Gutenberg University Mainz, Germany
+Copyright @copyright{} 1999-2005 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-2004 Johannes Gutenberg
+language is Copyright @copyright{} 1999-2005 Johannes Gutenberg
University Mainz, Germany.
This program is free software; you can redistribute it and/or
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
-MA 02111-1307, USA.
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+MA 02110-1301, USA.
@node A Tour of GiNaC, How to use it from within C++, Introduction, Top
Here we have made use of the @command{ginsh}-command @code{%} to pop the
previously evaluated element from @command{ginsh}'s internal stack.
+Often, functions don't have roots in closed form. Nevertheless, it's
+quite easy to compute a solution numerically, to arbitrary precision:
+
+@cindex fsolve
+@example
+> Digits=50:
+> fsolve(cos(x)-x,x,0,2);
+0.7390851332151606416553120876738734040134117589007574649658
+> f=exp(sin(x))-x:
+> X=fsolve(f,x,-10,10);
+2.2191071489137460325957851882042901681753665565320678854155
+> subs(f,x==X);
+-6.372367644529809108115521591070847222364418220770475144296E-58
+@end example
+
+Notice how the final result above differs slightly from zero by about
+@math{6*10^(-58)}. This is because with 50 decimal digits precision the
+root cannot be represented more accurately than @code{X}. Such
+inaccuracies are to be expected when computing with finite floating
+point values.
+
If you ever wanted to convert units in C or C++ and found this is
cumbersome, here is the solution. Symbolic types can always be used as
tags for different types of objects. Converting from wrong units to the
ex unit_matrix(unsigned x);
ex unit_matrix(unsigned r, unsigned c);
ex symbolic_matrix(unsigned r, unsigned c, const string & base_name);
-ex symbolic_matrix(unsigned r, unsigned c, const string & base_name, const string & tex_base_name);
+ex symbolic_matrix(unsigned r, unsigned c, const string & base_name,
+ const string & tex_base_name);
@end example
@code{diag_matrix()} constructs a diagonal matrix given the list of diagonal
method and linear systems may be solved with:
@example
-matrix matrix::solve(const matrix & vars, const matrix & rhs, unsigned algo=solve_algo::automatic) const;
+matrix matrix::solve(const matrix & vars, const matrix & rhs,
+ unsigned algo=solve_algo::automatic) const;
@end example
Assuming the matrix object this method is applied on is an @code{m}
@end itemize
-@strong{Note:} when printing expressions, covariant indices and indices
+@strong{Please notice:} when printing expressions, covariant indices and indices
without variance are denoted @samp{.i} while contravariant indices are
denoted @samp{~i}. Dotted indices have a @samp{*} in front of the index
value. In the following, we are going to use that notation in the text so
@}
@end example
+@cindex @code{expand_dummy_sum()}
+A dummy index summation like
+@tex
+$ a_i b^i$
+@end tex
+@ifnottex
+a.i b~i
+@end ifnottex
+can be expanded for indices with numeric
+dimensions (e.g. 3) into the explicit sum like
+@tex
+$a_1b^1+a_2b^2+a_3b^3 $.
+@end tex
+@ifnottex
+a.1 b~1 + a.2 b~2 + a.3 b~3.
+@end ifnottex
+This is performed by the function
+
+@example
+ ex expand_dummy_sum(const ex & e, bool subs_idx = false);
+@end example
+
+which takes an expression @code{e} and returns the expanded sum for all
+dummy indices with numeric dimensions. If the parameter @code{subs_idx}
+is set to @code{true} then all substitutions are made by @code{idx} class
+indices, i.e. without variance. In this case the above sum
+@tex
+$ a_i b^i$
+@end tex
+@ifnottex
+a.i b~i
+@end ifnottex
+will be expanded to
+@tex
+$a_1b_1+a_2b_2+a_3b_3 $.
+@end tex
+@ifnottex
+a.1 b.1 + a.2 b.2 + a.3 b.3.
+@end ifnottex
+
+
@cindex @code{simplify_indexed()}
@subsection Simplifying indexed expressions
k(symbol("k"), 3), l(symbol("l"), 3);
ex e = indexed(A, i, j) * indexed(B, k, l)
- * delta_tensor(i, k) * delta_tensor(j, l) << endl;
+ * delta_tensor(i, k) * delta_tensor(j, l);
cout << e.simplify_indexed() << endl;
// -> B.i.j*A.i.j
@example
ex epsilon_tensor(const ex & i1, const ex & i2);
ex epsilon_tensor(const ex & i1, const ex & i2, const ex & i3);
-ex lorentz_eps(const ex & i1, const ex & i2, const ex & i3, const ex & i4, bool pos_sig = false);
+ex lorentz_eps(const ex & i1, const ex & i2, const ex & i3, const ex & i4,
+ bool pos_sig = false);
@end example
The first two functions create an epsilon tensor in 2 or 3 Euclidean
ex dirac_ONE(unsigned char rl = 0);
@end example
-@strong{Note:} You must always use @code{dirac_ONE()} when referring to
+@strong{Please notice:} You must always use @code{dirac_ONE()} when referring to
multiples of the unity element, even though it's customary to omit it.
E.g. instead of @code{dirac_gamma(mu)*(dirac_slash(q,4)+m)} you have to
write @code{dirac_gamma(mu)*(dirac_slash(q,4)+m*dirac_ONE())}. Otherwise,
you use one of the functions
@example
-ex dirac_trace(const ex & e, const std::set<unsigned char> & rls, const ex & trONE = 4);
+ex dirac_trace(const ex & e, const std::set<unsigned char> & rls,
+ const ex & trONE = 4);
ex dirac_trace(const ex & e, const lst & rll, const ex & trONE = 4);
ex dirac_trace(const ex & e, unsigned char rl = 0, const ex & trONE = 4);
@end example
The @code{dirac_trace()} function is a linear functional that is equal to the
ordinary matrix trace only in @math{D = 4} dimensions. In particular, the
-functional is not cyclic in @math{D != 4} dimensions when acting on
+functional is not cyclic in
+@tex $D \ne 4$
+@end tex
+dimensions when acting on
expressions containing @samp{gamma5}, so it's not a proper trace. This
@samp{gamma5} scheme is described in greater detail in
@cite{The Role of gamma5 in Dimensional Regularization}.
The value of the trace itself is also usually different in 4 and in
-@math{D != 4} dimensions:
+@tex $D \ne 4$
+@end tex
+dimensions:
@example
@{
$2^n$
@end tex
dimensional algebra with
-generators @samp{e~k} satisfying the identities
-@samp{e~i e~j + e~j e~i = B(i, j)} for some matrix (@code{metric})
-@math{B(i, j)}, which may be non-symmetric. Such generators are created
-by the function
+generators
+@tex $e_k$
+@end tex
+satisfying the identities
+@tex
+$e_i e_j + e_j e_i = M(i, j) + M(j, i) $
+@end tex
+@ifnottex
+e~i e~j + e~j e~i = M(i, j) + M(j, i)
+@end ifnottex
+for some bilinear form (@code{metric})
+@math{M(i, j)}, which may be non-symmetric (see arXiv:math.QA/9911180)
+and contain symbolic entries. Such generators are created by the
+function
@example
- ex clifford_unit(const ex & mu, const ex & metr, unsigned char rl = 0);
+ ex clifford_unit(const ex & mu, const ex & metr, unsigned char rl = 0,
+ bool anticommuting = false);
@end example
where @code{mu} should be a @code{varidx} class object indexing the
-generators, @code{metr} defines the metric @math{B(i, j)} and can be
+generators, an index @code{mu} with a numeric value may be of type
+@code{idx} as well.
+Parameter @code{metr} defines the metric @math{M(i, j)} and can be
represented by a square @code{matrix}, @code{tensormetric} or @code{indexed} class
-object, optional parameter @code{rl} allows to distinguish different
-Clifford algebras (which will commute with each other). Note that the call
-@code{clifford_unit(mu, minkmetric())} creates something very close to
-@code{dirac_gamma(mu)}. The method @code{clifford::get_metric()} returns a
-metric defining this Clifford number.
-
-If the matrix @math{B(i, j)} is in fact symmetric you may prefer to create
+object. Optional parameter @code{rl} allows to distinguish different
+Clifford algebras, which will commute with each other. The last
+optional parameter @code{anticommuting} defines if the anticommuting
+assumption (i.e.
+@tex
+$e_i e_j + e_j e_i = 0$)
+@end tex
+@ifnottex
+e~i e~j + e~j e~i = 0)
+@end ifnottex
+will be used for contraction of Clifford units. If the @code{metric} is
+supplied by a @code{matrix} object, then the value of
+@code{anticommuting} is calculated automatically and the supplied one
+will be ignored. One can overcome this by giving @code{metric} through
+matrix wrapped into an @code{indexed} object.
+
+Note that the call @code{clifford_unit(mu, minkmetric())} creates
+something very close to @code{dirac_gamma(mu)}, although
+@code{dirac_gamma} have more efficient simplification mechanism.
+@cindex @code{clifford::get_metric()}
+The method @code{clifford::get_metric()} returns a metric defining this
+Clifford number.
+@cindex @code{clifford::is_anticommuting()}
+The method @code{clifford::is_anticommuting()} returns the
+@code{anticommuting} property of a unit.
+
+If the matrix @math{M(i, j)} is in fact symmetric you may prefer to create
the Clifford algebra units with a call like that
@example
- ex e = clifford_unit(mu, indexed(B, sy_symm(), i, j));
+ ex e = clifford_unit(mu, indexed(M, sy_symm(), i, j));
@end example
-since this may yield some further automatic simplifications.
+since this may yield some further automatic simplifications. Again, for a
+metric defined through a @code{matrix} such a symmetry is detected
+automatically.
Individual generators of a Clifford algebra can be accessed in several
ways. For example
@example
@{
...
- varidx nu(symbol("nu"), 3);
- matrix M(3, 3) = 1, 0, 0,
- 0,-1, 0,
- 0, 0, 0;
+ varidx nu(symbol("nu"), 4);
+ realsymbol s("s");
+ ex M = diag_matrix(lst(1, -1, 0, s));
ex e = clifford_unit(nu, M);
ex e0 = e.subs(nu == 0);
ex e1 = e.subs(nu == 1);
ex e2 = e.subs(nu == 2);
+ ex e3 = e.subs(nu == 3);
...
@}
@end example
-will produce three generators of a Clifford algebra with properties
-@code{pow(e0, 2) = 1}, @code{pow(e1, 2) = -1} and @code{pow(e2, 2) = 0}.
+will produce four anti-commuting generators of a Clifford algebra with properties
+@tex
+$e_0^2=1 $, $e_1^2=-1$, $e_2^2=0$ and $e_3^2=s$.
+@end tex
+@ifnottex
+@code{pow(e0, 2) = 1}, @code{pow(e1, 2) = -1}, @code{pow(e2, 2) = 0} and
+@code{pow(e3, 2) = s}.
+@end ifnottex
@cindex @code{lst_to_clifford()}
A similar effect can be achieved from the function
@example
ex lst_to_clifford(const ex & v, const ex & mu, const ex & metr,
- unsigned char rl = 0);
+ unsigned char rl = 0, bool anticommuting = false);
+ ex lst_to_clifford(const ex & v, const ex & e);
@end example
-which converts a list or vector @samp{v = (v~0, v~1, ..., v~n)} into
-the Clifford number @samp{v~0 e.0 + v~1 e.1 + ... + v~n e.n} with @samp{e.k}
-being created by @code{clifford_unit(mu, metr, rl)}. The previous code
-may be rewritten with the help of @code{lst_to_clifford()} as follows
+which converts a list or vector
+@tex
+$v = (v^0, v^1, ..., v^n)$
+@end tex
+@ifnottex
+@samp{v = (v~0, v~1, ..., v~n)}
+@end ifnottex
+into the
+Clifford number
+@tex
+$v^0 e_0 + v^1 e_1 + ... + v^n e_n$
+@end tex
+@ifnottex
+@samp{v~0 e.0 + v~1 e.1 + ... + v~n e.n}
+@end ifnottex
+with @samp{e.k}
+directly supplied in the second form of the procedure. In the first form
+the Clifford unit @samp{e.k} is generated by the call of
+@code{clifford_unit(mu, metr, rl, anticommuting)}. The previous code may be rewritten
+with the help of @code{lst_to_clifford()} as follows
@example
@{
...
- varidx nu(symbol("nu"), 3);
- matrix M(3, 3) = 1, 0, 0,
- 0,-1, 0,
- 0, 0, 0;
- ex e0 = lst_to_clifford(lst(1, 0, 0), nu, M);
- ex e1 = lst_to_clifford(lst(0, 1, 0), nu, M);
- ex e2 = lst_to_clifford(lst(0, 0, 1), nu, M);
+ varidx nu(symbol("nu"), 4);
+ realsymbol s("s");
+ ex M = diag_matrix(lst(1, -1, 0, s));
+ ex e0 = lst_to_clifford(lst(1, 0, 0, 0), nu, M);
+ ex e1 = lst_to_clifford(lst(0, 1, 0, 0), nu, M);
+ ex e2 = lst_to_clifford(lst(0, 0, 1, 0), nu, M);
+ ex e3 = lst_to_clifford(lst(0, 0, 0, 1), nu, M);
...
@}
@end example
@end example
which takes an expression @code{e} and tries to find a list
-@samp{v = (v~0, v~1, ..., v~n)} such that @samp{e = v~0 c.0 + v~1 c.1 + ...
-+ v~n c.n} with respect to the given Clifford units @code{c} and none of
-@samp{v~k} contains the Clifford units @code{c} (of course, this
+@tex
+$v = (v^0, v^1, ..., v^n)$
+@end tex
+@ifnottex
+@samp{v = (v~0, v~1, ..., v~n)}
+@end ifnottex
+such that
+@tex
+$e = v^0 c_0 + v^1 c_1 + ... + v^n c_n$
+@end tex
+@ifnottex
+@samp{e = v~0 c.0 + v~1 c.1 + ... + v~n c.n}
+@end ifnottex
+with respect to the given Clifford units @code{c} and with none of the
+@samp{v~k} containing Clifford units @code{c} (of course, this
may be impossible). This function can use an @code{algebraic} method
-(default) or a symbolic one. With the @code{algebraic} method @samp{v~k} are calculated as
-@samp{(e c.k + c.k e)/pow(c.k, 2)}. If @samp{pow(c.k, 2) = 0} for some @samp{k}
+(default) or a symbolic one. With the @code{algebraic} method the @samp{v~k} are calculated as
+@tex
+$(e c_k + c_k e)/c_k^2$. If $c_k^2$
+@end tex
+@ifnottex
+@samp{(e c.k + c.k e)/pow(c.k, 2)}. If @samp{pow(c.k, 2)}
+@end ifnottex
+is zero or is not @code{numeric} for some @samp{k}
then the method will be automatically changed to symbolic. The same effect
is obtained by the assignment (@code{algebraic = false}) in the procedure call.
@tex
$e^*$
@end tex
+@ifnottex
+e*
+@end ifnottex
and
@tex
$\overline{e}$
@end tex
+@ifnottex
+@code{\bar@{e@}}
+@end ifnottex
used in Clifford algebra textbooks.
@cindex @code{clifford_norm()}
@cindex @code{clifford_inverse()}
calculates the norm of a Clifford number from the expression
@tex
-$||e||^2 = e\overline{e}$
+$||e||^2 = e\overline{e}$.
@end tex
-. The inverse of a Clifford expression is returned
-by the function
+@ifnottex
+@code{||e||^2 = e \bar@{e@}}
+@end ifnottex
+ The inverse of a Clifford expression is returned by the function
@example
ex clifford_inverse(const ex & e);
which calculates it as
@tex
-$e^{-1} = e/||e||^2$
+$e^{-1} = \overline{e}/||e||^2$.
@end tex
-. If
+@ifnottex
+@math{e^@{-1@} = \bar@{e@}/||e||^2}
+@end ifnottex
+ If
@tex
$||e|| = 0$
@end tex
+@ifnottex
+@math{||e||=0}
+@end ifnottex
then an exception is raised.
@cindex @code{remove_dirac_ONE()}
The function @code{canonicalize_clifford()} works for a
generic Clifford algebra in a similar way as for Dirac gammas.
-The last provided function is
+The next provided function is
@cindex @code{clifford_moebius_map()}
@example
ex clifford_moebius_map(const ex & a, const ex & b, const ex & c,
- const ex & d, const ex & v, const ex & G, unsigned char rl = 0);
- ex clifford_moebius_map(const ex & M, const ex & v, const ex & G, unsigned char rl = 0);
+ const ex & d, const ex & v, const ex & G,
+ unsigned char rl = 0, bool anticommuting = false);
+ ex clifford_moebius_map(const ex & M, const ex & v, const ex & G,
+ unsigned char rl = 0, bool anticommuting = false);
@end example
-It takes a list or vector @code{v} and makes the Moebius
-(conformal or linear-fractional) transformation @samp{v ->
-(av+b)/(cv+d)} defined by the matrix @samp{M = [[a, b], [c, d]]}. The
-parameter @code{G} defines the metric of the surrounding
-(pseudo-)Euclidean space. The returned value of this function is a list
-of components of the resulting vector.
+It takes a list or vector @code{v} and makes the Moebius (conformal or
+linear-fractional) transformation @samp{v -> (av+b)/(cv+d)} defined by
+the matrix @samp{M = [[a, b], [c, d]]}. The parameter @code{G} defines
+the metric of the surrounding (pseudo-)Euclidean space. This can be an
+indexed object, tensormetric, matrix or a Clifford unit, in the later
+case the optional parameters @code{rl} and @code{anticommuting} are ignored
+even if supplied. The returned value of this function is a list of
+components of the resulting vector.
+
+@cindex @code{clifford_max_label()}
+Finally the function
+@example
+char clifford_max_label(const ex & e, bool ignore_ONE = false);
+@end example
+
+can detect a presence of Clifford objects in the expression @code{e}: if
+such objects are found it returns the maximal
+@code{representation_label} of them, otherwise @code{-1}. The optional
+parameter @code{ignore_ONE} indicates if @code{dirac_ONE} objects should
+be ignored during the search.
+
+LaTeX output for Clifford units looks like
+@code{\clifford[1]@{e@}^@{@{\nu@}@}}, where @code{1} is the
+@code{representation_label} and @code{\nu} is the index of the
+corresponding unit. This provides a flexible typesetting with a suitable
+defintion of the @code{\clifford} command. For example, the definition
+@example
+ \newcommand@{\clifford@}[1][]@{@}
+@end example
+typesets all Clifford units identically, while the alternative definition
+@example
+ \newcommand@{\clifford@}[2][]@{\ifcase #1 #2\or \tilde@{#2@} \or \breve@{#2@} \fi@}
+@end example
+prints units with @code{representation_label=0} as
+@tex
+$e$,
+@end tex
+@ifnottex
+@code{e},
+@end ifnottex
+with @code{representation_label=1} as
+@tex
+$\tilde{e}$
+@end tex
+@ifnottex
+@code{\tilde@{e@}}
+@end ifnottex
+ and with @code{representation_label=2} as
+@tex
+$\breve{e}$.
+@end tex
+@ifnottex
+@code{\breve@{e@}}.
+@end ifnottex
@cindex @code{color} (class)
@subsection Color algebra
ex color_ONE(unsigned char rl = 0);
@end example
-@strong{Note:} You must always use @code{color_ONE()} when referring to
+@strong{Please notice:} You must always use @code{color_ONE()} when referring to
multiples of the unity element, even though it's customary to omit it.
E.g. instead of @code{color_T(a)*(color_T(b)*indexed(X,b)+1)} you have to
write @code{color_T(a)*(color_T(b)*indexed(X,b)+color_ONE())}. Otherwise,
@math{f_abc} which satisfy @math{@{T_a, T_b@} = 1/3 delta_ab + d_abc T_c}
and @math{[T_a, T_b] = i f_abc T_c}.
+These functions evaluate to their numerical values,
+if you supply numeric indices to them. The index values should be in
+the range from 1 to 8, not from 0 to 7. This departure from usual conventions
+goes along better with the notations used in physical literature.
+
@cindex @code{color_h()}
There's an additional function
@example
> a=expand((sin(x)+sin(y))*(1+p+q)*(1+d));
-d*p*sin(x)+p*sin(x)+q*d*sin(x)+q*sin(y)+d*sin(x)+q*d*sin(y)+sin(y)+d*sin(y)+q*sin(x)+d*sin(y)*p+sin(x)+sin(y)*p
+d*p*sin(x)+p*sin(x)+q*d*sin(x)+q*sin(y)+d*sin(x)+q*d*sin(y)+sin(y)+d*sin(y)
++q*sin(x)+d*sin(y)*p+sin(x)+sin(y)*p
> collect(a,@{p,q@});
-d*sin(x)+(d*sin(x)+sin(y)+d*sin(y)+sin(x))*p+(d*sin(x)+sin(y)+d*sin(y)+sin(x))*q+sin(y)+d*sin(y)+sin(x)
+d*sin(x)+(d*sin(x)+sin(y)+d*sin(y)+sin(x))*p
++(d*sin(x)+sin(y)+d*sin(y)+sin(x))*q+sin(y)+d*sin(y)+sin(x)
> collect(a,find(a,sin($1)));
(1+q+d+q*d+d*p+p)*sin(y)+(1+q+d+q*d+d*p+p)*sin(x)
> collect(a,@{find(a,sin($1)),p,q@});
@code{a} and @code{b} as arguments and return a new expression, their
greatest common divisor or least common multiple, respectively. If the
polynomials @code{a} and @code{b} are coprime @code{gcd(a,b)} returns 1
-and @code{lcm(a,b)} returns the product of @code{a} and @code{b}.
+and @code{lcm(a,b)} returns the product of @code{a} and @code{b}. Note that all
+the coefficients must be rationals.
@example
#include <ginac/ginac.h>
needs to be solved:
@example
-ex lsolve(const ex &eqns, const ex &symbols, unsigned options=solve_algo::automatic);
+ex lsolve(const ex & eqns, const ex & symbols,
+ unsigned options = solve_algo::automatic);
@end example
Here, @code{eqns} is a @code{lst} of equalities (i.e. class
@example
// ...
- cout << latex; // all output to cout will be in LaTeX format from now on
+ cout << latex; // all output to cout will be in LaTeX format from
+ // now on
cout << e << endl; // prints '4.5 i+\frac@{3@}@{2@} x^@{2@}'
cout << sin(x/2) << endl; // prints '\sin(\frac@{1@}@{2@} x)'
cout << dflt; // revert to default output format
will print
@example
- @{(-\ln(\circ))@}+@{(-\gamma_E)@} \circ+@{(\frac@{1@}@{12@} \pi^@{2@})@} \circ^@{2@}+\mathcal@{O@}(\circ^@{3@})
+ @{(-\ln(\circ))@}+@{(-\gamma_E)@} \circ+@{(\frac@{1@}@{12@} \pi^@{2@})@} \circ^@{2@}
+ +\mathcal@{O@}(\circ^@{3@})
@end example
@cindex @code{index_dimensions}
// our own one
set_print_func<power, print_latex>(my_print_power_as_latex);
- // this prints "-1+@{@{(y+x)@}@}\uparrow@{2@}-3 \frac@{@{x@}\uparrow@{3@}@}@{@{y@}\uparrow@{2@}@}"
+ // this prints "-1+@{@{(y+x)@}@}\uparrow@{2@}-3 \frac@{@{x@}\uparrow@{3@}@}@{@{y@}
+ // \uparrow@{2@}@}"
cout << e << endl;
@}
@end example
inline bool operator<(const sprod_s & lhs, const sprod_s & rhs)
@{
- return lhs.left.compare(rhs.left) < 0 ? true : lhs.right.compare(rhs.right) < 0;
+ return lhs.left.compare(rhs.left) < 0
+ ? true : lhs.right.compare(rhs.right) < 0;
@}
@end example
by GiNaC to establish a canonical sort order for terms. It returns 0, +1 or
-1, depending on the relative order of this object and the @code{other}
object. If it returns 0, the objects are considered equal.
-@strong{Note:} This has nothing to do with the (numeric) ordering
+@strong{Please notice:} This has nothing to do with the (numeric) ordering
relationship expressed by @code{<}, @code{>=} etc (which cannot be defined
for non-numeric classes). For example, @code{numeric(1).compare_same_type(numeric(2))}
may return +1 even though 1 is clearly smaller than 2. Every GiNaC class
a macro to automate the process of checking for GiNaC.
@example
-AM_PATH_GINAC([@var{MINIMUM-VERSION}, [@var{ACTION-IF-FOUND} [, @var{ACTION-IF-NOT-FOUND}]]])
+AM_PATH_GINAC([@var{MINIMUM-VERSION}, [@var{ACTION-IF-FOUND}
+ [, @var{ACTION-IF-NOT-FOUND}]]])
@end example
This macro: