2

I am Trying to write a Matrix calculator, and have come across a difficulty. If I have A = B*C, then B*C is evaluated with my overloaded operator*(const Matrix&), in which I need some Temporary object for my calculations. This works fine. But once I come to more complicated stuff, I need more temporary objects, and obviously I don't want to do that by hand/have a miximum.

Say i want to evaluate:

Matrix A = B*C + D*E*F + G*H;

Then operator precedence tells me, that the * will be evaluated first. So:

Step 1) B*C -> t1
Step 2) D*E -> t2
Step 3) t2*F-> t3
Step 4) G*H -> t4
Step 5) t1+t2 -> t5
Step 6) t5+t4 -> t6
Step 7) A=t6

Is this the exact order? Or is the order non deterministic? My idea was to create A linked list, and i will check in my + and *, if the objects that are being calculated (eg. t2*F) are temporary, then I can remove them/insert appropriately.

timrau
  • 22,578
  • 4
  • 51
  • 64
spooky
  • 33
  • 1
  • 4
  • I have no idea what you're asking with the linked list, but the precise order of evaluation is unspecified. `B*C` will get evaluated before the `+` does, but you cannot assume that `B*C` is sequenced before `D*E*F` or `G*H`. – Barry May 08 '15 at 19:35
  • You should do some reading on [Order of operations](http://en.wikipedia.org/wiki/Order_of_operations) and possible using [Reverse Polish Notation Evaluation](http://stackoverflow.com/questions/22128772/rpn-evaluation-c) – NathanOliver May 08 '15 at 19:35
  • 1
    You have two questions followed by a statement of what you want to do. What's the perceived problem you are trying to solve? Does it depend on the answers to your questions? – R Sahu May 08 '15 at 19:41

3 Answers3

2

Expression templates can solve this problem. For example

Matrix M = 2*(A+B) + C;

Would normally create 3 temporary objects for A+B, 2*(A+B), 2*(A+B) + C. So this could get inefficient when Matrix objects are heavyweight.

Expression templates are a template metaprogramming technique where the operators are instead implemented such that they return an object that represents the entire expression, but compute the expression only at the end.

So 2*(A+B) + C would yield an object of a type something like

sum<multiple<float, sum<Matrix, Matrix>>, Matrix>

Which is capable of calculating M without allocating intermediary matrices. (in this case by component-wise addition and multiplication by a constant). That object itself is generated at zero runtime overhead.

Because this is complex, it may be better to use a linear algebra library for this, for example Eigen.

tmlen
  • 8,533
  • 5
  • 31
  • 84
  • Note that rvalue references can reduce the number of temporary objects which need to be created, but not the number of loops. Expression templates are the right way to get good cache behavior. – Ben Voigt May 08 '15 at 21:25
0

Operator precedence does not tell you which order things will be evaluated in. It tells you what the operands are for each operator.

The only guarantee of order of evaluation is that an operator's operands must be evaluated before that operator can operate.

To look at a simpler example, 2 + 3 * 4, precedence says that the thing being added to 2 is 3 * 4, as opposed to 3.


In your example B*C + D*E*F + G*H the only guarantees are:

  • G*H is evaluated before the second +
  • B*C is evaluated before the first +
  • D*E*F is evaluated before either +
  • The first + is evaluated before the second +
  • Within D*E*F, the first * is evaluated before the second *.

A possible ordering might be:

(1) D*E
(2) G*H
(3) B*C
(4) 1*F
(5) 3+4
(6) 5+2

Also note that if B, C etc. require any evaluation themselves , then those evaluations don't have any relative ordering either.

M.M
  • 138,810
  • 21
  • 208
  • 365
  • note: my answer answers the question in your title, although it seems the "root of the problem" is that you want to eliminate temporary objects; which actually has nothing to do with order of evaluation. Your "linked list" should actually be a tree, and it doesn't matter which order you traverse the tree in so long as you have the tree structure set up correctly. – M.M May 08 '15 at 23:03
  • The tree is easier to code than expression templates, but harder to use in code – M.M May 08 '15 at 23:10
-1

my idea was to create A linked list, and i will check in my + and *, if the objects that are being calculated (eg. t2*F) are temporary, then I can remove them/insert appropriatly.

Don´t.
This makes absolutely no sense, only additional problems. Big times.

The compiler can handle everything for you, you can safely rely on that. C++ is not Assembler-level. Just return temporary stack-based objects (no pointer or anything). The intermediate results of your calculation will clean up themselves.

Matrix operator+(const Matrix&) {...}  
Matrix operator*(const Matrix&) {...}  

and each such function has one temporary object insde to calcualte, which is returned then.
That´s everything you need.

deviantfan
  • 11,268
  • 3
  • 32
  • 49
  • For large matrices, it certainly makes sense to combine operations, performing more calculations in fewer loops. – Ben Voigt May 08 '15 at 21:23