Matrix3D.h (5273B)
1 // File : Matrix3D.h 2 // Date : Wed Nov 23 14:45:22 2016 3 // Author : Fabian Wermelinger 4 // Description: 3D Matrix 5 // Copyright 2016 ETH Zurich. All Rights Reserved. 6 #ifndef MATRIX3D_H_L9MVKQGE 7 #define MATRIX3D_H_L9MVKQGE 8 9 #include <cassert> 10 #include <cstdlib> 11 #include <cstddef> 12 #include <cstring> 13 #include <iostream> 14 15 template <typename T, int XS=0, int XE=0, int YS=0, int YE=0, int ZS=0, int ZE=0> 16 class Matrix3D 17 { 18 public: 19 static constexpr int XSTART = XS; 20 static constexpr int XEND = XE; 21 static constexpr int YSTART = YS; 22 static constexpr int YEND = YE; 23 static constexpr int ZSTART = ZS; 24 static constexpr int ZEND = ZE; 25 26 Matrix3D() : m_Nx(0), m_Ny(0), m_Nz(0), m_allocated(false), m_data(nullptr) { } 27 28 Matrix3D(const int Nx, const int Ny, const int Nz, const T* const data = nullptr) : 29 m_Nx(0), m_Ny(0), m_Nz(0), m_allocated(false), m_data(nullptr) 30 { 31 alloc(Nx, Ny, Nz, data); 32 } 33 34 Matrix3D(const Matrix3D& rhs) : 35 m_Nx(0), m_Ny(0), m_Nz(0), m_allocated(false), m_data(nullptr) 36 { 37 if (rhs.m_allocated) 38 { 39 m_data = _alloc(rhs.m_Nx, rhs.m_Ny, rhs.m_Nz); 40 _copy(rhs.m_data); 41 } 42 } 43 44 Matrix3D(Matrix3D&& rhs) : 45 m_Nx(rhs.m_Nx), m_Ny(rhs.m_Ny), m_Nz(rhs.m_Nz), 46 m_XS(rhs.m_XS), m_XE(rhs.m_XE), m_Xpitch(rhs.m_Xpitch), m_Npitched(rhs.m_Npitched), 47 m_allocated(rhs.m_allocated), m_data(std::move(rhs.m_data)) 48 { } 49 50 ~Matrix3D() { if (m_allocated) free(m_data); } 51 52 Matrix3D& operator=(const Matrix3D& rhs) 53 { 54 if (this != &rhs) 55 { 56 _reset(); 57 if (rhs.m_allocated) 58 { 59 m_data = _alloc(rhs.m_Nx, rhs.m_Ny, rhs.m_Nz); 60 _copy(rhs.m_data); 61 } 62 } 63 return *this; 64 } 65 66 Matrix3D& operator=(Matrix3D&& rhs) 67 { 68 if (this != &rhs) 69 { 70 _reset(); 71 if (rhs.m_allocated) 72 { 73 m_Nx = rhs.m_Nx; 74 m_Ny = rhs.m_Ny; 75 m_Nz = rhs.m_Nz; 76 m_XS = rhs.m_XS; 77 m_XE = rhs.m_XE; 78 m_Xpitch = rhs.m_Xpitch; 79 m_Npitched = rhs.m_Npitched; 80 m_allocated = rhs.m_allocated; 81 m_data = std::move(rhs.m_data); 82 rhs.m_allocated = false; 83 } 84 } 85 return *this; 86 } 87 88 T operator()(const int ix, const int iy, const int iz) const 89 { 90 assert(m_allocated); 91 assert(ix >= XS && ix < m_Nx+XE); 92 assert(iy >= YS && iy < m_Ny+YE); 93 assert(iz >= ZS && iz < m_Nz+ZE); 94 return m_data[(ix-XS) + m_Xpitch*(iy-YS) + m_Xpitch*(m_Ny+YE-YS)*(iz-ZS)]; 95 } 96 97 T& operator()(const int ix, const int iy, const int iz) 98 { 99 assert(m_allocated); 100 assert(ix >= XS && ix < m_Nx+XE); 101 assert(iy >= YS && iy < m_Ny+YE); 102 assert(iz >= ZS && iz < m_Nz+ZE); 103 return m_data[(ix-XS) + m_Xpitch*(iy-YS) + m_Xpitch*(m_Ny+YE-YS)*(iz-ZS)]; 104 } 105 106 inline void alloc(const int Nx, const int Ny, const int Nz, const T* const data = nullptr) 107 { 108 if (m_allocated) free(m_data); 109 m_data = _alloc(Nx, Ny, Nz); 110 111 if (data) 112 { 113 for (int iz = 0; iz < m_Nz; ++iz) 114 for (int iy = 0; iy < m_Ny; ++iy) 115 { 116 const T* const src = data + m_Nx*iy + m_Nx*m_Ny*iz; 117 T* dst = &(this->operator()(0,iy,iz)); 118 memcpy(dst, src, m_Nx*sizeof(T)); 119 } 120 } 121 } 122 123 inline int Nx() const { return m_Nx; } 124 inline int Ny() const { return m_Ny; } 125 inline int Nz() const { return m_Nz; } 126 127 private: 128 int m_Nx; 129 int m_Ny; 130 int m_Nz; 131 int m_XS, m_XE, m_Xpitch; 132 size_t m_Npitched; 133 bool m_allocated; 134 T* m_data; 135 136 inline T* _alloc(const int Nx, const int Ny, const int Nz) 137 { 138 m_Nx = Nx; 139 m_Ny = Ny; 140 m_Nz = Nz; 141 const int alignedElements = _ALIGN_/sizeof(T); 142 m_XS = alignedElements * ((XS - (alignedElements-1))/alignedElements); 143 m_XE = alignedElements * ((XE + (alignedElements-1))/alignedElements); 144 m_Xpitch = m_Nx+m_XE-m_XS; 145 m_Npitched = static_cast<size_t>(m_Xpitch) * static_cast<size_t>(m_Ny+YE-YS) * static_cast<size_t>(m_Nz+ZE-ZS); 146 147 void* pmem; 148 if (posix_memalign(&pmem, _ALIGN_, m_Npitched*sizeof(T))) 149 { 150 std::cerr << "ERROR: Matrix3D: can not allocate memory" << std::endl; 151 abort(); 152 } 153 memset(pmem, 0, m_Npitched*sizeof(T)); 154 m_allocated = true; 155 return (T*)pmem; 156 } 157 158 inline void _copy(const T* const base) 159 { 160 const size_t Nslice = static_cast<size_t>(m_Xpitch) * (m_Ny+YE-YS); 161 for (int iz = 0; iz < m_Nz+ZE-ZS; ++iz) 162 { 163 const T* const src = base + Nslice*iz; 164 T* dst = m_data + Nslice*iz; 165 memcpy(dst, src, Nslice*sizeof(T)); 166 } 167 } 168 169 inline void _reset() 170 { 171 if (m_allocated) free(m_data); 172 m_Nx = m_Ny = m_Nz = m_XS = m_XE = m_Xpitch = m_Npitched = 0; 173 m_allocated = false; 174 m_data = nullptr; 175 } 176 }; 177 178 #endif /* MATRIX3D_H_L9MVKQGE */