/***************************************************************************
* 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 "gtest/gtest.h"
#include "xtensor/xarray.hpp"
#include "xtensor/xtensor.hpp"
#include "xtensor/xmanipulation.hpp"
#include "xtensor/xio.hpp"
#include "test_common.hpp"
#include
namespace xt
{
using xarray_dynamic = xarray;
TEST(xarray, shaped_constructor)
{
{
SCOPED_TRACE("row_major constructor");
row_major_result rm;
xarray_dynamic ra(rm.m_shape, layout_type::row_major);
compare_shape(ra, rm);
}
{
SCOPED_TRACE("column_major constructor");
column_major_result cm;
xarray ca(cm.m_shape);
compare_shape(ca, cm);
}
{
SCOPED_TRACE("from shape");
std::array shp = {5, 4, 2};
std::vector shp_as_vec = {5, 4, 2};
auto ca = xarray::from_shape({3, 2, 1});
auto cb = xarray::from_shape(shp);
std::vector expected_shape = {3, 2, 1};
EXPECT_EQ(expected_shape, ca.shape());
EXPECT_EQ(shp_as_vec, cb.shape());
}
}
TEST(xarray, strided_constructor)
{
central_major_result cmr;
xarray cma(cmr.m_shape, cmr.m_strides);
compare_shape(cma, cmr);
}
TEST(xarray, valued_constructor)
{
{
SCOPED_TRACE("row_major valued constructor");
row_major_result rm;
int value = 2;
xarray_dynamic ra(rm.m_shape, value, layout_type::row_major);
compare_shape(ra, rm);
xarray_dynamic::storage_type vec(ra.size(), value);
EXPECT_EQ(ra.storage(), vec);
}
{
SCOPED_TRACE("column_major valued constructor");
column_major_result cm;
int value = 2;
xarray ca(cm.m_shape, value);
compare_shape(ca, cm);
xarray_dynamic::storage_type vec(ca.size(), value);
EXPECT_EQ(ca.storage(), vec);
}
}
TEST(xarray, strided_valued_constructor)
{
central_major_result cmr;
int value = 2;
xarray cma(cmr.m_shape, cmr.m_strides, value);
compare_shape(cma, cmr);
xarray_dynamic::storage_type vec(cma.size(), value);
EXPECT_EQ(cma.storage(), vec);
}
TEST(xarray, xscalar_constructor)
{
xscalar xs(2);
xarray a(xs);
EXPECT_EQ(a(), xs());
}
TEST(xarray, copy_semantic)
{
central_major_result res;
int value = 2;
xarray_dynamic a(res.m_shape, res.m_strides, value);
{
SCOPED_TRACE("copy constructor");
xarray_dynamic b(a);
compare_shape(a, b);
EXPECT_EQ(a.storage(), b.storage());
}
{
SCOPED_TRACE("assignment operator");
row_major_result r;
xarray_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(xarray, move_semantic)
{
central_major_result res;
int value = 2;
xarray_dynamic a(res.m_shape, res.m_strides, value);
{
SCOPED_TRACE("move constructor");
xarray_dynamic tmp(a);
xarray_dynamic b(std::move(tmp));
compare_shape(a, b);
EXPECT_EQ(a.storage(), b.storage());
}
{
SCOPED_TRACE("move assignment");
row_major_result r;
xarray_dynamic c(r.m_shape, 0);
EXPECT_NE(a.storage(), c.storage());
xarray_dynamic tmp(a);
c = std::move(tmp);
compare_shape(a, c);
EXPECT_EQ(a.storage(), c.storage());
}
}
TEST(xarray, resize)
{
xarray_dynamic a;
test_resize(a);
}
TEST(xarray, reshape)
{
xarray_dynamic a;
test_reshape(a);
test_throwing_reshape(a);
}
TEST(xarray, transpose)
{
xarray_dynamic a;
test_transpose(a);
}
TEST(xarray, transpose_row)
{
xarray a = {{0, 1, 1, 1}};
xarray res = xt::transpose(a);
xarray::shape_type sh = {4, 1};
EXPECT_EQ(res.shape(), sh);
EXPECT_EQ(res(0, 0), 0.f);
EXPECT_EQ(res(1, 0), 1.f);
EXPECT_EQ(res(2, 0), 1.f);
EXPECT_EQ(res(3, 0), 1.f);
}
#if !(defined(XTENSOR_ENABLE_ASSERT) && defined(XTENSOR_DISABLE_EXCEPTIONS))
TEST(xarray, access)
{
xarray_dynamic a;
test_access(a);
}
#endif
TEST(xarray, unchecked)
{
xarray_dynamic a;
test_unchecked(a);
}
TEST(xarray, at)
{
xarray_dynamic a;
test_at(a);
}
#if !(defined(XTENSOR_ENABLE_ASSERT) && defined(XTENSOR_DISABLE_EXCEPTIONS))
TEST(xarray, element)
{
xarray_dynamic a;
test_element(a);
}
#endif
TEST(xarray, indexed_access)
{
xarray_dynamic a;
test_indexed_access(a);
}
TEST(xarray, broadcast_shape)
{
xarray_dynamic a;
test_broadcast(a);
test_broadcast2(a);
}
TEST(xarray, iterator)
{
xarray arm;
xarray acm;
test_iterator(arm, acm);
}
TEST(xarray, fill)
{
xarray_dynamic a;
test_fill(a);
}
TEST(xarray, initializer_list)
{
xarray_dynamic a0(1);
xarray_dynamic a1({1, 2});
xarray_dynamic a2({{1, 2}, {2, 4}, {5, 6}});
EXPECT_EQ(1, a0());
EXPECT_EQ(2, a1(1));
EXPECT_EQ(4, a2(1, 1));
}
TEST(xarray, zerod)
{
xarray_dynamic a;
EXPECT_EQ(0u, a.dimension());
EXPECT_EQ(0, a());
xarray_dynamic b = {1, 2, 3};
xarray_dynamic c(2 + xt::sum(b));
EXPECT_EQ(8, c());
EXPECT_EQ(8, c(1, 2));
xindex idx = { 1, 2 };
EXPECT_EQ(8, c.element(idx.cbegin(), idx.cend()));
}
TEST(xarray, xiterator)
{
xarray_dynamic a;
test_xiterator(a);
}
TEST(xarray, reverse_xiterator)
{
xarray_dynamic a;
test_reverse_xiterator(a);
}
TEST(xarray, cross_layout_assign)
{
xarray a = {{1, 2, 3, 4},
{5, 6, 7, 8}};
xarray b = {{1, 2, 3, 4},
{5, 6, 7, 8}};
xarray ra = a;
EXPECT_EQ(b, ra);
xarray rb = b;
EXPECT_EQ(a, rb);
}
TEST(xarray, end_optimized_stride)
{
xarray_dynamic a = {1};
EXPECT_FALSE((a.begin() == a.end()));
}
TEST(xarray, move_from_xtensor)
{
xtensor a = {{{1,2,3}, {4,5,6}}, {{10, 10, 10}, {1,5,10}}};
xtensor a1 = a;
xarray 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());
xtensor a2 = a;
xarray 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(xarray, periodic)
{
xt::xarray a = {{0,1,2}, {3,4,5}};
xt::xarray 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(xarray, in_bounds)
{
xt::xarray a = {{0,1,2}, {3,4,5}};
EXPECT_TRUE(a.in_bounds(0,0) == true);
EXPECT_TRUE(a.in_bounds(2,0) == false);
}
TEST(xarray, iterator_types)
{
using array_type = xarray;
test_iterator_types();
}
auto test_reshape_compile() {
xt::xarray a = xt::zeros({5, 5});
return a.reshape({1, 25});
}
TEST(xarray, reshape_return)
{
auto a = test_reshape_compile();
EXPECT_EQ(a.shape(), std::vector({1, 25}));
}
TEST(xarray, type_traits)
{
using array_type = xt::xarray;
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(xarray, bool_container)
{
xt::xarray a{1, 0, 1, 0}, b{1, 1, 0, 0};
xt::xarray c = a & b;
EXPECT_TRUE(c(0));
EXPECT_FALSE(c(1));
EXPECT_FALSE(c(2));
EXPECT_FALSE(c(3));
xt::xarray d = a | b;
EXPECT_TRUE(d(0));
EXPECT_TRUE(d(1));
EXPECT_TRUE(d(2));
EXPECT_FALSE(d(3));
}
}