Added methods for taking real and imaginary parts.
authorChris Dams <Chris.Dams@mi.infn.it>
Fri, 21 Apr 2006 16:16:01 +0000 (16:16 +0000)
committerChris Dams <Chris.Dams@mi.infn.it>
Fri, 21 Apr 2006 16:16:01 +0000 (16:16 +0000)
31 files changed:
doc/tutorial/ginac.texi
ginac/add.cpp
ginac/add.h
ginac/basic.cpp
ginac/basic.h
ginac/constant.cpp
ginac/constant.h
ginac/container.h
ginac/ex.h
ginac/function.pl
ginac/indexed.cpp
ginac/indexed.h
ginac/inifcns.cpp
ginac/inifcns.h
ginac/inifcns_trans.cpp
ginac/matrix.cpp
ginac/matrix.h
ginac/mul.cpp
ginac/mul.h
ginac/ncmul.cpp
ginac/ncmul.h
ginac/numeric.cpp
ginac/numeric.h
ginac/power.cpp
ginac/power.h
ginac/pseries.cpp
ginac/pseries.h
ginac/symbol.cpp
ginac/symbol.h
ginac/tensor.cpp
ginac/tensor.h

index a6f802b..08fee76 100644 (file)
@@ -79,20 +79,20 @@ framework for symbolic computation within the C++ programming language.
 
 @menu
 * Introduction::                 GiNaC's purpose.
-* A Tour of GiNaC::              A quick tour of the library.
+* A tour of GiNaC::              A quick tour of the library.
 * Installation::                 How to install the package.
-* Basic Concepts::               Description of fundamental classes.
-* Methods and Functions::        Algorithms for symbolic manipulations.
+* Basic concepts::               Description of fundamental classes.
+* Methods and functions::        Algorithms for symbolic manipulations.
 * Extending GiNaC::              How to extend the library.
-* A Comparison With Other CAS::  Compares GiNaC to traditional CAS.
-* Internal Structures::          Description of some internal structures.
-* Package Tools::                Configuring packages to work with GiNaC.
+* A comparison with other CAS::  Compares GiNaC to traditional CAS.
+* Internal structures::          Description of some internal structures.
+* Package tools::                Configuring packages to work with GiNaC.
 * Bibliography::
-* Concept Index::
+* Concept index::
 @end menu
 
 
-@node Introduction, A Tour of GiNaC, Top, Top
+@node Introduction, A tour of GiNaC, Top, Top
 @c    node-name, next, previous, up
 @chapter Introduction
 @cindex history of GiNaC
@@ -154,7 +154,7 @@ 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
+@node A tour of GiNaC, How to use it from within C++, Introduction, Top
 @c    node-name, next, previous, up
 @chapter A Tour of GiNaC
 
@@ -168,7 +168,7 @@ leaves many open questions.
 @end menu
 
 
-@node How to use it from within C++, What it can do for you, A Tour of GiNaC, A Tour of GiNaC
+@node How to use it from within C++, What it can do for you, A tour of GiNaC, A tour of GiNaC
 @c    node-name, next, previous, up
 @section How to use it from within C++
 
@@ -206,7 +206,7 @@ $ ./hello
 355687428096000*x*y+20922789888000*y^2+6402373705728000*x^2
 @end example
 
-(@xref{Package Tools}, for tools that help you when creating a software
+(@xref{Package tools}, for tools that help you when creating a software
 package that uses GiNaC.)
 
 @cindex Hermite polynomial
@@ -256,7 +256,7 @@ the @command{ginsh}, a simple GiNaC interactive shell that provides a
 convenient window into GiNaC's capabilities.
 
 
-@node What it can do for you, Installation, How to use it from within C++, A Tour of GiNaC
+@node What it can do for you, Installation, How to use it from within C++, A tour of GiNaC
 @c    node-name, next, previous, up
 @section What it can do for you
 
@@ -638,7 +638,7 @@ subdirectories.  It is therefore safe to go into any subdirectory
 @var{target} there in case something went wrong.
 
 
-@node Installing GiNaC, Basic Concepts, Building GiNaC, Installation
+@node Installing GiNaC, Basic concepts, Building GiNaC, Installation
 @c    node-name, next, previous, up
 @section Installing GiNaC
 @cindex installation
@@ -691,9 +691,9 @@ do it by hand since you now know where all the files went during
 installation.}.
 
 
-@node Basic Concepts, Expressions, Installing GiNaC, Top
+@node Basic concepts, Expressions, Installing GiNaC, Top
 @c    node-name, next, previous, up
-@chapter Basic Concepts
+@chapter Basic concepts
 
 This chapter will describe the different fundamental objects that can be
 handled by GiNaC.  But before doing so, it is worthwhile introducing you
@@ -704,7 +704,7 @@ meta-class for storing all mathematical objects.
 * Expressions::                  The fundamental GiNaC class.
 * Automatic evaluation::         Evaluation and canonicalization.
 * Error handling::               How the library reports errors.
-* The Class Hierarchy::          Overview of GiNaC's classes.
+* The class hierarchy::          Overview of GiNaC's classes.
 * Symbols::                      Symbolic objects.
 * Numbers::                      Numerical objects.
 * Constants::                    Pre-defined constants.
@@ -716,11 +716,11 @@ meta-class for storing all mathematical objects.
 * Matrices::                     Matrices.
 * Indexed objects::              Handling indexed quantities.
 * Non-commutative objects::      Algebras with non-commutative products.
-* Hash Maps::                    A faster alternative to std::map<>.
+* Hash maps::                    A faster alternative to std::map<>.
 @end menu
 
 
-@node Expressions, Automatic evaluation, Basic Concepts, Basic Concepts
+@node Expressions, Automatic evaluation, Basic concepts, Basic concepts
 @c    node-name, next, previous, up
 @section Expressions
 @cindex expression (class @code{ex})
@@ -742,7 +742,7 @@ ex MyEx5 = MyEx4 + 1;               // similar to above
 
 Expressions are handles to other more fundamental objects, that often
 contain other expressions thus creating a tree of expressions
-(@xref{Internal Structures}, for particular examples).  Most methods on
+(@xref{Internal structures}, for particular examples).  Most methods on
 @code{ex} therefore run top-down through such an expression tree.  For
 example, the method @code{has()} scans recursively for occurrences of
 something inside an expression.  Thus, if you have declared @code{MyEx4}
@@ -769,11 +769,11 @@ 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
+@xref{Information about expressions}, for more about comparing and ordering
 expressions.
 
 
-@node Automatic evaluation, Error handling, Expressions, Basic Concepts
+@node Automatic evaluation, Error handling, Expressions, Basic concepts
 @c    node-name, next, previous, up
 @section Automatic evaluation and canonicalization of expressions
 @cindex evaluation
@@ -847,7 +847,7 @@ transform expressions, like @code{subs()} or @code{normal()}, automatically
 re-evaluate their results.
 
 
-@node Error handling, The Class Hierarchy, Automatic evaluation, Basic Concepts
+@node Error handling, The class hierarchy, Automatic evaluation, Basic concepts
 @c    node-name, next, previous, up
 @section Error handling
 @cindex exceptions
@@ -903,7 +903,7 @@ int main()
 @end example
 
 
-@node The Class Hierarchy, Symbols, Error handling, Basic Concepts
+@node The class hierarchy, Symbols, Error handling, Basic concepts
 @c    node-name, next, previous, up
 @section The class hierarchy
 
@@ -929,7 +929,7 @@ features.  An example is @code{expairseq}, a container for a sequence of
 pairs each consisting of one expression and a number (@code{numeric}).
 What @emph{is} visible to the user are the derived classes @code{add}
 and @code{mul}, representing sums and products.  @xref{Internal
-Structures}, where these two classes are described in more detail.  The
+structures}, where these two classes are described in more detail.  The
 following table shortly summarizes what kinds of mathematical objects
 are stored in the different classes:
 
@@ -977,7 +977,7 @@ $\sin 2x$
 @end cartouche
 
 
-@node Symbols, Numbers, The Class Hierarchy, Basic Concepts
+@node Symbols, Numbers, The class hierarchy, Basic concepts
 @c    node-name, next, previous, up
 @section Symbols
 @cindex @code{symbol} (class)
@@ -1128,7 +1128,7 @@ 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}).
+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:
@@ -1137,7 +1137,7 @@ 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
+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.).
@@ -1147,12 +1147,12 @@ 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}).
+(@pxref{Substituting expressions}).
 
 @cindex @code{realsymbol()}
 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,
-for example (@pxref{Complex Conjugation}), do @emph{not} evaluate if applied
+for example (@pxref{Complex expressions}), 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
@@ -1161,7 +1161,7 @@ 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.
 
 
-@node Numbers, Constants, Symbols, Basic Concepts
+@node Numbers, Constants, Symbols, Basic concepts
 @c    node-name, next, previous, up
 @section Numbers
 @cindex @code{numeric} (class)
@@ -1511,7 +1511,7 @@ rational number will return a floating-point approximation. Both
 part of complex numbers.
 
 
-@node Constants, Fundamental containers, Numbers, Basic Concepts
+@node Constants, Fundamental containers, Numbers, Basic concepts
 @c    node-name, next, previous, up
 @section Constants
 @cindex @code{constant} (class)
@@ -1541,7 +1541,7 @@ The predefined known constants are:
 @end cartouche
 
 
-@node Fundamental containers, Lists, Constants, Basic Concepts
+@node Fundamental containers, Lists, Constants, Basic concepts
 @c    node-name, next, previous, up
 @section Sums, products and powers
 @cindex polynomial
@@ -1612,7 +1612,7 @@ and safe simplifications are carried out like transforming
 @code{3*x+4-x} to @code{2*x+4}.
 
 
-@node Lists, Mathematical functions, Fundamental containers, Basic Concepts
+@node Lists, Mathematical functions, Fundamental containers, Basic concepts
 @c    node-name, next, previous, up
 @section Lists of expressions
 @cindex @code{lst} (class)
@@ -1777,7 +1777,7 @@ elements with @code{unique()}:
 @end example
 
 
-@node Mathematical functions, Relations, Lists, Basic Concepts
+@node Mathematical functions, Relations, Lists, Basic concepts
 @c    node-name, next, previous, up
 @section Mathematical functions
 @cindex @code{function} (class)
@@ -1786,7 +1786,7 @@ elements with @code{unique()}:
 
 There are quite a number of useful functions hard-wired into GiNaC.  For
 instance, all trigonometric and hyperbolic functions are implemented
-(@xref{Built-in Functions}, for a complete list).
+(@xref{Built-in functions}, for a complete list).
 
 These functions (better called @emph{pseudofunctions}) are all objects
 of class @code{function}.  They accept one or more expressions as
@@ -1829,7 +1829,7 @@ point number of class @code{numeric} you should call
 wrapped inside an @code{ex}.
 
 
-@node Relations, Integrals, Mathematical functions, Basic Concepts
+@node Relations, Integrals, Mathematical functions, Basic concepts
 @c    node-name, next, previous, up
 @section Relations
 @cindex @code{relational} (class)
@@ -1855,7 +1855,7 @@ conversion from @code{relational} to @code{bool} takes place.  Note,
 however, that @code{==} here does not perform any simplifications, hence
 @code{expand()} must be called explicitly.
 
-@node Integrals, Matrices, Relations, Basic Concepts
+@node Integrals, Matrices, Relations, Basic concepts
 @c    node-name, next, previous, up
 @section Integrals
 @cindex @code{integral} (class)
@@ -1916,7 +1916,7 @@ respectively calling @code{.op(0)}, @code{.op(1)}, @code{.op(2)}, and
 as expected. Note that it makes no sense to differentiate an integral
 with respect to the integration variable.
 
-@node Matrices, Indexed objects, Integrals, Basic Concepts
+@node Matrices, Indexed objects, Integrals, Basic concepts
 @c    node-name, next, previous, up
 @section Matrices
 @cindex @code{matrix} (class)
@@ -2180,7 +2180,7 @@ contain some of the indeterminates from @code{vars}.  If the system is
 overdetermined, an exception is thrown.
 
 
-@node Indexed objects, Non-commutative objects, Matrices, Basic Concepts
+@node Indexed objects, Non-commutative objects, Matrices, Basic concepts
 @c    node-name, next, previous, up
 @section Indexed objects
 
@@ -2329,7 +2329,7 @@ bool idx::is_dim_symbolic();
 
 for checking whether the value and dimension are numeric or symbolic
 (non-numeric). Using the @code{info()} method of an index (see @ref{Information
-About Expressions}) returns information about the index value.
+about expressions}) returns information about the index value.
 
 @cindex @code{varidx} (class)
 If you need co- and contravariant indices, use the @code{varidx} class:
@@ -2420,7 +2420,7 @@ and the same or opposite variance.
 Sometimes you will want to substitute one symbolic index with another
 symbolic or numeric index, for example when calculating one specific element
 of a tensor expression. This is done with the @code{.subs()} method, as it
-is done for symbols (see @ref{Substituting Expressions}).
+is done for symbols (see @ref{Substituting expressions}).
 
 You have two possibilities here. You can either substitute the whole index
 by another index or expression:
@@ -2956,7 +2956,7 @@ one form for @samp{F} and explicitly multiply it with a matrix representation
 of the metric tensor.
 
 
-@node Non-commutative objects, Hash Maps, Indexed objects, Basic Concepts
+@node Non-commutative objects, Hash maps, Indexed objects, Basic concepts
 @c    node-name, next, previous, up
 @section Non-commutative objects
 
@@ -3717,7 +3717,7 @@ example:
 @end example
 
 
-@node Hash Maps, Methods and Functions, Non-commutative objects, Basic Concepts
+@node Hash maps, Methods and functions, Non-commutative objects, Basic concepts
 @c    node-name, next, previous, up
 @section Hash Maps
 @cindex hash maps
@@ -3753,9 +3753,9 @@ table
 @end itemize
 
 
-@node Methods and Functions, Information About Expressions, Hash Maps, Top
+@node Methods and functions, Information about expressions, Hash maps, Top
 @c    node-name, next, previous, up
-@chapter Methods and Functions
+@chapter Methods and functions
 @cindex polynomial
 
 In this chapter the most important algorithms provided by GiNaC will be
@@ -3794,26 +3794,26 @@ method on class @code{ex} and sometimes calling a function cannot be
 avoided.
 
 @menu
-* Information About Expressions::
-* Numerical Evaluation::
-* Substituting Expressions::
-* Pattern Matching and Advanced Substitutions::
-* Applying a Function on Subexpressions::
-* Visitors and Tree Traversal::
-* Polynomial Arithmetic::           Working with polynomials.
-* Rational Expressions::            Working with rational functions.
-* Symbolic Differentiation::
-* Series Expansion::                Taylor and Laurent expansion.
+* Information about expressions::
+* Numerical evaluation::
+* Substituting expressions::
+* Pattern matching and advanced substitutions::
+* Applying a function on subexpressions::
+* Visitors and tree traversal::
+* Polynomial arithmetic::           Working with polynomials.
+* Rational expressions::            Working with rational functions.
+* Symbolic differentiation::
+* Series expansion::                Taylor and Laurent expansion.
 * Symmetrization::
-* Built-in Functions::              List of predefined mathematical functions.
+* Built-in functions::              List of predefined mathematical functions.
 * Multiple polylogarithms::
-* Complex Conjugation::
-* Solving Linear Systems of Equations::
-* Input/Output::                    Input and output of expressions.
+* Complex expressions::
+* Solving linear systems of equations::
+* Input/output::                    Input and output of expressions.
 @end menu
 
 
-@node Information About Expressions, Numerical Evaluation, 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
 
@@ -3840,7 +3840,7 @@ unsigned ex::return_type_tinfo() const;
 
 When the test made by @code{is_a<T>()} returns true, it is safe to call
 one of the functions @code{ex_to<T>()}, where @code{T} is one of the
-class names (@xref{The Class Hierarchy}, for a list of all classes). For
+class names (@xref{The class hierarchy}, for a list of all classes). For
 example, assuming @code{e} is an @code{ex}:
 
 @example
@@ -3854,7 +3854,7 @@ example, assuming @code{e} is an @code{ex}:
 
 @code{is_a<T>(e)} allows you to check whether the top-level object of
 an expression @samp{e} is an instance of the GiNaC class @samp{T}
-(@xref{The Class Hierarchy}, for a list of all classes). This is most useful,
+(@xref{The class hierarchy}, for a list of all classes). This is most useful,
 e.g., for checking whether an expression is a number, a sum, or a product:
 
 @example
@@ -4170,7 +4170,7 @@ if @code{*this} sorts before @code{other}, and @math{1} if @code{*this} sorts
 after @code{other}.
 
 
-@node Numerical Evaluation, Substituting Expressions, Information About Expressions, Methods and Functions
+@node Numerical evaluation, Substituting expressions, Information about expressions, Methods and functions
 @c    node-name, next, previous, up
 @section Numerical evaluation
 @cindex @code{evalf()}
@@ -4210,7 +4210,7 @@ call @code{evalf()} followed by @code{numeric::to_double()}, like this:
 @end example
 
 
-@node Substituting Expressions, Pattern Matching and Advanced Substitutions, Numerical Evaluation, Methods and Functions
+@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()}
@@ -4283,7 +4283,7 @@ The optional last argument to @code{subs()} is a combination of
 large @code{subs()} operations significantly faster if you are not using
 patterns. The second option, @code{subs_options::algebraic} enables
 algebraic substitutions in products and powers.
-@ref{Pattern Matching and Advanced Substitutions}, for more information
+@ref{Pattern matching and advanced substitutions}, for more information
 about patterns and algebraic substitutions. The third option,
 @code{subs_options::no_index_renaming} disables the feature that dummy
 indices are renamed if the subsitution could give a result in which a
@@ -4317,7 +4317,7 @@ A more powerful form of substitution using wildcards is described in the
 next section.
 
 
-@node Pattern Matching and Advanced Substitutions, Applying a Function on Subexpressions, Substituting Expressions, Methods and Functions
+@node Pattern matching and advanced substitutions, Applying a function on subexpressions, Substituting expressions, Methods and functions
 @c    node-name, next, previous, up
 @section Pattern matching and advanced substitutions
 @cindex @code{wildcard} (class)
@@ -4610,7 +4610,7 @@ return @code{x^(-1)*c^2*z}. Note that this only works for multiplications
 and not for locating @code{x+y} within @code{x+y+z}.
 
 
-@node Applying a Function on Subexpressions, Visitors and Tree Traversal, Pattern Matching and Advanced Substitutions, Methods and Functions
+@node Applying a function on subexpressions, Visitors and tree traversal, Pattern matching and advanced substitutions, Methods and functions
 @c    node-name, next, previous, up
 @section Applying a function on subexpressions
 @cindex tree traversal
@@ -4755,7 +4755,7 @@ argument. You can not use functions like @samp{diff()}, @samp{op()},
 @end example
 
 
-@node Visitors and Tree Traversal, Polynomial Arithmetic, Applying a Function on Subexpressions, Methods and Functions
+@node Visitors and tree traversal, Polynomial arithmetic, Applying a function on subexpressions, Methods and functions
 @c    node-name, next, previous, up
 @section Visitors and tree traversal
 @cindex tree traversal
@@ -4977,7 +4977,7 @@ lst gather_indices(const ex & e)
 @end example
 
 
-@node Polynomial Arithmetic, Rational Expressions, Visitors and Tree Traversal, Methods and Functions
+@node Polynomial arithmetic, Rational expressions, Visitors and tree traversal, Methods and functions
 @c    node-name, next, previous, up
 @section Polynomial arithmetic
 
@@ -5351,7 +5351,7 @@ 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
+@node Rational expressions, Symbolic differentiation, Polynomial arithmetic, Methods and functions
 @c    node-name, next, previous, up
 @section Rational expressions
 
@@ -5477,7 +5477,7 @@ The following more useful example will print @samp{sin(x)-cos(x)}:
 @end example
 
 
-@node Symbolic Differentiation, Series Expansion, Rational Expressions, Methods and Functions
+@node Symbolic differentiation, Series expansion, Rational expressions, Methods and functions
 @c    node-name, next, previous, up
 @section Symbolic differentiation
 @cindex differentiation
@@ -5543,7 +5543,7 @@ When you run it, it produces the sequence @code{1}, @code{-1}, @code{5},
 @code{i} by two since all odd Euler numbers vanish anyways.
 
 
-@node Series Expansion, Symmetrization, Symbolic Differentiation, Methods and Functions
+@node Series expansion, Symmetrization, Symbolic differentiation, Methods and functions
 @c    node-name, next, previous, up
 @section Series expansion
 @cindex @code{series()}
@@ -5656,7 +5656,7 @@ program, it will type out:
 @end example
 
 
-@node Symmetrization, Built-in Functions, Series Expansion, Methods and Functions
+@node Symmetrization, Built-in functions, Series expansion, Methods and functions
 @c    node-name, next, previous, up
 @section Symmetrization
 @cindex @code{symmetrize()}
@@ -5702,7 +5702,7 @@ almost any kind of object (anything that is @code{subs()}able):
 @}
 @end example
 
-@node Built-in Functions, Multiple polylogarithms, Symmetrization, Methods and Functions
+@node Built-in functions, Multiple polylogarithms, Symmetrization, Methods and functions
 @c    node-name, next, previous, up
 @section Predefined mathematical functions
 @c
@@ -5724,7 +5724,12 @@ GiNaC contains the following predefined mathematical functions:
 @cindex @code{conjugate()}
 @item @code{conjugate(x)}
 @tab complex conjugation
-@cindex @code{conjugate()}
+@cindex @code{real_part()}
+@item @code{real_part(x)}
+@tab real part
+@cindex @code{imag_part()}
+@item @code{imag_part(x)}
+@tab imaginary part
 @item @code{sqrt(x)}
 @tab square root (not a GiNaC function, rather an alias for @code{pow(x, numeric(1, 2))})
 @cindex @code{sqrt()}
@@ -5841,7 +5846,7 @@ serious CAS.  It is to be expected that future revisions of the C++
 standard incorporate these functions in the complex domain in a manner
 compatible with C99.
 
-@node Multiple polylogarithms, Complex Conjugation, Built-in Functions, Methods and Functions
+@node Multiple polylogarithms, Complex expressions, Built-in functions, Methods and functions
 @c    node-name, next, previous, up
 @subsection Multiple polylogarithms
 
@@ -6001,21 +6006,32 @@ J.Borwein, D.Bradley, D.Broadhurst, P.Lisonek, Trans.Amer.Math.Soc. 353/3 (2001)
 @cite{Numerical Evaluation of Multiple Polylogarithms}, 
 J.Vollinga, S.Weinzierl, hep-ph/0410259
 
-@node Complex Conjugation, Solving Linear Systems of Equations, Multiple polylogarithms, Methods and Functions
+@node Complex expressions, Solving linear systems of equations, Multiple polylogarithms, Methods and functions
 @c    node-name, next, previous, up
-@section Complex conjugation
+@section Complex expressions
 @c
 @cindex @code{conjugate()}
 
-The method
+For dealing with complex expressions there are the methods
 
 @example
 ex ex::conjugate();
+ex ex::real_part();
+ex ex::imag_part();
 @end example
 
-returns the complex conjugate of the expression. For all built-in functions and objects the
-conjugation gives the expected results:
+that return respectively the complex conjugate, the real part and the
+imaginary part of an expression. Complex conjugation works as expected
+for all built-in functinos and objects. Taking real and imaginary
+parts has not yet been implemented for all built-in functions. In cases where
+it is not known how to conjugate or take a real/imaginary part one
+of the functions @code{conjugate}, @code{real_part} or @code{imag_part}
+is returned. For instance, in case of a complex symbol @code{x}
+(symbols are complex by default), one could not simplify
+@code{conjugate(x)}. In the case of strings of gamma matrices,
+the @code{conjugate} method takes the Dirac conjugate.
 
+For example,
 @example
 @{
     varidx a(symbol("a"), 4), b(symbol("b"), 4);
@@ -6029,13 +6045,14 @@ conjugation gives the expected results:
 @}
 @end example
 
-For symbols in the complex domain the conjugation can not be evaluated and the GiNaC function
-@code{conjugate} is returned. GiNaC functions conjugate by applying the conjugation to their
-arguments. This is the default strategy. If you want to define your own functions and want to
-change this behavior, you have to supply a specialized conjugation method for your function
-(see @ref{Symbolic functions} and the GiNaC source-code for @code{abs} as an example).
+If you declare your own GiNaC functions, then they will conjugate themselves
+by conjugating their arguments. This is the default strategy. If you want to
+change this behavior, you have to supply a specialized conjugation method
+for your function (see @ref{Symbolic functions} and the GiNaC source-code
+for @code{abs} as an example). Also, specialized methods can be provided
+to take real and imaginary parts of user-defined functions.
 
-@node Solving Linear Systems of Equations, Input/Output, Complex Conjugation, Methods and Functions
+@node Solving linear systems of equations, Input/output, Complex expressions, Methods and functions
 @c    node-name, next, previous, up
 @section Solving linear systems of equations
 @cindex @code{lsolve()}
@@ -6051,7 +6068,7 @@ ex lsolve(const ex & eqns, const ex & symbols,
 
 Here, @code{eqns} is a @code{lst} of equalities (i.e. class
 @code{relational}) while @code{symbols} is a @code{lst} of
-indeterminates.  (@xref{The Class Hierarchy}, for an exposition of class
+indeterminates.  (@xref{The class hierarchy}, for an exposition of class
 @code{lst}).
 
 It returns the @code{lst} of solutions as an expression.  As an example,
@@ -6076,7 +6093,7 @@ to @code{lsolve()}: it accepts the same parameters as
 around that method.
 
 
-@node Input/Output, Extending GiNaC, Solving Linear Systems of Equations, Methods and Functions
+@node Input/output, Extending GiNaC, Solving linear systems of equations, Methods and functions
 @c    node-name, next, previous, up
 @section Input and output of expressions
 @cindex I/O
@@ -6518,7 +6535,7 @@ Be warned, however, that the set of properties and their meaning for each
 class may change between GiNaC versions.
 
 
-@node Extending GiNaC, What does not belong into GiNaC, Input/Output, Top
+@node Extending GiNaC, What does not belong into GiNaC, Input/output, Top
 @c    node-name, next, previous, up
 @chapter Extending GiNaC
 
@@ -6876,7 +6893,7 @@ code for the @code{psi()} function (@file{inifcns.h} and
 @section GiNaC's expression output system
 
 GiNaC allows the output of expressions in a variety of different formats
-(@pxref{Input/Output}). This section will explain how expression output
+(@pxref{Input/output}). This section will explain how expression output
 is implemented internally, and how to define your own output formats or
 change the output format of built-in algebraic objects. You will also want
 to read this section if you plan to write your own algebraic classes or
@@ -7558,7 +7575,7 @@ Note that the unarchiving constructor is @code{sprod::structure} and not
 @code{sprod::unarchive()} function.
 
 
-@node Adding classes, A Comparison With Other CAS, Structures, Extending GiNaC
+@node Adding classes, A comparison with other CAS, Structures, Extending GiNaC
 @c    node-name, next, previous, up
 @section Adding classes
 
@@ -8066,7 +8083,7 @@ should become a need.
 That's it. May the source be with you!
 
 
-@node A Comparison With Other CAS, Advantages, Adding classes, Top
+@node A comparison with other CAS, Advantages, Adding classes, Top
 @c    node-name, next, previous, up
 @chapter A Comparison With Other CAS
 @cindex advocacy
@@ -8082,7 +8099,7 @@ disadvantages over these systems.
 * Why C++?::                         Attractiveness of C++.
 @end menu
 
-@node Advantages, Disadvantages, A Comparison With Other CAS, A Comparison With Other CAS
+@node Advantages, Disadvantages, A comparison with other CAS, A comparison with other CAS
 @c    node-name, next, previous, up
 @section Advantages
 
@@ -8162,7 +8179,7 @@ speed with other CAS.
 @end itemize
 
 
-@node Disadvantages, Why C++?, Advantages, A Comparison With Other CAS
+@node Disadvantages, Why C++?, Advantages, A comparison with other CAS
 @c    node-name, next, previous, up
 @section Disadvantages
 
@@ -8197,7 +8214,7 @@ yet ANSI compliant, support all needed features.
 @end itemize
 
 
-@node Why C++?, Internal Structures, Disadvantages, A Comparison With Other CAS
+@node Why C++?, Internal structures, Disadvantages, A comparison with other CAS
 @c    node-name, next, previous, up
 @section Why C++?
 
@@ -8214,16 +8231,16 @@ Furthermore, the main developers are more familiar with C++ than with
 any other programming language.
 
 
-@node Internal Structures, Expressions are reference counted, Why C++? , Top
+@node Internal structures, Expressions are reference counted, Why C++? , Top
 @c    node-name, next, previous, up
-@appendix Internal Structures
+@appendix Internal structures
 
 @menu
 * Expressions are reference counted::
 * Internal representation of products and sums::
 @end menu
 
-@node Expressions are reference counted, Internal representation of products and sums, Internal Structures, Internal Structures
+@node Expressions are reference counted, Internal representation of products and sums, Internal structures, Internal structures
 @c    node-name, next, previous, up
 @appendixsection Expressions are reference counted
 
@@ -8312,7 +8329,7 @@ Marshall Cline.  Chapter 16 covers this issue and presents an
 implementation which is pretty close to the one in GiNaC.
 
 
-@node Internal representation of products and sums, Package Tools, Expressions are reference counted, Internal Structures
+@node Internal representation of products and sums, Package tools, Expressions are reference counted, Internal structures
 @c    node-name, next, previous, up
 @appendixsection Internal representation of products and sums
 
@@ -8380,9 +8397,9 @@ expansion and the like are reimplemented for @code{add} and @code{mul},
 but the data structure is inherited from @code{expairseq}.
 
 
-@node Package Tools, ginac-config, Internal representation of products and sums, Top
+@node Package tools, ginac-config, Internal representation of products and sums, Top
 @c    node-name, next, previous, up
-@appendix Package Tools
+@appendix Package tools
 
 If you are creating a software package that uses the GiNaC library,
 setting the correct command line options for the compiler and linker
@@ -8394,7 +8411,7 @@ can be difficult. GiNaC includes two tools to make this process easier.
 @end menu
 
 
-@node ginac-config, AM_PATH_GINAC, Package Tools, Package Tools
+@node ginac-config, AM_PATH_GINAC, Package tools, Package tools
 @c    node-name, next, previous, up
 @section @command{ginac-config}
 @cindex ginac-config
@@ -8441,7 +8458,7 @@ Not only is the form using @command{ginac-config} easier to type, it will
 work on any system, no matter how GiNaC was configured.
 
 
-@node AM_PATH_GINAC, Configure script options, ginac-config, Package Tools
+@node AM_PATH_GINAC, Configure script options, ginac-config, Package tools
 @c    node-name, next, previous, up
 @section @samp{AM_PATH_GINAC}
 @cindex AM_PATH_GINAC
@@ -8654,7 +8671,7 @@ $ make install
 @end example
 
 
-@node Bibliography, Concept Index, Example package, Top
+@node Bibliography, Concept index, Example package, Top
 @c    node-name, next, previous, up
 @appendix Bibliography
 
@@ -8699,9 +8716,9 @@ ISBN 3-540-66572-2, 2001, Springer, Heidelberg
 @end itemize
 
 
-@node Concept Index, , Bibliography, Top
+@node Concept index, , Bibliography, Top
 @c    node-name, next, previous, up
-@unnumbered Concept Index
+@unnumbered Concept index
 
 @printindex cp
 
index acced78..9c314ee 100644 (file)
@@ -424,6 +424,36 @@ ex add::conjugate() const
        return *this;
 }
 
+ex add::real_part() const
+{
+       epvector v;
+       v.reserve(seq.size());
+       for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i)
+               if ((i->coeff).info(info_flags::real))
+                       v.push_back(expair((i->rest).real_part(), i->coeff));
+               else {
+                       ex rp=recombine_pair_to_ex(*i).real_part();
+                       v.push_back(split_ex_to_pair(rp));
+               }
+       return (new add(v, overall_coeff.real_part()))
+               -> setflag(status_flags::dynallocated);
+}
+
+ex add::imag_part() const
+{
+       epvector v;
+       v.reserve(seq.size());
+       for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i)
+               if ((i->coeff).info(info_flags::real))
+                       v.push_back(expair((i->rest).imag_part(), i->coeff));
+               else {
+                       ex ip=recombine_pair_to_ex(*i).imag_part();
+                       v.push_back(split_ex_to_pair(ip));
+               }
+       return (new add(v, overall_coeff.imag_part()))
+               -> setflag(status_flags::dynallocated);
+}
+
 ex add::eval_ncmul(const exvector & v) const
 {
        if (seq.empty())
index 6d87f6b..cee93aa 100644 (file)
@@ -58,6 +58,8 @@ public:
        ex smod(const numeric &xi) const;
        numeric max_coefficient() const;
        ex conjugate() const;
+       ex real_part() const;
+       ex imag_part() const;
        exvector get_free_indices() const;
        ex eval_ncmul(const exvector & v) const;
 protected:
index a3c727b..f86483e 100644 (file)
@@ -38,6 +38,7 @@
 #include "wildcard.h"
 #include "archive.h"
 #include "utils.h"
+#include "inifcns.h"
 
 namespace GiNaC {
 
@@ -711,6 +712,16 @@ ex basic::conjugate() const
        return *this;
 }
 
+ex basic::real_part() const
+{
+       return real_part_function(*this).hold();
+}
+
+ex basic::imag_part() const
+{
+       return imag_part_function(*this).hold();
+}
+
 ex basic::eval_ncmul(const exvector & v) const
 {
        return hold_ncmul(v);
index 6b117cc..b08ad66 100644 (file)
@@ -215,8 +215,10 @@ public:
        virtual unsigned return_type() const;
        virtual tinfo_t return_type_tinfo() const;
 
-       // complex conjugation
+       // functions for complex expressions
        virtual ex conjugate() const;
+       virtual ex real_part() const;
+       virtual ex imag_part() const;
 
        // functions that should be called from class ex only
 protected:
index 8ae372b..cff955a 100644 (file)
@@ -29,6 +29,7 @@
 #include "ex.h"
 #include "archive.h"
 #include "utils.h"
+#include "inifcns.h"
 
 namespace GiNaC {
 
@@ -161,6 +162,27 @@ bool constant::is_polynomial(const ex & var) const
        return true;
 }
 
+ex constant::conjugate() const
+{
+       if ( domain == domain::real )
+               return *this;
+       return conjugate_function(*this).hold();
+}
+
+ex constant::real_part() const
+{
+       if ( domain == domain::real )
+               return *this;
+       return real_part_function(*this).hold();
+}
+
+ex constant::imag_part() const
+{
+       if ( domain == domain::real )
+               return 0;
+       return imag_part_function(*this).hold();
+}
+
 // protected
 
 /** Implementation of ex::diff() for a constant always returns 0.
index 4b4a5e4..5ba3298 100644 (file)
@@ -51,6 +51,9 @@ public:
        bool info(unsigned inf) const;
        ex evalf(int level = 0) const;
        bool is_polynomial(const ex & var) const;
+       ex conjugate() const;
+       ex real_part() const;
+       ex imag_part() const;
 protected:
        ex derivative(const symbol & s) const;
        bool is_equal_same_type(const basic & other) const;
index 5774d5a..28cf05e 100644 (file)
@@ -394,6 +394,28 @@ protected:
                return *this;
        }
 
+       ex real_part() const
+       {
+               STLT cont;
+               reserve(cont, nops());
+               const_iterator b = begin();
+               const_iterator e = end();
+               for(const_iterator i=b; i!=e; ++i)
+                       cont.push_back(i->real_part());
+               return thiscontainer(cont);
+       }
+
+       ex imag_part() const
+       {
+               STLT cont;
+               reserve(cont, nops());
+               const_iterator b = begin();
+               const_iterator e = end();
+               for(const_iterator i=b; i!=e; ++i)
+                       cont.push_back(i->imag_part());
+               return thiscontainer(cont);
+       }
+
        bool is_equal_same_type(const basic & other) const;
 
        // new virtual functions which can be overridden by derived classes
index c23336b..030046c 100644 (file)
@@ -134,8 +134,10 @@ public:
        ex lhs() const;
        ex rhs() const;
 
-       // complex conjugation
+       // function for complex expressions
        ex conjugate() const { return bp->conjugate(); }
+       ex real_part() const { return bp->real_part(); }
+       ex imag_part() const { return bp->imag_part(); }
 
        // pattern matching
        bool has(const ex & pattern, unsigned options = 0) const { return bp->has(pattern, options); }
@@ -685,6 +687,12 @@ inline ex expand(const ex & thisex, unsigned options = 0)
 inline ex conjugate(const ex & thisex)
 { return thisex.conjugate(); }
 
+inline ex real_part(const ex & thisex)
+{ return thisex.real_part(); }
+
+inline ex imag_part(const ex & thisex)
+{ return thisex.imag_part(); }
+
 inline bool has(const ex & thisex, const ex & pattern, unsigned options = 0)
 { return thisex.has(pattern, options); }
 
index e3c10f1..4354346 100755 (executable)
@@ -79,6 +79,14 @@ $typedef_conjugate_funcp=generate(
 'typedef ex (* conjugate_funcp_${N})(${SEQ1});'."\n",
 'const ex &','','');
 
+$typedef_real_part_funcp=generate(
+'typedef ex (* real_part_funcp_${N})(${SEQ1});'."\n",
+'const ex &','','');
+
+$typedef_imag_part_funcp=generate(
+'typedef ex (* imag_part_funcp_${N})(${SEQ1});'."\n",
+'const ex &','','');
+
 $typedef_derivative_funcp=generate(
 'typedef ex (* derivative_funcp_${N})(${SEQ1}, unsigned);'."\n",
 'const ex &','','');
@@ -101,6 +109,10 @@ $evalf_func_interface=generate('    function_options & evalf_func(evalf_funcp_${
 
 $conjugate_func_interface=generate('    function_options & conjugate_func(conjugate_funcp_${N} d);'."\n",'','','');
 
+$real_part_func_interface=generate('    function_options & real_part_func(real_part_funcp_${N} d);'."\n",'','','');
+
+$imag_part_func_interface=generate('    function_options & imag_part_func(imag_part_funcp_${N} d);'."\n",'','','');
+
 $derivative_func_interface=generate('    function_options & derivative_func(derivative_funcp_${N} d);'."\n",'','','');
 
 $power_func_interface=generate('    function_options & power_func(power_funcp_${N} d);'."\n",'','','');
@@ -149,6 +161,18 @@ $conjugate_switch_statement=generate(
                return ((conjugate_funcp_${N})(opt.conjugate_f))(${SEQ1});
 END_OF_DIFF_SWITCH_STATEMENT
 
+$real_part_switch_statement=generate(
+       <<'END_OF_DIFF_SWITCH_STATEMENT','seq[${N}-1]','','');
+       case ${N}:
+               return ((real_part_funcp_${N})(opt.real_part_f))(${SEQ1});
+END_OF_DIFF_SWITCH_STATEMENT
+
+$imag_part_switch_statement=generate(
+       <<'END_OF_DIFF_SWITCH_STATEMENT','seq[${N}-1]','','');
+       case ${N}:
+               return ((imag_part_funcp_${N})(opt.imag_part_f))(${SEQ1});
+END_OF_DIFF_SWITCH_STATEMENT
+
 $diff_switch_statement=generate(
        <<'END_OF_DIFF_SWITCH_STATEMENT','seq[${N}-1]','','');
        case ${N}:
@@ -209,6 +233,26 @@ function_options & function_options::conjugate_func(conjugate_funcp_${N} c)
 }
 END_OF_CONJUGATE_FUNC_IMPLEMENTATION
 
+$real_part_func_implementation=generate(
+       <<'END_OF_REAL_PART_FUNC_IMPLEMENTATION','','','');
+function_options & function_options::real_part_func(real_part_funcp_${N} c)
+{
+       test_and_set_nparams(${N});
+       real_part_f = real_part_funcp(c);
+       return *this;
+}
+END_OF_REAL_PART_FUNC_IMPLEMENTATION
+
+$imag_part_func_implementation=generate(
+       <<'END_OF_IMAG_PART_FUNC_IMPLEMENTATION','','','');
+function_options & function_options::imag_part_func(imag_part_funcp_${N} c)
+{
+       test_and_set_nparams(${N});
+       imag_part_f = imag_part_funcp(c);
+       return *this;
+}
+END_OF_IMAG_PART_FUNC_IMPLEMENTATION
+
 $derivative_func_implementation=generate(
        <<'END_OF_DERIVATIVE_FUNC_IMPLEMENTATION','','','');
 function_options & function_options::derivative_func(derivative_funcp_${N} d)
@@ -293,6 +337,8 @@ class symmetry;
 typedef ex (* eval_funcp)();
 typedef ex (* evalf_funcp)();
 typedef ex (* conjugate_funcp)();
+typedef ex (* real_part_funcp)();
+typedef ex (* imag_part_funcp)();
 typedef ex (* derivative_funcp)();
 typedef ex (* power_funcp)();
 typedef ex (* series_funcp)();
@@ -302,6 +348,8 @@ typedef void (* print_funcp)();
 $typedef_eval_funcp
 $typedef_evalf_funcp
 $typedef_conjugate_funcp
+$typedef_real_part_funcp
+$typedef_imag_part_funcp
 $typedef_derivative_funcp
 $typedef_power_funcp
 $typedef_series_funcp
@@ -313,6 +361,8 @@ $typedef_print_funcp
 typedef ex (* eval_funcp_exvector)(const exvector &);
 typedef ex (* evalf_funcp_exvector)(const exvector &);
 typedef ex (* conjugate_funcp_exvector)(const exvector &);
+typedef ex (* real_part_funcp_exvector)(const exvector &);
+typedef ex (* imag_part_funcp_exvector)(const exvector &);
 typedef ex (* derivative_funcp_exvector)(const exvector &, unsigned);
 typedef ex (* power_funcp_exvector)(const exvector &, const ex &);
 typedef ex (* series_funcp_exvector)(const exvector &, const relational &, int, unsigned);
@@ -337,6 +387,8 @@ public:
 $eval_func_interface
 $evalf_func_interface
 $conjugate_func_interface
+$real_part_func_interface
+$imag_part_func_interface
 $derivative_func_interface
 $power_func_interface
 $series_func_interface
@@ -345,6 +397,8 @@ $print_func_interface
        function_options & eval_func(eval_funcp_exvector e);
        function_options & evalf_func(evalf_funcp_exvector ef);
        function_options & conjugate_func(conjugate_funcp_exvector d);
+       function_options & real_part_func(real_part_funcp_exvector d);
+       function_options & imag_part_func(imag_part_funcp_exvector d);
        function_options & derivative_func(derivative_funcp_exvector d);
        function_options & power_func(power_funcp_exvector d);
        function_options & series_func(series_funcp_exvector s);
@@ -380,6 +434,8 @@ protected:
        eval_funcp eval_f;
        evalf_funcp evalf_f;
        conjugate_funcp conjugate_f;
+       real_part_funcp real_part_f;
+       imag_part_funcp imag_part_f;
        derivative_funcp derivative_f;
        power_funcp power_f;
        series_funcp series_f;
@@ -399,6 +455,8 @@ protected:
        bool eval_use_exvector_args;
        bool evalf_use_exvector_args;
        bool conjugate_use_exvector_args;
+       bool real_part_use_exvector_args;
+       bool imag_part_use_exvector_args;
        bool derivative_use_exvector_args;
        bool power_use_exvector_args;
        bool series_use_exvector_args;
@@ -454,6 +512,8 @@ public:
        ex thiscontainer(const exvector & v) const;
        ex thiscontainer(std::auto_ptr<exvector> vp) const;
        ex conjugate() const;
+       ex real_part() const;
+       ex imag_part() const;
 protected:
        ex derivative(const symbol & s) const;
        bool is_equal_same_type(const basic & other) const;
@@ -581,12 +641,15 @@ void function_options::initialize()
 {
        set_name("unnamed_function", "\\\\mbox{unnamed}");
        nparams = 0;
-       eval_f = evalf_f = conjugate_f = derivative_f = power_f = series_f = 0;
+       eval_f = evalf_f = real_part_f = imag_part_f = conjugate_f = derivative_f
+               = power_f = series_f = 0;
        evalf_params_first = true;
        use_return_type = false;
        eval_use_exvector_args = false;
        evalf_use_exvector_args = false;
        conjugate_use_exvector_args = false;
+       real_part_use_exvector_args = false;
+       imag_part_use_exvector_args = false;
        derivative_use_exvector_args = false;
        power_use_exvector_args = false;
        series_use_exvector_args = false;
@@ -617,6 +680,8 @@ function_options & function_options::latex_name(std::string const & tn)
 $eval_func_implementation
 $evalf_func_implementation
 $conjugate_func_implementation
+$real_part_func_implementation
+$imag_part_func_implementation
 $derivative_func_implementation
 $power_func_implementation
 $series_func_implementation
@@ -640,6 +705,19 @@ function_options& function_options::conjugate_func(conjugate_funcp_exvector c)
        conjugate_f = conjugate_funcp(c);
        return *this;
 }
+function_options& function_options::real_part_func(real_part_funcp_exvector c)
+{
+       real_part_use_exvector_args = true;
+       real_part_f = real_part_funcp(c);
+       return *this;
+}
+function_options& function_options::imag_part_func(imag_part_funcp_exvector c)
+{
+       imag_part_use_exvector_args = true;
+       imag_part_f = imag_part_funcp(c);
+       return *this;
+}
+
 function_options& function_options::derivative_func(derivative_funcp_exvector d)
 {
        derivative_use_exvector_args = true;
@@ -1049,6 +1127,46 @@ ${conjugate_switch_statement}
        throw(std::logic_error("function::conjugate(): invalid nparams"));
 }
 
+/** Implementation of ex::real_part for functions. */
+ex function::real_part() const
+{
+       GINAC_ASSERT(serial<registered_functions().size());
+       const function_options & opt = registered_functions()[serial];
+
+       if (opt.real_part_f==0)
+               return basic::real_part();
+
+       if (opt.real_part_use_exvector_args)
+               return ((real_part_funcp_exvector)(opt.real_part_f))(seq);
+
+       switch (opt.nparams) {
+               // the following lines have been generated for max. ${maxargs} parameters
+${real_part_switch_statement}
+               // end of generated lines
+       }
+       throw(std::logic_error("function::real_part(): invalid nparams"));
+}
+
+/** Implementation of ex::imag_part for functions. */
+ex function::imag_part() const
+{
+       GINAC_ASSERT(serial<registered_functions().size());
+       const function_options & opt = registered_functions()[serial];
+
+       if (opt.imag_part_f==0)
+               return basic::imag_part();
+
+       if (opt.imag_part_use_exvector_args)
+               return ((imag_part_funcp_exvector)(opt.imag_part_f))(seq);
+
+       switch (opt.nparams) {
+               // the following lines have been generated for max. ${maxargs} parameters
+${imag_part_switch_statement}
+               // end of generated lines
+       }
+       throw(std::logic_error("function::imag_part(): invalid nparams"));
+}
+
 // protected
 
 /** Implementation of ex::diff() for functions. It applies the chain rule,
index b8b70f7..26867dc 100644 (file)
@@ -39,6 +39,7 @@
 #include "utils.h"
 #include "integral.h"
 #include "matrix.h"
+#include "inifcns.h"
 
 namespace GiNaC {
 
@@ -317,6 +318,20 @@ ex indexed::eval(int level) const
        return ex_to<basic>(base).eval_indexed(*this);
 }
 
+ex indexed::real_part() const
+{
+       if(op(0).info(info_flags::real))
+               return *this;
+       return real_part_function(*this).hold();
+}
+
+ex indexed::imag_part() const
+{
+       if(op(0).info(info_flags::real))
+               return 0;
+       return imag_part_function(*this).hold();
+}
+
 ex indexed::thiscontainer(const exvector & v) const
 {
        return indexed(ex_to<symmetry>(symtree), v);
index 4ad25cb..bbe9400 100644 (file)
@@ -147,6 +147,8 @@ public:
        unsigned precedence() const {return 55;}
        bool info(unsigned inf) const;
        ex eval(int level = 0) const;
+       ex real_part() const;
+       ex imag_part() const;
        exvector get_free_indices() const;
 
 protected:
index a8f82d8..c49fc70 100644 (file)
@@ -66,12 +66,114 @@ static ex conjugate_conjugate(const ex & arg)
        return arg;
 }
 
+static ex conjugate_real_part(const ex & arg)
+{
+       return arg.real_part();
+}
+
+static ex conjugate_imag_part(const ex & arg)
+{
+       return -arg.imag_part();
+}
+
 REGISTER_FUNCTION(conjugate_function, eval_func(conjugate_eval).
                                       evalf_func(conjugate_evalf).
                                       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"));
 
+//////////
+// real part
+//////////
+
+static ex real_part_evalf(const ex & arg)
+{
+       if (is_exactly_a<numeric>(arg)) {
+               return ex_to<numeric>(arg).real();
+       }
+       return real_part_function(arg).hold();
+}
+
+static ex real_part_eval(const ex & arg)
+{
+       return arg.real_part();
+}
+
+static void real_part_print_latex(const ex & arg, const print_context & c)
+{
+       c.s << "\\Re"; arg.print(c); c.s << "";
+}
+
+static ex real_part_conjugate(const ex & arg)
+{
+       return real_part_function(arg).hold();
+}
+
+static ex real_part_real_part(const ex & arg)
+{
+       return real_part_function(arg).hold();
+}
+
+static ex real_part_imag_part(const ex & arg)
+{
+       return 0;
+}
+
+REGISTER_FUNCTION(real_part_function, eval_func(real_part_eval).
+                                      evalf_func(real_part_evalf).
+                                      print_func<print_latex>(real_part_print_latex).
+                                      conjugate_func(real_part_conjugate).
+                                      real_part_func(real_part_real_part).
+                                      imag_part_func(real_part_imag_part).
+                                      set_name("real_part","real_part"));
+
+//////////
+// imag part
+//////////
+
+static ex imag_part_evalf(const ex & arg)
+{
+       if (is_exactly_a<numeric>(arg)) {
+               return ex_to<numeric>(arg).imag();
+       }
+       return imag_part_function(arg).hold();
+}
+
+static ex imag_part_eval(const ex & arg)
+{
+       return arg.imag_part();
+}
+
+static void imag_part_print_latex(const ex & arg, const print_context & c)
+{
+       c.s << "\\Im"; arg.print(c); c.s << "";
+}
+
+static ex imag_part_conjugate(const ex & arg)
+{
+       return imag_part_function(arg).hold();
+}
+
+static ex imag_part_real_part(const ex & arg)
+{
+       return imag_part_function(arg).hold();
+}
+
+static ex imag_part_imag_part(const ex & arg)
+{
+       return 0;
+}
+
+REGISTER_FUNCTION(imag_part_function, eval_func(imag_part_eval).
+                                      evalf_func(imag_part_evalf).
+                                      print_func<print_latex>(imag_part_print_latex).
+                                      conjugate_func(imag_part_conjugate).
+                                      real_part_func(imag_part_real_part).
+                                      imag_part_func(imag_part_imag_part).
+                                      set_name("imag_part","imag_part"));
+
 //////////
 // absolute value
 //////////
@@ -107,6 +209,16 @@ static ex abs_conjugate(const ex & arg)
        return abs(arg);
 }
 
+static ex abs_real_part(const ex & arg)
+{
+       return abs(arg).hold();
+}
+
+static ex abs_imag_part(const ex& arg)
+{
+       return 0;
+}
+
 static ex abs_power(const ex & arg, const ex & exp)
 {
        if (arg.is_equal(arg.conjugate()) && is_a<numeric>(exp) && ex_to<numeric>(exp).is_even())
@@ -121,6 +233,8 @@ REGISTER_FUNCTION(abs, eval_func(abs_eval).
                        print_func<print_csrc_float>(abs_print_csrc_float).
                        print_func<print_csrc_double>(abs_print_csrc_float).
                        conjugate_func(abs_conjugate).
+                       real_part_func(abs_real_part).
+                       imag_part_func(abs_imag_part).
                        power_func(abs_power));
 
 //////////
@@ -182,13 +296,25 @@ static ex step_series(const ex & arg,
 
 static ex step_conjugate(const ex& arg)
 {
-       return step(arg);
+       return step(arg).hold();
+}
+
+static ex step_real_part(const ex& arg)
+{
+       return step(arg).hold();
+}
+
+static ex step_imag_part(const ex& arg)
+{
+       return 0;
 }
 
 REGISTER_FUNCTION(step, eval_func(step_eval).
                         evalf_func(step_evalf).
                         series_func(step_series).
-                        conjugate_func(step_conjugate));
+                        conjugate_func(step_conjugate).
+                                                               real_part_func(step_real_part).
+                                                               imag_part_func(step_imag_part));
 
 //////////
 // Complex sign
@@ -249,7 +375,17 @@ static ex csgn_series(const ex & arg,
 
 static ex csgn_conjugate(const ex& arg)
 {
-       return csgn(arg);
+       return csgn(arg).hold();
+}
+
+static ex csgn_real_part(const ex& arg)
+{
+       return csgn(arg).hold();
+}
+
+static ex csgn_imag_part(const ex& arg)
+{
+       return 0;
 }
 
 static ex csgn_power(const ex & arg, const ex & exp)
@@ -268,6 +404,8 @@ REGISTER_FUNCTION(csgn, eval_func(csgn_eval).
                         evalf_func(csgn_evalf).
                         series_func(csgn_series).
                         conjugate_func(csgn_conjugate).
+                        real_part_func(csgn_real_part).
+                        imag_part_func(csgn_imag_part).
                         power_func(csgn_power));
 
 
@@ -345,7 +483,17 @@ static ex eta_series(const ex & x, const ex & y,
 
 static ex eta_conjugate(const ex & x, const ex & y)
 {
-       return -eta(x,y);
+       return -eta(x, y);
+}
+
+static ex eta_real_part(const ex & x, const ex & y)
+{
+       return 0;
+}
+
+static ex eta_imag_part(const ex & x, const ex & y)
+{
+       return -I*eta(x, y).hold();
 }
 
 REGISTER_FUNCTION(eta, eval_func(eta_eval).
@@ -353,7 +501,9 @@ REGISTER_FUNCTION(eta, eval_func(eta_eval).
                        series_func(eta_series).
                        latex_name("\\eta").
                        set_symmetry(sy_symm(0, 1)).
-                       conjugate_func(eta_conjugate));
+                       conjugate_func(eta_conjugate).
+                       real_part_func(eta_real_part).
+                       imag_part_func(eta_imag_part));
 
 
 //////////
@@ -568,14 +718,26 @@ static void factorial_print_dflt_latex(const ex & x, const print_context & c)
 
 static ex factorial_conjugate(const ex & x)
 {
-       return factorial(x);
+       return factorial(x).hold();
+}
+
+static ex factorial_real_part(const ex & x)
+{
+       return factorial(x).hold();
+}
+
+static ex factorial_imag_part(const ex & x)
+{
+       return 0;
 }
 
 REGISTER_FUNCTION(factorial, eval_func(factorial_eval).
                              evalf_func(factorial_evalf).
                              print_func<print_dflt>(factorial_print_dflt_latex).
                              print_func<print_latex>(factorial_print_dflt_latex).
-                             conjugate_func(factorial_conjugate));
+                             conjugate_func(factorial_conjugate).
+                             real_part_func(factorial_real_part).
+                             imag_part_func(factorial_imag_part));
 
 //////////
 // binomial
@@ -620,12 +782,24 @@ static ex binomial_eval(const ex & x, const ex &y)
 // function, also complex conjugation should be changed (or rather, deleted).
 static ex binomial_conjugate(const ex & x, const ex & y)
 {
-       return binomial(x,y);
+       return binomial(x,y).hold();
+}
+
+static ex binomial_real_part(const ex & x, const ex & y)
+{
+       return binomial(x,y).hold();
+}
+
+static ex binomial_imag_part(const ex & x, const ex & y)
+{
+       return 0;
 }
 
 REGISTER_FUNCTION(binomial, eval_func(binomial_eval).
                             evalf_func(binomial_evalf).
-                            conjugate_func(binomial_conjugate));
+                            conjugate_func(binomial_conjugate).
+                            real_part_func(binomial_real_part).
+                            imag_part_func(binomial_imag_part));
 
 //////////
 // Order term function (for truncated power series)
@@ -660,7 +834,19 @@ static ex Order_series(const ex & x, const relational & r, int order, unsigned o
 
 static ex Order_conjugate(const ex & x)
 {
-       return Order(x);
+       return Order(x).hold();
+}
+
+static ex Order_real_part(const ex & x)
+{
+       return Order(x).hold();
+}
+
+static ex Order_imag_part(const ex & x)
+{
+       if(x.info(info_flags::real))
+               return 0;
+       return Order(x).hold();
 }
 
 // Differentiation is handled in function::derivative because of its special requirements
@@ -668,7 +854,9 @@ static ex Order_conjugate(const ex & x)
 REGISTER_FUNCTION(Order, eval_func(Order_eval).
                          series_func(Order_series).
                          latex_name("\\mathcal{O}").
-                         conjugate_func(Order_conjugate));
+                         conjugate_func(Order_conjugate).
+                         real_part_func(Order_real_part).
+                         imag_part_func(Order_imag_part));
 
 //////////
 // Solve linear system
index 0e13a04..af5516d 100644 (file)
@@ -31,13 +31,19 @@ namespace GiNaC {
 
 /** Complex conjugate. */
 DECLARE_FUNCTION_1P(conjugate_function)
+
+/** Real part. */
+DECLARE_FUNCTION_1P(real_part_function)
+
+/** Imaginary part. */
+DECLARE_FUNCTION_1P(imag_part_function)
        
 /** Absolute value. */
 DECLARE_FUNCTION_1P(abs)
        
 /** Step function. */
 DECLARE_FUNCTION_1P(step)
-
+       
 /** Complex sign. */
 DECLARE_FUNCTION_1P(csgn)
 
index 364ec55..3f9c380 100644 (file)
@@ -89,9 +89,21 @@ static ex exp_deriv(const ex & x, unsigned deriv_param)
        return exp(x);
 }
 
+static ex exp_real_part(const ex & x)
+{
+       return exp(GiNaC::real_part(x))*cos(GiNaC::imag_part(x));
+}
+
+static ex exp_imag_part(const ex & x)
+{
+       return exp(GiNaC::real_part(x))*sin(GiNaC::imag_part(x));
+}
+
 REGISTER_FUNCTION(exp, eval_func(exp_eval).
                        evalf_func(exp_evalf).
                        derivative_func(exp_deriv).
+                       real_part_func(exp_real_part).
+                       imag_part_func(exp_imag_part).
                        latex_name("\\exp"));
 
 //////////
@@ -232,10 +244,22 @@ static ex log_series(const ex &arg,
        throw do_taylor();  // caught by function::series()
 }
 
+static ex log_real_part(const ex & x)
+{
+       return log(abs(x));
+}
+
+static ex log_imag_part(const ex & x)
+{
+       return atan2(GiNaC::imag_part(x), GiNaC::real_part(x));
+}
+
 REGISTER_FUNCTION(log, eval_func(log_eval).
                        evalf_func(log_evalf).
                        derivative_func(log_deriv).
                        series_func(log_series).
+                       real_part_func(log_real_part).
+                       imag_part_func(log_imag_part).
                        latex_name("\\ln"));
 
 //////////
@@ -321,9 +345,21 @@ static ex sin_deriv(const ex & x, unsigned deriv_param)
        return cos(x);
 }
 
+static ex sin_real_part(const ex & x)
+{
+       return cosh(GiNaC::imag_part(x))*sin(GiNaC::real_part(x));
+}
+
+static ex sin_imag_part(const ex & x)
+{
+       return sinh(GiNaC::imag_part(x))*cos(GiNaC::real_part(x));
+}
+
 REGISTER_FUNCTION(sin, eval_func(sin_eval).
                        evalf_func(sin_evalf).
                        derivative_func(sin_deriv).
+                       real_part_func(sin_real_part).
+                       imag_part_func(sin_imag_part).
                        latex_name("\\sin"));
 
 //////////
@@ -409,9 +445,21 @@ static ex cos_deriv(const ex & x, unsigned deriv_param)
        return -sin(x);
 }
 
+static ex cos_real_part(const ex & x)
+{
+       return cosh(GiNaC::imag_part(x))*cos(GiNaC::real_part(x));
+}
+
+static ex cos_imag_part(const ex & x)
+{
+       return -sinh(GiNaC::imag_part(x))*sin(GiNaC::real_part(x));
+}
+
 REGISTER_FUNCTION(cos, eval_func(cos_eval).
                        evalf_func(cos_evalf).
                        derivative_func(cos_deriv).
+                       real_part_func(cos_real_part).
+                       imag_part_func(cos_imag_part).
                        latex_name("\\cos"));
 
 //////////
@@ -494,6 +542,20 @@ static ex tan_deriv(const ex & x, unsigned deriv_param)
        return (_ex1+power(tan(x),_ex2));
 }
 
+static ex tan_real_part(const ex & x)
+{
+       ex a = GiNaC::real_part(x);
+       ex b = GiNaC::imag_part(x);
+       return tan(a)/(1+power(tan(a),2)*power(tan(b),2));
+}
+
+static ex tan_imag_part(const ex & x)
+{
+       ex a = GiNaC::real_part(x);
+       ex b = GiNaC::imag_part(x);
+       return tanh(b)/(1+power(tan(a),2)*power(tan(b),2));
+}
+
 static ex tan_series(const ex &x,
                      const relational &rel,
                      int order,
@@ -514,6 +576,8 @@ REGISTER_FUNCTION(tan, eval_func(tan_eval).
                        evalf_func(tan_evalf).
                        derivative_func(tan_deriv).
                        series_func(tan_series).
+                       real_part_func(tan_real_part).
+                       imag_part_func(tan_imag_part).
                        latex_name("\\tan"));
 
 //////////
@@ -896,9 +960,21 @@ static ex sinh_deriv(const ex & x, unsigned deriv_param)
        return cosh(x);
 }
 
+static ex sinh_real_part(const ex & x)
+{
+       return sinh(GiNaC::real_part(x))*cos(GiNaC::imag_part(x));
+}
+
+static ex sinh_imag_part(const ex & x)
+{
+       return cosh(GiNaC::real_part(x))*sin(GiNaC::imag_part(x));
+}
+
 REGISTER_FUNCTION(sinh, eval_func(sinh_eval).
                         evalf_func(sinh_evalf).
                         derivative_func(sinh_deriv).
+                        real_part_func(sinh_real_part).
+                        imag_part_func(sinh_imag_part).
                         latex_name("\\sinh"));
 
 //////////
@@ -961,9 +1037,21 @@ static ex cosh_deriv(const ex & x, unsigned deriv_param)
        return sinh(x);
 }
 
+static ex cosh_real_part(const ex & x)
+{
+       return cosh(GiNaC::real_part(x))*cos(GiNaC::imag_part(x));
+}
+
+static ex cosh_imag_part(const ex & x)
+{
+       return sinh(GiNaC::real_part(x))*sin(GiNaC::imag_part(x));
+}
+
 REGISTER_FUNCTION(cosh, eval_func(cosh_eval).
                         evalf_func(cosh_evalf).
                         derivative_func(cosh_deriv).
+                        real_part_func(cosh_real_part).
+                        imag_part_func(cosh_imag_part).
                         latex_name("\\cosh"));
 
 //////////
@@ -1042,10 +1130,26 @@ static ex tanh_series(const ex &x,
        return (sinh(x)/cosh(x)).series(rel, order, options);
 }
 
+static ex tanh_real_part(const ex & x)
+{
+       ex a = GiNaC::real_part(x);
+       ex b = GiNaC::imag_part(x);
+       return tanh(a)/(1+power(tanh(a),2)*power(tan(b),2));
+}
+
+static ex tanh_imag_part(const ex & x)
+{
+       ex a = GiNaC::real_part(x);
+       ex b = GiNaC::imag_part(x);
+       return tan(b)/(1+power(tanh(a),2)*power(tan(b),2));
+}
+
 REGISTER_FUNCTION(tanh, eval_func(tanh_eval).
                         evalf_func(tanh_evalf).
                         derivative_func(tanh_deriv).
                         series_func(tanh_series).
+                        real_part_func(tanh_real_part).
+                        imag_part_func(tanh_imag_part).
                         latex_name("\\tanh"));
 
 //////////
index f62e2d4..3f3b2e6 100644 (file)
@@ -262,6 +262,24 @@ ex matrix::conjugate() const
        return *this;
 }
 
+ex matrix::real_part() const
+{
+       exvector v;
+       v.reserve(m.size());
+       for (exvector::const_iterator i=m.begin(); i!=m.end(); ++i)
+               v.push_back(i->real_part());
+       return matrix(row, col, v);
+}
+
+ex matrix::imag_part() const
+{
+       exvector v;
+       v.reserve(m.size());
+       for (exvector::const_iterator i=m.begin(); i!=m.end(); ++i)
+               v.push_back(i->imag_part());
+       return matrix(row, col, v);
+}
+
 // protected
 
 int matrix::compare_same_type(const basic & other) const
index a1ac7cb..08c9fe8 100644 (file)
@@ -121,6 +121,8 @@ public:
        ex scalar_mul_indexed(const ex & self, const numeric & other) const;
        bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const;
        ex conjugate() const;
+       ex real_part() const;
+       ex imag_part() const;
 
 protected:
        bool match_same_type(const basic & other) const;
index dd929f7..d2dd675 100644 (file)
@@ -461,6 +461,41 @@ ex mul::evalf(int level) const
        return mul(s, overall_coeff.evalf(level));
 }
 
+void mul::find_real_imag(ex & rp, ex & ip) const
+{
+       rp = overall_coeff.real_part();
+       ip = overall_coeff.imag_part();
+       for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) {
+               ex factor = recombine_pair_to_ex(*i);
+               ex new_rp = factor.real_part();
+               ex new_ip = factor.imag_part();
+               if(new_ip.is_zero()) {
+                       rp *= new_rp;
+                       ip *= new_rp;
+               } else {
+                       ex temp = rp*new_rp - ip*new_ip;
+                       ip = ip*new_rp + rp*new_ip;
+                       rp = temp;
+               }
+       }
+       rp = rp.expand();
+       ip = ip.expand();
+}
+
+ex mul::real_part() const
+{
+       ex rp, ip;
+       find_real_imag(rp, ip);
+       return rp;
+}
+
+ex mul::imag_part() const
+{
+       ex rp, ip;
+       find_real_imag(rp, ip);
+       return ip;
+}
+
 ex mul::evalm() const
 {
        // numeric*matrix
index 7730bad..d9023c2 100644 (file)
@@ -55,6 +55,8 @@ public:
        bool has(const ex & other, unsigned options = 0) const;
        ex eval(int level=0) const;
        ex evalf(int level=0) const;
+       ex real_part() const;
+       ex imag_part() const;
        ex evalm() const;
        ex series(const relational & s, int order, unsigned options = 0) const;
        ex normal(exmap & repl, exmap & rev_lookup, int level = 0) const;
@@ -79,6 +81,7 @@ protected:
        void combine_overall_coeff(const ex & c1, const ex & c2);
        bool can_make_flat(const expair & p) const;
        ex expand(unsigned options=0) const;
+       void find_real_imag(ex&, ex&) const;
        
        // new virtual functions which can be overridden by derived classes
        // none
index 81d0653..21f7730 100644 (file)
@@ -508,6 +508,16 @@ ex ncmul::conjugate() const
        return (new ncmul(ev, true))->setflag(status_flags::dynallocated).eval();
 }
 
+ex ncmul::real_part() const
+{
+       return basic::real_part();
+}
+
+ex ncmul::imag_part() const
+{
+       return basic::imag_part();
+}
+
 // protected
 
 /** Implementation of ex::diff() for a non-commutative product. It applies
index cc156d5..d6fb40d 100644 (file)
@@ -65,6 +65,8 @@ public:
        ex thiscontainer(const exvector & v) const;
        ex thiscontainer(std::auto_ptr<exvector> vp) const;
        ex conjugate() const;
+       ex real_part() const;
+       ex imag_part() const;
 
 protected:
        ex derivative(const symbol & s) const;
index 278741f..cc72565 100644 (file)
@@ -687,6 +687,16 @@ ex numeric::conjugate() const
        return numeric(cln::conjugate(this->value));
 }
 
+ex numeric::real_part() const
+{
+       return numeric(cln::realpart(value));
+}
+
+ex numeric::imag_part() const
+{
+       return numeric(cln::imagpart(value));
+}
+
 // protected
 
 int numeric::compare_same_type(const basic &other) const
index ff46063..09603f6 100644 (file)
@@ -120,6 +120,8 @@ public:
        ex smod(const numeric &xi) const;
        numeric max_coefficient() const;
        ex conjugate() const;
+       ex real_part() const;
+       ex imag_part() const;
 protected:
        /** Implementation of ex::diff for a numeric always returns 0.
         *  @see ex::diff */
index 0ebc8dc..75fd2ff 100644 (file)
@@ -40,6 +40,7 @@
 #include "lst.h"
 #include "archive.h"
 #include "utils.h"
+#include "relational.h"
 
 namespace GiNaC {
 
@@ -614,6 +615,59 @@ ex power::conjugate() const
        return (new power(newbasis, newexponent))->setflag(status_flags::dynallocated);
 }
 
+ex power::real_part() const
+{
+       if (exponent.info(info_flags::integer)) {
+               ex basis_real = basis.real_part();
+               if (basis_real == basis)
+                       return *this;
+               realsymbol a("a"),b("b");
+               ex result;
+               if (exponent.info(info_flags::posint))
+                       result = power(a+I*b,exponent);
+               else
+                       result = power(a/(a*a+b*b)-I*b/(a*a+b*b),-exponent);
+               result = result.expand();
+               result = result.real_part();
+               result = result.subs(lst( a==basis_real, b==basis.imag_part() ));
+               return result;
+       }
+       
+       ex a = basis.real_part();
+       ex b = basis.imag_part();
+       ex c = exponent.real_part();
+       ex d = exponent.imag_part();
+       return power(abs(basis),c)*exp(-d*atan2(b,a))*cos(c*atan2(b,a)+d*log(abs(basis)));
+}
+
+ex power::imag_part() const
+{
+       if (exponent.info(info_flags::integer)) {
+               ex basis_real = basis.real_part();
+               if (basis_real == basis)
+                       return 0;
+               realsymbol a("a"),b("b");
+               ex result;
+               if (exponent.info(info_flags::posint))
+                       result = power(a+I*b,exponent);
+               else
+                       result = power(a/(a*a+b*b)-I*b/(a*a+b*b),-exponent);
+               result = result.expand();
+               result = result.imag_part();
+               result = result.subs(lst( a==basis_real, b==basis.imag_part() ));
+               return result;
+       }
+       
+       ex a=basis.real_part();
+       ex b=basis.imag_part();
+       ex c=exponent.real_part();
+       ex d=exponent.imag_part();
+       return
+               power(abs(basis),c)*exp(-d*atan2(b,a))*sin(c*atan2(b,a)+d*log(abs(basis)));
+}
+
+// protected
+
 // protected
 
 /** Implementation of ex::diff() for a power.
index c764524..ad2b4af 100644 (file)
@@ -68,6 +68,8 @@ public:
        ex to_rational(exmap & repl) const;
        ex to_polynomial(exmap & repl) const;
        ex conjugate() const;
+       ex real_part() const;
+       ex imag_part() const;
 protected:
        ex derivative(const symbol & s) const;
        ex eval_ncmul(const exvector & v) const;
index 41ec903..14488ba 100644 (file)
@@ -412,21 +412,53 @@ ex pseries::evalf(int level) const
 
 ex pseries::conjugate() const
 {
+       if(!var.info(info_flags::real))
+               return conjugate_function(*this).hold();
+
        epvector * newseq = conjugateepvector(seq);
-       ex newvar = var.conjugate();
        ex newpoint = point.conjugate();
 
-       if (!newseq     && are_ex_trivially_equal(newvar, var) && are_ex_trivially_equal(point, newpoint)) {
+       if (!newseq     && are_ex_trivially_equal(point, newpoint)) {
                return *this;
        }
 
-       ex result = (new pseries(newvar==newpoint, newseq ? *newseq : seq))->setflag(status_flags::dynallocated);
+       ex result = (new pseries(var==newpoint, newseq ? *newseq : seq))->setflag(status_flags::dynallocated);
        if (newseq) {
                delete newseq;
        }
        return result;
 }
 
+ex pseries::real_part() const
+{
+       if(!var.info(info_flags::real))
+               return real_part_function(*this).hold();
+       ex newpoint = point.real_part();
+       if(newpoint != point)
+               return real_part_function(*this).hold();
+
+       epvector v;
+       v.reserve(seq.size());
+       for(epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i)
+               v.push_back(expair((i->rest).real_part(), i->coeff));
+       return (new pseries(var==point, v))->setflag(status_flags::dynallocated);
+}
+
+ex pseries::imag_part() const
+{
+       if(!var.info(info_flags::real))
+               return imag_part_function(*this).hold();
+       ex newpoint = point.real_part();
+       if(newpoint != point)
+               return imag_part_function(*this).hold();
+
+       epvector v;
+       v.reserve(seq.size());
+       for(epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i)
+               v.push_back(expair((i->rest).imag_part(), i->coeff));
+       return (new pseries(var==point, v))->setflag(status_flags::dynallocated);
+}
+
 ex pseries::eval_integ() const
 {
        epvector *newseq = NULL;
index fe88508..0d1813a 100644 (file)
@@ -56,6 +56,8 @@ public:
        ex normal(exmap & repl, exmap & rev_lookup, int level = 0) const;
        ex expand(unsigned options = 0) const;
        ex conjugate() const;
+       ex real_part() const;
+       ex imag_part() const;
        ex eval_integ() const;
 protected:
        ex derivative(const symbol & s) const;
index 10b38a8..59dda65 100644 (file)
@@ -220,12 +220,26 @@ ex symbol::eval(int level) const
 ex symbol::conjugate() const
 {
        if (this->domain == domain::complex) {
-               return GiNaC::conjugate_function(*this).hold();
+               return conjugate_function(*this).hold();
        } else {
                return *this;
        }
 }
 
+ex symbol::real_part() const
+{
+       if (domain == domain::real)
+               return *this;
+       return real_part_function(*this).hold();
+}
+
+ex symbol::imag_part() const
+{
+       if (domain == domain::real)
+               return 0;
+       return imag_part_function(*this).hold();
+}
+
 bool symbol::is_polynomial(const ex & var) const
 {
        return true;
index b7c17a8..9c7e526 100644 (file)
@@ -75,6 +75,8 @@ public:
        unsigned return_type() const { return ret_type; }
        tinfo_t return_type_tinfo() const { return ret_type_tinfo; }
        ex conjugate() const;
+       ex real_part() const;
+       ex imag_part() const;
        bool is_polynomial(const ex & var) const;
 protected:
        ex derivative(const symbol & s) const;
index 5b43e65..c215237 100644 (file)
@@ -141,6 +141,22 @@ DEFAULT_COMPARE(tensdelta)
 DEFAULT_COMPARE(tensmetric)
 DEFAULT_COMPARE(spinmetric)
 
+bool tensdelta::info(unsigned inf) const
+{
+       if(inf == info_flags::real)
+               return true;
+
+       return false;
+}
+
+bool tensmetric::info(unsigned inf) const
+{
+       if(inf == info_flags::real)
+               return true;
+
+       return false;
+}
+
 int minkmetric::compare_same_type(const basic & other) const
 {
        GINAC_ASSERT(is_a<minkmetric>(other));
@@ -152,6 +168,14 @@ int minkmetric::compare_same_type(const basic & other) const
                return inherited::compare_same_type(other);
 }
 
+bool minkmetric::info(unsigned inf) const
+{
+       if(inf == info_flags::real)
+               return true;
+
+       return false;
+}
+
 int tensepsilon::compare_same_type(const basic & other) const
 {
        GINAC_ASSERT(is_a<tensepsilon>(other));
@@ -165,6 +189,22 @@ int tensepsilon::compare_same_type(const basic & other) const
                return inherited::compare_same_type(other);
 }
 
+bool tensepsilon::info(unsigned inf) const
+{
+       if(inf == info_flags::real)
+               return true;
+
+       return false;
+}
+
+bool spinmetric::info(unsigned inf) const
+{
+       if(inf == info_flags::real)
+               return true;
+
+       return false;
+}
+
 DEFAULT_PRINT_LATEX(tensdelta, "delta", "\\delta")
 DEFAULT_PRINT(tensmetric, "g")
 DEFAULT_PRINT_LATEX(minkmetric, "eta", "\\eta")
index b424ced..d33603a 100644 (file)
@@ -60,6 +60,7 @@ class tensdelta : public tensor
 
        // functions overriding virtual functions from base classes
 public:
+       bool info(unsigned inf) const;
        ex eval_indexed(const basic & i) const;
        bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const;
 
@@ -80,6 +81,7 @@ class tensmetric : public tensor
 
        // functions overriding virtual functions from base classes
 public:
+       bool info(unsigned inf) const;
        ex eval_indexed(const basic & i) const;
        bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const;
 
@@ -104,6 +106,7 @@ public:
 
        // functions overriding virtual functions from base classes
 public:
+       bool info(unsigned inf) const;
        ex eval_indexed(const basic & i) const;
 
        // non-virtual functions in this class
@@ -128,6 +131,7 @@ class spinmetric : public tensmetric
 
        // functions overriding virtual functions from base classes
 public:
+       bool info(unsigned inf) const;
        ex eval_indexed(const basic & i) const;
        bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const;
 
@@ -151,6 +155,7 @@ public:
 
        // functions overriding virtual functions from base classes
 public:
+       bool info(unsigned inf) const;
        ex eval_indexed(const basic & i) const;
        bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const;