diff --git a/diagonal.cpp b/diagonal.cpp new file mode 100644 index 0000000..55cc556 --- /dev/null +++ b/diagonal.cpp @@ -0,0 +1,210 @@ + +#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__ */ \ No newline at end of file