Skip to content

Commit fd7ba8d

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents 34ed69a + 849665a commit fd7ba8d

8 files changed

Lines changed: 129 additions & 6 deletions

File tree

include/xtensor/containers/xstorage.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,6 +1640,16 @@ namespace xt
16401640
return m_array.cend();
16411641
}
16421642

1643+
auto crbegin() const
1644+
{
1645+
return m_array.crbegin();
1646+
}
1647+
1648+
auto crend() const
1649+
{
1650+
return m_array.crend();
1651+
}
1652+
16431653
constexpr std::size_t operator[](std::size_t idx) const
16441654
{
16451655
return m_array[idx];

include/xtensor/generators/xbuilder.hpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,6 +910,32 @@ namespace xt
910910

911911
namespace detail
912912
{
913+
template <class S>
914+
struct vstack_fixed_shape_impl;
915+
916+
template <std::size_t N>
917+
struct vstack_fixed_shape_impl<fixed_shape<N>>
918+
{
919+
using type = fixed_shape<1, N>;
920+
};
921+
922+
template <std::size_t I, std::size_t... J>
923+
struct vstack_fixed_shape_impl<fixed_shape<I, J...>>
924+
{
925+
using type = fixed_shape<I, J...>;
926+
};
927+
928+
template <class... CT>
929+
struct vstack_fixed_shape
930+
{
931+
using type = concat_fixed_shape_t<
932+
0,
933+
typename vstack_fixed_shape_impl<typename std::decay_t<CT>::shape_type>::type...>;
934+
};
935+
936+
template <class... CT>
937+
using vstack_fixed_shape_t = typename vstack_fixed_shape<CT...>::type;
938+
913939
template <class S, class... CT>
914940
inline auto vstack_shape(std::tuple<CT...>& t, const S& shape)
915941
{
@@ -948,6 +974,21 @@ namespace xt
948974
return detail::make_xgenerator(detail::vstack_impl<CT...>(std::move(t), size_t(0)), new_shape);
949975
}
950976

977+
/**
978+
* @brief Stack fixed-shape xexpressions in sequence vertically (row wise).
979+
* This overload preserves the result shape at compile time by treating
980+
* 1-D fixed shapes as ``(1, N)`` row vectors before concatenation.
981+
*
982+
* @param t \ref xtuple of fixed-shape xexpressions to stack
983+
* @return xgenerator evaluating to stacked elements with a fixed compile-time shape
984+
*/
985+
template <fixed_shape_container_concept... CT>
986+
inline auto vstack(std::tuple<CT...>&& t)
987+
{
988+
using shape_type = detail::vstack_fixed_shape_t<CT...>;
989+
return detail::make_xgenerator(detail::vstack_impl<CT...>(std::move(t), size_t(0)), shape_type{});
990+
}
991+
951992
namespace detail
952993
{
953994

include/xtensor/views/index_mapper.hpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ namespace xt
193193
* @throws Assertion failure if `i != 0` for integral slices.
194194
* @throws Assertion failure if `i >= slice.size()` for non-integral slices.
195195
*/
196-
template <size_t I, std::integral Index>
196+
template <access_t ACCESS, size_t I, std::integral Index>
197197
size_t map_ith_index(const view_type& view, const Index i) const;
198198

199199
/**
@@ -490,16 +490,16 @@ namespace xt
490490
{
491491
if constexpr (ACCESS == access_t::SAFE)
492492
{
493-
return container.at(map_ith_index<Is>(view, indices[Is])...);
493+
return container.at(map_ith_index<ACCESS, Is>(view, indices[Is])...);
494494
}
495495
else
496496
{
497-
return container(map_ith_index<Is>(view, indices[Is])...);
497+
return container(map_ith_index<ACCESS, Is>(view, indices[Is])...);
498498
}
499499
}
500500

501501
template <class UnderlyingContainer, class... Slices>
502-
template <size_t I, std::integral Index>
502+
template <access_t ACCESS, size_t I, std::integral Index>
503503
auto
504504
index_mapper<xt::xview<UnderlyingContainer, Slices...>>::map_ith_index(const view_type& view, const Index i) const
505505
-> size_t
@@ -518,10 +518,17 @@ namespace xt
518518
assert(i == 0);
519519
return size_t(slice);
520520
}
521+
else if constexpr (xt::detail::is_xall_slice<std::decay_t<current_slice>>::value)
522+
{
523+
return size_t(i);
524+
}
521525
else
522526
{
523527
using slice_size_type = typename current_slice::size_type;
524-
assert(i < slice.size());
528+
if constexpr (ACCESS == access_t::UNSAFE)
529+
{
530+
assert(static_cast<slice_size_type>(i) < slice.size());
531+
}
525532
return size_t(slice(static_cast<slice_size_type>(i)));
526533
}
527534
}

include/xtensor/views/xslice.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ namespace xt
484484
template <class R = std::ptrdiff_t, class T>
485485
inline auto drop(T&& indices)
486486
{
487-
if constexpr (xtl::is_integral<T>::value)
487+
if constexpr (xtl::is_integral<std::remove_cvref_t<T>>::value)
488488
{
489489
using slice_type = xdrop_slice<R>;
490490
using container_type = typename slice_type::container_type;

test/test_xbuilder.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,21 @@ namespace xt
424424
ASSERT_TRUE(arange(8) == w1);
425425
ASSERT_TRUE(w1 == w2);
426426
}
427+
428+
TEST(xbuilder, vstack_fixed)
429+
{
430+
xtensor_fixed<float, fixed_shape<1, 2>> a = {{1.f, 2.f}};
431+
xtensor_fixed<float, fixed_shape<2, 2>> b = {{3.f, 4.f}, {5.f, 6.f}};
432+
433+
auto c = vstack(xtuple(a, b));
434+
435+
using expected_shape_t = fixed_shape<3, 2>;
436+
ASSERT_EQ(expected_shape_t{}, c.shape());
437+
EXPECT_EQ(1.f, c(0, 0));
438+
EXPECT_EQ(2.f, c(0, 1));
439+
EXPECT_EQ(3.f, c(1, 0));
440+
EXPECT_EQ(6.f, c(2, 1));
441+
}
427442
#endif
428443

429444
TEST(xbuilder, access)

test/test_xfixed.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "xtensor/core/xnoalias.hpp"
2323
#include "xtensor/io/xio.hpp"
2424
#include "xtensor/misc/xmanipulation.hpp"
25+
#include "xtensor/views/xview.hpp"
2526

2627
#include "test_common_macros.hpp"
2728

@@ -306,6 +307,13 @@ namespace xt
306307
using tiny_tensor = xtensor_fixed<double, xshape<2>, layout_type::row_major, false>;
307308
EXPECT_GT(sizeof(fixed_tensor), sizeof(tiny_tensor));
308309
}
310+
311+
TEST(xtensor_fixed, iterators)
312+
{
313+
auto arr = xt::xtensor<double, 1>({5, 5, 5, 5, 5});
314+
auto fixed_arr = xt::xtensor_fixed<double, xt::xshape<3>>{1, 2, 3};
315+
xt::view(arr, xt::range(0, 3)) = fixed_arr + 1;
316+
}
309317
}
310318

311319
#endif

test/test_xoperation.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,29 @@ namespace xt
858858
EXPECT_EQ(expected1, res3);
859859
EXPECT_EQ(expected2, res4);
860860
}
861+
862+
TEST_CASE("divide_4d")
863+
{
864+
using T4 = xt::xtensor<float, 4, xt::layout_type::row_major>;
865+
using shape_type = typename T4::shape_type;
866+
867+
shape_type shape = {2, 3, 2, 2};
868+
T4 a(shape, 4.5f);
869+
T4 b(shape, 1.3f);
870+
871+
EXPECT_EQ((a / b)(0, 0, 0, 0), a(0, 0, 0, 0) / b(0, 0, 0, 0));
872+
873+
float sb = 1.2f;
874+
EXPECT_EQ((a / sb)(0, 0, 0, 0), a(0, 0, 0, 0) / sb);
875+
876+
float sa = 4.6f;
877+
EXPECT_EQ((sa / b)(0, 0, 0, 0), sa / b(0, 0, 0, 0));
878+
879+
// self-divide assignment: a = a / b (no zeros in b)
880+
auto a_before = a(1, 2, 1, 1);
881+
a = a / b;
882+
EXPECT_EQ(a(1, 2, 1, 1), a_before / b(1, 2, 1, 1));
883+
}
861884
}
862885

863886
#undef XOPERATION_TEST_TYPES

test/test_xview.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1861,4 +1861,23 @@ namespace xt
18611861

18621862
XT_ASSERT_THROW(const auto col = xt::col(arr, 0), std::invalid_argument);
18631863
}
1864+
1865+
TEST(xview, drop_on_1dim_array)
1866+
{
1867+
auto my_array = xt::xtensor<double, 1>({1, 2, 3});
1868+
1869+
// drop(1) creates a view excluding index 1
1870+
auto v1 = xt::view(my_array, xt::drop(1));
1871+
EXPECT_EQ(v1, (xt::xtensor<double, 1>{1, 3}));
1872+
1873+
// Assign through the drop view
1874+
xt::view(my_array, xt::drop(1)) = 0.;
1875+
EXPECT_EQ(my_array, (xt::xtensor<double, 1>{0, 2, 0}));
1876+
1877+
// Reset, then test drop with a variable (the original compilation issue)
1878+
my_array = xt::xtensor<double, 1>({1, 2, 3});
1879+
const size_t index = 1;
1880+
auto v2 = xt::view(my_array, xt::drop(index));
1881+
EXPECT_EQ(v2, (xt::xtensor<double, 1>{1, 3}));
1882+
}
18641883
}

0 commit comments

Comments
 (0)