00001 #ifndef GAMMA_CONTAINERS_H_INC
00002 #define GAMMA_CONTAINERS_H_INC
00003
00004
00005
00006
00007
00008
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; }
00027 void operator()(uint32_t v){ mBitsI = scl::log2(convert(v)); mBitsF = 32U - mBitsI; }
00028 static uint32_t convert(uint32_t v){ v=scl::ceilPow2(v); return v!=1 ? v : 2; }
00029 uint32_t mBitsI;
00030 uint32_t mBitsF;
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
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
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();
00318 T dly = (*this)[pos()];
00319 (*this)[pos()] = input;
00320 return dly;
00321 }
00322 };
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
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(){
00378
00379
00380
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
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
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
00426 if(newElems){
00427
00428 uint32_t nOldToCopy = newSize<size() ? newSize : size();
00429
00430
00431 for(uint32_t i=0; i<nOldToCopy; ++i){
00432 A::construct(newElems+i, (*this)[i]);
00433 }
00434
00435
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
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
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
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();
00494 (*this)[pos()] = v;
00495 }
00496
00497 TEM void Ring<T,A>::copy(T * dst, uint32_t len, uint32_t delay) const{
00498
00499
00500 uint32_t tap = (uint32_t)scl::wrap((int32_t)pos() - (int32_t)delay, (int32_t)size());
00501
00502
00503
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 }
00540 #endif