#include <catch2/catch.hpp> #include <alib/vector> #include <alib/type_traits> #include <alib/algorithm> namespace { class Moveable { int& m_moves; int& m_copies; public: Moveable(int& moves, int& copies) : m_moves(moves), m_copies(copies) { m_moves = 0; m_copies = 0; } Moveable(const Moveable& src) : m_moves(src.m_moves), m_copies(src.m_copies) { m_copies++; } Moveable(Moveable&& src) : m_moves(src.m_moves), m_copies(src.m_copies) { m_moves++; } Moveable & operator = ( const Moveable & ) { m_copies ++; return * this; } Moveable & operator = ( Moveable && ) { m_moves ++; return * this; } bool operator<(const Moveable&) const { return false; } }; } TEST_CASE ( "Vector", "[unit][std][container]" ) { SECTION ( "Properties test" ) { ext::vector<int> data = {1, 2, 3, 4}; ext::vector<int> dataRef = {1, 2, 3, 4}; const ext::vector<int>& constData = data; auto iter1 = data.erase ( data.begin ( ) ); CHECK ( iter1 == data.begin ( ) ); auto iter2 = data.erase ( data.rbegin ( ) ); CHECK ( iter2 == data.rbegin ( ) ); CHECK ( data.size ( ) == 2 ); auto iter3 = data.insert ( data.begin ( ), 1 ); CHECK ( iter3 == data.begin ( ) ); auto iter4 = data.insert ( data.rbegin ( ), 4 ); CHECK ( iter4 == data.rbegin ( ) ); CHECK ( data.size ( ) == 4 ); CHECK((std::is_same<decltype(constData[0]), const int&>::value)); CHECK ( data == dataRef ); int moves; int copies; ext::vector < Moveable > vec; vec.push_back ( Moveable ( moves, copies ) ); vec.push_back ( Moveable ( moves, copies ) ); vec.push_back ( Moveable ( moves, copies ) ); vec.push_back ( Moveable ( moves, copies ) ); vec.erase ( ext::unique ( vec.begin ( ), vec.end ( ), [ ] ( const Moveable &, const Moveable & ) { return true; } ), vec.end ( ) ); CHECK ( vec.size ( ) == 1 ); CHECK(copies == 0); } SECTION ( "Vector<bool>" ) { ext::vector < bool > A; A.push_back ( true ); A.push_back ( false ); A.push_back ( true ); A.push_back ( false ); ext::vector < bool > B; B.push_back ( true ); B.push_back ( true ); B.push_back ( false ); B.push_back ( false ); { ext::vector < bool > C = A | B; ext::vector < bool > D = A; D |= B; ext::vector < bool > X; X.push_back ( true ); X.push_back ( true ); X.push_back ( true ); X.push_back ( false ); CAPTURE ( X, C, D ); CHECK ( C == X ); CHECK ( D == X ); } { ext::vector < bool > C = A & B; ext::vector < bool > D = A; D &= B; ext::vector < bool > X; X.push_back ( true ); X.push_back ( false ); X.push_back ( false ); X.push_back ( false ); CHECK ( C == X ); CHECK ( D == X ); } { ext::vector < bool > C = A ^ B; ext::vector < bool > D = A; D ^= B; ext::vector < bool > X; X.push_back ( false ); X.push_back ( true ); X.push_back ( true ); X.push_back ( false ); CHECK ( C == X ); CHECK ( D == X ); } } SECTION ( "vector<bool> 2" ) { auto testOffset = [] ( long offset, long shift ) { unsigned long long shadow = 0x2A76B147D6521C87ULL; ext::vector < bool > data; for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 16 + offset; ++ i ) { data.push_back ( true ); } for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 8; ++ i ) { data.push_back ( ( bool ) ( shadow & ( 1ULL << i ) ) ); } data >>= sizeof ( unsigned long long ) * 6 + shift; ext::vector < bool > ref; for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 10 + offset - shift; ++ i ) { ref.push_back ( true ); } for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 8; ++ i ) { ref.push_back ( ( bool ) ( shadow & ( 1ULL << i ) ) ); } ref.resize ( 192 + offset ); /* std::cout << "offset = " << offset << std::endl; std::cout << "shift = " << shift << std::endl; std::cout << "data = " << data << std::endl; std::cout << "ref = " << ref << std::endl;*/ CHECK ( data == ref ); }; unsigned long long shadow = 0x2A76B147D6521C87ULL; ext::vector < bool > data; for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 8; ++ i ) { data.push_back ( ( bool ) ( shadow & ( 1ULL << i ) ) ); } shadow >>= 10; data >>= 10; ext::vector < bool > ref; for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 8; ++ i ) { ref.push_back ( ( bool ) ( shadow & ( 1ULL << i ) ) ); } CAPTURE ( data ,ref ); CHECK ( data == ref ); for ( long i = - ( long ) sizeof ( unsigned long long ) / 2 ; i < ( long ) sizeof ( unsigned long long ) * 8; ++ i ) for ( long j = - ( long ) sizeof ( unsigned long long ) / 2 ; j < ( long ) sizeof ( unsigned long long ) * 8; ++ j ) testOffset ( i, j ); } SECTION ( "vector<bool> 3" ) { unsigned long long shadow = 0x2A76B147D6521C87ULL; ext::vector < bool > data; for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 8; ++ i ) { data.push_back ( ( bool ) ( shadow & ( 1ULL << i ) ) ); } for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 8; ++ i ) { data.push_back ( ( bool ) ( shadow & ( 1ULL << i ) ) ); } for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 8; ++ i ) { data.push_back ( ( bool ) ( shadow & ( 1ULL << i ) ) ); } ext::vector < bool > data2 = data; data2 >>= 64; data >>= 32; data >>= 16; data >>= 8; data >>= 4; data >>= 2; data >>= 1; data >>= 1; std::cout << "data = " << data << std::endl; std::cout << "data2 = " << data2 << std::endl; data2 >>= 1; data2 >>= 2; data2 >>= 4; data2 >>= 8; data2 >>= 16; data2 >>= 32; data2 >>= 1; data >>= 27; data >>= 17; data >>= 13; data >>= 7; std::cout << "data = " << data << std::endl; std::cout << "data2 = " << data2 << std::endl; CHECK ( data2 == data ); } SECTION ( "vector<bool> 4" ) { auto testOffset = [] ( long offset, long shift ) { unsigned long long shadow = 0x2A76B147D6521C87ULL; ext::vector < bool > data; for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 8 + offset; ++ i ) { data.push_back ( true ); } for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 8; ++ i ) { data.push_back ( ( bool ) ( shadow & ( 1ULL << i ) ) ); } data <<= sizeof ( unsigned long long ) * 2 + shift; ext::vector < bool > ref; for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 2 + shift; ++ i ) { ref.push_back ( false ); } for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 8 + offset; ++ i ) { ref.push_back ( true ); } for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 8; ++ i ) { ref.push_back ( ( bool ) ( shadow & ( 1ULL << i ) ) ); } ref.resize ( 128 + offset ); /* std::cout << "offset = " << offset << std::endl; std::cout << "shift = " << shift << std::endl; std::cout << "data = " << data << std::endl; std::cout << "ref = " << ref << std::endl;*/ CHECK ( data == ref ); }; unsigned long long shadow = 0x2A76B147D6521C87ULL; ext::vector < bool > data; for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 8; ++ i ) { data.push_back ( ( bool ) ( shadow & ( 1ULL << i ) ) ); } shadow <<= 10; data <<= 10; ext::vector < bool > ref; for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 8; ++ i ) { ref.push_back ( ( bool ) ( shadow & ( 1ULL << i ) ) ); } std::cout << "data = " << data << std::endl; std::cout << "ref = " << ref << std::endl; CHECK ( data == ref ); for ( long i = - ( long ) sizeof ( unsigned long long ) / 2 ; i < ( long ) sizeof ( unsigned long long ) * 8; ++ i ) for ( long j = - ( long ) sizeof ( unsigned long long ) / 2 ; j < ( long ) sizeof ( unsigned long long ) * 8; ++ j ) testOffset ( i, j ); } SECTION ( "vector<bool> 5" ) { unsigned long long shadow = 0x2A76B147D6521C87ULL; ext::vector < bool > data; for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 8; ++ i ) { data.push_back ( ( bool ) ( shadow & ( 1ULL << i ) ) ); } for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 8; ++ i ) { data.push_back ( ( bool ) ( shadow & ( 1ULL << i ) ) ); } for ( unsigned i = 0; i < sizeof ( unsigned long long ) * 8; ++ i ) { data.push_back ( ( bool ) ( shadow & ( 1ULL << i ) ) ); } ext::vector < bool > data2 = data; data2 <<= 64; data <<= 32; data <<= 16; data <<= 8; data <<= 4; data <<= 2; data <<= 1; data <<= 1; std::cout << "data = " << data << std::endl; std::cout << "data2 = " << data2 << std::endl; data2 <<= 1; data2 <<= 2; data2 <<= 4; data2 <<= 8; data2 <<= 16; data2 <<= 32; data2 <<= 1; data <<= 27; data <<= 17; data <<= 13; data <<= 7; std::cout << "data = " << data << std::endl; std::cout << "data2 = " << data2 << std::endl; CHECK ( data2 == data ); } SECTION ( "vector<bool> 6" ) { for ( size_t i = 1; i < 1000; i += 31 ) { for ( size_t j = 1; j < 1000; j += 31 ) { ext::vector < bool > first; ext::vector < bool > second; first.resize ( i ); second.resize ( j ); ext::fill ( first ); ext::clear ( second ); ext::vector < bool > res = first & second; CHECK ( ext::any ( res ) == false ); } } } SECTION ( "Test Range" ) { ext::vector < int > data { 1, 2, 3, 4 }; ext::vector < int > data2 ( data.range ( ) ); CHECK ( data == data2 ); int moves; int copies; ext::vector < Moveable > vec; vec.push_back ( Moveable ( moves, copies ) ); vec.push_back ( Moveable ( moves, copies ) ); vec.push_back ( Moveable ( moves, copies ) ); vec.push_back ( Moveable ( moves, copies ) ); ext::vector < Moveable > vec2 ( ext::range ( std::move ( vec ) ) ); CHECK ( copies == 0 ); } }