/*************************************************************************** * 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)); } }