normal method
Some basic form of simplification of expressions is called for frequently.
GiNaC provides the method .normal(), which converts a rational function
into an equivalent rational function of the form ‘numerator/denominator’
where numerator and denominator are coprime. If the input expression is already
a fraction, it just finds the GCD of numerator and denominator and cancels it,
otherwise it performs fraction addition and multiplication.
.normal() can also be used on expressions which are not rational functions
as it will replace all non-rational objects (like functions or non-integer
powers) by temporary symbols to bring the expression to the domain of rational
functions before performing the normalization, and re-substituting these
symbols afterwards. This algorithm is also available as a separate method
.to_rational(), described below.
This means that both expressions t1 and t2 are indeed
simplified in this little code snippet:
{
symbol x("x");
ex t1 = (pow(x,2) + 2*x + 1)/(x + 1);
ex t2 = (pow(sin(x),2) + 2*sin(x) + 1)/(sin(x) + 1);
std::cout << "t1 is " << t1.normal() << std::endl;
std::cout << "t2 is " << t2.normal() << std::endl;
}
Of course this works for multivariate polynomials too, so the ratio of
the sample-polynomials from the section about GCD and LCM above would be
normalized to P_a/P_b = (4*y+z)/(y+3*z).
The numerator and denominator of an expression can be obtained with
ex ex::numer();
ex ex::denom();
ex ex::numer_denom();
These functions will first normalize the expression as described above and
then return the numerator, denominator, or both as a list, respectively.
If you need both numerator and denominator, calling numer_denom() is
faster than using numer() and denom() separately.
Some of the methods described so far only work on polynomials or rational functions. GiNaC provides a way to extend the domain of these functions to general expressions by using the temporary replacement algorithm described above. You do this by calling
ex ex::to_polynomial(exmap & m);
ex ex::to_polynomial(lst & l);
or
ex ex::to_rational(exmap & m);
ex ex::to_rational(lst & l);
on the expression to be converted. The supplied exmap or lst
will be filled with the generated temporary symbols and their replacement
expressions in a format that can be used directly for the subs()
method. It can also already contain a list of replacements from an earlier
application of .to_polynomial() or .to_rational(), so it's
possible to use it on multiple expressions and get consistent results.
The difference between .to_polynomial() and .to_rational()
is probably best illustrated with an example:
{
symbol x("x"), y("y");
ex a = 2*x/sin(x) - y/(3*sin(x));
cout << a << endl;
lst lp;
ex p = a.to_polynomial(lp);
cout << " = " << p << "\n with " << lp << endl;
// = symbol3*symbol2*y+2*symbol2*x
// with {symbol2==sin(x)^(-1),symbol3==-1/3}
lst lr;
ex r = a.to_rational(lr);
cout << " = " << r << "\n with " << lr << endl;
// = -1/3*symbol4^(-1)*y+2*symbol4^(-1)*x
// with {symbol4==sin(x)}
}
The following more useful example will print ‘sin(x)-cos(x)’:
{
symbol x("x");
ex a = pow(sin(x), 2) - pow(cos(x), 2);
ex b = sin(x) + cos(x);
ex q;
exmap m;
divide(a.to_polynomial(m), b.to_polynomial(m), q);
cout << q.subs(m) << endl;
}