PIVector2D - add funcs, optimize, tests, fixes, doxygen (#194)
Reviewed-on: #194 Co-authored-by: andrey.bychkov <andrey@signalmodelling.ru> Co-committed-by: andrey.bychkov <andrey@signalmodelling.ru>
This commit was merged in pull request #194.
This commit is contained in:
@@ -379,6 +379,419 @@ TEST_F(Vector2DTest, addRow_with_shorter_vector_uses_min) {
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== APPEND ROWS TESTS ====================
|
||||
|
||||
TEST_F(Vector2DTest, appendRows_adds_rows_at_bottom) {
|
||||
size_t oldRows = vec.rows();
|
||||
size_t oldCols = vec.cols();
|
||||
|
||||
vec.appendRows(5, 42);
|
||||
|
||||
EXPECT_EQ(vec.rows(), oldRows + 5);
|
||||
EXPECT_EQ(vec.cols(), oldCols);
|
||||
|
||||
// Original data preserved
|
||||
for (size_t r = 0; r < oldRows; ++r) {
|
||||
for (size_t c = 0; c < oldCols; ++c) {
|
||||
EXPECT_EQ(vec.element(r, c), static_cast<int>(r * COLS_COUNT_INIT + c));
|
||||
}
|
||||
}
|
||||
|
||||
// New rows filled with 42
|
||||
for (size_t r = oldRows; r < vec.rows(); ++r) {
|
||||
for (size_t c = 0; c < oldCols; ++c) {
|
||||
EXPECT_EQ(vec.element(r, c), 42);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, appendRows_with_zero_count_does_nothing) {
|
||||
auto oldVec = vec;
|
||||
vec.appendRows(0);
|
||||
EXPECT_EQ(vec, oldVec);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, appendRows_on_empty_matrix) {
|
||||
PIVector2D<int> empty;
|
||||
empty.appendRows(5, 99);
|
||||
EXPECT_TRUE(empty.isNotEmpty());
|
||||
EXPECT_EQ(empty.rows(), 5);
|
||||
EXPECT_EQ(empty.cols(), 1);
|
||||
EXPECT_EQ(empty.size(), empty.entries(99));
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, appendRows_with_default_value) {
|
||||
size_t oldRows = vec.rows();
|
||||
|
||||
vec.appendRows(3);
|
||||
|
||||
for (size_t r = oldRows; r < vec.rows(); ++r) {
|
||||
for (size_t c = 0; c < vec.cols(); ++c) {
|
||||
EXPECT_EQ(vec.element(r, c), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== APPEND COLUMNS TESTS ====================
|
||||
|
||||
TEST_F(Vector2DTest, appendColumns_adds_columns_at_right) {
|
||||
size_t oldRows = vec.rows();
|
||||
size_t oldCols = vec.cols();
|
||||
|
||||
vec.appendColumns(3, 99);
|
||||
|
||||
EXPECT_EQ(vec.rows(), oldRows);
|
||||
EXPECT_EQ(vec.cols(), oldCols + 3);
|
||||
|
||||
// Original data preserved in original columns
|
||||
for (size_t r = 0; r < oldRows; ++r) {
|
||||
for (size_t c = 0; c < oldCols; ++c) {
|
||||
EXPECT_EQ(vec.element(r, c), static_cast<int>(r * COLS_COUNT_INIT + c));
|
||||
}
|
||||
}
|
||||
|
||||
// New columns filled with 99
|
||||
for (size_t r = 0; r < oldRows; ++r) {
|
||||
for (size_t c = oldCols; c < vec.cols(); ++c) {
|
||||
EXPECT_EQ(vec.element(r, c), 99);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, appendColumns_with_zero_count_does_nothing) {
|
||||
auto oldVec = vec;
|
||||
vec.appendColumns(0);
|
||||
EXPECT_EQ(vec, oldVec);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, appendColumns_on_empty_matrix) {
|
||||
PIVector2D<int> empty;
|
||||
empty.appendColumns(5, 99);
|
||||
EXPECT_TRUE(empty.isNotEmpty());
|
||||
EXPECT_EQ(empty.cols(), 5);
|
||||
EXPECT_EQ(empty.rows(), 1);
|
||||
EXPECT_EQ(empty.size(), empty.entries(99));
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, appendColumns_single_column) {
|
||||
auto oldVec = vec;
|
||||
|
||||
vec.appendColumns(1, 77);
|
||||
|
||||
EXPECT_EQ(vec.rows(), oldVec.rows());
|
||||
EXPECT_EQ(vec.cols(), oldVec.cols() + 1);
|
||||
|
||||
// Check original data
|
||||
for (size_t r = 0; r < vec.rows(); ++r) {
|
||||
for (size_t c = 0; c < oldVec.cols(); ++c) {
|
||||
EXPECT_EQ(vec.element(r, c), oldVec.element(r, c));
|
||||
}
|
||||
}
|
||||
|
||||
// Check new column
|
||||
for (size_t r = 0; r < vec.rows(); ++r) {
|
||||
EXPECT_EQ(vec.element(r, oldVec.cols()), 77);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== DELETE ROWS TESTS ====================
|
||||
|
||||
TEST_F(Vector2DTest, deleteRows_removes_rows_from_middle) {
|
||||
size_t oldRows = vec.rows();
|
||||
size_t oldCols = vec.cols();
|
||||
|
||||
vec.deleteRows(5, 3);
|
||||
|
||||
EXPECT_EQ(vec.rows(), oldRows - 3);
|
||||
EXPECT_EQ(vec.cols(), oldCols);
|
||||
|
||||
// Rows before deleted remain
|
||||
for (size_t r = 0; r < 5; ++r) {
|
||||
for (size_t c = 0; c < oldCols; ++c) {
|
||||
EXPECT_EQ(vec.element(r, c), static_cast<int>(r * COLS_COUNT_INIT + c));
|
||||
}
|
||||
}
|
||||
|
||||
// Rows after deleted shifted up
|
||||
for (size_t r = 5; r < vec.rows(); ++r) {
|
||||
for (size_t c = 0; c < oldCols; ++c) {
|
||||
EXPECT_EQ(vec.element(r, c), static_cast<int>((r + 3) * COLS_COUNT_INIT + c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, deleteRows_at_end_works) {
|
||||
size_t oldRows = vec.rows();
|
||||
size_t oldCols = vec.cols();
|
||||
|
||||
vec.deleteRows(oldRows - 2, 2);
|
||||
|
||||
EXPECT_EQ(vec.rows(), oldRows - 2);
|
||||
EXPECT_EQ(vec.cols(), oldCols);
|
||||
|
||||
// All remaining rows should have original content
|
||||
for (size_t r = 0; r < vec.rows(); ++r) {
|
||||
for (size_t c = 0; c < oldCols; ++c) {
|
||||
EXPECT_EQ(vec.element(r, c), static_cast<int>(r * COLS_COUNT_INIT + c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, deleteRows_beyond_bounds_is_limited) {
|
||||
size_t oldRows = vec.rows();
|
||||
size_t oldCols = vec.cols();
|
||||
size_t count = 10;
|
||||
|
||||
vec.deleteRows(oldRows - 2, count);
|
||||
|
||||
EXPECT_EQ(vec.rows(), oldRows - count);
|
||||
EXPECT_EQ(vec.cols(), oldCols);
|
||||
|
||||
// All remaining rows should have original content
|
||||
for (size_t r = 0; r < oldRows; ++r) {
|
||||
for (size_t c = 0; c < vec.cols(); ++c) {
|
||||
EXPECT_EQ(vec.element(r, c), static_cast<int>(r * COLS_COUNT_INIT + c));
|
||||
}
|
||||
}
|
||||
|
||||
// All new rows should have original content
|
||||
for (size_t r = oldRows; r < vec.rows(); ++r) {
|
||||
for (size_t c = 0; c < vec.cols(); ++c) {
|
||||
EXPECT_EQ(vec.element(r, c), static_cast<int>((r+count) * COLS_COUNT_INIT + c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, deleteRows_invalid_start_does_nothing) {
|
||||
auto oldVec = vec;
|
||||
vec.deleteRows(oldVec.rows() + 10, 2);
|
||||
EXPECT_EQ(vec, oldVec);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, deleteRows_zero_count_does_nothing) {
|
||||
auto oldVec = vec;
|
||||
vec.deleteRows(5, 0);
|
||||
EXPECT_EQ(vec, oldVec);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, deleteRows_all_rows_creates_empty) {
|
||||
vec.deleteRows(0, vec.rows());
|
||||
EXPECT_TRUE(vec.isEmpty());
|
||||
EXPECT_EQ(vec.rows(), 0);
|
||||
EXPECT_EQ(vec.cols(), 0);
|
||||
}
|
||||
|
||||
// ==================== DELETE COLUMNS TESTS ====================
|
||||
|
||||
TEST_F(Vector2DTest, deleteColumns_removes_columns_from_middle) {
|
||||
size_t oldRows = vec.rows();
|
||||
size_t oldCols = vec.cols();
|
||||
|
||||
vec.deleteColumns(4, 3);
|
||||
|
||||
EXPECT_EQ(vec.rows(), oldRows);
|
||||
EXPECT_EQ(vec.cols(), oldCols - 3);
|
||||
|
||||
// Columns before deleted remain
|
||||
for (size_t r = 0; r < oldRows; ++r) {
|
||||
for (size_t c = 0; c < 4; ++c) {
|
||||
EXPECT_EQ(vec.element(r, c), static_cast<int>(r * COLS_COUNT_INIT + c));
|
||||
}
|
||||
}
|
||||
|
||||
// Columns after deleted shifted left
|
||||
for (size_t r = 0; r < oldRows; ++r) {
|
||||
for (size_t c = 4; c < vec.cols(); ++c) {
|
||||
EXPECT_EQ(vec.element(r, c), static_cast<int>(r * COLS_COUNT_INIT + c + 3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, deleteColumns_at_end_works) {
|
||||
size_t oldRows = vec.rows();
|
||||
size_t oldCols = vec.cols();
|
||||
|
||||
vec.deleteColumns(oldCols - 2, 2);
|
||||
|
||||
EXPECT_EQ(vec.rows(), oldRows);
|
||||
EXPECT_EQ(vec.cols(), oldCols - 2);
|
||||
|
||||
// All remaining columns should have original content
|
||||
for (size_t r = 0; r < oldRows; ++r) {
|
||||
for (size_t c = 0; c < vec.cols(); ++c) {
|
||||
EXPECT_EQ(vec.element(r, c), static_cast<int>(r * COLS_COUNT_INIT + c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, deleteColumns_beyond_bounds_is_limited) {
|
||||
size_t oldRows = vec.rows();
|
||||
size_t oldCols = vec.cols();
|
||||
|
||||
vec.deleteColumns(oldCols - 2, 10);
|
||||
|
||||
EXPECT_EQ(vec.rows(), oldRows);
|
||||
EXPECT_EQ(vec.cols(), oldCols - 2);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, deleteColumns_invalid_start_does_nothing) {
|
||||
auto oldVec = vec;
|
||||
vec.deleteColumns(oldVec.cols() + 10, 2);
|
||||
EXPECT_EQ(vec, oldVec);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, deleteColumns_zero_count_does_nothing) {
|
||||
auto oldVec = vec;
|
||||
vec.deleteColumns(5, 0);
|
||||
EXPECT_EQ(vec, oldVec);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, deleteColumns_all_columns_preserves_rows) {
|
||||
vec.deleteColumns(0, vec.cols());
|
||||
EXPECT_EQ(vec.rows(), ROWS_COUNT_INIT);
|
||||
EXPECT_EQ(vec.cols(), 0);
|
||||
EXPECT_EQ(vec.size(), 0);
|
||||
}
|
||||
|
||||
// ==================== ADD COLUMN TESTS ====================
|
||||
|
||||
TEST_F(Vector2DTest, addColumn_appends_column_to_empty) {
|
||||
PIVector2D<int> empty;
|
||||
PIVector<int> newCol(5);
|
||||
for (size_t i = 0; i < 5; ++i)
|
||||
newCol[i] = static_cast<int>(100 + i);
|
||||
|
||||
empty.addColumn(newCol);
|
||||
|
||||
EXPECT_EQ(empty.rows(), 5);
|
||||
EXPECT_EQ(empty.cols(), 1);
|
||||
for (size_t r = 0; r < 5; ++r) {
|
||||
EXPECT_EQ(empty.element(r, 0), static_cast<int>(100 + r));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, addColumn_appends_column_to_existing) {
|
||||
size_t oldRows = vec.rows();
|
||||
size_t oldCols = vec.cols();
|
||||
|
||||
PIVector<int> newCol(oldRows, [](size_t i){return -900 - (int)i;});
|
||||
vec.addColumn(newCol);
|
||||
|
||||
EXPECT_EQ(vec.rows(), oldRows);
|
||||
EXPECT_EQ(vec.cols(), oldCols + 1);
|
||||
|
||||
// Check that old data is preserved
|
||||
for (size_t r = 0; r < oldRows; ++r) {
|
||||
for (size_t c = 0; c < oldCols; ++c) {
|
||||
EXPECT_EQ(vec.element(r, c), static_cast<int>(r * COLS_COUNT_INIT + c));
|
||||
}
|
||||
}
|
||||
|
||||
// Check new column
|
||||
for (size_t r = 0; r < oldRows; ++r) {
|
||||
EXPECT_EQ(vec.element(r, oldCols), -900 - (int)r);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, addColumn_with_shorter_vector_uses_min) {
|
||||
size_t oldRows = vec.rows();
|
||||
size_t oldCols = vec.cols();
|
||||
size_t shortLen = oldRows - 10;
|
||||
PIVector<int> shortCol(shortLen, 777);
|
||||
|
||||
vec.addColumn(shortCol);
|
||||
|
||||
EXPECT_EQ(vec.cols(), oldCols + 1);
|
||||
|
||||
// First shortLen rows should be 777
|
||||
for (size_t r = 0; r < shortLen; ++r) {
|
||||
EXPECT_EQ(vec.element(r, oldCols), 777);
|
||||
}
|
||||
// Remaining rows should be default-initialized (0)
|
||||
for (size_t r = shortLen; r < oldRows; ++r) {
|
||||
EXPECT_EQ(vec.element(r, oldCols), 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, addColumn_with_longer_vector_truncates) {
|
||||
size_t oldRows = vec.rows();
|
||||
size_t oldCols = vec.cols();
|
||||
size_t longLen = oldRows + 10;
|
||||
PIVector<int> longCol(longLen, 555);
|
||||
|
||||
vec.addColumn(longCol);
|
||||
|
||||
EXPECT_EQ(vec.cols(), oldCols + 1);
|
||||
|
||||
// All rows should be 555 (only first oldRows elements are used)
|
||||
for (size_t r = 0; r < oldRows; ++r) {
|
||||
EXPECT_EQ(vec.element(r, oldCols), 555);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, addColumn_with_empty_source_does_nothing_on_empty) {
|
||||
PIVector2D<int> empty;
|
||||
PIVector<int> emptyCol;
|
||||
|
||||
empty.addColumn(emptyCol);
|
||||
EXPECT_TRUE(empty.isEmpty());
|
||||
EXPECT_EQ(empty.rows(), 0);
|
||||
EXPECT_EQ(empty.cols(), 0);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, addColumn_with_empty_source_adds_default_column) {
|
||||
auto oldVec = vec;
|
||||
|
||||
vec.addColumn({});
|
||||
|
||||
EXPECT_EQ(vec.cols(), oldVec.cols());
|
||||
EXPECT_EQ(vec.rows(), oldVec.rows());
|
||||
|
||||
for (size_t r = 0; r < oldVec.rows(); ++r) {
|
||||
for (size_t c = 0; c < oldVec.cols(); ++c) {
|
||||
EXPECT_EQ(vec.element(r, c), oldVec.element(r, c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, addColumn_with_Col_proxy_works) {
|
||||
auto oldVec = vec;
|
||||
const size_t colIndex = 5;
|
||||
|
||||
auto srcCol = oldVec.col(colIndex);
|
||||
vec.addColumn(srcCol);
|
||||
|
||||
EXPECT_EQ(vec.cols(), oldVec.cols() + 1);
|
||||
EXPECT_EQ(vec.rows(), oldVec.rows());
|
||||
|
||||
for (size_t r = 0; r < oldVec.rows(); ++r) {
|
||||
for (size_t c = 0; c < oldVec.cols(); ++c) {
|
||||
EXPECT_EQ(vec.element(r, c), oldVec.element(r, c));
|
||||
}
|
||||
}
|
||||
for (size_t r = 0; r < vec.rows(); ++r) {
|
||||
// EXPECT_EQ(vec.element(r, oldVec.cols()), int());
|
||||
EXPECT_EQ(vec.element(r, oldVec.cols()), oldVec.element(r, colIndex));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, addColumn_with_ColConst_proxy_works) {
|
||||
size_t oldRows = vec.rows();
|
||||
size_t oldCols = vec.cols();
|
||||
|
||||
const auto & constVec = vec;
|
||||
auto srcCol = constVec.col(7);
|
||||
// Need a non-const array to add to
|
||||
PIVector2D<int> mutableVec = vec; // copy
|
||||
mutableVec.addColumn(srcCol);
|
||||
|
||||
EXPECT_EQ(mutableVec.cols(), oldCols + 1);
|
||||
|
||||
for (size_t r = 0; r < oldRows; ++r) {
|
||||
EXPECT_EQ(mutableVec.element(r, oldCols), vec.element(r, 7));
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== RESIZE TESTS ====================
|
||||
class Vector2DResizeTest: public Vector2DTest {
|
||||
protected:
|
||||
@@ -470,17 +883,15 @@ TEST_F(Vector2DTest, contains_finds_element_in_flat_vector) {
|
||||
TEST_F(Vector2DTest, contains_with_start_parameter_works) {
|
||||
int target = 10 * COLS_COUNT_INIT + 15;
|
||||
EXPECT_TRUE(vec.contains(target));
|
||||
EXPECT_TRUE(vec.contains(target, target)); // start exactly at target (inclusive)
|
||||
EXPECT_FALSE(vec.contains(target, target + 1)); // start after target
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, contains_vector_of_elements_works) {
|
||||
PIVector<int> searchFor;
|
||||
searchFor << 100 << 200 << 300;
|
||||
EXPECT_TRUE(vec.contains(searchFor));
|
||||
EXPECT_TRUE(vec.asPlainVector().containsAll(searchFor));
|
||||
|
||||
searchFor << -999;
|
||||
EXPECT_FALSE(vec.contains(searchFor));
|
||||
EXPECT_FALSE(vec.asPlainVector().containsAll(searchFor));
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, entries_counts_occurrences) {
|
||||
@@ -652,6 +1063,53 @@ TEST_F(Vector2DTest, transposed_returns_correct_dimensions) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Vector2DTransposeTest, emptyMatrix_returnsEmpty) {
|
||||
PIVector2D<int> empty;
|
||||
auto transposed = empty.transposed();
|
||||
EXPECT_TRUE(transposed.isEmpty());
|
||||
EXPECT_EQ(transposed.rows(), 0);
|
||||
EXPECT_EQ(transposed.cols(), 0);
|
||||
}
|
||||
|
||||
TEST(Vector2DTransposeTest, singleElement_returnsSame) {
|
||||
PIVector2D<int> single(1, 1, 42);
|
||||
auto transposed = single.transposed();
|
||||
EXPECT_EQ(transposed.rows(), 1);
|
||||
EXPECT_EQ(transposed.cols(), 1);
|
||||
EXPECT_EQ(transposed.element(0, 0), 42);
|
||||
}
|
||||
|
||||
TEST(Vector2DTransposeTest, oneRow_becomesOneColumn) {
|
||||
PIVector2D<int> rowVec(1, 5);
|
||||
for (size_t c = 0; c < 5; ++c)
|
||||
rowVec.element(0, c) = static_cast<int>(c);
|
||||
auto transposed = rowVec.transposed();
|
||||
EXPECT_EQ(transposed.rows(), 5);
|
||||
EXPECT_EQ(transposed.cols(), 1);
|
||||
for (size_t r = 0; r < 5; ++r) {
|
||||
EXPECT_EQ(transposed.element(r, 0), static_cast<int>(r));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Vector2DTransposeTest, oneColumn_becomesOneRow) {
|
||||
PIVector2D<int> colVec(5, 1);
|
||||
for (size_t r = 0; r < 5; ++r)
|
||||
colVec.element(r, 0) = static_cast<int>(r);
|
||||
auto transposed = colVec.transposed();
|
||||
EXPECT_EQ(transposed.rows(), 1);
|
||||
EXPECT_EQ(transposed.cols(), 5);
|
||||
for (size_t c = 0; c < 5; ++c) {
|
||||
EXPECT_EQ(transposed.element(0, c), static_cast<int>(c));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, transposed_doesNotModifyOriginal) {
|
||||
auto original = vec; // копия для сравнения
|
||||
auto transposed = vec.transposed();
|
||||
// Проверяем, что исходный массив не изменился
|
||||
EXPECT_EQ(vec, original);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, reverseRows_reverses_row_order) {
|
||||
auto original = vec;
|
||||
vec.reverseRows();
|
||||
@@ -767,36 +1225,36 @@ TEST_F(Vector2DTest, forEach_modifying_changes_elements) {
|
||||
|
||||
TEST_F(Vector2DTest, indexOf_returns_correct_pair) {
|
||||
auto p = vec.indexOf(vec.element(10, 15));
|
||||
EXPECT_EQ(p.first, 10);
|
||||
EXPECT_EQ(p.second, 15);
|
||||
EXPECT_EQ(p.row, 10);
|
||||
EXPECT_EQ(p.col, 15);
|
||||
p = vec.indexOf(-999);
|
||||
EXPECT_EQ(p.first, -1);
|
||||
EXPECT_EQ(p.second, -1);
|
||||
EXPECT_EQ(p.row, -1);
|
||||
EXPECT_EQ(p.col, -1);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, indexWhere_returns_correct_pair) {
|
||||
vec.element(5, 5) = -42;
|
||||
auto isTarget = [](const int & e) { return e == -42; };
|
||||
auto p = vec.indexWhere(isTarget);
|
||||
EXPECT_EQ(p.first, 5);
|
||||
EXPECT_EQ(p.second, 5);
|
||||
EXPECT_EQ(p.row, 5);
|
||||
EXPECT_EQ(p.col, 5);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, lastIndexOf_works) {
|
||||
int val = vec.element(10, 10);
|
||||
vec.element(20, 20) = val; // duplicate
|
||||
auto p = vec.lastIndexOf(val);
|
||||
EXPECT_EQ(p.first, 20);
|
||||
EXPECT_EQ(p.second, 20);
|
||||
EXPECT_EQ(p.row, 20);
|
||||
EXPECT_EQ(p.col, 20);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, lastIndexWhere_works) {
|
||||
auto isLarge = [](const int & e) { return e > 500; };
|
||||
auto p = vec.lastIndexWhere(isLarge);
|
||||
EXPECT_GE(p.first, 0);
|
||||
EXPECT_GE(p.second, 0);
|
||||
EXPECT_GE(p.row, 0);
|
||||
EXPECT_GE(p.col, 0);
|
||||
// The last element with value >500 should be the largest index
|
||||
size_t lastFlat = p.first * vec.cols() + p.second;
|
||||
size_t lastFlat = p.row * vec.cols() + p.col;
|
||||
size_t expectedLastFlat = vec.size() - 1;
|
||||
EXPECT_EQ(lastFlat, expectedLastFlat);
|
||||
}
|
||||
@@ -993,6 +1451,242 @@ TEST(Vector2DEdgeTest, single_element_vector) {
|
||||
EXPECT_EQ(single.element(0, 0), 42);
|
||||
}
|
||||
|
||||
// ==================== PROXY ADDITIONAL OPERATIONS TESTS ====================
|
||||
TEST_F(Vector2DTest, row_proxy_forEach_modifies_elements) {
|
||||
auto row = vec[5];
|
||||
row.forEach([](int & e) { e += 100; });
|
||||
for (size_t c = 0; c < COLS_COUNT_INIT; ++c) {
|
||||
EXPECT_EQ(vec.element(5, c), 5 * COLS_COUNT_INIT + c + 100);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, row_proxy_forEach_const_iterates) {
|
||||
const auto & constVec = vec;
|
||||
auto row = constVec[5];
|
||||
size_t count = 0;
|
||||
row.forEach([&count](const int &) { ++count; });
|
||||
EXPECT_EQ(count, COLS_COUNT_INIT);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, row_proxy_fill_sets_all_elements) {
|
||||
auto row = vec[12];
|
||||
row.fill(999);
|
||||
for (size_t c = 0; c < COLS_COUNT_INIT; ++c) {
|
||||
EXPECT_EQ(vec.element(12, c), 999);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, row_proxy_contains_finds_element) {
|
||||
auto row = vec[8];
|
||||
EXPECT_TRUE(row.contains(vec.element(8, 10)));
|
||||
EXPECT_FALSE(row.contains(-999));
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, row_proxy_entries_counts_occurrences) {
|
||||
auto row = vec[15];
|
||||
// Add a duplicate
|
||||
int val = vec.element(15, 5);
|
||||
vec.element(15, 20) = val;
|
||||
EXPECT_EQ(row.entries(val), 2);
|
||||
EXPECT_EQ(row.entries(-999), 0);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, row_proxy_entries_with_predicate_counts_matches) {
|
||||
auto row = vec[20];
|
||||
auto isEven = [](const int & e) { return e % 2 == 0; };
|
||||
int expected = 0;
|
||||
for (size_t c = 0; c < COLS_COUNT_INIT; ++c) {
|
||||
if (row[c] % 2 == 0) ++expected;
|
||||
}
|
||||
EXPECT_EQ(row.entries(isEven), expected);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, row_proxy_any_returns_true_if_any_match) {
|
||||
auto row = vec[25];
|
||||
auto isNegative = [](const int & e) { return e < 0; };
|
||||
EXPECT_FALSE(row.any(isNegative));
|
||||
auto isPositive = [](const int & e) { return e >= 0; };
|
||||
EXPECT_TRUE(row.any(isPositive));
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, row_proxy_every_returns_true_if_all_match) {
|
||||
auto row = vec[30];
|
||||
auto isLessThanMax = [&](const int & e) { return e < static_cast<int>(vec.size()); };
|
||||
EXPECT_TRUE(row.every(isLessThanMax));
|
||||
auto isEven = [](const int & e) { return e % 2 == 0; };
|
||||
EXPECT_FALSE(row.every(isEven));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
TEST_F(Vector2DTest, col_proxy_forEach_modifies_elements) {
|
||||
auto col = vec.col(7);
|
||||
col.forEach([](int & e) { e += 50; });
|
||||
for (size_t r = 0; r < ROWS_COUNT_INIT; ++r) {
|
||||
EXPECT_EQ(vec.element(r, 7), r * COLS_COUNT_INIT + 7 + 50);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, col_proxy_forEach_const_iterates) {
|
||||
const auto & constVec = vec;
|
||||
auto col = constVec.col(9);
|
||||
size_t count = 0;
|
||||
col.forEach([&count](const int &) { ++count; });
|
||||
EXPECT_EQ(count, ROWS_COUNT_INIT);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, col_proxy_fill_sets_all_elements) {
|
||||
auto col = vec.col(11);
|
||||
col.fill(777);
|
||||
for (size_t r = 0; r < ROWS_COUNT_INIT; ++r) {
|
||||
EXPECT_EQ(vec.element(r, 11), 777);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, col_proxy_contains_finds_element) {
|
||||
auto col = vec.col(13);
|
||||
EXPECT_TRUE(col.contains(vec.element(5, 13)));
|
||||
EXPECT_FALSE(col.contains(-999));
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, col_proxy_entries_counts_occurrences) {
|
||||
auto col = vec.col(17);
|
||||
int val = vec.element(3, 17);
|
||||
vec.element(22, 17) = val; // duplicate
|
||||
EXPECT_EQ(col.entries(val), 2);
|
||||
EXPECT_EQ(col.entries(-999), 0);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, col_proxy_entries_with_predicate_counts_matches) {
|
||||
auto col = vec.col(19);
|
||||
auto isOdd = [](const int & e) { return e % 2 != 0; };
|
||||
int expected = 0;
|
||||
for (size_t r = 0; r < ROWS_COUNT_INIT; ++r) {
|
||||
if (col[r] % 2 != 0) ++expected;
|
||||
}
|
||||
EXPECT_EQ(col.entries(isOdd), expected);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, col_proxy_any_returns_true_if_any_match) {
|
||||
auto col = vec.col(21);
|
||||
auto isNegative = [](const int & e) { return e < 0; };
|
||||
EXPECT_FALSE(col.any(isNegative));
|
||||
auto isPositive = [](const int & e) { return e >= 0; };
|
||||
EXPECT_TRUE(col.any(isPositive));
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, col_proxy_every_returns_true_if_all_match) {
|
||||
auto col = vec.col(23);
|
||||
auto isLessThanMax = [&](const int & e) { return e < static_cast<int>(vec.size()); };
|
||||
EXPECT_TRUE(col.every(isLessThanMax));
|
||||
auto isEven = [](const int & e) { return e % 2 == 0; };
|
||||
EXPECT_FALSE(col.every(isEven));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
TEST_F(Vector2DTest, rowconst_proxy_forEach_iterates) {
|
||||
const auto & constVec = vec;
|
||||
auto row = constVec[5];
|
||||
size_t count = 0;
|
||||
row.forEach([&count](const int &) { ++count; });
|
||||
EXPECT_EQ(count, COLS_COUNT_INIT);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, rowconst_proxy_contains_finds_element) {
|
||||
const auto & constVec = vec;
|
||||
auto row = constVec[6];
|
||||
EXPECT_TRUE(row.contains(vec.element(6, 10)));
|
||||
EXPECT_FALSE(row.contains(-999));
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, rowconst_proxy_entries_counts_occurrences) {
|
||||
const auto & constVec = vec;
|
||||
auto row = constVec[7];
|
||||
int val = vec.element(7, 5);
|
||||
// We can't modify through const proxy, but duplicates already exist from previous tests
|
||||
EXPECT_GE(row.entries(val), 1); // at least one
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, rowconst_proxy_entries_with_predicate_counts_matches) {
|
||||
const auto & constVec = vec;
|
||||
auto row = constVec[9];
|
||||
auto isEven = [](const int & e) { return e % 2 == 0; };
|
||||
int expected = 0;
|
||||
for (size_t c = 0; c < COLS_COUNT_INIT; ++c) {
|
||||
if (vec.element(9, c) % 2 == 0) ++expected;
|
||||
}
|
||||
EXPECT_EQ(row.entries(isEven), expected);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, rowconst_proxy_any_returns_true_if_any_match) {
|
||||
const auto & constVec = vec;
|
||||
auto row = constVec[10];
|
||||
auto isNegative = [](const int & e) { return e < 0; };
|
||||
EXPECT_FALSE(row.any(isNegative));
|
||||
auto isPositive = [](const int & e) { return e >= 0; };
|
||||
EXPECT_TRUE(row.any(isPositive));
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, rowconst_proxy_every_returns_true_if_all_match) {
|
||||
const auto & constVec = vec;
|
||||
auto row = constVec[11];
|
||||
auto isLessThanMax = [&](const int & e) { return e < static_cast<int>(vec.size()); };
|
||||
EXPECT_TRUE(row.every(isLessThanMax));
|
||||
auto isEven = [](const int & e) { return e % 2 == 0; };
|
||||
EXPECT_FALSE(row.every(isEven));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
TEST_F(Vector2DTest, colconst_proxy_forEach_iterates) {
|
||||
const auto & constVec = vec;
|
||||
auto col = constVec.col(25);
|
||||
size_t count = 0;
|
||||
col.forEach([&count](const int &) { ++count; });
|
||||
EXPECT_EQ(count, ROWS_COUNT_INIT);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, colconst_proxy_contains_finds_element) {
|
||||
const auto & constVec = vec;
|
||||
auto col = constVec.col(27);
|
||||
EXPECT_TRUE(col.contains(vec.element(4, 27)));
|
||||
EXPECT_FALSE(col.contains(-999));
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, colconst_proxy_entries_counts_occurrences) {
|
||||
const auto & constVec = vec;
|
||||
auto col = constVec.col(29);
|
||||
int val = vec.element(8, 29);
|
||||
EXPECT_GE(col.entries(val), 1);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, colconst_proxy_entries_with_predicate_counts_matches) {
|
||||
const auto & constVec = vec;
|
||||
auto col = constVec.col(31);
|
||||
auto isOdd = [](const int & e) { return e % 2 != 0; };
|
||||
int expected = 0;
|
||||
for (size_t r = 0; r < ROWS_COUNT_INIT; ++r) {
|
||||
if (vec.element(r, 31) % 2 != 0) ++expected;
|
||||
}
|
||||
EXPECT_EQ(col.entries(isOdd), expected);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, colconst_proxy_any_returns_true_if_any_match) {
|
||||
const auto & constVec = vec;
|
||||
auto col = constVec.col(33);
|
||||
auto isNegative = [](const int & e) { return e < 0; };
|
||||
EXPECT_FALSE(col.any(isNegative));
|
||||
auto isPositive = [](const int & e) { return e >= 0; };
|
||||
EXPECT_TRUE(col.any(isPositive));
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, colconst_proxy_every_returns_true_if_all_match) {
|
||||
const auto & constVec = vec;
|
||||
auto col = constVec.col(0);
|
||||
auto isLessThanMax = [&](const int & e) { return e < static_cast<int>(vec.size()); };
|
||||
EXPECT_TRUE(col.every(isLessThanMax));
|
||||
auto isNotEven = [](const int & e) { return e % 2 != 0; };
|
||||
EXPECT_FALSE(col.every(isNotEven));
|
||||
}
|
||||
|
||||
// ==================== OUTPUT TESTS ====================
|
||||
TEST_F(Vector2DTest, picout_operator_works) {
|
||||
// Just test that it compiles and doesn't crash
|
||||
@@ -1010,3 +1704,94 @@ TEST_F(Vector2DTest, iostream_operator_works) {
|
||||
// No assertion, just ensure it runs
|
||||
}
|
||||
#endif
|
||||
|
||||
// ==================== INDEX STRUCTURE ACCESS TESTS ====================
|
||||
TEST_F(Vector2DTest, operator_bracket_with_index_allows_read_access) {
|
||||
PIVector2D<int>::Index idx = {5, 7};
|
||||
int value = vec[idx];
|
||||
int expected = vec.element(5, 7);
|
||||
EXPECT_EQ(value, expected);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, operator_bracket_with_index_allows_write_access) {
|
||||
PIVector2D<int>::Index idx = {10, 15};
|
||||
vec[idx] = 999;
|
||||
EXPECT_EQ(vec.element(10, 15), 999);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, operator_bracket_with_const_index_works) {
|
||||
const auto & constVec = vec;
|
||||
PIVector2D<int>::Index idx = {3, 12};
|
||||
int value = constVec[idx];
|
||||
int expected = vec.element(3, 12);
|
||||
EXPECT_EQ(value, expected);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, element_function_with_index_works) {
|
||||
PIVector2D<int>::Index idx = {8, 20};
|
||||
int value = vec.element(idx);
|
||||
int expected = vec.element(8, 20);
|
||||
EXPECT_EQ(value, expected);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, element_function_with_index_modifies_value) {
|
||||
PIVector2D<int>::Index idx = {12, 8};
|
||||
vec.element(idx) = 555;
|
||||
EXPECT_EQ(vec.element(12, 8), 555);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, element_function_with_const_index_works) {
|
||||
const auto & constVec = vec;
|
||||
PIVector2D<int>::Index idx = {7, 5};
|
||||
int value = constVec.element(idx);
|
||||
int expected = vec.element(7, 5);
|
||||
EXPECT_EQ(value, expected);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, at_function_with_index_works) {
|
||||
PIVector2D<int>::Index idx = {4, 11};
|
||||
int value = vec.at(idx);
|
||||
int expected = vec.at(4, 11);
|
||||
EXPECT_EQ(value, expected);
|
||||
}
|
||||
|
||||
TEST_F(Vector2DTest, index_structure_with_brace_initialization_works) {
|
||||
vec[{0, 0}] = 100;
|
||||
EXPECT_EQ(vec.element(0, 0), 100);
|
||||
|
||||
vec[{static_cast<ssize_t>(ROWS_COUNT_INIT - 1), static_cast<ssize_t>(COLS_COUNT_INIT - 1)}] = 200;
|
||||
EXPECT_EQ(vec.element(ROWS_COUNT_INIT - 1, COLS_COUNT_INIT - 1), 200);
|
||||
}
|
||||
|
||||
TEST(Vector2DIndexTest, default_constructor_initializes_to_invalid) {
|
||||
PIVector2D<int>::Index idx;
|
||||
EXPECT_TRUE(idx.isNotValid());
|
||||
EXPECT_FALSE(idx.isValid());
|
||||
EXPECT_EQ(idx.row, -1);
|
||||
EXPECT_EQ(idx.col, -1);
|
||||
}
|
||||
|
||||
TEST(Vector2DIndexTest, parameterized_constructor_initializes_correctly) {
|
||||
PIVector2D<int>::Index idx(5, 10);
|
||||
EXPECT_TRUE(idx.isValid());
|
||||
EXPECT_FALSE(idx.isNotValid());
|
||||
EXPECT_EQ(idx.row, 5);
|
||||
EXPECT_EQ(idx.col, 10);
|
||||
}
|
||||
|
||||
TEST(Vector2DIndexTest, isValid_returns_true_for_non_negative_values) {
|
||||
PIVector2D<int>::Index idx(0, 0);
|
||||
EXPECT_TRUE(idx.isValid());
|
||||
EXPECT_FALSE(idx.isNotValid());
|
||||
}
|
||||
|
||||
TEST(Vector2DIndexTest, isNotValid_returns_true_for_negative_values) {
|
||||
PIVector2D<int>::Index idx1;
|
||||
EXPECT_TRUE(idx1.isNotValid());
|
||||
|
||||
PIVector2D<int>::Index idx2(-1, 5);
|
||||
EXPECT_TRUE(idx2.isNotValid());
|
||||
|
||||
PIVector2D<int>::Index idx3(5, -1);
|
||||
EXPECT_TRUE(idx3.isNotValid());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user