PA2-zkouska/diagonal.cpp

210 lines
4.4 KiB
C++

#ifndef __PROGTEST__
#include <cassert>
#include <cmath>
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <list>
#include <forward_list>
#include <algorithm>
#include <memory>
#include <stdexcept>
using namespace std;
#endif /* __PROGTEST__ */
template <typename T_>
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<int> 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<int> 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<int> m3(5, 6);
assert("Missing an exception" == nullptr);
}
catch (const std::out_of_range &e)
{
// assert(e.what() == "invalid matrix size"s);
}
CDiagonalMatrix<CTestCnt> 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__ */