/* ============================================================================== LayerArray.hpp Created: 21 Sep 2014 1:55:15pm Author: jens ============================================================================== */ #ifndef LAYERARRAY_HPP #define LAYERARRAY_HPP #include #include using namespace Eigen; template class LayerArray; template class LayerArrayListener { public: LayerArrayListener() {} virtual~LayerArrayListener() {} virtual void onChanged(const LayerArray &obj) = 0; }; template class LayerArray { class Entry : public T { public: Entry(uint32_t numUnits, const VectorXd *pInit) : T(numUnits, pInit) , pPrev(nullptr) , pNext(nullptr) { } ~Entry() { } Entry *pPrev; Entry *pNext; private: }; public: LayerArray(LayerArrayListener *pListener = nullptr) : m_size(0) , m_pRoot(nullptr) , m_ppIndex(nullptr) , m_pListener(pListener) { } LayerArray(uint32_t numLayers, uint32_t numUnitsPerLayer) : m_size(0) , m_pRoot(nullptr) , m_ppIndex(nullptr) , m_pListener(nullptr) { uint32_t i; for (i=0; i < numLayers; i++) { add(nullptr, numUnitsPerLayer); } } LayerArray (const LayerArray &rhs) : m_size(0) , m_pRoot(nullptr) , m_ppIndex(nullptr) , m_pListener(nullptr) { uint32_t i; for (i=0; i < rhs.getSize(); i++) { this->add(&rhs[i].states(), rhs[i].states().size()); } } virtual ~LayerArray() { m_pListener = nullptr; clear(); } T* add(const VectorXd *pData, uint32_t size) { Entry *pNew; Entry *pL = m_pRoot; pNew = new Entry(size, pData); if (!m_pRoot) { m_pRoot = pNew; } else { pL = m_pRoot; while(pL->pNext) { pL = pL->pNext; } pL->pNext = pNew; pL->pNext->pPrev = pL; } rebuildIndex(); if (m_pListener) m_pListener->onChanged(*this); return (T*)pNew; } void clear() { if (m_ppIndex) { for (int i=0; i < m_size; i++) { if (m_ppIndex[i]) delete m_ppIndex[i]; m_ppIndex[i] = nullptr; } } m_ppIndex = nullptr; m_pRoot = nullptr; m_size = 0; allocIndex(0); if (m_pListener) m_pListener->onChanged(*this); } T& getAt(uint32_t index) const { return *m_ppIndex[index]; } T& operator[](uint32_t index) const { return getAt(index); } void removeAt(uint32_t index) { if (m_ppIndex[index]->pPrev) { m_ppIndex[index]->pPrev->pNext = m_ppIndex[index]->pNext; } else { m_pRoot = m_ppIndex[index]->pNext; m_ppIndex[index]->pNext->pPrev = nullptr; } delete m_ppIndex[index]; m_ppIndex[index] = nullptr; rebuildIndex(); if (m_pListener) m_pListener->onChanged(*this); } uint32_t getSize() const { return m_size; } void save(const char *pFilename) { FILE *pFile; pFile = fopen(pFilename,"w"); if (!pFile) return; fprintf(pFile, "%d\n", m_size); uint32_t i, j; for (i=0; i < m_size; i++) { uint32_t numUnits = m_ppIndex[i]->getNumUnits(); fprintf(pFile, "%d\n", numUnits); for (j=0; j < numUnits; j++) { fprintf(pFile, "%3.6f\n", m_ppIndex[i]->states()(j)); } } fclose(pFile); } void load(const char *pFilename) { uint32_t size = 0; FILE *pFile; pFile = fopen(pFilename,"r"); if (!pFile) return; fscanf(pFile, "%d\n", &size); uint32_t i, j; float v; double *pData; for (i=0; i < size; i++) { uint32_t numUnits; fscanf(pFile, "%d\n", &numUnits); if (numUnits == 0) break; pData = new double[numUnits]; T* data = add(nullptr, numUnits); for (j=0; j < numUnits; j++) { fscanf(pFile, "%f", &v); data->states()(j) = v; } delete [] pData; } fclose(pFile); } private: uint32_t m_size; Entry *m_pRoot; Entry **m_ppIndex; LayerArrayListener *m_pListener; void allocIndex(size_t size) { if (m_ppIndex) { delete [] m_ppIndex; m_ppIndex = nullptr; allocIndex(size); } else { if (size) { m_ppIndex = new Entry*[size]; } } } void rebuildIndex() { Entry *pL; uint32_t size; size = 0; pL = m_pRoot; while(pL) { size++; pL = pL->pNext; } allocIndex(size); size = 0; pL = m_pRoot; while(pL) { m_ppIndex[size++] = pL; pL = pL->pNext; } m_size = size; } }; #endif // LAYERARRAY_HPP