/***************************************************************************
* Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
* Copyright (c) QuantStack *
* *
* Distributed under the terms of the BSD 3-Clause License. *
* *
* The full license is in the file LICENSE, distributed with this software. *
****************************************************************************/
#include
#include "xtensor/containers/xarray.hpp"
#include "xtensor/containers/xtensor.hpp"
#include "xtensor/io/xio.hpp"
#include "test_common.hpp"
#include "test_common_macros.hpp"
namespace xt
{
using storage_type = std::array;
using xtensor_dynamic = xtensor;
TEST(xtensor, default_constructor)
{
xtensor_dynamic a = {};
a.size();
EXPECT_EQ(a.size(), size_t(0));
EXPECT_EQ(a.dimension(), size_t(3));
}
TEST(xtensor, initializer_constructor)
{
xtensor_dynamic t{{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}}, {{9, 10, 11}, {12, 13, 14}, {15, 16, 17}}};
EXPECT_EQ(t.dimension(), size_t(3));
EXPECT_EQ(t(0, 0, 1), 1);
EXPECT_EQ(t.shape()[0], size_t(2));
}
TEST(xtensor, shaped_constructor)
{
SUBCASE("row_major constructor")
{
row_major_result rm;
xtensor_dynamic ra(rm.m_shape, layout_type::row_major);
compare_shape(ra, rm);
}
SUBCASE("column_major constructor")
{
column_major_result cm;
xtensor_dynamic ca(cm.m_shape, layout_type::column_major);
compare_shape(ca, cm);
}
SUBCASE("from shape")
{
std::array shp = {5, 4, 2};
std::vector shp_as_vec = {5, 4, 2};
auto ca = xtensor::from_shape({3, 2, 1});
auto cb = xtensor::from_shape(shp_as_vec);
std::vector expected_shape = {3, 2, 1};
EXPECT_TRUE(std::equal(expected_shape.begin(), expected_shape.end(), ca.shape().begin()));
EXPECT_TRUE(std::equal(shp.begin(), shp.end(), cb.shape().begin()));
}
}
TEST(xtensor, strided_constructor)
{
central_major_result cmr;
xtensor_dynamic cma(cmr.m_shape, cmr.m_strides);
compare_shape(cma, cmr);
}
TEST(xtensor, valued_constructor)
{
SUBCASE("row_major valued constructor")
{
row_major_result rm;
int value = 2;
xtensor_dynamic ra(rm.m_shape, value, layout_type::row_major);
compare_shape(ra, rm);
xtensor_dynamic::storage_type vec(ra.size(), value);
EXPECT_EQ(ra.storage(), vec);
}
SUBCASE("column_major valued constructor")
{
column_major_result cm;
int value = 2;
xtensor_dynamic ca(cm.m_shape, value, layout_type::column_major);
compare_shape(ca, cm);
xtensor_dynamic::storage_type vec(ca.size(), value);
EXPECT_EQ(ca.storage(), vec);
}
}
TEST(xtensor, strided_valued_constructor)
{
central_major_result cmr;
int value = 2;
xtensor_dynamic cma(cmr.m_shape, cmr.m_strides, value);
compare_shape(cma, cmr);
xtensor_dynamic::storage_type vec(cma.size(), value);
EXPECT_EQ(cma.storage(), vec);
}
TEST(xtensor, xscalar_constructor)
{
xscalar xs(2);
xtensor a(xs);
EXPECT_EQ(a(), xs());
}
TEST(xtensor, copy_semantic)
{
central_major_result res;
int value = 2;
xtensor_dynamic a(res.m_shape, res.m_strides, value);
SUBCASE("copy constructor")
{
xtensor_dynamic b(a);
compare_shape(a, b);
EXPECT_EQ(a.storage(), b.storage());
}
SUBCASE("assignment operator")
{
row_major_result r;
xtensor_dynamic c(r.m_shape, 0);
EXPECT_NE(a.storage(), c.storage());
c = a;
compare_shape(a, c);
EXPECT_EQ(a.storage(), c.storage());
}
}
TEST(xtensor, move_semantic)
{
central_major_result res;
int value = 2;
xtensor_dynamic a(res.m_shape, res.m_strides, value);
SUBCASE("move constructor")
{
xtensor_dynamic tmp(a);
xtensor_dynamic b(std::move(tmp));
compare_shape(a, b);
EXPECT_EQ(a.storage(), b.storage());
}
SUBCASE("move assignment")
{
row_major_result r;
xtensor_dynamic c(r.m_shape, 0);
EXPECT_NE(a.storage(), c.storage());
xtensor_dynamic tmp(a);
c = std::move(tmp);
compare_shape(a, c);
EXPECT_EQ(a.storage(), c.storage());
}
}
TEST(xtensor, missing)
{
xt::xtensor a{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
EXPECT_EQ(a(0), 0);
EXPECT_EQ(a(1), 1);
EXPECT_EQ(a(2), 2);
EXPECT_EQ(a(0, 0), 0);
EXPECT_EQ(a(1, 0), 3);
EXPECT_EQ(a(2, 0), 6);
EXPECT_EQ(a(xt::missing), 0);
EXPECT_EQ(a(0, xt::missing), 0);
EXPECT_EQ(a(1, xt::missing), 3);
EXPECT_EQ(a(2, xt::missing), 6);
EXPECT_EQ(a(0, 0), 0);
EXPECT_EQ(a(0, 1), 1);
EXPECT_EQ(a(0, 2), 2);
EXPECT_EQ(a(1, 0), 3);
EXPECT_EQ(a(1, 1), 4);
EXPECT_EQ(a(1, 2), 5);
EXPECT_EQ(a(2, 0), 6);
EXPECT_EQ(a(2, 1), 7);
EXPECT_EQ(a(2, 2), 8);
EXPECT_EQ(a(9, 9, 9, 0, 0), 0);
EXPECT_EQ(a(9, 9, 9, 0, 1), 1);
EXPECT_EQ(a(9, 9, 9, 0, 2), 2);
EXPECT_EQ(a(9, 9, 9, 1, 0), 3);
EXPECT_EQ(a(9, 9, 9, 1, 1), 4);
EXPECT_EQ(a(9, 9, 9, 1, 2), 5);
EXPECT_EQ(a(9, 9, 9, 2, 0), 6);
EXPECT_EQ(a(9, 9, 9, 2, 1), 7);
EXPECT_EQ(a(9, 9, 9, 2, 2), 8);
EXPECT_EQ(a.periodic(-1, xt::missing), a(2, xt::missing));
EXPECT_EQ(a.periodic(-2, xt::missing), a(1, xt::missing));
EXPECT_EQ(a.periodic(-3, xt::missing), a(0, xt::missing));
EXPECT_EQ(a.at(0, xt::missing), a.at(0, 0));
EXPECT_EQ(a.at(1, xt::missing), a.at(1, 0));
EXPECT_EQ(a.at(2, xt::missing), a.at(2, 0));
EXPECT_TRUE(a.in_bounds(0, xt::missing));
EXPECT_TRUE(a.in_bounds(1, xt::missing));
EXPECT_TRUE(a.in_bounds(2, xt::missing));
EXPECT_FALSE(a.in_bounds(3, xt::missing));
}
TEST(xtensor, resize)
{
xtensor_dynamic a;
test_resize(a);
#ifdef XTENSOR_ENABLE_ASSERT
xtensor_dynamic b;
std::vector s = {2u, 2u};
xtensor_dynamic::strides_type strides = {2u, 1u};
EXPECT_THROW(b.resize(s), std::runtime_error);
EXPECT_THROW(b.resize(s, layout_type::dynamic), std::runtime_error);
EXPECT_THROW(b.resize(s, strides), std::runtime_error);
#endif
}
TEST(xtensor, reshape)
{
xtensor_dynamic a;
test_reshape(a);
xtensor b;
test_throwing_reshape(b);
}
TEST(xtensor, transpose)
{
xtensor_dynamic a;
test_transpose(a);
}
#if !(defined(XTENSOR_ENABLE_ASSERT) && defined(XTENSOR_DISABLE_EXCEPTIONS))
TEST(xtensor, access)
{
xtensor_dynamic a;
test_access(a);
}
#endif
TEST(xtensor, unchecked)
{
xtensor_dynamic a;
test_unchecked(a);
}
TEST(xtensor, at)
{
xtensor_dynamic a;
test_at(a);
}
#if !(defined(XTENSOR_ENABLE_ASSERT) && defined(XTENSOR_DISABLE_EXCEPTIONS))
TEST(xtensor, element)
{
xtensor_dynamic a;
test_element(a);
}
#endif
TEST(xtensor, indexed_access)
{
xtensor_dynamic a;
test_indexed_access(a);
}
TEST(xtensor, broadcast_shape)
{
xtensor a;
test_broadcast(a);
}
TEST(xtensor, iterator)
{
using xtensor_rm = xtensor;
using xtensor_cm = xtensor;
xtensor_rm arm;
xtensor_cm acm;
test_iterator(arm, acm);
}
TEST(xtensor, fill)
{
xtensor a;
test_fill(a);
}
TEST(xtensor, zerod)
{
xtensor b;
EXPECT_EQ(b(), 0);
}
TEST(xtensor, xiterator)
{
xtensor_dynamic a;
test_xiterator(a);
}
TEST(xtensor, reverse_xiterator)
{
xtensor_dynamic a;
test_reverse_xiterator(a);
}
TEST(xtensor, single_element)
{
xtensor a = {1};
xtensor res = 2 * a;
EXPECT_EQ(2, res(0));
EXPECT_EQ(2, res(1));
xtensor b = {1, 2};
xt::xarray ca = a * b;
}
TEST(xtensor, move_from_xarray)
{
xarray a = {{{1, 2, 3}, {4, 5, 6}}, {{10, 10, 10}, {1, 5, 10}}};
xarray a1 = a;
xtensor b(std::move(a1));
EXPECT_EQ(a, b);
EXPECT_TRUE(
std::equal(a.strides().begin(), a.strides().end(), b.strides().begin())
&& a.strides().size() == b.strides().size()
);
EXPECT_TRUE(
std::equal(a.backstrides().begin(), a.backstrides().end(), b.backstrides().begin())
&& a.backstrides().size() == b.backstrides().size()
);
EXPECT_EQ(a.layout(), b.layout());
xarray a2 = a;
xtensor c;
c = std::move(a2);
EXPECT_EQ(a, c);
EXPECT_TRUE(
std::equal(a.strides().begin(), a.strides().end(), c.strides().begin())
&& a.strides().size() == c.strides().size()
);
EXPECT_TRUE(
std::equal(a.backstrides().begin(), a.backstrides().end(), c.backstrides().begin())
&& a.backstrides().size() == c.backstrides().size()
);
EXPECT_EQ(a.layout(), c.layout());
}
TEST(xtensor, from_indices)
{
xt::xtensor a = {{1, 0, 0}, {1, 1, 0}, {1, 1, 1}};
xt::xtensor jdx = {{0, 0}, {1, 0}, {1, 1}, {2, 0}, {2, 1}, {2, 2}};
xt::xtensor idx = xt::from_indices(xt::argwhere(xt::equal(a, 1)));
EXPECT_TRUE(idx == jdx);
}
TEST(xtensor, flatten_indices)
{
xt::xtensor a = {1, 0, 0, 1, 1, 0, 1, 1, 1};
xt::xtensor jdx = {0, 3, 4, 6, 7, 8};
xt::xtensor idx = xt::flatten_indices(xt::argwhere(xt::equal(a, 1)));
EXPECT_TRUE(idx == jdx);
}
TEST(xtensor, ravel_indices)
{
xt::xtensor a = {{1, 0, 0}, {1, 1, 0}, {1, 1, 1}};
xt::xtensor jdx = {0, 3, 4, 6, 7, 8};
xt::xtensor idx = xt::ravel_indices(xt::argwhere(xt::equal(a, 1)), a.shape());
EXPECT_TRUE(idx == jdx);
}
TEST(xtensor, ravel_indices_column_major)
{
xt::xtensor a = {{1, 0, 0}, {1, 1, 0}, {1, 1, 1}};
xt::xtensor jdx = {0, 1, 4, 2, 5, 8};
xt::xtensor idx = xt::ravel_indices(
xt::argwhere(xt::equal(a, 1)),
a.shape(),
xt::layout_type::column_major
);
EXPECT_TRUE(idx == jdx);
}
TEST(xarray, operator_brace)
{
#ifdef XTENSOR_ENABLE_ASSERT
xt::xtensor a = {{0, 1, 2}, {3, 4, 5}};
EXPECT_THROW(a(2, 0), std::runtime_error);
EXPECT_THROW(a(0, 3), std::runtime_error);
xt::xtensor b = {{0, 1, 2}};
EXPECT_THROW(a(0, 3), std::runtime_error);
EXPECT_THROW(a(1, 3), std::runtime_error);
#endif
}
TEST(xtensor, periodic)
{
xt::xtensor a = {{0, 1, 2}, {3, 4, 5}};
xt::xtensor b = {{0, 1, 2}, {30, 40, 50}};
a.periodic(-1, 3) = 30;
a.periodic(-1, 4) = 40;
a.periodic(-1, 5) = 50;
EXPECT_EQ(a, b);
}
TEST(xtensor, flat)
{
{
xt::xtensor a = {{0, 1, 2}, {3, 4, 5}};
xt::xtensor b = {{0, 1, 2}, {30, 40, 50}};
a.flat(3) = 30;
a.flat(4) = 40;
a.flat(5) = 50;
EXPECT_EQ(a, b);
#ifdef XTENSOR_ENABLE_ASSERT
EXPECT_THROW(a.flat(6), std::runtime_error);
#endif
}
{
xt::xtensor a = {{0, 1, 2}, {3, 4, 5}};
xt::xtensor b = {{0, 1, 2}, {30, 40, 50}};
a.flat(1) = 30;
a.flat(3) = 40;
a.flat(5) = 50;
EXPECT_EQ(a, b);
#ifdef XTENSOR_ENABLE_ASSERT
EXPECT_THROW(a.flat(6), std::runtime_error);
#endif
}
}
TEST(xtensor, in_bounds)
{
xt::xtensor a = {{0, 1, 2}, {3, 4, 5}};
EXPECT_TRUE(a.in_bounds(0, 0) == true);
EXPECT_TRUE(a.in_bounds(2, 0) == false);
}
TEST(xtensor, iterator_types)
{
using tensor_type = xtensor;
test_iterator_types();
}
TEST(xtensor, type_traits)
{
using tensor_type = xt::xtensor;
EXPECT_TRUE(std::is_constructible::value);
EXPECT_TRUE(std::is_constructible::value);
EXPECT_TRUE(std::is_default_constructible::value);
EXPECT_TRUE(std::is_copy_constructible::value);
EXPECT_TRUE(std::is_move_constructible::value);
EXPECT_TRUE(std::is_nothrow_move_constructible::value);
EXPECT_TRUE(std::is_copy_assignable::value);
EXPECT_TRUE(std::is_move_assignable::value);
EXPECT_TRUE(std::is_nothrow_move_assignable::value);
EXPECT_TRUE(std::is_destructible::value);
EXPECT_TRUE(std::is_nothrow_destructible::value);
}
TEST(xtensor, bool_container)
{
xt::xtensor a{1, 0, 1, 0}, b{1, 1, 0, 0};
xt::xtensor c = a & b;
EXPECT_TRUE(c(0));
EXPECT_FALSE(c(1));
EXPECT_FALSE(c(2));
EXPECT_FALSE(c(3));
xt::xtensor d = a | b;
EXPECT_TRUE(d(0));
EXPECT_TRUE(d(1));
EXPECT_TRUE(d(2));
EXPECT_FALSE(d(3));
}
}