Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I added tests to core/impl/tensor_impl.hpp #3

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cmake/headers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,5 @@ set(TNT_HEADERS include/tnt/tnt.hpp
include/tnt/linear/impl/convolution_3d_impl.hpp
include/tnt/linear/discrete_cosine_transform.hpp
include/tnt/linear/impl/discrete_cosine_transform_impl.hpp
)
)

221 changes: 221 additions & 0 deletions include/tnt/core/impl/tensor_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,45 @@ namespace tnt
template <typename DataType>
inline Tensor<DataType>::Tensor() noexcept {}

TEST_CASE_TEMPLATE("Tensor()", T, test_data_types)
{
Tensor<T> t1;
REQUIRE(t1.data == AlignedPtr<T>());
REQUIRE(t1.shape == Shape());
}

template <typename DataType>
inline Tensor<DataType>::Tensor(const Shape& shape)
{
this->shape = shape;
this->data = AlignedPtr<DataType>(shape.total());
}

TEST_CASE_TEMPLATE("Tensor(Shape&)", T, test_data_types)
{
/* generic Shape constructor test */
Shape s1;
Tensor<T> t1(s1);

REQUIRE(t1.shape == s1);
REQUIRE(t1.data.size == s1.total());

/* Shape given initializer_list */
Shape s2{0, 1, 2};
Tensor<T> t2(s2);

REQUIRE(t2.shape == s2);
REQUIRE(t2.data.size == s2.total());

/* Shape given vector */
Shape s3(std::vector<int>{1, 2, 3, 4});
Tensor<T> t3(s3);

REQUIRE(t3.shape == s3);
REQUIRE(t3.data.size == s3.total());

}

// Shape + Data
template <typename DataType>
inline Tensor<DataType>::Tensor(const Shape& shape, const PtrType& data)
Expand All @@ -41,6 +73,34 @@ inline Tensor<DataType>::Tensor(const Shape& shape, const PtrType& data)
this->data = data;
}

TEST_CASE_TEMPLATE("Tensor(Shape&, PtrType&)", T, test_data_types)
{
/* Generic Shape, only testing Aligned_ptr
*
* Ptr with no parameters
*/

Shape s1;
AlignedPtr<T> ptr1;
Tensor<T> t1(s1, ptr1);
REQUIRE(t1.shape == s1);
REQUIRE(t1.data == ptr1);

/* ptr with size parameter only */
AlignedPtr<T> ptr2(10);
Tensor<T> t2(s1, ptr2);
REQUIRE(t2.data.size == 10);

/* ptr with size and value parameters */
T data[5] = {1, 2, 3, 4, 5};
AlignedPtr<T> ptr3(data, 5);
Tensor<T> t3(s1, ptr3);
REQUIRE(t3.data.size == 5);
REQUIRE(t3.data[2] == 3);
REQUIRE(t3.data[4] == 5);

}

// Shape + Value
template <typename DataType>
inline Tensor<DataType>::Tensor(const Shape& shape, const DataType& value)
Expand All @@ -51,13 +111,36 @@ inline Tensor<DataType>::Tensor(const Shape& shape, const DataType& value)
this->operator=(value); // Set to value
}

TEST_CASE_TEMPLATE("Tensor(const Shape&, const DataType&)", T, test_data_types)
{
Shape s1{2, 2};
Tensor<T> t1(s1, (T) 4);
AlignedPtr<T> test = t1.data;

for (int i = 0; i < 4; i++) {
REQUIRE(test[i] == 4);
}
}

template <typename DataType>
inline Tensor<DataType>::Tensor(const SelfType& other)
{
this->shape = other.shape;
this->data = other.data;
}

TEST_CASE_TEMPLATE("Tensor(const SelfType&)", T, test_data_types)
{
Shape s1{2, 2};
T data[4] = {1, 2, 3, 4};
AlignedPtr<T> ptr(data, 4);
const Tensor<T> t1(s1, ptr);
Tensor<T> t2(t1);

REQUIRE(t2.shape == t1.shape);
REQUIRE(t2.data == t1.data);
}

template <typename DataType>
inline Tensor<DataType>& Tensor<DataType>::operator=(const SelfType& other)
{
Expand All @@ -67,6 +150,18 @@ inline Tensor<DataType>& Tensor<DataType>::operator=(const SelfType& other)
return *this;
}

TEST_CASE_TEMPLATE("Tensor::operator=(const SelfType&)", T, test_data_types)
{
Shape s1{2, 2};
T data[4] = {1, 2, 3, 4};
AlignedPtr<T> ptr(data, 4);
Tensor<T> t1(s1, ptr);
Tensor<T> t2 = t1;

REQUIRE(t2.shape == t1.shape);
REQUIRE(t2.data == t1.data);
}

template <typename DataType>
inline Tensor<DataType>::Tensor(SelfType&& other) noexcept
{
Expand All @@ -78,6 +173,21 @@ inline Tensor<DataType>::Tensor(SelfType&& other) noexcept
other.data = PtrType();
}

TEST_CASE_TEMPLATE("Tensor(const SelfType&&)", T, test_data_types)
{
Shape s1{2, 2};
T data[4] = {1, 2, 3, 4};
AlignedPtr<T> ptr(data, 4);
Tensor<T> t1(s1, ptr);
Tensor<T> t2(std::move(t1));

REQUIRE(t2.shape == s1);
REQUIRE(t2.data == ptr);
REQUIRE(t1.shape == Shape());
REQUIRE(t1.data == AlignedPtr<T>());

}

template <typename DataType>
inline Tensor<DataType>& Tensor<DataType>::operator=(SelfType&& other) noexcept
{
Expand All @@ -91,6 +201,20 @@ inline Tensor<DataType>& Tensor<DataType>::operator=(SelfType&& other) noexcept
return *this;
}

TEST_CASE_TEMPLATE("Tensor::operator=(const SelfType&&)", T, test_data_types)
{
Shape s1{2, 2};
T data[4] = {1, 2, 3, 4};
AlignedPtr<T> ptr(data, 4);
Tensor<T> t1(s1, ptr);
Tensor<T> t2 = std::move(t1);

REQUIRE(t2.shape == s1);
REQUIRE(t2.data == ptr);
REQUIRE(t1.shape == Shape());
REQUIRE(t1.data == AlignedPtr<T>());
}

// ----------------------------------------------------------------------------
// Iterators

Expand All @@ -100,24 +224,90 @@ inline typename Tensor<DataType>::IteratorType Tensor<DataType>::begin() const n
return this->data.data;
}

TEST_CASE_TEMPLATE("Tensor::begin()", T, test_data_types)
{
/* int */
Shape s1{2, 2};
T data[4] = {(T) 1, (T) 2, (T) 3, (T) 4};
AlignedPtr<T> ptr(data, 4);
Tensor<T> t1(s1, ptr);

REQUIRE(*t1.begin() == 1);

data[0] = (T) 5;
AlignedPtr<T> ptr1(data, 4);
Tensor<T> t2(s1, ptr1);
REQUIRE(*t2.begin() == 5);

}

template <typename DataType>
inline typename Tensor<DataType>::IteratorType Tensor<DataType>::end() const noexcept
{
return this->data.is_null() ? nullptr : this->data.data + this->shape.total();
}

TEST_CASE_TEMPLATE("Tensor::end()", T, test_data_types)
{
Shape s1{2, 2};
T data[4] = {(T) 1, (T) 2, (T) 3, (T) 4};
AlignedPtr<T> ptr(data, 4);
Tensor<T> t1(s1, ptr);
T* it = t1.begin();

int cnt = 1;
while (*it != *t1.end()) {
REQUIRE(*it == (T) cnt);
it++;
cnt++;
}
}

template <typename DataType>
inline typename Tensor<DataType>::ConstIteratorType Tensor<DataType>::cbegin() const noexcept
{
return this->data.data;
}

TEST_CASE_TEMPLATE("Tensor::cbegin()", T, test_data_types)
{
/* int */
Shape s1{2, 2};
T data[4] = {(T) 1, (T) 2, (T) 3, (T) 4};
AlignedPtr<T> ptr(data, 4);
const Tensor<T> t1(s1, ptr);

REQUIRE(*t1.begin() == 1);

data[0] = (T) 5;
AlignedPtr<T> ptr1(data, 4);
const Tensor<T> t2(s1, ptr1);
REQUIRE(*t2.begin() == 5);

}

template <typename DataType>
inline typename Tensor<DataType>::ConstIteratorType Tensor<DataType>::cend() const noexcept
{
return this->data.is_null() ? nullptr : this->data.data + this->shape.total();
}

TEST_CASE_TEMPLATE("Tensor::cend()", T, test_data_types)
{
Shape s1{2, 2};
T data[4] = {(T) 1, (T) 2, (T) 3, (T) 4};
AlignedPtr<T> ptr(data, 4);
const Tensor<T> t1(s1, ptr);
T* it = t1.begin();

int cnt = 1;
while (*it != *t1.end()) {
REQUIRE(*it == (T) cnt);
it++;
cnt++;
}
}

// ----------------------------------------------------------------------------
// Operators

Expand All @@ -128,13 +318,36 @@ inline bool Tensor<DataType>::operator== (const SelfType& other) const noexcept
&& this->data == other.data;
}

TEST_CASE_TEMPLATE("Tensor::operator== (const SelfType&", T, test_data_types)
{
Shape s1{2, 2};
T data[3] = {1, 2, 3};
AlignedPtr<T> ptr(data, 3);
Tensor<T> t1(s1, ptr);
Tensor<T> t2(s1, ptr);
REQUIRE(t1 == t2);

}

template <typename DataType>
inline bool Tensor<DataType>::operator!= (const SelfType& other) const noexcept
{
return this->shape != other.shape
|| this->data != other.data;
}

TEST_CASE_TEMPLATE("Tensor::operator== (const SelfType&", T, test_data_types)
{
Shape s1{2, 2};
T data[3] = {1, 2, 3};
T data1[3] = {3, 2, 1};
AlignedPtr<T> ptr(data, 3);
AlignedPtr<T> ptr1(data1, 3);
Tensor<T> t1(s1, ptr);
Tensor<T> t2(s1, ptr1);
REQUIRE(t1 != t2);
}

template <typename DataType>
inline Tensor<DataType>::operator DataType()
{
Expand All @@ -147,6 +360,14 @@ inline Tensor<DataType>::operator DataType()
return this->data[0];
}

TEST_CASE_TEMPLATE("Tensor::operator DataType()", T, test_data_types)
{
Shape s1{2, 2};
T data[3] = {1, 2, 3};
AlignedPtr<T> ptr(data, 3);
Tensor<T> t1(s1, ptr);
}

template <typename DataType>
inline Tensor<DataType>::operator TensorView<DataType>()
{
Expand Down
57 changes: 57 additions & 0 deletions include/tnt/linear/Gaussian_elimination.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#ifndef TNT_GAUSSIAN_ELIMINATION_HPP
#define TNT_GAUSSIAN_ELIMINATION_HPP

#include <tnt/core/tensor.hpp>
#include <type_traits>

namespace tnt
{

namespace detail
{

template <typename DataType, typename Enable = void>
struct OptimizedGaussianElimination
{
static Tensor<DataType> eval(const Tensor<DataType>&);
static Tensor<DataType> eval(const Tensor<DataType>&, const Tensor<DataType>&);
};

} // namespace detail

/// \brief Executes Gaussian Elimination of a Matrix
///
/// \param T1 The tensor. It has size `MxN`
/// \returns A tensor in Reduced Row Echelon Form
/// \requires T1 shall be two dimensional

template <typename DataType>
inline Tensor<DataType> gaussian_elim(Tensor<DataType>& T1)
{
static_assert(std::is_floating_point<DataType>::value,
"eigenvalues() requires signed data");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you forgot to change eigenvalues() :)


TNT_ASSERT(T1.shape.num_axes() == 2, InvalidParameterException("tnt::gaussian_elim()",
__FILE__, __LINE__, "Gaussian elimination requires 2D tensors"))

return detail::OptimizedGaussianElimination<DataType>::eval(T1);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation

}

template <typename DataType>
inline Tensor<DataType> gaussian_elim(Tensor<DataType>& T1, Tensor<DataType>& V1)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add documentation for the 2 tensor case

{
static_assert(std::is_floating_point<DataType>::value,
"eigenvalues() requires signed data");

TNT_ASSERT(T1.shape.num_axes() == 2, InvalidParameterException("tnt::gaussian_elim()",
__FILE__, __LINE__, "Gaussian elimination requires 2D tensors"))

TNT_ASSERT(V1.shape.axes[1] == 1, InvalidParameterException("tnt::gaussian_elim()",
__FILE__, __LINE__, "Solution vector requires vector"));

return detail::OptimizedGaussianElimination<DataType>::eval(T1, V1);
}

} // namespace tnt

#endif // TNT_GAUSSIAN_ELIMINATION_HPP
Loading