#pragma once /** * @file DenseStorage.h * * @brief Stockage dense pour des données à taille fixe ou dynamique. * * Nom: William Nolin * Code permanent : NOLW76060101 * Email : william.nolin.1@ens.etsmtl.ca * */ #include #include namespace gti320 { enum SizeType { Dynamic = -1 }; /** * Stockage à taille fixe. * * Le nombre de données à stocker est connu au moment de la compilation. * Ce nombre est donné par le paramètre de patron : _Size * * Un tampon (tableau) de taille `_Size_` est alloué sur la pile d'exécution. */ template class DenseStorage { private: _Scalar m_data[_Size]; public: /** * Constructeur par défaut */ DenseStorage() {} /** * Constructeur de copie */ DenseStorage(const DenseStorage &other) { memcpy(m_data, other.m_data, sizeof(m_data)); } /** * Constructeur avec taille spécifiée * * (doit être la même que la taille spécifiée dans le patron) */ explicit DenseStorage(int _size) { } /** * Constructor avec taille (_size) et données initiales (_data). */ explicit DenseStorage(const _Scalar *_data, int _size) { assert(_size >= 0 && _size == _Size); memcpy(m_data, _data, sizeof(_Scalar) * _size); } /** * Opérateur de copie */ DenseStorage &operator=(const DenseStorage &other) { if (this != &other) { assert(other.size() == _Size); memcpy(m_data, other.m_data, sizeof(m_data)); } return *this; } static int size() { return _Size; } /** * Redimensionne le stockage pour qu'il contienne `size` élément. */ void resize(int size) { // Ne rien faire. Invalide pour les matrices à taille fixe. } /** * Mets tous les éléments à zéro. */ void setZero() { memset(m_data, 0, sizeof(_Scalar) * _Size); } /** * Accès au tampon de données (en lecteur seulement) */ const _Scalar *data() const { return &m_data[0]; } /** * Accès au tampon de données (pour lecture et écriture) */ _Scalar *data() { return &m_data[0]; } }; /** * Stockage à taille dynamique. * * Le nombre de données à stocker est déterminé à l'exécution. * Un tampon de la taille demandée doit être alloué sur le tas via * l'opérateur `new []` et la mémoire doit être libérée avec `delete[]` */ template class DenseStorage<_Scalar, Dynamic> { private: _Scalar *m_data; int m_size; public: /** * Constructeur par défaut */ DenseStorage() : m_data(nullptr), m_size(0) {} /** * Constructeur avec taille spécifiée */ explicit DenseStorage(int _size) : m_data(new _Scalar[_size]), m_size(_size) { setZero(); } /** * Constructeur de copie */ DenseStorage(const DenseStorage &other) : m_data(new _Scalar[m_size]), m_size(other.m_size) { memcpy(m_data, other.m_data, m_size * sizeof(_Scalar)); } /** * Opérateur de copie */ DenseStorage &operator=(const DenseStorage &other) { if (m_size != other.size()) { resize(other.size()); } m_size = other.m_size; memcpy(m_data, other.m_data, m_size * sizeof(_Scalar)); return *this; } /** * Destructeur */ ~DenseStorage() { delete[] m_data; } /** * Retourne la taille du tampon */ inline int size() const { return m_size; } /** * Redimensionne le tampon alloué pour le stockage. * La mémoire qui n'est plus utilisée doit être libérée. * * Note :​ Toutes opérations de redimensionnement entraînent une réallocation de mémoire. * Il n’est pas pertinent de copier les données car le résultat serait de toute façon incohérent. */ void resize(int _size) { auto *data = new _Scalar[_size]; delete[] m_data; m_data = data; m_size = _size; setZero(); } /** * Met tous les éléments à zéro. */ void setZero() { memset(m_data, 0, m_size * sizeof(_Scalar)); } /** * Accès au tampon de données (en lecteur seulement) */ const _Scalar *data() const { return m_data; } /** * Accès au tampon de données (pour lecture et écriture) */ _Scalar *data() { return m_data; } }; }