Skip to content

Commit

Permalink
Add test and correct equality test
Browse files Browse the repository at this point in the history
  • Loading branch information
cbritopacheco committed Feb 13, 2025
1 parent 5bd8532 commit 682d81e
Show file tree
Hide file tree
Showing 2 changed files with 191 additions and 27 deletions.
9 changes: 4 additions & 5 deletions src/Rodin/Array.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,17 @@ namespace Rodin

struct IndexArrayEquality
{
inline
bool operator()(const IndexArray& lhs, const IndexArray& rhs) const
{
return (lhs == rhs).all();
if (lhs.size() != rhs.size())
return false;
else
return (lhs == rhs).all();
}
};

struct IndexArraySymmetricEquality
{
inline
bool operator()(const IndexArray& lhs, const IndexArray& rhs) const
{
assert(lhs.size() > 0);
Expand Down Expand Up @@ -66,7 +67,6 @@ namespace Rodin

struct IndexArrayHash
{
inline
size_t operator()(const IndexArray& arr) const
{
size_t seed = 0;
Expand Down Expand Up @@ -119,7 +119,6 @@ namespace Rodin

struct IndexArraySymmetricHash
{
inline
size_t operator()(const IndexArray& arr) const
{
size_t seed = 0;
Expand Down
209 changes: 187 additions & 22 deletions tests/unit/Rodin/ArrayTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

namespace Rodin::Tests::Unit
{
TEST(Rodin_IndexArray_EqualityTest, EqualArrays)
// -----------------------------------------------------------------------------
// IndexArrayEquality Tests
// -----------------------------------------------------------------------------
TEST(IndexArrayEqualityTest, EqualArrays)
{
// Create two arrays with the same size and same elements.
Rodin::IndexArray a(3), b(3);
Expand All @@ -15,7 +18,7 @@ namespace Rodin::Tests::Unit
EXPECT_TRUE(eq(a, b));
}

TEST(Rodin_IndexArray_EqualityTest, DifferentArrays)
TEST(IndexArrayEqualityTest, DifferentArrays)
{
// Create two arrays with same size but differing in at least one element.
Rodin::IndexArray a(3), b(3);
Expand All @@ -26,12 +29,55 @@ namespace Rodin::Tests::Unit
EXPECT_FALSE(eq(a, b));
}

TEST(IndexArrayEqualityTest, DifferentSizes)
{
// Create arrays of different sizes.
Rodin::IndexArray a(3), b(4);
a << 1, 2, 3;
b << 1, 2, 3, 4;

Rodin::IndexArrayEquality eq;
EXPECT_FALSE(eq(a, b));
}

// Additional tests for arrays with sizes 6 through 10.
TEST(IndexArrayEqualityLargeTest, EqualArraysLarge)
{
for (int n = 6; n <= 10; n++)
{
Rodin::IndexArray a(n), b(n);
for (int i = 0; i < n; i++)
{
a(i) = i + 1;
b(i) = i + 1;
}
Rodin::IndexArrayEquality eq;
EXPECT_TRUE(eq(a, b)) << "Equality failed for array size " << n;
}
}

TEST(IndexArrayEqualityLargeTest, DifferentArraysLarge)
{
for (int n = 6; n <= 10; n++)
{
Rodin::IndexArray a(n), b(n);
for (int i = 0; i < n; i++)
{
a(i) = i + 1;
b(i) = i + 1;
}
// Modify one element in b.
b(0) = 999;
Rodin::IndexArrayEquality eq;
EXPECT_FALSE(eq(a, b)) << "Inequality not detected for array size " << n;
}
}

// -----------------------------------------------------------------------------
// IndexArraySymmetricEquality Tests
// -----------------------------------------------------------------------------
TEST(Rodin_IndexArray_SymmetricEqualityTest, SingleElement)
TEST(IndexArraySymmetricEqualityTest, SingleElement)
{
// For size 1, order is trivial.
Rodin::IndexArray a(1), b(1);
a << 5;
b << 5;
Expand All @@ -43,9 +89,8 @@ namespace Rodin::Tests::Unit
EXPECT_FALSE(seq(a, b));
}

TEST(Rodin_IndexArray_SymmetricEqualityTest, TwoElementsOrderIndependent)
TEST(IndexArraySymmetricEqualityTest, TwoElementsOrderIndependent)
{
// For size 2, order should not matter.
Rodin::IndexArray a(2), b(2);
a << 1, 2;
b << 1, 2;
Expand All @@ -55,31 +100,74 @@ namespace Rodin::Tests::Unit
b << 2, 1;
EXPECT_TRUE(seq(a, b));

// Change one element.
b << 2, 3;
EXPECT_FALSE(seq(a, b));
}

TEST(Rodin_IndexArray_SymmetricEqualityTest, ThreeOrMoreElementsPermutation)
TEST(IndexArraySymmetricEqualityTest, ThreeOrMoreElementsPermutation)
{
// For size > 2, the function uses std::is_permutation.
Rodin::IndexArray a(3), b(3);
a << 3, 1, 2;
b << 1, 2, 3;
Rodin::IndexArraySymmetricEquality seq;
EXPECT_TRUE(seq(a, b));

// Not a permutation.
b << 1, 2, 4;
EXPECT_FALSE(seq(a, b));
}

TEST(IndexArraySymmetricEqualityTest, DifferentSizes)
{
// Arrays with different sizes (non-empty) should return false.
Rodin::IndexArray a(3), b(4);
a << 1, 2, 3;
b << 1, 2, 3, 4;
Rodin::IndexArraySymmetricEquality seq;
EXPECT_FALSE(seq(a, b));
}

// Additional tests for arrays with sizes 6 through 10.
TEST(IndexArraySymmetricEqualityLargeTest, PermutationEqualityLarge)
{
for (int n = 6; n <= 10; n++)
{
Rodin::IndexArray a(n), b(n);
for (int i = 0; i < n; i++)
{
a(i) = i + 1;
}
// b is a permutation of a: reverse the order.
for (int i = 0; i < n; i++)
{
b(i) = a(n - i - 1);
}
Rodin::IndexArraySymmetricEquality seq;
EXPECT_TRUE(seq(a, b)) << "Symmetric equality failed for array size " << n;
}
}

TEST(IndexArraySymmetricEqualityLargeTest, DifferentElementsLarge)
{
for (int n = 6; n <= 10; n++)
{
Rodin::IndexArray a(n), b(n);
for (int i = 0; i < n; i++)
{
a(i) = i + 1;
b(i) = i + 1;
}
// Modify one element in b so that b is no longer a permutation of a.
b(0) = 999;
Rodin::IndexArraySymmetricEquality seq;
EXPECT_FALSE(seq(a, b)) << "Symmetric inequality failed for array size " << n;
}
}

// -----------------------------------------------------------------------------
// IndexArrayHash Tests
// -----------------------------------------------------------------------------
TEST(Rodin_IndexArray_HashTest, SameArrayProducesSameHash)
TEST(IndexArrayHashTest, SameArrayProducesSameHash)
{
// Two arrays with the same ordering should have the same hash.
Rodin::IndexArray a(3), b(3);
a << 4, 5, 6;
b << 4, 5, 6;
Expand All @@ -90,25 +178,66 @@ namespace Rodin::Tests::Unit
EXPECT_EQ(hashA, hashB);
}

TEST(Rodin_IndexArray_HashTest, OrderMattersForHash)
TEST(IndexArrayHashTest, OrderMattersForHash)
{
// For IndexArrayHash, order is important.
Rodin::IndexArray a(2), b(2);
a << 10, 20;
b << 20, 10;
Rodin::IndexArrayHash hashFunc;

size_t hashA = hashFunc(a);
size_t hashB = hashFunc(b);
// Although hash collisions can occur in principle, with these small values
// it is very likely that the hash values are different.
// Although hash collisions can occur, with these values it is very unlikely.
EXPECT_NE(hashA, hashB);
}

// Additional tests for arrays with sizes 6 through 10.
TEST(IndexArrayHashLargeTest, SameArrayProducesSameHashLarge)
{
for (int n = 6; n <= 10; n++)
{
Rodin::IndexArray a(n), b(n);
for (int i = 0; i < n; i++)
{
a(i) = i + 10;
b(i) = i + 10;
}
Rodin::IndexArrayHash hashFunc;
size_t hashA = hashFunc(a);
size_t hashB = hashFunc(b);
EXPECT_EQ(hashA, hashB) << "Hash values differ for equal arrays of size " << n;
}
}

TEST(IndexArrayHashLargeTest, OrderMattersLarge)
{
for (int n = 6; n <= 10; n++)
{
Rodin::IndexArray a(n), b(n);
for (int i = 0; i < n; i++)
{
a(i) = i + 1;
b(i) = i + 1;
}
// Reverse b.
for (int i = 0; i < n / 2; i++)
{
std::swap(b(i), b(n - i - 1));
}
Rodin::IndexArrayHash hashFunc;
size_t hashA = hashFunc(a);
size_t hashB = hashFunc(b);
if (!(a == b).all())
{
EXPECT_NE(hashA, hashB) << "Order does not affect hash for array size " << n;
}
}
}

// -----------------------------------------------------------------------------
// IndexArraySymmetricHash Tests
// -----------------------------------------------------------------------------
TEST(Rodin_IndexArray_SymmetricHashTest, SingleElement)
TEST(IndexArraySymmetricHashTest, SingleElement)
{
Rodin::IndexArray a(1), b(1);
a << 7;
Expand All @@ -117,29 +246,65 @@ namespace Rodin::Tests::Unit
EXPECT_EQ(symHash(a), symHash(b));
}

TEST(Rodin_IndexArray_SymmetricHashTest, TwoElementsOrderIndependent)
TEST(IndexArraySymmetricHashTest, TwoElementsOrderIndependent)
{
// For size 2, the symmetric hash should yield the same value regardless of order.
Rodin::IndexArray a(2), b(2);
a << 100, 200;
b << 200, 100;
Rodin::IndexArraySymmetricHash symHash;
EXPECT_EQ(symHash(a), symHash(b));
}

TEST(Rodin_IndexArray_SymmetricHashTest, ThreeOrMoreElementsOrderIndependent)
TEST(IndexArraySymmetricHashTest, ThreeOrMoreElementsOrderIndependent)
{
// For size > 2, symmetric hash should be independent of ordering.
Rodin::IndexArray a(4), b(4);
a << 1, 2, 3, 4;
b << 4, 3, 2, 1;
Rodin::IndexArraySymmetricHash symHash;
EXPECT_EQ(symHash(a), symHash(b));

// Changing an element should change the hash.
b << 4, 3, 2, 5;
EXPECT_NE(symHash(a), symHash(b));
}

// Additional tests for arrays with sizes 6 through 10.
TEST(IndexArraySymmetricHashLargeTest, PermutationHashLarge)
{
for (int n = 6; n <= 10; n++)
{
Rodin::IndexArray a(n), b(n);
for (int i = 0; i < n; i++)
{
a(i) = i + 100;
b(i) = i + 100;
}
// Permute b by reversing its order.
for (int i = 0; i < n / 2; i++)
{
std::swap(b(i), b(n - i - 1));
}
Rodin::IndexArraySymmetricHash symHash;
EXPECT_EQ(symHash(a), symHash(b))
<< "Symmetric hash does not match for permutation of array size " << n;
}
}

TEST(IndexArraySymmetricHashLargeTest, DifferentElementsHashLarge)
{
for (int n = 6; n <= 10; n++)
{
Rodin::IndexArray a(n), b(n);
for (int i = 0; i < n; i++)
{
a(i) = i + 50;
b(i) = i + 50;
}
b(0) = 999;
Rodin::IndexArraySymmetricHash symHash;
EXPECT_NE(symHash(a), symHash(b))
<< "Symmetric hash failed to detect difference for array size " << n;
}
}
}


0 comments on commit 682d81e

Please sign in to comment.