Gamma  0.9.5
Generic Synthesis Library
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
/Users/ljp/code/gamma/trunk/Gamma/Containers.h
00001 #ifndef GAMMA_CONTAINERS_H_INC
00002 #define GAMMA_CONTAINERS_H_INC
00003 
00004 /*  Gamma - Generic processing library
00005     See COPYRIGHT file for authors and license information
00006 
00007     File Description:
00008     Dynamically sizable generic containers.
00009 */
00010 
00011 #include <stdlib.h>
00012 #include <vector>
00013 #include <map>
00014 
00015 #include "Gamma/Allocator.h"
00016 #include "Gamma/Conversion.h"
00017 #include "Gamma/mem.h"
00018 #include "Gamma/scl.h"
00019 
00020 namespace gam{
00021 
00022 
00024 struct SizeArrayPow2{
00025     SizeArrayPow2(uint32_t size){ (*this)(size); }
00026     uint32_t operator()() const { return (1<<mBitsI) & 0xfffffffe/*avoids 1*/; }
00027     void operator()(uint32_t v){ mBitsI = scl::log2(convert(v)); mBitsF = 32U - mBitsI; /*printf("%d %d\n", mBitsI, mBitsF);*/ }
00028     static uint32_t convert(uint32_t v){ v=scl::ceilPow2(v); return v!=1 ? v : 2; } // should return 0,2,4,8,16,...
00029     uint32_t mBitsI;    // integer portion # bits
00030     uint32_t mBitsF;    // fraction portion # bits
00031 };
00032 
00033 
00035 struct SizeArray{
00036     SizeArray(uint32_t size): mSize(size){}
00037     uint32_t operator()() const { return mSize; }
00038     void operator()(uint32_t v){ mSize = v; }
00039     static uint32_t convert(uint32_t v){ return v; }
00040     uint32_t mSize;
00041 };
00042 
00043 
00045 
00049 template <class T, class S, class A=gam::Allocator<T> >
00050 class ArrayBase : private A{
00051 public:
00052 
00053     ArrayBase();
00054     explicit ArrayBase(uint32_t size);
00055     ArrayBase(uint32_t size, const T& init);
00056     ArrayBase(T * src, uint32_t size);
00057     explicit ArrayBase(ArrayBase<T,S,A>& src);
00058 
00059     virtual ~ArrayBase();
00060 
00062     T& operator[](uint32_t i);
00063     
00065     const T& operator[](uint32_t i) const;
00066     
00068     ArrayBase& assign(const T& v);
00069 
00071     
00076     ArrayBase& assign(const T& v, uint32_t end, uint32_t stride=1, uint32_t start=0);
00077 
00078     T * elems();                    
00079     const T * elems() const;        
00080     uint32_t size() const;          
00081 
00083     void clear();
00084 
00086     
00089     void own();
00090     
00092     bool isSoleOwner() const;
00093     
00094     bool usingExternalSource() const;
00095     
00097     
00101     void resize(uint32_t newSize, const T& c=T());
00102     void source(ArrayBase<T,S,A>& src);     
00103     void source(T * src, uint32_t size);    
00104 
00105     virtual void onResize(){}
00106 
00108     static int references(T* m){
00109         typename RefCount::const_iterator it = refCount().find(m);
00110         return it != refCount().end() ? it->second : 0;
00111     }
00112 
00113 protected:
00114     T * mElems;
00115     S mSize;
00116 
00117     typedef std::map<T *, int> RefCount;
00118 
00119     static RefCount& refCount(){
00120         static RefCount * o = new RefCount;
00121         return *o;
00122     }
00123     
00124     // is memory being managed automatically?
00125     static bool managing(T* m){ return references(m) != 0; }
00126 
00127 private: ArrayBase& operator=(const ArrayBase& v);
00128 };
00129 
00130 
00131 
00133 template <class T, class A=gam::Allocator<T> >
00134 class Array : public ArrayBase<T, SizeArray, A>{
00135 public:
00136     typedef ArrayBase<T, SizeArray, A> Base;
00137 
00138     Array(): Base(){}
00139     explicit Array(uint32_t size): Base(size){}
00140     Array(uint32_t size, const T& init): Base(size, init){}
00141     Array(T * src, uint32_t size): Base(src, size){}
00142     Array(Array& src): Base(src){}
00143 
00144     virtual ~Array(){}
00145 
00146 private: Array& operator=(const Array& v);
00147 };
00148 
00149 
00150 
00152 template <class T, class A=gam::Allocator<T> >
00153 class ArrayPow2 : public ArrayBase<T, SizeArrayPow2, A>{
00154 public:
00155     typedef ArrayBase<T, SizeArrayPow2, A> Base;
00156 
00157     ArrayPow2(): Base(){}
00158     explicit ArrayPow2(uint32_t size): Base(size){}
00159     ArrayPow2(uint32_t size, const T& initial): Base(size, initial){}
00160     ArrayPow2(T * src, uint32_t size): Base(src, size){}
00161     explicit ArrayPow2(const ArrayPow2& src): Base(src){}
00162 
00163     virtual ~ArrayPow2(){}
00164 
00165     uint32_t fracBits() const;              
00166     float fraction(uint32_t phase) const;   
00167     uint32_t index(uint32_t phase) const;   
00168     uint32_t log2Size() const;              
00169     uint32_t oneIndex() const;              
00170 
00171     const T& atPhase(uint32_t phase) const; 
00172     void putPhase(uint32_t phase, T v);     
00173     
00174 private:
00175     using Base::mSize;
00176 private: ArrayPow2& operator=(const ArrayPow2& v);
00177 };
00178 
00179 
00180 
00182 template <class T, class A=gam::Allocator<T> >
00183 class Ring : public Array<T,A> {
00184 public:
00185 
00186     typedef Array<T,A> Base; using Base::elems; using Base::size;
00187 
00190     explicit Ring(uint32_t size=0, const T& value=T());
00191 
00193     T& readBack(){ return (*this)[indexBack()]; }
00194     const T& readBack() const { return (*this)[indexBack()]; }
00195     
00197     T& readFront(){ return (*this)[indexFront()]; }
00198     const T& readFront() const { return (*this)[indexFront()]; }
00199     
00201     T& read(uint32_t ago){ return (*this)[indexPrev(ago)]; }
00202     const T& read(uint32_t ago) const { return (*this)[indexPrev(ago)]; }
00203 
00205     void copy(T * dst, uint32_t len, uint32_t delay) const;
00206     
00208     void copyUnwrap(T * dst, uint32_t len) const;
00209     
00210     uint32_t pos() const;           
00211     bool reachedEnd() const;        
00212     uint32_t indexBack() const;     
00213     uint32_t indexFront() const;    
00214     uint32_t indexPrev(uint32_t ago) const; 
00215 
00216     void operator()(const T& v);    
00217     void pos(uint32_t index);       
00218     void reset();                   
00219     void writeClip(const T& v);     
00220     
00221 protected:
00222     uint32_t mPos;
00223     void incPos();
00224 };
00225 
00226 
00228 template <class T, class A=gam::Allocator<T> >
00229 class RingFill : public Ring<T,A> {
00230 public:
00231     typedef Ring<T,A> Base;
00232     
00235     explicit RingFill(uint32_t size=0, const T& value=T())
00236     :   Base(size, value), mFill(0)
00237     {}
00238 
00240     void operator()(const T& v){
00241         this->Base::operator()(v);
00242         if(mFill < Base::size()) ++mFill;
00243     }
00244     
00246     void reset(){ mFill=0; Base::reset(); }
00247     
00249     
00253     uint32_t fill() const { return mFill; }
00254     
00255 protected:
00256     uint32_t mFill;
00257     virtual void onResize(){ reset(); }
00258 };
00259 
00260 
00261 
00263 
00266 template <class T, class A=gam::Allocator<T> >
00267 class DoubleRing : public Ring<T,A>{
00268 public:
00271     explicit DoubleRing(uint32_t size=0, const T& value=T())
00272     :   Ring<T>(size, value), mRead(size)
00273     {}
00274 
00276     const Array<T,A>& readBuf() const { return mRead; }
00277 
00279     
00282     T * copyUnwrap(){ Ring<T,A>::copyUnwrap(mRead.elems(), mRead.size()); return mRead.elems(); }
00283     
00285     
00288     T * copy(){
00289         mem::deepCopy(mRead.elems(), Ring<T,A>::elems(), mRead.size());
00290         //for(uint32_t i=0; i<read.size(); ++i) construct(read.elems()+i, (*this)[i]);
00291         return mRead.elems();
00292     }
00293 
00295     void resize(int n){ Ring<T,A>::resize(n); mRead.resize(n); }
00296 
00297 protected:  
00298     Array<T,A> mRead;
00299 };
00300 
00301 
00302 
00303 
00305 template <class T, class A=gam::Allocator<T> >
00306 struct DelayN: public Ring<T,A>{
00307     using Ring<T,A>::incPos; using Ring<T,A>::pos;
00308 
00311     explicit DelayN(uint32_t size, const T& value=T())
00312     :   Ring<T,A>(size, value)
00313     {}
00314 
00316     T operator()(const T& input){
00317         incPos();               // inc write pos
00318         T dly = (*this)[pos()]; // read oldest element
00319         (*this)[pos()] = input; // write new element
00320         return dly;             //  ... write pos left at last written element
00321     }
00322 };
00323 
00324 
00325 
00326 
00327 
00328 
00329 // Implementation_______________________________________________________________
00330 
00331 
00332 // ArrayBase
00333 
00334 #define TEM3 template <class T, class S, class A>
00335 #define ARRAYBASE_INIT mElems(0), mSize(0)
00336 
00337 TEM3 ArrayBase<T,S,A>::ArrayBase()
00338 :   ARRAYBASE_INIT{}
00339 
00340 TEM3 ArrayBase<T,S,A>::ArrayBase(uint32_t sz)
00341 :   ARRAYBASE_INIT
00342 {   resize(sz); }
00343 
00344 TEM3 ArrayBase<T,S,A>::ArrayBase(uint32_t sz, const T& initial)
00345 :   ARRAYBASE_INIT
00346 {   resize(sz); for(uint32_t i=0;i<this->size();++i) (*this)[i] = initial; }
00347 
00348 TEM3 ArrayBase<T,S,A>::ArrayBase(T * src, uint32_t sz)
00349 :   ARRAYBASE_INIT
00350 {   source(src, sz); }
00351 
00352 TEM3 ArrayBase<T,S,A>::ArrayBase(ArrayBase<T,S,A>& src)
00353 :   ARRAYBASE_INIT
00354 {   source(src); }
00355 
00356 #undef ARRAYBASE_INIT
00357 
00358 TEM3 ArrayBase<T,S,A>::~ArrayBase(){ clear(); }
00359 
00360 TEM3 inline ArrayBase<T,S,A>& ArrayBase<T,S,A>::assign(const T& v){
00361     return assign(v, size());
00362 }
00363 
00364 TEM3 inline ArrayBase<T,S,A>& ArrayBase<T,S,A>::assign(
00365     const T& v, uint32_t end, uint32_t stride, uint32_t start
00366 ){
00367     for(uint32_t i=start; i<end; i+=stride) A::construct(mElems+i, v);
00368     return *this;
00369 }
00370 
00371 TEM3 inline T& ArrayBase<T,S,A>::operator[](uint32_t i){ return elems()[i]; }
00372 TEM3 inline const T& ArrayBase<T,S,A>::operator[](uint32_t i) const { return elems()[i]; }
00373 
00374 TEM3 inline T * ArrayBase<T,S,A>::elems(){ return mElems; }
00375 TEM3 inline const T * ArrayBase<T,S,A>::elems() const { return mElems; }
00376 
00377 TEM3 void ArrayBase<T,S,A>::clear(){ //printf("ArrayBase::clear(): mElems=%p\n", mElems);
00378     
00379     // We will only attempt to deallocate the data if it exists and is being 
00380     // managed (reference counted) by ArrayBase.
00381     if(mElems && managing(mElems)){
00382         int& c = refCount()[mElems];
00383         --c;
00384         if(0 == c){
00385             refCount().erase(mElems);
00386             for(uint32_t i=0; i<size(); ++i) A::destroy(mElems+i);
00387             A::deallocate(mElems, size());
00388         }
00389         mElems=0; mSize(0);
00390     }
00391 }
00392 
00393 TEM3 void ArrayBase<T,S,A>::own(){  
00394     T * oldElems = elems();
00395     
00396     // If we are not the sole owner, do nothing...
00397     if(!isSoleOwner()){
00398         uint32_t oldSize = size();
00399         clear();
00400         resize(oldSize);
00401         for(uint32_t i=0; i<size(); ++i) A::construct(mElems+i, oldElems[i]);
00402     }
00403 }
00404 
00405 TEM3 bool ArrayBase<T,S,A>::isSoleOwner() const {
00406     return references((T*)elems()) == 1;
00407 }
00408 
00409 TEM3 bool ArrayBase<T,S,A>::usingExternalSource() const {
00410     return elems() && !managing((T*)elems());
00411 }
00412 
00413 TEM3 void ArrayBase<T,S,A>::resize(uint32_t newSize, const T& c){
00414 //printf("ArrayBase::resize() %p\n", this);
00415     newSize = mSize.convert(newSize);
00416 
00417     if(0 == newSize){
00418         clear();
00419     }
00420 
00421     if(newSize != size()){
00422         
00423         T * newElems = A::allocate(newSize);
00424 
00425         // If successful allocation...
00426         if(newElems){
00427 
00428             uint32_t nOldToCopy = newSize<size() ? newSize : size();
00429         
00430             // Copy over old elements
00431             for(uint32_t i=0; i<nOldToCopy; ++i){
00432                 A::construct(newElems+i, (*this)[i]);
00433             }
00434             
00435             // Copy argument into any additional elements
00436             for(uint32_t i=nOldToCopy; i<newSize; ++i){
00437                 A::construct(newElems+i, c);
00438             }
00439         
00440             clear();
00441             mElems = newElems;
00442         
00443             refCount()[mElems] = 1;
00444             mSize(newSize);
00445             onResize();
00446         }
00447     }
00448     //printf("ArrayBase::resize(): mElems=%p, size=%d\n", mElems, size());
00449 }
00450 
00451 TEM3 inline uint32_t ArrayBase<T,S,A>::size() const { return mSize(); }
00452 
00453 TEM3 void ArrayBase<T,S,A>::source(ArrayBase<T,S,A>& src){
00454     source(src.elems(), src.size());
00455 }
00456 
00457 TEM3 void ArrayBase<T,S,A>::source(T * src, uint32_t size){
00458     clear();
00459     if(managing(src)){
00460         ++refCount()[src];
00461     }
00462     mElems = src;
00463     mSize(size);
00464     onResize();
00465 }
00466 
00467 #undef TEM3
00468 
00469 
00470 #define TEM template<class T, class A>
00471 
00472 // ArrayPow2
00473 
00474 TEM inline uint32_t ArrayPow2<T,A>::oneIndex() const { return 1<<fracBits(); }
00475 TEM inline uint32_t ArrayPow2<T,A>::log2Size() const { return mSize.mBitsI; }
00476 TEM inline uint32_t ArrayPow2<T,A>::fracBits() const { return mSize.mBitsF; }
00477 TEM inline uint32_t ArrayPow2<T,A>::index(uint32_t phase) const { return phase >> fracBits(); }
00478 
00479 TEM inline const T& ArrayPow2<T,A>::atPhase(uint32_t phase) const { return (*this)[index(phase)]; }
00480 TEM inline void ArrayPow2<T,A>::putPhase(uint32_t phase, T v){ (*this)[index(phase)] = v; }
00481 
00482 TEM inline float ArrayPow2<T,A>::fraction(uint32_t phase) const{        
00483     return gam::fraction(log2Size(), phase);
00484 }
00485 
00486 
00487 
00488 //---- Ring
00489 
00490 TEM Ring<T,A>::Ring(uint32_t size, const T& v) : Array<T,A>(size,v), mPos(size-1){}
00491 
00492 TEM inline void Ring<T,A>::operator()(const T& v){
00493     incPos();               // inc write pos; do first to avoid out-of-bounds access
00494     (*this)[pos()] = v;     // write new element
00495 }
00496 
00497 TEM void Ring<T,A>::copy(T * dst, uint32_t len, uint32_t delay) const{
00498     // pos() points to most recently written slot
00499     //uint32_t tap = (pos() - delay) % size();
00500     uint32_t tap = (uint32_t)scl::wrap((int32_t)pos() - (int32_t)delay, (int32_t)size());
00501 
00502     // this ensures that we don't copy across the ring tap boundary
00503     // we add one to maxLen because of a fence post anomaly
00504     uint32_t maxLen = (tap < pos() ? (pos() - tap) : (pos() + (size() - tap))) + 1;
00505     len = scl::min(len, maxLen);
00506     
00507     mem::copyFromRing(elems(), size(), tap, dst, len);
00508 }
00509 
00510 TEM void Ring<T,A>::copyUnwrap(T * dst, uint32_t len) const { copy(dst, len, size() - 1); }
00511 
00512 TEM inline uint32_t Ring<T,A>::indexBack() const {
00513     uint32_t i = pos() + 1;
00514     return (i != size()) ? i : 0;
00515 }
00516 
00517 TEM inline uint32_t Ring<T,A>::indexFront() const { return pos(); }
00518 
00519 TEM inline uint32_t Ring<T,A>::indexPrev(uint32_t v) const {
00520     return scl::wrapOnce<int>(pos() - v, size());
00521 }
00522 
00523 TEM inline uint32_t Ring<T,A>::pos() const { return mPos; }
00524 TEM inline bool Ring<T,A>::reachedEnd() const { return pos() == (size()-1); }
00525 
00526 TEM inline void Ring<T,A>::incPos(){ if(++mPos >= size()) mPos = 0; }
00527 TEM void Ring<T,A>::pos(uint32_t index){ mPos = index; }
00528 
00529 TEM void Ring<T,A>::reset(){ pos(size()-1); }
00530 
00531 TEM inline void Ring<T,A>::writeClip(const T& v){
00532     if(mPos < size()){
00533         (*this)[mPos] = v;
00534         mPos++;
00535     }
00536 }
00537 
00538 #undef TEM
00539 } // gam::
00540 #endif