// Description: Testing for refinable partition
// DocumentationOf: refinable_partition.h
#include "test/test_init.h"
#include <pastel/sys/refinable_partition/refinable_partition.h>
#include <algorithm>
#include <iostream>
namespace
{
typedef RefinablePartition<integer, integer>
Partition;
typedef Partition::Set_Iterator
Set_Iterator;
typedef Partition::Set_ConstIterator
Set_ConstIterator;
typedef Partition::Element_Iterator
Element_Iterator;
typedef Partition::Element_ConstIterator
Element_ConstIterator;
template <integer N, typename Type>
bool same(Type (&data)[N],
Partition::Set_ConstIterator set)
{
if (N != set->elements())
{
return false;
}
std::vector<Type> aSet(
std::begin(data), std::end(data));
std::sort(aSet.begin(), aSet.end());
auto iter = set->cbegin();
auto end = set->cend();
std::vector<Type> bSet;
while(iter != end)
{
bSet.push_back(**iter);
++iter;
}
std::sort(bSet.begin(), bSet.end());
return std::equal(aSet.begin(), aSet.end(),
bSet.begin());
}
}
TEST_CASE("Various (RefinablePartition)")
{
integer data[] = {0, 1, 2, 3, 4};
Partition partition;
Set_Iterator set =
partition.addSet();
partition.insert(
set, std::begin(data), std::end(data));
{
REQUIRE(partition.splits() == 0);
REQUIRE(partition.sets() == 1);
REQUIRE(partition.elements() == 5);
REQUIRE(same(data, partition.setBegin()));
REQUIRE(*partition.setBegin() == 0);
}
partition.mark(
partition.elementBegin());
{
REQUIRE(partition.splits() == 1);
}
partition.mark(
std::next(partition.elementBegin(), 2));
{
REQUIRE(partition.splits() == 1);
}
partition.mark(
std::next(partition.elementBegin(), 4));
{
REQUIRE(partition.setBegin()->marked() == 3);
REQUIRE(partition.setBegin()->unmarked() == 2);
}
partition.split();
{
REQUIRE(partition.splits() == 0);
REQUIRE(partition.sets() == 2);
REQUIRE(partition.elements() == 5);
// In the splitting, the smaller part
// should get the new set.
int data[] = {0, 2, 4};
REQUIRE(same(data, partition.setBegin()));
auto set = partition.setBegin();
++set;
int data2[] = {1, 3};
REQUIRE(same(data2, set));
REQUIRE(set->marked() == 0);
REQUIRE(set->unmarked() == 2);
REQUIRE(set->elements() == 2);
REQUIRE(std::next(partition.elementBegin())->set() == set);
REQUIRE(std::next(partition.elementBegin(), 3)->set() == set);
}
partition.mark(
std::next(partition.elementBegin(), 1));
partition.mark(
std::next(partition.elementBegin(), 3));
{
Partition::Set_ConstIterator set =
partition.setBegin();
++set;
REQUIRE(set->elements() == 2);
REQUIRE(set->marked() == 2);
REQUIRE(set->unmarked() == 0);
REQUIRE(partition.splits() == 1);
}
partition.split();
{
// Nothing should happen when all
// the elements in a set are marked.
REQUIRE(partition.sets() == 2);
REQUIRE(partition.splits() == 0);
}
partition.clear();
REQUIRE(partition.splits() == 0);
REQUIRE(partition.sets() == 0);
REQUIRE(partition.elements() == 0);
}
TEST_CASE("Copy (RefinablePartition)")
{
Partition partition;
Set_ConstIterator set = partition.addSet(0);
partition.insertOne(set, 0);
partition.insertOne(set, 1);
partition.insertOne(set, 2);
partition.mark(partition.elementBegin());
Partition copy(partition);
{
REQUIRE(partition.elements() == copy.elements());
REQUIRE(partition.splits() == copy.splits());
REQUIRE(partition.sets() == copy.sets());
Set_ConstIterator set =
partition.cSetBegin();
Set_ConstIterator copySet =
copy.cSetBegin();
REQUIRE(set->elements() == copySet->elements());
REQUIRE(set->marked() == copySet->marked());
REQUIRE(set->unmarked() == copySet->unmarked());
}
}
namespace
{
void print(const Partition& partition)
{
std::for_each(
partition.cSetBegin()->cbegin(),
partition.cSetBegin()->cend(),
[&](const Element_ConstIterator& element)
{
std::cout << *element << " ";
});
std::cout << std::endl;
}
}
TEST_CASE("Remove (RefinablePartition)")
{
integer data[] = {0, 1, 2, 3, 4};
Partition partition;
partition.addSet(
std::begin(data), std::end(data));
partition.erase(
std::next(partition.elementBegin()));
{
Set_ConstIterator set =
partition.setBegin();
REQUIRE(set->elements() == 4);
REQUIRE(set->marked() == 0);
REQUIRE(set->unmarked() == 4);
REQUIRE(partition.elements() == 4);
REQUIRE(partition.sets() == 1);
integer data[] = {0, 2, 3, 4};
REQUIRE(same(data, set));
}
partition.mark(
std::next(partition.elementBegin()));
{
Set_ConstIterator set =
partition.setBegin();
REQUIRE(set->elements() == 4);
REQUIRE(set->marked() == 1);
REQUIRE(set->unmarked() == 3);
REQUIRE(partition.elements() == 4);
REQUIRE(partition.splits() == 1);
REQUIRE(partition.sets() == 1);
}
partition.erase(
std::next(partition.elementBegin()));
{
Set_ConstIterator set =
partition.setBegin();
REQUIRE(set->elements() == 3);
REQUIRE(set->marked() == 0);
REQUIRE(set->unmarked() == 3);
REQUIRE(partition.elements() == 3);
REQUIRE(partition.splits() == 0);
REQUIRE(partition.sets() == 1);
integer data[] = {0, 3, 4};
REQUIRE(same(data, set));
}
partition.erase(
partition.elementBegin());
partition.erase(
partition.elementBegin());
partition.erase(
partition.elementBegin());
{
Set_ConstIterator set =
partition.setBegin();
REQUIRE(set->elements() == 0);
REQUIRE(set->marked() == 0);
REQUIRE(set->unmarked() == 0);
REQUIRE(partition.elements() == 0);
REQUIRE(partition.splits() == 0);
REQUIRE(partition.sets() == 1);
}
partition.erase(
partition.setBegin());
{
REQUIRE(partition.elements() == 0);
REQUIRE(partition.splits() == 0);
REQUIRE(partition.sets() == 0);
}
Set_Iterator set = partition.addSet(
std::begin(data), std::end(data));
partition.erase(set);
{
REQUIRE(partition.elements() == 0);
REQUIRE(partition.splits() == 0);
REQUIRE(partition.sets() == 0);
}
}