/***************************************************************************
* 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 "xtensor/containers/xarray.hpp"
#include "xtensor/containers/xtensor.hpp"
#include "xtensor/core/xnoalias.hpp"
#include "xtensor/generators/xbuilder.hpp"
#include "xtensor/generators/xrandom.hpp"
#include "xtensor/io/xio.hpp"
#include "xtensor/views/xdynamic_view.hpp"
#include "xtensor/views/xindex_view.hpp"
#include "xtensor/views/xview.hpp"
#include "test_common_macros.hpp"
namespace xt
{
using shape_t = std::vector;
using view_shape_type = dynamic_shape;
TEST(xdynamic_view, keep)
{
xarray a = {
{{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}},
{{12, 13, 14, 15}, {16, 17, 18, 19}, {20, 21, 22, 23}}
};
auto view0 = dynamic_view(a, xdynamic_slice_vector({1, keep(0, 2), range(1, 4)}));
EXPECT_EQ(view0.dimension(), size_t(2));
EXPECT_EQ(view0.shape()[0], size_t(2));
EXPECT_EQ(view0.shape()[1], size_t(3));
EXPECT_EQ(view0(0, 0), a(1, 0, 1));
EXPECT_EQ(view0(0, 1), a(1, 0, 2));
EXPECT_EQ(view0(0, 2), a(1, 0, 3));
EXPECT_EQ(view0(1, 0), a(1, 2, 1));
EXPECT_EQ(view0(1, 1), a(1, 2, 2));
EXPECT_EQ(view0(1, 2), a(1, 2, 3));
auto view1 = dynamic_view(a, xdynamic_slice_vector({all(), 1, keep(0, 2, 3)}));
EXPECT_EQ(view1.dimension(), size_t(2));
EXPECT_EQ(view1.shape()[0], size_t(2));
EXPECT_EQ(view1.shape()[1], size_t(3));
EXPECT_EQ(view1(0, 0), a(0, 1, 0));
EXPECT_EQ(view1(0, 1), a(0, 1, 2));
EXPECT_EQ(view1(0, 2), a(0, 1, 3));
EXPECT_EQ(view1(1, 0), a(1, 1, 0));
EXPECT_EQ(view1(1, 1), a(1, 1, 2));
EXPECT_EQ(view1(1, 2), a(1, 1, 3));
auto view2 = dynamic_view(a, {all(), 1, keep(0, 2, 3)});
EXPECT_EQ(view1, view2);
auto view3 = dynamic_view(a, {all(), 1, newaxis(), keep(0, 2, 3)});
EXPECT_EQ(view3.dimension(), size_t(3));
EXPECT_EQ(view3.shape()[0], size_t(2));
EXPECT_EQ(view3.shape()[1], size_t(1));
EXPECT_EQ(view3.shape()[2], size_t(3));
EXPECT_EQ(view3(0, 0, 0), a(0, 1, 0));
EXPECT_EQ(view3(0, 0, 1), a(0, 1, 2));
EXPECT_EQ(view3(0, 0, 2), a(0, 1, 3));
EXPECT_EQ(view3(1, 0, 0), a(1, 1, 0));
EXPECT_EQ(view3(1, 0, 1), a(1, 1, 2));
EXPECT_EQ(view3(1, 0, 2), a(1, 1, 3));
auto view4 = dynamic_view(a, {1, keep(0, 2), xrange(1, 4)});
EXPECT_EQ(view0, view4);
auto view5 = dynamic_view(a, {1, keep(0, 2), xstepped_range(1, 4, 1)});
EXPECT_EQ(view0, view5);
}
TEST(xdynamic_view, keep_iterator)
{
xarray a = {
{{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}},
{{12, 13, 14, 15}, {16, 17, 18, 19}, {20, 21, 22, 23}}
};
auto view0 = dynamic_view(a, xdynamic_slice_vector({1, keep(0, 2), range(1, 4)}));
auto iter = view0.template begin();
auto iter_end = view0.template end();
EXPECT_EQ(*iter, a(1, 0, 1));
++iter;
EXPECT_EQ(*iter, a(1, 0, 2));
++iter;
EXPECT_EQ(*iter, a(1, 0, 3));
++iter;
EXPECT_EQ(*iter, a(1, 2, 1));
++iter;
EXPECT_EQ(*iter, a(1, 2, 2));
++iter;
EXPECT_EQ(*iter, a(1, 2, 3));
++iter;
EXPECT_EQ(iter, iter_end);
}
TEST(xdynamic_view, drop)
{
xarray a = {
{{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}},
{{12, 13, 14, 15}, {16, 17, 18, 19}, {20, 21, 22, 23}}
};
auto view0 = dynamic_view(a, xdynamic_slice_vector({1, drop(1), range(1, 4)}));
EXPECT_EQ(view0.dimension(), size_t(2));
EXPECT_EQ(view0.shape()[0], size_t(2));
EXPECT_EQ(view0.shape()[1], size_t(3));
EXPECT_EQ(view0(0, 0), a(1, 0, 1));
EXPECT_EQ(view0(0, 1), a(1, 0, 2));
EXPECT_EQ(view0(0, 2), a(1, 0, 3));
EXPECT_EQ(view0(1, 0), a(1, 2, 1));
EXPECT_EQ(view0(1, 1), a(1, 2, 2));
EXPECT_EQ(view0(1, 2), a(1, 2, 3));
auto view1 = dynamic_view(a, xdynamic_slice_vector({all(), 1, drop(1, 2)}));
EXPECT_EQ(view1.dimension(), size_t(2));
EXPECT_EQ(view1.shape()[0], size_t(2));
EXPECT_EQ(view1.shape()[1], size_t(2));
EXPECT_EQ(view1(0, 0), a(0, 1, 0));
EXPECT_EQ(view1(0, 1), a(0, 1, 3));
EXPECT_EQ(view1(1, 0), a(1, 1, 0));
EXPECT_EQ(view1(1, 1), a(1, 1, 3));
auto view3 = dynamic_view(a, {all(), 1, newaxis(), drop(1, 2)});
EXPECT_EQ(view3.dimension(), size_t(3));
EXPECT_EQ(view3.shape()[0], size_t(2));
EXPECT_EQ(view3.shape()[1], size_t(1));
EXPECT_EQ(view3.shape()[2], size_t(2));
EXPECT_EQ(view3(0, 0, 0), a(0, 1, 0));
EXPECT_EQ(view3(0, 0, 1), a(0, 1, 3));
EXPECT_EQ(view3(1, 0, 0), a(1, 1, 0));
EXPECT_EQ(view3(1, 0, 1), a(1, 1, 3));
}
TEST(xdynamic_view, drop_iterator)
{
xarray a = {
{{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}},
{{12, 13, 14, 15}, {16, 17, 18, 19}, {20, 21, 22, 23}}
};
auto view0 = dynamic_view(a, xdynamic_slice_vector({1, drop(1), range(1, 4)}));
auto iter = view0.template begin();
auto iter_end = view0.template end();
EXPECT_EQ(*iter, a(1, 0, 1));
++iter;
EXPECT_EQ(*iter, a(1, 0, 2));
++iter;
EXPECT_EQ(*iter, a(1, 0, 3));
++iter;
EXPECT_EQ(*iter, a(1, 2, 1));
++iter;
EXPECT_EQ(*iter, a(1, 2, 2));
++iter;
EXPECT_EQ(*iter, a(1, 2, 3));
++iter;
EXPECT_EQ(iter, iter_end);
}
TEST(xdynamic_view, semantic)
{
xarray a = {
{{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}},
{{12, 13, 14, 15}, {16, 17, 18, 19}, {20, 21, 22, 23}}
};
xarray b1 = {{13, 14, 15}, {21, 22, 23}};
xarray b2 = {{0, 1, 2}, {3, 4, 5}};
xarray exp = b1 + b2;
auto view0 = dynamic_view(a, {1, keep(0, 2), range(1, 4)});
view0 += b2;
EXPECT_EQ(view0, exp);
}
TEST(xdynamic_view, slice_conversion)
{
xrange ru(std::size_t(1), std::size_t(12));
xrange rs = ru;
EXPECT_EQ(rs.size(), 11);
EXPECT_EQ(rs(0), 1);
auto rs2 = ru.convert();
EXPECT_EQ(rs2, rs);
xstepped_range sru(std::size_t(1), std::size_t(5), std::size_t(2));
xstepped_range srs = sru;
EXPECT_EQ(srs.size(), 2);
EXPECT_EQ(srs(0), 1);
EXPECT_EQ(srs.step_size(), 2);
auto srs2 = sru.convert();
EXPECT_EQ(srs2, srs);
xall au(std::size_t(11));
xall as(au);
EXPECT_EQ(as.size(), 11);
EXPECT_EQ(as(0), 0);
auto as2 = au.convert();
EXPECT_EQ(as2, as);
xnewaxis nau;
xnewaxis nas(nau);
EXPECT_EQ(nas.size(), 1);
EXPECT_EQ(nas(0), 0);
auto nas2 = nau.convert();
EXPECT_EQ(nas2, nas);
xkeep_slice ks({2, 3, -1});
ks.normalize(6);
xkeep_slice ku(ks);
EXPECT_EQ(ku.size(), std::size_t(3));
EXPECT_FALSE(ku.contains(0));
EXPECT_FALSE(ku.contains(1));
EXPECT_TRUE(ku.contains(2));
EXPECT_TRUE(ku.contains(3));
EXPECT_FALSE(ku.contains(4));
EXPECT_TRUE(ku.contains(5));
auto ks2 = ku.convert();
EXPECT_EQ(ks2, ks);
xdrop_slice ds({2, 3, -1});
ds.normalize(6);
xdrop_slice du(ds);
EXPECT_EQ(du.size(), std::size_t(3));
EXPECT_TRUE(du.contains(0));
EXPECT_TRUE(du.contains(1));
EXPECT_FALSE(du.contains(2));
EXPECT_FALSE(du.contains(3));
EXPECT_TRUE(du.contains(4));
EXPECT_FALSE(du.contains(5));
auto ds2 = du.convert();
EXPECT_EQ(ds2, ds);
}
TEST(xdynamic_view, compilation_linux_issue_1349)
{
xt::xarray array(xt::random::rand({5, 4}));
auto v = xt::view(array, xt::keep(2), xt::all());
auto res = xt::xarray(xt::dynamic_view(v, {xt::keep(0)}));
EXPECT_EQ(res(1), array(2, 1));
}
TEST(xdynamic_view, assignment)
{
xt::xarray x = {{1, 4}, {2, 5}, {3, 6}};
xt::xdynamic_slice_vector sv({});
sv.push_back(xt::all());
sv.push_back(xt::all());
auto res = xt::dynamic_view(x, sv);
xt::xarray xrs = res;
EXPECT_EQ(x, res);
}
}