Commit 8b08c873 authored by Andrew Wilson's avatar Andrew Wilson 🐘
Browse files

Merge branch 'fix/additions-fixes-dataarray' into 'master'

Additions and some DataArray fixes

See merge request !537
parents 4f474e43 54168961
Pipeline #217341 created
/*=========================================================================
Library: iMSTK
Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
& Imaging in Medicine, Rensselaer Polytechnic Institute.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/
#include "gtest/gtest.h"
#include "imstkDataArray.h"
using namespace imstk;
template<class T>
bool
isEqualTo(const DataArray<T>& original, std::initializer_list<T>&& p)
{
DataArray<T> other(p);
if (original.size() != other.size())
{
return false;
}
for (int i = 0; i < original.size(); ++i)
{
if (original[i] != other[i])
{
return false;
}
}
return true;
}
TEST(imstkDataArrayTest, Constructors)
{
EXPECT_NO_THROW(DataArray<int> sample);
DataArray<int> a;
EXPECT_EQ(0, a.size());
EXPECT_EQ(1, a.getCapacity());
DataArray<int> b{ 0, 1, 2, 3 };
EXPECT_EQ(4, b.size());
EXPECT_EQ(4, b.getCapacity());
EXPECT_TRUE(isEqualTo(b, { 0, 1, 2, 3 }));
DataArray<int> c(128);
EXPECT_EQ(128, c.size());
EXPECT_EQ(128, c.getCapacity());
DataArray<int> d(std::move(b));
EXPECT_EQ(4, d.size());
EXPECT_EQ(4, d.getCapacity());
EXPECT_TRUE(isEqualTo(d, { 0, 1, 2, 3 }));
}
TEST(imstkDataArrayTest, Assignment)
{
DataArray<int> a;
a = { 1, 2, 3, 4 };
EXPECT_EQ(4, a.size());
EXPECT_TRUE(isEqualTo(a, { 1, 2, 3, 4 }));
DataArray<int> b{ 0, 2, 4, 6 };
b = a;
EXPECT_TRUE(isEqualTo(b, { 1, 2, 3, 4 }));
}
TEST(imstkDataArrayTest, Mapping)
{
std::vector<int> other{ -1, -2, -3 };
{
DataArray<int> a{ 1, 2, 3, 4 };
a.setData(other.data(), static_cast<int>(other.size()));
EXPECT_EQ(3, a.size());
EXPECT_TRUE(isEqualTo(a, { -1, -2, -3 }));
EXPECT_EQ(other.data(), a.getPointer());
DataArray<int> b = a;
EXPECT_EQ(3, b.size());
EXPECT_TRUE(isEqualTo(b, { -1, -2, -3 }));
EXPECT_EQ(other.data(), b.getPointer());
}
}
TEST(imstkDataArrayTest, CapacityManagement)
{
{
DataArray<int> a;
EXPECT_EQ(0, a.size());
EXPECT_EQ(1, a.getCapacity());
a.push_back(0);
EXPECT_EQ(1, a.size());
EXPECT_EQ(1, a.getCapacity());
for (int i = 1; i < 10; ++i)
{
a.push_back(i);
EXPECT_EQ(i + 1, a.size());
}
EXPECT_TRUE(isEqualTo(a, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }));
}
{
DataArray<int> a;
a.resize(100);
EXPECT_EQ(100, a.size());
EXPECT_EQ(100, a.getCapacity());
a.resize(50);
EXPECT_EQ(50, a.size());
EXPECT_EQ(50, a.getCapacity());
a.resize(0);
EXPECT_EQ(0, a.size());
EXPECT_EQ(1, a.getCapacity());
}
{
DataArray<int> a{ 1, 2, 3, 4 };
a.reserve(256);
EXPECT_EQ(4, a.size());
EXPECT_EQ(256, a.getCapacity());
a.reserve(100);
EXPECT_EQ(256, a.getCapacity());
EXPECT_EQ(4, a.size());
a.squeeze();
EXPECT_EQ(4, a.getCapacity());
EXPECT_EQ(4, a.size());
}
}
TEST(imstkDataArrayTest, Iterators)
{
DataArray<int> a;
for (const auto& val : a)
{
GTEST_FAIL() << "Should not enter here";
}
auto itBegin = a.begin();
auto itEnd = a.end();
EXPECT_EQ(itBegin, itEnd);
a = { 1, 2, 3, 4 };
auto it = a.begin();
itEnd = a.end();
int expected = 1;
while (it != itEnd)
{
EXPECT_EQ(expected, *it);
++it;
++expected;
}
}
int
imstkDataArrayTest(int argc, char* argv[])
{
// Init Google Test
::testing::InitGoogleTest(&argc, argv);
// Run tests with gtest
return RUN_ALL_TESTS();
}
\ No newline at end of file
/*=========================================================================
Library: iMSTK
Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
& Imaging in Medicine, Rensselaer Polytechnic Institute.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/
#include "gtest/gtest.h"
#include "imstkDataArray.h"
#include "imstkVecDataArray.h"
using namespace imstk;
namespace
{
template<class T, int N>
bool
isEqualTo(const VecDataArray<T, N>& original, std::initializer_list<Eigen::Matrix<T, N, 1>>&& p)
{
VecDataArray<T, N> other(p);
if (original.size() != other.size())
{
return false;
}
for (int i = 0; i < original.size(); ++i)
{
if (original[i] != other[i])
{
return false;
}
}
return true;
}
}
TEST(imstkVecDataArrayTest, Constructors)
{
using SampleType = VecDataArray<int, 2>;
EXPECT_NO_THROW(SampleType sample);
// Note, size and capacity return the underlying total size e.g. for
// VecDataArray<int, 2>, 2 * n
VecDataArray<int, 2> a;
EXPECT_EQ(0, a.size());
EXPECT_EQ(2, a.getCapacity());
EXPECT_EQ(2, a.getNumberOfComponents());
VecDataArray<int, 2> b{ imstk::Vec2i{ 0, 1 }, { 2, 3 } };
EXPECT_EQ(2, b.size());
EXPECT_EQ(4, b.getCapacity());
EXPECT_TRUE(isEqualTo(b, { imstk::Vec2i{ 0, 1, }, { 2, 3 } }));
VecDataArray<int, 2> c(128);
EXPECT_EQ(128, c.size());
EXPECT_EQ(128 * 2, c.getCapacity());
auto ptr = b.getPointer();
VecDataArray<int, 2> d(std::move(b));
EXPECT_EQ(2, d.size());
EXPECT_EQ(4, d.getCapacity());
EXPECT_TRUE(isEqualTo(d, { imstk::Vec2i{ 0, 1, }, { 2, 3 } }));
EXPECT_EQ(ptr, d.getPointer());
}
TEST(imstkVecDataArrayTest, Assignment)
{
VecDataArray<int, 2> a;
a = { imstk::Vec2i{ 1, 2, }, { 3, 4 }, { 5, 6 } };
EXPECT_EQ(3, a.size());
EXPECT_EQ(3 * 2, a.getCapacity());
EXPECT_TRUE(isEqualTo(a, { imstk::Vec2i{ 1, 2, }, { 3, 4 }, { 5, 6 } }));
VecDataArray<int, 2> b{ imstk::Vec2i{ 0, 2, }, { 4, 6 } };
b = a;
EXPECT_TRUE(isEqualTo(b, { imstk::Vec2i{ 1, 2, }, { 3, 4 }, { 5, 6 } }));
EXPECT_EQ(a.size(), b.size());
EXPECT_EQ(a.getCapacity(), b.getCapacity());
EXPECT_NE(a.getPointer(), b.getPointer());
}
TEST(imstkVecDataArrayTest, Mapping)
{
std::vector<imstk::Vec2i> other{ { -1, -2, }, { -3, -4 } };
{
VecDataArray<int, 2> a{ imstk::Vec2i{ 1, 2, } };
a.setData(other.data(), static_cast<int>(other.size()));
EXPECT_EQ(2, a.size());
EXPECT_EQ(2 * 2, a.getCapacity());
EXPECT_TRUE(isEqualTo(a, { imstk::Vec2i{ -1, -2, }, { -3, -4 } }));
EXPECT_EQ(other.data(), a.getPointer());
VecDataArray<int, 2> b = a;
EXPECT_EQ(2, b.size());
EXPECT_TRUE(isEqualTo(b, { imstk::Vec2i{ -1, -2, }, { -3, -4 } }));
EXPECT_EQ(other.data(), b.getPointer());
}
}
TEST(imstkVecDataArrayTest, CapacityManagement)
{
{
VecDataArray<int, 2> a;
EXPECT_EQ(0, a.size());
EXPECT_EQ(2, a.getCapacity());
a.push_back({ 0, 0 });
EXPECT_EQ(1, a.size());
EXPECT_EQ(2, a.getCapacity());
for (int i = 1; i < 10; ++i)
{
a.push_back({ i, i });
EXPECT_EQ(i + 1, a.size());
}
EXPECT_TRUE(isEqualTo(a, { { 0, 0 }, { 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 }, { 7, 7 }, { 8, 8 }, { 9, 9 } }));
}
{
VecDataArray<int, 2> a;
a.resize(100);
EXPECT_EQ(100, a.size());
EXPECT_EQ(100 * 2, a.getCapacity());
a.resize(50);
EXPECT_EQ(50, a.size());
EXPECT_EQ(50 * 2, a.getCapacity());
a.resize(0);
EXPECT_EQ(0, a.size());
EXPECT_EQ(1 * 2, a.getCapacity());
}
{
VecDataArray<int, 2> a{ imstk::Vec2i{ 0, 2, }, { 4, 6 } };
a.reserve(256);
EXPECT_EQ(2, a.size());
EXPECT_EQ(256 * 2, a.getCapacity());
a.reserve(100);
EXPECT_EQ(2, a.size());
EXPECT_EQ(256 * 2, a.getCapacity());
a.squeeze();
EXPECT_EQ(2, a.size());
EXPECT_EQ(2 * 2, a.getCapacity());
}
}
TEST(imstkVecDataArrayTest, Iterators)
{
VecDataArray<int, 2> a;
for (const auto& val : a)
{
GTEST_FAIL() << "Should not enter here";
}
auto itBegin = a.begin();
auto itEnd = a.end();
EXPECT_EQ(itBegin, itEnd);
a = { imstk::Vec2i{ 1, 1 }, { 2, 2 }, { 3, 3 } };
auto it = a.begin();
itEnd = a.end();
int expected = 1;
while (it != itEnd)
{
EXPECT_EQ(imstk::Vec2i(expected, expected), *it);
++it;
++expected;
}
}
TEST(imstkVecDataArrayTest, ConstructorCast)
{
VecDataArray<long, 2> a{ Vec2i{ 1, 2 }, { 3, 4 } };
EXPECT_EQ(Vec2i(1, 2), a[0].cast<int>());
}
TEST(imstkVecDataArrayTest, Erase)
{
VecDataArray<int, 2> a{ imstk::Vec2i{ 1, 1 }, { 2, 2 }, { 3, 3 }, { 4, 4 } };
a.erase(1);
EXPECT_EQ(3, a.size());
EXPECT_EQ(8, a.getCapacity());
EXPECT_TRUE(isEqualTo(a, { imstk::Vec2i{ 1, 1, }, { 3, 3 }, { 4, 4 } }));
EXPECT_EQ(8, a.getCapacity());
a.erase(-1);
EXPECT_EQ(3, a.size());
a.erase(20);
EXPECT_EQ(3, a.size());
a.erase(1);
a.erase(0);
EXPECT_TRUE(isEqualTo(a, { imstk::Vec2i{ 4, 4, } }));
EXPECT_EQ(8, a.getCapacity());
a.erase(0);
EXPECT_EQ(0, a.size());
EXPECT_EQ(2, a.getCapacity());
}
int
imstkVecDataArrayTest(int argc, char* argv[])
{
// Init Google Test
::testing::InitGoogleTest(&argc, argv);
// Run tests with gtest
return RUN_ALL_TESTS();
}
\ No newline at end of file
......@@ -68,9 +68,9 @@ public:
pointer operator->() { return ptr_; }
bool operator==(const self_type& rhs) { return ptr_ == rhs.ptr_; }
bool operator==(const self_type& rhs) const { return ptr_ == rhs.ptr_; }
bool operator!=(const self_type& rhs) { return ptr_ != rhs.ptr_; }
bool operator!=(const self_type& rhs) const { return ptr_ != rhs.ptr_; }
private:
pointer ptr_;
......@@ -102,9 +102,9 @@ public:
const pointer operator->() { return ptr_; }
bool operator==(const self_type& rhs) { return ptr_ == rhs.ptr_; }
bool operator==(const self_type& rhs) const { return ptr_ == rhs.ptr_; }
bool operator!=(const self_type& rhs) { return ptr_ != rhs.ptr_; }
bool operator!=(const self_type& rhs) const { return ptr_ != rhs.ptr_; }
private:
pointer ptr_;
......@@ -133,7 +133,7 @@ public:
/// \brief Constructs from intializer list
///
template<typename U>
DataArray(std::initializer_list<U> list) : AbstractDataArray(size), m_mapped(false), m_data(new T[list.size()])
DataArray(std::initializer_list<U> list) : AbstractDataArray(static_cast<int>(list.size())), m_mapped(false), m_data(new T[list.size()])
{
int j = 0;
for (auto i : list)
......@@ -163,7 +163,7 @@ public:
}
}
DataArray(const DataArray&& other)
DataArray(DataArray&& other)
{
m_mapped = other.m_mapped;
m_size = other.m_size;
......@@ -189,8 +189,14 @@ public:
inline void resize(const int size) override
{
// Can't resize a mapped vector
if (m_mapped || size == m_size)
if (m_mapped)
{
return;
}
if (size == m_capacity)
{
m_size = m_capacity;
return;
}
......@@ -242,10 +248,9 @@ public:
}
const int newSize = m_size + 1;
if (newSize > m_capacity) // If the new size exceeds capacity
if (newSize > m_capacity) // If the new size exceeds capacity
{
m_capacity *= 2;
resize(m_capacity); // Conservative/copies values
resize(m_capacity * 2); // Conservative/copies values
}
m_size = newSize;
m_data[newSize - 1] = val;
......@@ -260,10 +265,9 @@ public:
}
const int newSize = m_size + 1;
if (newSize > m_capacity) // If the new size exceeds capacity
if (newSize > m_capacity) // If the new size exceeds capacity
{
m_capacity *= 2;
resize(m_capacity); // Conservative/copies values
resize(m_capacity * 2); // Conservative/copies values
}
m_size = newSize;
m_data[newSize - 1] = val;
......@@ -280,15 +284,17 @@ public:
///
/// \brief Allocates extra capacity, for the number of values, conservative reallocate
///
inline void reserve(const int size) override
inline void reserve(const int capacity) override
{
if (m_mapped)
{
return;
}
if (capacity <= m_capacity) { return; }
const int currSize = m_size;
resize(size); // Reallocate
resize(capacity); // Reallocate
m_size = currSize; // Keep current size
}
......
......@@ -69,9 +69,9 @@ public:
pointer operator->() { return ptr_; }
bool operator==(const self_type& rhs) { return ptr_ == rhs.ptr_; }
bool operator==(const self_type& rhs) const { return ptr_ == rhs.ptr_; }
bool operator!=(const self_type& rhs) { return ptr_ != rhs.ptr_; }
bool operator!=(const self_type& rhs) const { return ptr_ != rhs.ptr_; }
private:
pointer ptr_;
......@@ -103,9 +103,9 @@ public:
const pointer operator->() { return ptr_; }
bool operator==(const self_type& rhs) { return ptr_ == rhs.ptr_; }
bool operator==(const self_type& rhs) const { return ptr_ == rhs.ptr_; }
bool operator!=(const self_type& rhs) { return ptr_ != rhs.ptr_; }
bool operator!=(const self_type& rhs) const { return ptr_ != rhs.ptr_; }
private:
pointer ptr_;
......@@ -126,20 +126,21 @@ public:
/// \brief Constructs from intializer list
///
template<typename U, int M>
VecDataArray(std::initializer_list<Eigen::Matrix<U, M, 1>> list) : DataArray<T>(list.size() * N), m_vecSize(list.size()), m_vecCapacity(list.size()),
VecDataArray(std::initializer_list<Eigen::Matrix<U, M, 1>> list) : DataArray<T>(static_cast<int>(list.size() * N)),
m_vecSize(static_cast<int>(list.size())),
m_vecCapacity(static_cast<int>(list.size())),
m_dataCast(reinterpret_cast<VecType*>(DataArray<T>::m_data))
{
int j = 0;
for (auto i : list)
{
m_dataCast[j] = i;
m_dataCast[j] = i.cast<T>();
j++;
}
}
VecDataArray(const VecDataArray& other)
{
// Copy the buffer instead of the pointer
DataArray<T>::m_mapped = other.m_mapped;
AbstractDataArray::m_size = other.m_size;
AbstractDataArray::m_capacity = other.m_capacity;
......@@ -158,7 +159,7 @@ public:
m_dataCast = reinterpret_cast<VecType*>(DataArray<T>::m_data);
}
VecDataArray(const VecDataArray&& other)
VecDataArray(VecDataArray&& other)
{
DataArray<T>::m_mapped = other.m_mapped;
AbstractDataArray::m_size = other.m_size;
......@@ -167,8 +168,8 @@ public:
m_vecCapacity = other.m_vecCapacity;
AbstractDataArray::m_scalarType = other.m_scalarType;
DataArray<T>::m_data = other.m_data; // Take the others buffer
other.m_data = new T[N]; // Back to default
other.m_dataCast = reinterpret_cast<VecType>(other.m_data);
m_dataCast = other.m_dataCast;
other.m_mapped = true;
}
virtual ~VecDataArray() override = default;
......@@ -180,7 +181,7 @@ public:
inline void resize(const int size) override
{
// Can't resize a mapped vector
if (DataArray<T>::m_mapped || size == m_vecSize)
if (DataArray<T>::m_mapped || size == m_vecCapacity)
{
return;
}
......@@ -218,10 +219,9 @@ public:
}
const int newVecSize = m_vecSize + 1;
if (newVecSize > m_vecCapacity) // If the new size exceeds capacity
if (newVecSize > m_vecCapacity) // If the new size exceeds capacity
{
m_vecCapacity *= 2;
VecDataArray::resize(m_vecCapacity); // Conservative/copies values
VecDataArray::resize(m_vecCapacity * 2); // Conservative/copies values
}
m_vecSize = newVecSize;
AbstractDataArray::m_size = newVecSize * N;
......@@ -237,10 +237,9 @@ public:
}
const int newVecSize = m_vecSize + 1;
if (newVecSize > m_vecCapacity) // If the new size exceeds capacity
if (newVecSize > m_vecCapacity) // If the new size exceeds capacity
{
m_vecCapacity *= 2;
VecDataArray::resize(m_vecCapacity); // Conservative/copies values
VecDataArray::resize(m_vecCapacity * 2); // Conservative/copies values
}
m_vecSize = newVecSize;
AbstractDataArray::m_size = newVecSize * N;
......@@ -265,6 +264,8 @@ public:
return;
}
if (size < m_vecCapacity) { return