FLAMEGPU2 icon indicating copy to clipboard operation
FLAMEGPU2 copied to clipboard

RunPlan / RunPlanVectory operator+ and operator+=

Open ptheywood opened this issue 3 years ago • 0 comments

Currently RunPlan and RunPlanVector have several operator+ and operator+= operator overloads, which combine one or more plans into a single RunPlanVector.

I.e. (for illustration only)

flamegpu::RunPlanVector AB(model, 2); // Contains 2 plans, [A, B]
flamegpu::RunPlanVector CD(model, 2); // Contains 2 plans, [C, D]
flamegpu::RunPlan E(model); // A single Plan, E

// vector + vector
flamegpu::RunPlan ABCD = AB + CD; // contains [A, B, C, D]

// Vector += vector
flamegpu::RunPlan ABCD(model, 0); 
ABCD += AB;
ABCD += CD; // Contains [A, B, C, D]

// Vector + Plan
flamegpu::RunPlanVector ABE = AB + E; // Contains [A, B, E]

// Vector += Plan
flamegpu::RunPlanVector ABE(model, 0);
ABE += AB;
ABE += E; // Contains [A, B, E]

However, as a vector is used internally, this is implemented as push_back only, which leads to potentially unexpected orders when operator+

I.e. (for illustration only)

flamegpu::RunPlanVector AB(model, 2); // Contains 2 plans, [A, B]
flamegpu::RunPlanVector CD(model, 2); // Contains 2 plans, [C, D]
flamegpu::RunPlan E(model); // A single Plan, E

// vector + vector
flamegpu::RunPlan CDAB = CD + AB; // contains [A, B, C, D] - i.e. it was an append not a prepend

// Vector += vector
flamegpu::RunPlan CDAB(model, 0); 
CDAB += AB;
CDAB += CD; // Contains [A, B, C, D], not the expected/intended  [C, D, A, B]

// Vector + Plan
flamegpu::RunPlanVector EAB = E + AB; // Contains [A, B, E] - not the intended/expected [E, A, B]

// Vector += Plan
flamegpu::RunPlanVector EAB(model, 0);
ABE += E;
ABE += AB; // Contains [A, B, E] as expected. Cannot directly E+= AB would however not make sense / be possible.

We could define/implement operator+(lhs, rhs) outside of the classes (and/or friend it in) to enable append / prepend behaviour, but this doesn't make sense for operator+=, nor versions which return a reference like the current implementations.

Given this is essentially a thin wrapper around std::vector, instead we could just implement push_back rather than provide these operator overloads. This might not be as user-friendly, but also avoids operator+ leading to confusion of order.

Or as another alternative, we could move to an underlying implementation other than Vector, which supports high performance prepend/push_front operations (std::list?). There might be other consequences of this, but I think this would still suit the same purpose, and grand-scheme the performance of run plan construction will be negligible compared to the simulations themselves.

Any of these will be a breaking change, so sooner rather than later is better.

These are also not being wrapped correctly by swig currently, so this should be addressed at the same time.

ptheywood avatar Sep 02 '21 17:09 ptheywood