| [ < ] | [ > ] | [ << ] | [ 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] | [ ? ] |
