#ifndef __PROGTEST__ #include #include #include #include #include #include #include #include #include #include #include using namespace std; #endif /* __PROGTEST__ */ template class CDiagonalMatrix { public: // constructor ( n, k ) CDiagonalMatrix( int n, int k ) : _n(n), _k(0) { reshape(k); } // destructor, copy cons, operator = (if needed) ~CDiagonalMatrix() {} // operator () ( row, col ) T_& operator()( int row, int col ) { int diag = std::abs(row - col); if ( diag >= _k || row >= _n || col >= _n ) throw std::out_of_range(""); if (!diag) { return _data[diag][row]; //center } bool mid = row > col; if (mid) { return _data[diag][ (row - diag) ]; } else { // offset return _data[diag][ (_n - diag) + (col - diag) ]; } } // exists ( row, col ) const bool exists( int row, int col ) const { int diag = std::abs(row - col); if ( diag >= _k || row >= _n || col >= _n ) return false; return true; } // reshape ( k ) void reshape( int k ) { if (!k || k > _n) throw std::out_of_range(""); if (k < _k) { _data.resize( k ); _k = k; } else { while ( _k < k ) { _data.emplace_back( _k ? ((_n - _k) * 2) : _n, T_() ); ++_k; } } } private: std::vector< std::vector< T_ > > _data; int _n, _k; }; #ifndef __PROGTEST__ class CTestCnt { public: CTestCnt(int val = 0) : m_Val(val) { c_Inst++; } CTestCnt(const CTestCnt &src) noexcept : m_Val(src.m_Val) { c_Inst++; } CTestCnt(CTestCnt &&src) noexcept : m_Val(src.m_Val) { c_Inst++; } ~CTestCnt(void) noexcept { c_Inst--; } CTestCnt &operator=(CTestCnt src) noexcept { swap(src.m_Val, m_Val); return *this; } inline static size_t c_Inst = 0; private: int m_Val; }; int main(void) { CDiagonalMatrix m1(5, 4); for (int i = 0; i < 5; i++) m1(i, i) = 10 + i; for (int i = 0; i < 4; i++) { m1(i, i + 1) = 20 + i; m1(i + 1, i) = 30 + i; } for (int i = 0; i < 3; i++) { m1(i, i + 2) = 40 + i; m1(i + 2, i) = 50 + i; } m1(0, 3) = 60; m1(1, 4) = 61; m1(3, 0) = 70; m1(4, 1) = 71; CDiagonalMatrix m2(m1); for (int i = 0; i < 5; i++) assert(m2(i, i) == 10 + i); for (int i = 0; i < 4; i++) { assert(m2(i, i + 1) == 20 + i); assert(m2(i + 1, i) == 30 + i); } for (int i = 0; i < 3; i++) { assert(m2(i, i + 2) == 40 + i); assert(m2(i + 2, i) == 50 + i); } assert(m2(0, 3) == 60); assert(m2(1, 4) == 61); assert(m2(3, 0) == 70); assert(m2(4, 1) == 71); m2(0, 0) = 100; assert(m1(0, 0) == 10); assert(m2(0, 0) == 100); assert(m1.exists(4, 1) && m1(4, 1) == 71); m1.reshape(2); assert(m1.exists(0, 1) && m1(0, 1) == 20); assert(!m1.exists(0, 2)); try { m1(0, 0) = m1(0, 2); assert("Missing an exception" == nullptr); } catch (const std::out_of_range &e) { // assert(e.what() == "invalid index ( 0, 2 )"s); } m1.reshape(4); assert(m1.exists(0, 1) && m1(0, 1) == 20); assert(m1.exists(0, 2) && m1(0, 2) == 0); try { m1.reshape(6); assert("Missing an exception" == nullptr); } catch (const std::out_of_range &e) { // assert(e.what() == "invalid matrix size"s); } try { CDiagonalMatrix m3(5, 6); assert("Missing an exception" == nullptr); } catch (const std::out_of_range &e) { // assert(e.what() == "invalid matrix size"s); } CDiagonalMatrix m10(12, 1); assert(CTestCnt::c_Inst == 12); m10.reshape(4); assert(CTestCnt::c_Inst == 72); m10.reshape(2); assert(CTestCnt::c_Inst == 34); m10.reshape(11); assert(CTestCnt::c_Inst == 142); m10.reshape(12); assert(CTestCnt::c_Inst == 144); m10.reshape(8); assert(CTestCnt::c_Inst == 124); std::cout << "success!\n"; return EXIT_SUCCESS; } #endif /* __PROGTEST__ */