Skip to content

Commit 43b1d15

Browse files
committed
Compressed push and pop
1 parent f67c66e commit 43b1d15

File tree

4 files changed

+324
-25
lines changed

4 files changed

+324
-25
lines changed

include/compressedStack.hpp

Lines changed: 226 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,29 +25,48 @@ template <class T, class D>
2525
class CompressedStack: public Stack<T,D>{
2626
friend class Problem<T,D>;
2727

28-
private:
28+
public:
2929
CompressedStack<T,D>(int size, int space, int buffer, std::shared_ptr<T> context, std::streampos position = std::streampos(0));
30+
CompressedStack<T,D>(int size, int space, int buffer, const Signature<T,D> &sign);
3031

32+
private:
3133
// Internals
3234
Data<T,D> top(int k);
33-
void push(const Data<T,D> &data);
34-
Data<T,D> pop();
35+
void push(const Data<T,D> &data, std::streampos position);
36+
Data<T,D> pop(Problem<T,D> &Problem);
3537
bool isempty();
3638

39+
bool isSecondEmpty();
40+
3741
// Setters
3842
void setContext(std::shared_ptr<T> context);
3943

44+
// Getters
45+
Block<T,D> getFirstPartial(int lvl);
46+
Block<T,D> getCompressed();
47+
ExplicitPointer<T,D> getFirstExplicit();
48+
4049
// IO
4150
std::string toString();
4251

4352
// Push Internals
4453
void pushExplicit(std::shared_ptr<Data<T,D>> elt);
45-
void pushCompressed(std::shared_ptr<Data<T,D>> elt, int lvl);
54+
void pushCompressed(std::shared_ptr<Data<T,D>> elt, int lvl, std::streampos position);
4655
Data<T,D> top();
4756
int topIndex();
4857
void compress();
4958
void resetBlock(Signature<T,D> sign, int lvl);
5059

60+
// Pop Internals
61+
void reconstruct(Problem<T,D> &problem);
62+
void reconstruct(Problem<T,D> &problem,const Signature<T,D> &sign, int lvl);
63+
void popFirst();
64+
void popSecond();
65+
void propagateFirst(int index, int lvl);
66+
void propagateSecond(int index, int lvl);
67+
void emptyFirst(int index, int lvl);
68+
void emptySecond(int index, int lvl);
69+
5170
// Structure constraints
5271
int mSize; // (Expected) size of the input in #elements
5372
int mSpace; // Maximum space order of the compressed stack
@@ -84,6 +103,20 @@ CompressedStack<T,D>::CompressedStack(int size, int space, int buffer, std::shar
84103
mContext = context;
85104
}
86105

106+
template <class T, class D>
107+
CompressedStack<T,D>::CompressedStack(int size, int space, int buffer, const Signature<T,D> &sign)
108+
: mFirst(space, int( ceil(log(size)/log(space)-.1)))
109+
, mSecond(space, int( ceil(log(size)/log(space)-.1)))
110+
, mBuffer(buffer){
111+
mSize = size;
112+
mSpace = space;
113+
mDepth = int( ceil(log(size)/log(space)-.1));
114+
mCompressed = initBlock<T,D>(mSpace);
115+
116+
mPosition = sign.mPosition;
117+
mContext = sign.mContext;
118+
}
119+
87120
/*==============================================================================
88121
Setters : setContext
89122
==============================================================================*/
@@ -92,6 +125,24 @@ void CompressedStack<T,D>::setContext(std::shared_ptr<T> context){
92125
mContext = context;
93126
}
94127

128+
/*==============================================================================
129+
Getters : getFirstPartial
130+
==============================================================================*/
131+
template <class T, class D>
132+
Block<T,D> CompressedStack<T,D>::getFirstPartial(int lvl){
133+
return mFirst.mPartial[lvl];
134+
}
135+
136+
template <class T, class D>
137+
Block<T,D> CompressedStack<T,D>::getCompressed(){
138+
return mCompressed;
139+
}
140+
141+
template <class T, class D>
142+
ExplicitPointer<T,D> CompressedStack<T,D>::getFirstExplicit(){
143+
return mFirst.mExplicit;
144+
}
145+
95146
/*==============================================================================
96147
IO : toString
97148
==============================================================================*/
@@ -111,9 +162,18 @@ std::string CompressedStack<T,D>::toString(){
111162
return str;
112163
}
113164

165+
/*==============================================================================
166+
167+
==============================================================================*/
168+
114169
/*==============================================================================
115170
Stack Functions: push, pop, isempty, compress
116171
==============================================================================*/
172+
template <class T, class D>
173+
bool CompressedStack<T,D>::isSecondEmpty(){
174+
return mSecond.mPartial.empty();
175+
}
176+
117177
// Function that compress the top block of mSecond to a sign in mCompressed
118178
template <class T, class D>
119179
void CompressedStack<T,D>::compress(){
@@ -136,7 +196,7 @@ void CompressedStack<T,D>::resetBlock(Signature<T,D> sign, int lvl){
136196

137197
// Function push that push the data in explicit and index in partial/compressed
138198
template <class T, class D>
139-
void CompressedStack<T,D>::push(const Data<T,D> &elt){
199+
void CompressedStack<T,D>::push(const Data<T,D> &elt, std::streampos position){
140200
// update the buffer (if buffer size is bigger than 0)
141201
std::shared_ptr<Data<T,D>> ptr_elt = std::make_shared<Data<T,D>>(elt);
142202
mBuffer.push(ptr_elt);
@@ -145,7 +205,7 @@ void CompressedStack<T,D>::push(const Data<T,D> &elt){
145205
// update the compressed Blocks at each levels (including fully compressed)
146206
for (int lvl = 0; lvl < mDepth - 1; lvl++) {
147207
std::cout << "Pushing on level " << lvl << std::endl;
148-
pushCompressed(ptr_elt, lvl);
208+
pushCompressed(ptr_elt, lvl, position);
149209
}
150210
}
151211

@@ -188,11 +248,11 @@ void CompressedStack<T,D>::pushExplicit(std::shared_ptr<Data<T,D>> elt){
188248

189249
// Function push for the part. and fully compressed members of the stack
190250
template <class T, class D>
191-
void CompressedStack<T,D>::pushCompressed(std::shared_ptr<Data<T,D>> elt, int lvl){
251+
void CompressedStack<T,D>::pushCompressed(std::shared_ptr<Data<T,D>> elt, int lvl, std::streampos position){
192252
int distSubBlock = std::pow(mSpace,(mDepth - lvl));
193253
int distBlock = distSubBlock * mSpace;
194254
int index = elt->mIndex;
195-
Signature<T,D> sign (index, mPosition, mContext);
255+
Signature<T,D> sign (index, position, mContext);
196256

197257
if (mFirst.isempty(lvl)) {
198258
mFirst.push(sign, lvl);
@@ -229,9 +289,156 @@ void CompressedStack<T,D>::pushCompressed(std::shared_ptr<Data<T,D>> elt, int lv
229289
}
230290

231291
template <class T, class D>
232-
Data<T,D> CompressedStack<T,D>::pop(){
233-
Data<T,D> d (1,1);
234-
return d;
292+
void CompressedStack<T,D>::popFirst(){
293+
// Pop the explicit data from the 1st component
294+
mFirst.mExplicit.pop_back();
295+
296+
int index = topIndex();
297+
if (mDepth > 1) {
298+
if (mFirst.mExplicit.empty()) {
299+
emptyFirst(index, mDepth - 1);
300+
} else {
301+
int newIndex = (*(mFirst.mExplicit.back())).mIndex;
302+
propagateFirst(newIndex, mDepth - 1);
303+
}
304+
}
305+
}
306+
307+
template <class T, class D>
308+
void CompressedStack<T,D>::popSecond(){
309+
// Pop the explicit data from the 2nd component
310+
mSecond.mExplicit.pop_back();
311+
312+
int index = topIndex();
313+
if (mDepth > 1) {
314+
if (mSecond.mExplicit.empty()) {
315+
emptySecond(index, mDepth - 1);
316+
} else {
317+
int newIndex = (*(mSecond.mExplicit.back())).mIndex;
318+
propagateSecond(newIndex, mDepth - 1);
319+
}
320+
}
321+
}
322+
323+
template <class T, class D>
324+
void CompressedStack<T,D>::propagateFirst(int index, int lvl){
325+
for (int i = 0; i < lvl; i++) {
326+
mFirst.mPartial[i].back().mLast = index;
327+
}
328+
}
329+
330+
template <class T, class D>
331+
void CompressedStack<T,D>::propagateSecond(int index, int lvl){
332+
if (mFirst.mPartial.empty()) {
333+
mSecond.mPartial[lvl].back().mLast = index;
334+
if (lvl > 0) {
335+
propagateSecond(index, lvl - 1);
336+
}
337+
} else {
338+
propagateFirst(index, lvl);
339+
}
340+
}
341+
342+
template <class T, class D>
343+
void CompressedStack<T,D>::emptyFirst(int index, int lvl){
344+
mFirst.mPartial[lvl].pop_back();
345+
if (lvl > 0) {
346+
if (mFirst.mPartial[lvl].size() == 0) {
347+
emptyFirst(index, lvl - 1);
348+
} else {
349+
int newIndex = mFirst.mPartial[lvl].back().mLast;
350+
propagateFirst(newIndex, lvl - 1);
351+
}
352+
}
353+
}
354+
355+
template <class T, class D>
356+
void CompressedStack<T,D>::emptySecond(int index, int lvl){
357+
if (mFirst.mPartial[lvl].empty()) {
358+
mSecond.mPartial[lvl].pop_back();
359+
if (lvl > 0) {
360+
if (mSecond.mPartial[lvl].size() == 0) {
361+
emptySecond(index, lvl - 1);
362+
} else {
363+
int newIndex = mSecond.mPartial[lvl].back().mLast;
364+
propagateSecond(newIndex, lvl - 1);
365+
}
366+
}
367+
} else {
368+
emptyFirst(index, lvl);
369+
}
370+
}
371+
372+
// Look for the first level of information available to reconstruct
373+
template <class T, class D>
374+
void CompressedStack<T,D>::reconstruct(Problem<T,D> &problem){
375+
for (int i = 1; i <= mDepth; i++) {
376+
int lvl = mDepth - 1 - i; // lvl == -1 is for the fully compressed part
377+
if (lvl < 0) {
378+
Signature<T,D> sign = Signature<T,D>(mCompressed.back());
379+
reconstruct(problem, sign, lvl + 1);
380+
break;
381+
} else {
382+
if (mFirst.mPartial[lvl].empty()) {
383+
Signature<T,D> sign = Signature<T,D>(mFirst.mPartial[lvl].back());
384+
reconstruct(problem, sign, lvl + 1);
385+
break;
386+
} else if (mSecond.mPartial[lvl].empty()) {
387+
Signature<T,D> sign = Signature<T,D>(mSecond.mPartial[lvl].back());
388+
reconstruct(problem, sign, lvl + 1);
389+
break;
390+
}
391+
}
392+
}
393+
}
394+
395+
// Reconstruct an auxiliary stack based on the signature found above
396+
template <class T, class D>
397+
void CompressedStack<T,D>::reconstruct(Problem<T,D> &problem, const Signature<T,D> &sign, int lvl){
398+
std::streampos posReminder = mPosition;
399+
int indexReminder = problem.mIndex;
400+
401+
problem.mIndex = sign.mFirst;
402+
int auxSize = std::pow(mSpace, mDepth - lvl);
403+
std::shared_ptr<Stack<T,D>> auxStack = std::make_shared<CompressedStack<T,D>>(auxSize, mSpace, mBuffer.mSize, sign);
404+
405+
// Swap stack pointers + run + swap back
406+
swap(problem.mStack, auxStack);
407+
problem.run(sign.mLast - sign.mFirst);
408+
swap(problem.mStack, auxStack);
409+
problem.mIndex = indexReminder;
410+
mPosition = posReminder;
411+
412+
// Copy the First component of the reconstructed stack into the main stack
413+
int auxDepth = int( ceil(log(auxSize)/log(mSpace)-.1));
414+
int delta = mDepth - auxDepth;
415+
for (int i = 0; i < auxDepth; i++) {
416+
mSecond.mPartial[delta + i] = (*auxStack).getFirstPartial(i);
417+
}
418+
if (lvl == 0) {
419+
if (!(*auxStack).isSecondEmpty()) {
420+
(*auxStack).compress();
421+
}
422+
mCompressed = (*auxStack).getCompressed();
423+
}
424+
mSecond.mExplicit = (*auxStack).getFirstExplicit();
425+
}
426+
427+
template <class T, class D>
428+
Data<T,D> CompressedStack<T,D>::pop(Problem<T,D> &problem){
429+
std::shared_ptr<Data<T,D>> elt;
430+
if (mFirst.mExplicit.empty()) {
431+
if (mSecond.mExplicit.empty()) {
432+
// Reconstruct the compressed stack with the first available signature
433+
reconstruct(problem);
434+
}
435+
elt = mSecond.mExplicit.back();
436+
popSecond();
437+
} else {
438+
elt = mFirst.mExplicit.back();
439+
popFirst();
440+
}
441+
return *elt;
235442
}
236443

237444
template <class T, class D>
@@ -251,9 +458,14 @@ Data<T,D> CompressedStack<T,D>::top(){
251458
}
252459
// Top index of a Compressed Stack
253460
template <class T, class D>
254-
int topIndex(){
255-
Data<T,D> elt = CompressedStack<T,D>::top();
256-
return elt.getIndex();
461+
int CompressedStack<T,D>::topIndex(){
462+
if (mFirst.mExplicit.empty()) {
463+
if (mSecond.mExplicit.empty()) {
464+
return mCompressed.back().mLast;
465+
}
466+
return (*(mSecond.mExplicit.back())).mIndex;
467+
}
468+
return (*(mFirst.mExplicit.back())).mIndex;
257469
}
258470

259471
#endif /* COMPRESSEDSTACK */

0 commit comments

Comments
 (0)