[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
5.15.1 Expression output
Expressions can simply be written to any stream:
{ symbol x("x"); ex e = 4.5*I+pow(x,2)*3/2; cout << e << endl; // prints '4.5*I+3/2*x^2' // ... |
The default output format is identical to the ginsh
input syntax and
to that used by most computer algebra systems, but not directly pastable
into a GiNaC C++ program (note that in the above example, pow(x,2)
is printed as ‘x^2’).
It is possible to print expressions in a number of different formats with a set of stream manipulators;
std::ostream & dflt(std::ostream & os); std::ostream & latex(std::ostream & os); std::ostream & tree(std::ostream & os); std::ostream & csrc(std::ostream & os); std::ostream & csrc_float(std::ostream & os); std::ostream & csrc_double(std::ostream & os); std::ostream & csrc_cl_N(std::ostream & os); std::ostream & index_dimensions(std::ostream & os); std::ostream & no_index_dimensions(std::ostream & os); |
The tree
, latex
and csrc
formats are also available in
ginsh
via the print()
, print_latex()
and
print_csrc()
functions, respectively.
All manipulators affect the stream state permanently. To reset the output
format to the default, use the dflt
manipulator:
// ... 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 cout << e << endl; // prints '4.5*I+3/2*x^2' // ... |
If you don't want to affect the format of the stream you're working with,
you can output to a temporary ostringstream
like this:
// ... ostringstream s; s << latex << e; // format of cout remains unchanged cout << s.str() << endl; // prints '4.5 i+\frac{3}{2} x^{2}' // ... |
The csrc
(an alias for csrc_double
), csrc_float
,
csrc_double
and csrc_cl_N
manipulators set the output to a
format that can be directly used in a C or C++ program. The three possible
formats select the data types used for numbers (csrc_cl_N
uses the
classes provided by the CLN library):
// ... cout << "f = " << csrc_float << e << ";\n"; cout << "d = " << csrc_double << e << ";\n"; cout << "n = " << csrc_cl_N << e << ";\n"; // ... |
The above example will produce (note the x^2
being converted to
x*x
):
f = (3.0/2.0)*(x*x)+std::complex<float>(0.0,4.5000000e+00); d = (3.0/2.0)*(x*x)+std::complex<double>(0.0,4.5000000000000000e+00); n = cln::cl_RA("3/2")*(x*x)+cln::complex(cln::cl_I("0"),cln::cl_F("4.5_17")); |
The tree
manipulator allows dumping the internal structure of an
expression for debugging purposes:
// ... cout << tree << e; } |
produces
add, hash=0x0, flags=0x3, nops=2 power, hash=0x0, flags=0x3, nops=2 x (symbol), serial=0, hash=0xc8d5bcdd, flags=0xf 2 (numeric), hash=0x6526b0fa, flags=0xf 3/2 (numeric), hash=0xf9828fbd, flags=0xf ----- overall_coeff 4.5L0i (numeric), hash=0xa40a97e0, flags=0xf ===== |
The latex
output format is for LaTeX parsing in mathematical mode.
It is rather similar to the default format but provides some braces needed
by LaTeX for delimiting boxes and also converts some common objects to
conventional LaTeX names. It is possible to give symbols a special name for
LaTeX output by supplying it as a second argument to the symbol
constructor.
For example, the code snippet
{ symbol x("x", "\\circ"); ex e = lgamma(x).series(x==0,3); cout << latex << e << endl; } |
will print
{(-\ln(\circ))}+{(-\gamma_E)} \circ+{(\frac{1}{12} \pi^{2})} \circ^{2} +\mathcal{O}(\circ^{3}) |
Index dimensions are normally hidden in the output. To make them visible, use
the index_dimensions
manipulator. The dimensions will be written in
square brackets behind each index value in the default and LaTeX output
formats:
{ symbol x("x"), y("y"); varidx mu(symbol("mu"), 4), nu(symbol("nu"), 4); ex e = indexed(x, mu) * indexed(y, nu); cout << e << endl; // prints 'x~mu*y~nu' cout << index_dimensions << e << endl; // prints 'x~mu[4]*y~nu[4]' cout << no_index_dimensions << e << endl; // prints 'x~mu*y~nu' } |
If you need any fancy special output format, e.g. for interfacing GiNaC with other algebra systems or for producing code for different programming languages, you can always traverse the expression tree yourself:
static void my_print(const ex & e) { if (is_a<function>(e)) cout << ex_to<function>(e).get_name(); else cout << ex_to<basic>(e).class_name(); cout << "("; size_t n = e.nops(); if (n) for (size_t i=0; i<n; i++) { my_print(e.op(i)); if (i != n-1) cout << ","; } else cout << e; cout << ")"; } int main() { my_print(pow(3, x) - 2 * sin(y / Pi)); cout << endl; return 0; } |
This will produce
add(power(numeric(3),symbol(x)),mul(sin(mul(power(constant(Pi),numeric(-1)), symbol(y))),numeric(-2))) |
If you need an output format that makes it possible to accurately
reconstruct an expression by feeding the output to a suitable parser or
object factory, you should consider storing the expression in an
archive
object and reading the object properties from there.
See the section on archiving for more information.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |