For some numerical calculations in C++ I have, for example, this complicated expression to evaluate. Given as Mathematica input, in its original form it is
w - 4(w - y)((w - y)^2 y + 6(1 + y)((w - y)y + (1 + y)^2)) /
((w - y)^2 ((w - y)y + 6y^2 + 8y(1 + y)) + (1 + y)^2 (36(w - y)y + 24(1 + y)^2))
The goal is to reduce the number of required floating point operations to evaluate it in C++. Using useful code from Counting multiplications (complexity function) we can see it requires the following operations and their respective counts: {{Times, 22}, {Plus, 18}, {Power, 7}}
. The FullSimplify
'ed expression is a bit shorter
w - 4(w - y)(6 + y(18 + 6w + w^2 + 4(3 + w)y + y^2)) /
(24 + y(w^3 + w^2 (8 + 11y) + (2 + y)(48 + y(30 + y)) + w(36 + y(56 + 11y))))
and requires the following operation counts: {{Times, 16}, {Plus, 18}, {Power, 5}}
.
One way to reduce the number of operations is to identify common components and evaluate them beforehand as temporaries. After staring at the expression for an hour I could find the following substitutions:
f0 = w - y;
f1 = 1 + y;
f00 = f0 f0;
f11 = f1 f1;
f0y = f0 y;
and the expression now reads
w - 4f0(6f1(f11 + f0y) + f00 y) / (f11(24f11 + 36f0y) + f00(6y y + 8f1 y + f0y))
The operation count is now: {{Times, 19}, {Plus, 9}, {Power, 0}}
.
Is there a way to express this process of finding sub-expressions more formally in Mathematica? And automatize it at least for such simple expressions involving only multiplication and addition?
--ffast-math
which probably knows very well how to reorder this kind of expressions. Otherwise - well, I'm intrigued to hear of a solution in Mathematica. $\endgroup$Simplify
. You can see that during all these stages, the expressions get reordered randomly, either by human standards of beauty or length. $\endgroup$--ffast-math
specifically for this purpose. It's enabled only on "unsafe" optimization levels by default if ever. The funniest part about IEEE754 arithmetic is that even summation is an ordered operation;a+b+c
is likely to produce different result froma+c+b
. Compilers wear the consistency straightjacket by default, but if you use--ffast-math
, are relieved (at least to some useful extent) of it. Of course, this is relatively irrelevant point if your question is considered purely on the context of Mathematica. $\endgroup$