#include <iostream>
#include <deque>
using namespace std;
template <class T>
struct Operation
{
virtual ~Operation() {}
virtual Operation * Clone() const = 0;
virtual T ApplyDirect (T value) const = 0;
virtual T ApplyInverse(T value) const = 0;
};
template <class T>
struct Add : Operation<T>
{
T amount;
Add(T amount_) : amount(amount_) {}
Add * Clone() const { return new Add(amount); }
T ApplyDirect (T value) const { return value + amount; }
T ApplyInverse(T value) const { return value - amount; }
};
template <class T>
struct Mul : Operation<T>
{
T amount;
Mul(T amount_) : amount(amount_) {}
Mul * Clone() const { return new Mul(amount); }
T ApplyDirect (T value) const { return value * amount; }
T ApplyInverse(T value) const { return value / amount; }
};
template <class T, unsigned N>
class MassiveValArray
{
deque<T> data;
deque<unsigned> changedElements;
deque<Operation<T>*> operations;
void makeSomeCalculations()
{
if (changedElements.empty()) return;
static const unsigned elementsChangedPerCall = 3;
for (unsigned i = 0; i < elementsChangedPerCall; ++ i)
{
unsigned index = changedElements[0] + i;
if (index >= N) break;
data[index] = operations[0]->ApplyDirect(data[index]);
}
changedElements[0] += elementsChangedPerCall;
if (changedElements[0] >= N)
{
changedElements.pop_front();
delete operations[0];
operations.pop_front();
}
}
public:
MassiveValArray() : data(N) {}
MassiveValArray(T initialValue) : data(N, initialValue) {}
~MassiveValArray() { for (unsigned i = 0; i < operations.size(); ++ i) delete operations[i]; }
T Get(unsigned index)
{
if (operations.empty()) return data[index];
makeSomeCalculations();
T ret = data[index];
for (unsigned i = 0, size = operations.size(); i < size; ++ i)
if (changedElements[i] <= index)
ret = operations[i]->ApplyDirect(ret);
return ret;
}
void Set(unsigned index, T value)
{
if (operations.empty()) { data[index] = value; return; }
makeSomeCalculations();
for (unsigned i = operations.size() - 1; i + 1 > 0; -- i)
if (changedElements[i] <= index)
value = operations[i]->ApplyInverse(value);
data[index] = value;
}
void ApplyToAll(const Operation<T> & op)
{
operations.push_back(op.Clone());
changedElements.push_back(0);
makeSomeCalculations();
}
ostream & Print()
{
for (unsigned i = 0; i < N; ++ i)
cout << Get(i) << " ";
return cout << endl;
}
ostream & PrintOpInfo() const
{
unsigned opCount = operations.size();
cout << "stacked ops : " << opCount << endl;
if (opCount > 0)
cout << "front op completion : "
<< changedElements[0] * 100 / N
<< "%" << endl;
return cout;
}
};
int main()
{
MassiveValArray<double, 35> arr(1);
arr.Print();
arr.ApplyToAll(Mul<double>(2.0)); arr.ApplyToAll(Add<double>(1.0));
arr.ApplyToAll(Mul<double>(2.0)); arr.ApplyToAll(Add<double>(3.0));
arr.Set(0, 0.0); arr.Set(1, 1.0); arr.Set(2, 2.0); arr.Set(3, 3.0); arr.Set(4, 4.0); arr.Set(5, 5.0);
cout << "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n" << endl;
arr.PrintOpInfo();
cout << "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n" << endl;
arr.Print() << endl; arr.PrintOpInfo();
cout << "\n=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n" << endl;
arr.Print() << endl; arr.PrintOpInfo();
}