Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-27 07:24:24

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 // detray core
0010 #include "detray/utils/ranges.hpp"
0011 
0012 #include "detray/definitions/containers.hpp"
0013 
0014 // Vecmem include(s)
0015 #include "vecmem/containers/device_vector.hpp"
0016 #include "vecmem/containers/jagged_device_vector.hpp"
0017 #include "vecmem/containers/jagged_vector.hpp"
0018 
0019 // GTest include(s)
0020 #include <gtest/gtest.h>
0021 
0022 // System include(s)
0023 #include <forward_list>
0024 #include <list>
0025 #include <type_traits>
0026 
0027 using namespace detray;
0028 
0029 // Test basic ranges definitions
0030 GTEST_TEST(detray_utils, ranges) {
0031   //
0032   // detray containers
0033   //
0034   // std::vector
0035   static_assert(detray::ranges::range<dvector<float>>);
0036   static_assert(!detray::ranges::view<dvector<float>>);
0037   static_assert(detray::ranges::random_access_range<dvector<float>>);
0038   static_assert(detray::ranges::common_range<dvector<float>>);
0039 
0040   // std::array
0041   static_assert(detray::ranges::range<darray<float, 1>>);
0042   static_assert(!detray::ranges::view<darray<float, 1>>);
0043   static_assert(detray::ranges::random_access_range<darray<float, 1>>);
0044   static_assert(detray::ranges::common_range<darray<float, 1>>);
0045 
0046   // std::map
0047   static_assert(detray::ranges::range<dmap<int, float>>);
0048   static_assert(!detray::ranges::view<dmap<int, float>>);
0049   static_assert(detray::ranges::bidirectional_range<dmap<int, float>>);
0050   static_assert(!detray::ranges::random_access_range<dmap<int, float>>);
0051   static_assert(detray::ranges::common_range<dmap<int, float>>);
0052 
0053   // std::tuple
0054   static_assert(!detray::ranges::range<dtuple<int, float>>);
0055   static_assert(!detray::ranges::view<dtuple<int, float>>);
0056 
0057   //
0058   // vecmem containers
0059   //
0060 
0061   // vecmem::device_vector
0062   static_assert(detray::ranges::range<vecmem::device_vector<float>>);
0063   static_assert(!detray::ranges::view<vecmem::device_vector<float>>);
0064   static_assert(
0065       detray::ranges::random_access_range<vecmem::device_vector<float>>);
0066   static_assert(detray::ranges::common_range<vecmem::device_vector<float>>);
0067 
0068   // vecmem::jagged_vector
0069   static_assert(detray::ranges::range<djagged_vector<float>>);
0070   static_assert(!detray::ranges::view<djagged_vector<float>>);
0071   static_assert(detray::ranges::bidirectional_range<djagged_vector<float>>);
0072   static_assert(detray::ranges::common_range<djagged_vector<float>>);
0073 
0074   // vecmem::jagged_device_vector
0075   static_assert(detray::ranges::range<vecmem::jagged_device_vector<float>>);
0076   static_assert(!detray::ranges::view<vecmem::jagged_device_vector<float>>);
0077   static_assert(
0078       detray::ranges::bidirectional_range<vecmem::jagged_device_vector<float>>);
0079   static_assert(
0080       detray::ranges::common_range<vecmem::jagged_device_vector<float>>);
0081 
0082   //
0083   // Some additional STL containers
0084   //
0085 
0086   // std::forward_list
0087   static_assert(detray::ranges::range<std::forward_list<float>>);
0088   static_assert(!detray::ranges::view<std::forward_list<float>>);
0089   static_assert(detray::ranges::forward_range<std::forward_list<float>>);
0090   static_assert(!detray::ranges::bidirectional_range<std::forward_list<float>>);
0091   static_assert(detray::ranges::common_range<std::forward_list<float>>);
0092 
0093   // std::list
0094   static_assert(detray::ranges::range<std::list<float>>);
0095   static_assert(!detray::ranges::view<std::list<float>>);
0096   static_assert(detray::ranges::bidirectional_range<std::list<float>>);
0097   static_assert(!detray::ranges::random_access_range<std::list<float>>);
0098   static_assert(detray::ranges::common_range<std::list<float>>);
0099 }
0100 
0101 // Unittest for an empty view
0102 GTEST_TEST(detray_utils, ranges_empty) {
0103   auto ev = detray::views::empty<float>();
0104 
0105   // general tests
0106   static_assert(std::is_copy_assignable_v<decltype(ev)>);
0107   static_assert(detray::ranges::range<decltype(ev)>);
0108   static_assert(detray::ranges::view<decltype(ev)>);
0109   static_assert(detray::ranges::random_access_range<decltype(ev)>);
0110 
0111   // Test prerequisites for LagacyIterator
0112   static_assert(
0113       std::is_copy_constructible_v<typename decltype(ev)::iterator_t>);
0114   static_assert(std::is_copy_assignable_v<typename decltype(ev)::iterator_t>);
0115   static_assert(std::is_destructible_v<typename decltype(ev)::iterator_t>);
0116 
0117   // Test inherited member functions
0118   ASSERT_EQ(ev.size(), 0u);
0119 
0120   for (const auto i : ev) {
0121     ASSERT_TRUE(i != i);
0122   }
0123 }
0124 
0125 // Unittest for the generation of a single element sequence
0126 GTEST_TEST(detray_utils, ranges_single) {
0127   const dindex value{251u};
0128 
0129   auto sngl = detray::views::single(value);
0130 
0131   // general tests
0132   static_assert(std::is_copy_assignable_v<decltype(sngl)>);
0133   static_assert(detray::ranges::range<decltype(sngl)>);
0134   static_assert(detray::ranges::view<decltype(sngl)>);
0135   static_assert(detray::ranges::random_access_range<decltype(sngl)>);
0136 
0137   // Test prerequisites for LagacyIterator
0138   static_assert(
0139       std::is_copy_constructible_v<typename decltype(sngl)::iterator_t>);
0140   static_assert(std::is_copy_assignable_v<typename decltype(sngl)::iterator_t>);
0141   static_assert(std::is_destructible_v<typename decltype(sngl)::iterator_t>);
0142 
0143   // Test inherited member functions
0144   ASSERT_EQ(sngl[0], value);
0145   ASSERT_EQ(sngl.size(), 1u);
0146   ASSERT_EQ(sngl.front(), 251u);
0147   ASSERT_EQ(sngl.back(), 251u);
0148 
0149   for (auto i : sngl) {
0150     ASSERT_EQ(251u, i);
0151   }
0152 }
0153 
0154 // Unittest for the generation of a pointer to an element
0155 GTEST_TEST(detray_utils, ranges_pointer) {
0156   const dindex value{251u};
0157 
0158   auto ptr = detray::views::pointer(value);
0159 
0160   // general tests
0161   static_assert(std::is_copy_assignable_v<decltype(ptr)>);
0162   static_assert(detray::ranges::range<decltype(ptr)>);
0163   static_assert(detray::ranges::view<decltype(ptr)>);
0164   static_assert(detray::ranges::random_access_range<decltype(ptr)>);
0165 
0166   // Test prerequisites for LagacyIterator
0167   static_assert(
0168       std::is_copy_constructible_v<typename decltype(ptr)::iterator_t>);
0169   static_assert(std::is_copy_assignable_v<typename decltype(ptr)::iterator_t>);
0170   static_assert(std::is_destructible_v<typename decltype(ptr)::iterator_t>);
0171 
0172   // Test inherited member functions
0173   ASSERT_EQ(ptr[0], value);
0174   ASSERT_EQ(ptr.size(), 1u);
0175   ASSERT_EQ(ptr.front(), 251u);
0176   ASSERT_EQ(ptr.back(), 251u);
0177 
0178   for (auto i : ptr) {
0179     ASSERT_EQ(251u, i);
0180   }
0181 }
0182 
0183 // Unittest for the generation of a single element sequence
0184 GTEST_TEST(detray_utils, ranges_iota_single) {
0185   dindex check{0u};
0186   dindex single{7u};
0187 
0188   auto seq = detray::views::iota(single);
0189 
0190   // general tests
0191   static_assert(std::is_copy_assignable_v<decltype(seq)>);
0192   static_assert(detray::ranges::range<decltype(seq)>);
0193   static_assert(detray::ranges::view<decltype(seq)>);
0194   static_assert(detray::ranges::forward_range<decltype(seq)>);
0195   static_assert(detray::ranges::bidirectional_range<decltype(seq)>);
0196   static_assert(detray::ranges::random_access_range<decltype(seq)>);
0197 
0198   // Test prerequisites for LagacyIterator
0199   static_assert(
0200       std::is_copy_constructible_v<typename decltype(seq)::iterator_t>);
0201   static_assert(std::is_copy_assignable_v<typename decltype(seq)::iterator_t>);
0202   static_assert(std::is_destructible_v<typename decltype(seq)::iterator_t>);
0203 
0204   // Test inherited member functions
0205   ASSERT_EQ(seq.size(), 1u);
0206 
0207   for (auto i : seq) {
0208     check += i;
0209   }
0210   ASSERT_EQ(check, single);
0211 }
0212 
0213 // Unittest for the generation of a sequence in an interval
0214 GTEST_TEST(detray_utils, ranges_iota_interval) {
0215   darray<dindex, 2> interval = {2u, 7u};
0216 
0217   auto seq = detray::views::iota(interval);
0218 
0219   // general tests
0220   static_assert(detray::ranges::range<decltype(seq)>);
0221   static_assert(detray::ranges::view<decltype(seq)>);
0222   static_assert(std::is_copy_assignable_v<decltype(seq)>);
0223   static_assert(detray::ranges::forward_range<decltype(seq)>);
0224   static_assert(detray::ranges::bidirectional_range<decltype(seq)>);
0225   static_assert(detray::ranges::random_access_range<decltype(seq)>);
0226 
0227   // Test prerequisites for LagacyIterator
0228   static_assert(
0229       std::is_copy_constructible_v<typename decltype(seq)::iterator_t>);
0230   static_assert(std::is_copy_assignable_v<typename decltype(seq)::iterator_t>);
0231   static_assert(std::is_destructible_v<typename decltype(seq)::iterator_t>);
0232 
0233   // Test inherited member functions
0234   ASSERT_EQ(seq.size(), 5u);
0235 
0236   std::vector<dindex> reference = {2u, 3u, 4u, 5u, 6u};
0237   std::vector<dindex> check = {};
0238   for (auto i : seq) {
0239     check.push_back(i);
0240   }
0241   ASSERT_EQ(check.size(), reference.size());
0242   ASSERT_EQ(check, reference);
0243 }
0244 
0245 // Unittest for the generation of a cartesian product (trivial case)
0246 GTEST_TEST(detray_utils, ranges_cartesian_product_trivial) {
0247   auto seq1 = detray::views::iota(dindex_range{1u, 2u});
0248   auto seq2 = detray::views::iota(dindex_range{2u, 3u});
0249   auto seq3 = detray::views::iota(dindex_range{3u, 4u});
0250 
0251   detray::views::cartesian_product cp{seq1, seq2, seq3};
0252 
0253   // General tests
0254   static_assert(detray::ranges::range<decltype(cp)>);
0255   static_assert(detray::ranges::view<decltype(cp)>);
0256   static_assert(std::is_copy_assignable_v<decltype(cp)>);
0257   static_assert(detray::ranges::input_range<decltype(cp)>);
0258   static_assert(detray::ranges::forward_range<decltype(cp)>);
0259   static_assert(detray::ranges::bidirectional_range<decltype(cp)>);
0260   static_assert(!detray::ranges::random_access_range<decltype(cp)>);
0261 
0262   // Test prerequisites for LagacyIterator
0263   static_assert(
0264       std::is_copy_constructible_v<typename decltype(cp)::iterator_t>);
0265   static_assert(std::is_copy_assignable_v<typename decltype(cp)::iterator_t>);
0266   static_assert(std::is_destructible_v<typename decltype(cp)::iterator_t>);
0267 
0268   // Test size
0269   ASSERT_EQ(cp.size(), 1u);
0270 
0271   std::size_t r{0u};
0272   for (const auto [i, j, k] : cp) {
0273     ++r;
0274     ASSERT_EQ(i, 1u);
0275     ASSERT_EQ(j, 2u);
0276     ASSERT_EQ(k, 3u);
0277   }
0278 
0279   ASSERT_EQ(r, 1u);
0280 }
0281 // Unittest for the generation of a cartesian product from a range of intervals
0282 GTEST_TEST(detray_utils, ranges_cartesian_product) {
0283   const dindex_range range1{2u, 7u};
0284   const dindex_range range2{1u, 10u};
0285   const dindex_range range3{3u, 4u};
0286 
0287   auto seq1 = detray::views::iota(range1);
0288   auto seq2 = detray::views::iota(range2);
0289   auto seq3 = detray::views::iota(range3);
0290 
0291   const std::size_t size{seq1.size() * seq2.size() * seq3.size()};
0292 
0293   detray::views::cartesian_product cp{seq1, seq2, seq3};
0294 
0295   // General tests
0296   static_assert(detray::ranges::range<decltype(cp)>);
0297   static_assert(detray::ranges::view<decltype(cp)>);
0298   static_assert(std::is_copy_assignable_v<decltype(cp)>);
0299   static_assert(detray::ranges::input_range<decltype(cp)>);
0300   static_assert(detray::ranges::forward_range<decltype(cp)>);
0301   static_assert(detray::ranges::bidirectional_range<decltype(cp)>);
0302   static_assert(!detray::ranges::random_access_range<decltype(cp)>);
0303 
0304   // Test prerequisites for LagacyIterator
0305   static_assert(
0306       std::is_copy_constructible_v<typename decltype(cp)::iterator_t>);
0307   static_assert(std::is_copy_assignable_v<typename decltype(cp)::iterator_t>);
0308   static_assert(std::is_destructible_v<typename decltype(cp)::iterator_t>);
0309 
0310   // Test size
0311   ASSERT_EQ(cp.size(), size);
0312 
0313   // Generate truth
0314   std::vector<std::tuple<dindex, dindex, dindex>> result;
0315   for (auto i : detray::views::iota(range1)) {
0316     for (auto j : detray::views::iota(range2)) {
0317       for (auto k : detray::views::iota(range3)) {
0318         result.emplace_back(i, j, k);
0319       }
0320     }
0321   }
0322 
0323   std::size_t r{0u};
0324   for (const auto [i, j, k] : cp) {
0325     const auto [l, m, n] = result[r];
0326     ++r;
0327     ASSERT_EQ(i, l);
0328     ASSERT_EQ(j, m);
0329     ASSERT_EQ(k, n);
0330   }
0331 }
0332 
0333 // Unittest for the convenience enumeration of a range
0334 GTEST_TEST(detray_utils, ranges_enumerate) {
0335   struct uint_holder {
0336     unsigned int ui{0u};
0337   };
0338 
0339   dvector<uint_holder> seq = {{0u}, {1u}, {2u}, {3u}, {4u}, {5u}};
0340 
0341   auto enumerator = detray::views::enumerate(seq);
0342 
0343   // general tests
0344   static_assert(detray::ranges::range<decltype(enumerator)>);
0345   static_assert(detray::ranges::view<decltype(enumerator)>);
0346   static_assert(std::is_copy_assignable_v<decltype(enumerator)>);
0347   static_assert(detray::ranges::random_access_range<decltype(enumerator)>);
0348 
0349   // Test prerequisites for LagacyIterator
0350   static_assert(
0351       std::is_copy_constructible_v<typename decltype(enumerator)::iterator_t>);
0352   static_assert(
0353       std::is_copy_assignable_v<typename decltype(enumerator)::iterator_t>);
0354   static_assert(
0355       std::is_destructible_v<typename decltype(enumerator)::iterator_t>);
0356 
0357   // Test inherited member functions
0358   const auto [i, v] = enumerator[2];
0359   ASSERT_EQ(i, 2u);
0360   ASSERT_EQ(v.ui, 2u);
0361   ASSERT_EQ(enumerator.size(), 6u);
0362   const auto [i_front, v_front] = enumerator.front();
0363   ASSERT_EQ(i_front, 0u);
0364   ASSERT_EQ(v_front.ui, 0u);
0365   const auto [i_back, v_back] = enumerator.back();
0366   ASSERT_EQ(i_back, 5u);
0367   ASSERT_EQ(v_back.ui, 5u);
0368 
0369   for (auto [j, w] : enumerator) {
0370     ASSERT_TRUE(j == w.ui);
0371     ASSERT_EQ(j, w.ui);
0372   }
0373 }
0374 
0375 // Integration test for the picking of indexed elements from another range
0376 GTEST_TEST(detray_utils, ranges_pick) {
0377   // The indices of the iota elements to be picked
0378   std::vector<dindex> indices = {2u, 3u, 7u, 8u};
0379   std::vector<dindex> check = {};
0380 
0381   struct uint_holder {
0382     unsigned int ui{0u};
0383   };
0384 
0385   dvector<uint_holder> seq = {{0u}, {1u}, {2u}, {3u}, {4u},
0386                               {5u}, {6u}, {7u}, {8u}};
0387 
0388   auto selected = detray::views::pick(seq, indices);
0389 
0390   // general tests
0391   static_assert(detray::ranges::range<decltype(selected)>);
0392   static_assert(detray::ranges::view<decltype(selected)>);
0393   static_assert(std::is_copy_assignable_v<decltype(selected)>);
0394   static_assert(detray::ranges::random_access_range<decltype(selected)>);
0395 
0396   // Test prerequisites for LagacyIterator
0397   static_assert(
0398       std::is_copy_constructible_v<typename decltype(selected)::iterator_t>);
0399   static_assert(
0400       std::is_copy_assignable_v<typename decltype(selected)::iterator_t>);
0401   static_assert(
0402       std::is_destructible_v<typename decltype(selected)::iterator_t>);
0403 
0404   // Test inherited member functions
0405   const auto [i, v] = selected[2];
0406   ASSERT_EQ(i, 7u);
0407   ASSERT_EQ(v.ui, 7u);
0408   ASSERT_EQ(selected.size(), 4u);
0409   const auto [i_front, v_front] = selected.front();
0410   ASSERT_EQ(i_front, 2u);
0411   ASSERT_EQ(v_front.ui, 2u);
0412   const auto [i_back, v_back] = selected.back();
0413   ASSERT_EQ(i_back, 8u);
0414   ASSERT_EQ(v_back.ui, 8u);
0415 
0416   for (auto [j, w] : selected) {
0417     ASSERT_EQ(j, w.ui);
0418     check.push_back(w.ui);
0419   }
0420   ASSERT_EQ(check.size(), indices.size());
0421   ASSERT_EQ(check, indices);
0422 }
0423 
0424 // Unittest for the joining of multiple ranges
0425 GTEST_TEST(detray_utils, ranges_join) {
0426   dvector<dindex> interval_0 = {};
0427   dvector<dindex> interval_1 = {2u, 3u, 4u};
0428   dvector<dindex> interval_2 = {7u, 8u, 9u};
0429   dvector<dindex> interval_3 = {10u, 11u, 12u, 13u};
0430   dvector<dvector<dindex>> intervals{interval_0, interval_0, interval_1,
0431                                      interval_2, interval_0, interval_3,
0432                                      interval_0};
0433 
0434   std::vector<dindex> reference = {2u, 3u, 4u, 7u, 8u, 9u, 10u, 11u, 12u, 13u};
0435   std::vector<dindex> check = {};
0436 
0437   auto joined = detray::views::join(intervals);
0438 
0439   // general tests
0440   static_assert(detray::ranges::range<decltype(joined)>);
0441   static_assert(detray::ranges::view<decltype(joined)>);
0442   static_assert(std::is_copy_assignable_v<decltype(joined)>);
0443   static_assert(detray::ranges::random_access_range<decltype(joined)>);
0444 
0445   // Test prerequisites for LagacyIterator
0446   static_assert(
0447       std::is_copy_constructible_v<typename decltype(joined)::iterator_t>);
0448   static_assert(
0449       std::is_copy_assignable_v<typename decltype(joined)::iterator_t>);
0450   static_assert(std::is_destructible_v<typename decltype(joined)::iterator_t>);
0451 
0452   // Test inherited member functions
0453   ASSERT_EQ(joined[1], 3u);
0454   ASSERT_EQ(joined[4], 8u);
0455   ASSERT_EQ(joined[7], 11u);
0456   ASSERT_EQ(joined.size(), 10u);
0457   ASSERT_EQ(joined.front(), 2u);
0458   ASSERT_EQ(joined.back(), 13u);
0459 
0460   for (auto j : joined) {
0461     static_assert(!std::is_const_v<decltype(j)>, "Non-const element in join");
0462     check.push_back(j);
0463   }
0464   ASSERT_EQ(check.size(), reference.size());
0465   ASSERT_EQ(check, reference);
0466 
0467   auto joined_comp = intervals | detray::views::join();
0468 
0469   check.clear();
0470   for (auto j : joined_comp) {
0471     static_assert(!std::is_const_v<decltype(j)>, "Non-const element in join");
0472     check.push_back(j);
0473   }
0474   ASSERT_EQ(check.size(), reference.size());
0475   ASSERT_EQ(check, reference);
0476 }
0477 
0478 // Unittest for the joining of multiple ranges
0479 GTEST_TEST(detray_utils, ranges_static_join) {
0480   dvector<dindex> interval_1 = {2u, 3u, 4u};
0481   dvector<dindex> interval_2 = {7u, 8u, 9u};
0482 
0483   std::vector<dindex> reference = {2u, 3u, 4u, 7u, 8u, 9u};
0484   std::vector<dindex> check = {};
0485 
0486   auto joined = detray::views::static_join(interval_1, interval_2);
0487 
0488   // general tests
0489   static_assert(detray::ranges::range<decltype(joined)>);
0490   static_assert(detray::ranges::view<decltype(joined)>);
0491   static_assert(std::is_copy_assignable_v<decltype(joined)>);
0492   static_assert(detray::ranges::random_access_range<decltype(joined)>);
0493 
0494   // Test prerequisites for LagacyIterator
0495   static_assert(
0496       std::is_copy_constructible_v<typename decltype(joined)::iterator_t>);
0497   static_assert(
0498       std::is_copy_assignable_v<typename decltype(joined)::iterator_t>);
0499   static_assert(std::is_destructible_v<typename decltype(joined)::iterator_t>);
0500 
0501   // Test inherited member functions
0502   ASSERT_EQ(joined[1], 3u);
0503   ASSERT_EQ(joined[4], 8u);
0504   ASSERT_EQ(joined.size(), 6u);
0505   ASSERT_EQ(joined.front(), 2u);
0506   ASSERT_EQ(joined.back(), 9u);
0507 
0508   for (const auto j : joined) {
0509     check.push_back(j);
0510   }
0511   ASSERT_EQ(check.size(), reference.size());
0512   ASSERT_EQ(check, reference);
0513 }
0514 
0515 // Unittest for the subrange implementation
0516 GTEST_TEST(detray_utils, ranges_subrange) {
0517   std::size_t begin{1u};
0518   std::size_t end{4u};
0519   std::array<std::size_t, 2> interval{begin, end};
0520 
0521   dvector<int> seq = {0, 1, 2, 3, 4, 5};
0522 
0523   auto sr = detray::ranges::subrange(seq, interval);
0524 
0525   // general tests
0526   static_assert(detray::ranges::range<decltype(sr)>);
0527   static_assert(detray::ranges::view<decltype(sr)>);
0528   static_assert(std::is_copy_assignable_v<decltype(sr)>);
0529   static_assert(detray::ranges::random_access_range<decltype(sr)>);
0530 
0531   // Test prerequisites for LagacyIterator
0532   static_assert(
0533       std::is_copy_constructible_v<typename decltype(sr)::iterator_t>);
0534   static_assert(std::is_copy_assignable_v<typename decltype(sr)::iterator_t>);
0535   static_assert(std::is_destructible_v<typename decltype(sr)::iterator_t>);
0536 
0537   ASSERT_EQ(sr[1], seq[begin + 1u]);
0538   ASSERT_EQ(sr.size(), 3u);
0539   ASSERT_EQ(sr.front(), 1u);
0540   ASSERT_EQ(sr.back(), 3u);
0541 
0542   // non-const iteration
0543   std::size_t i{1u};
0544   for (const auto& v : sr) {
0545     ASSERT_NE(v, 0u);
0546     ASSERT_NE(v, 4u);
0547     ASSERT_EQ(v, seq[i++]);
0548   }
0549 
0550   // const iteration
0551   const dvector<int> seq_c(seq);
0552   i = 1u;
0553   for (const auto& v : detray::ranges::subrange(seq_c, interval)) {
0554     ASSERT_EQ(v, seq[i++]);
0555   }
0556 
0557   // Check that an empty subrange does not get iterated
0558   interval[0] = 0u;
0559   interval[1] = 0u;
0560   for (const auto& v : detray::ranges::subrange(seq_c, interval)) {
0561     (void)v;
0562     ASSERT_TRUE(false);
0563   }
0564 }