Skip to content

Commit 3ef7dde

Browse files
committed
Don't modify range in count_cycles (and allow for general range inputs)
Fixes #503
1 parent d7a9475 commit 3ef7dde

File tree

1 file changed

+26
-38
lines changed

1 file changed

+26
-38
lines changed

SeQuant/core/utility/permutation.hpp

Lines changed: 26 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
#ifndef SEQUANT_PERMUTATION_HPP
22
#define SEQUANT_PERMUTATION_HPP
33

4+
#include <SeQuant/core/container.hpp>
45
#include <SeQuant/core/index.hpp>
56
#include <SeQuant/core/utility/macros.hpp>
67

7-
#include <range/v3/algorithm.hpp>
8-
98
#include <algorithm>
109
#include <cstddef>
1110
#include <cstdlib>
11+
#include <ranges>
1212
#include <set>
13-
#include <type_traits>
14-
#include <utility>
1513

1614
namespace sequant {
1715

@@ -21,63 +19,53 @@ namespace sequant {
2119
/// by stacking \p v0 and \p v1 on top of each other.
2220
/// @tparam Seq0 (reference to) a container type
2321
/// @tparam Seq1 (reference to) a container type
24-
/// @param v0 first sequence; if passed as an rvalue reference, it is moved from
25-
/// @param[in] v1 second sequence
22+
/// @param v0 first range
23+
/// @param v1 second range
2624
/// @pre \p v0 is a permutation of \p v1
2725
/// @return the number of cycles
2826
template <typename Seq0, typename Seq1>
29-
std::size_t count_cycles(Seq0&& v0, const Seq1& v1) {
30-
std::remove_reference_t<Seq0> v(std::forward<Seq0>(v0));
31-
using T = std::decay_t<decltype(v[0])>;
32-
SEQUANT_ASSERT(ranges::is_permutation(v, v1));
27+
std::size_t count_cycles(Seq0&& v0, Seq1&& v1) {
28+
using std::ranges::begin;
29+
using std::ranges::end;
30+
using std::ranges::size;
31+
SEQUANT_ASSERT(std::ranges::is_permutation(v0, v1));
3332
// This function can't deal with duplicate entries in v0 or v1
34-
SEQUANT_ASSERT(std::set(std::begin(v0), std::end(v0)).size() == v0.size());
35-
SEQUANT_ASSERT(std::set(std::begin(v1), std::end(v1)).size() == v1.size());
36-
37-
auto make_null = []() -> T {
38-
if constexpr (std::is_arithmetic_v<T>) {
39-
return -1;
40-
} else if constexpr (std::is_same_v<T, Index>) {
41-
return L"p_50";
42-
}
43-
44-
SEQUANT_UNREACHABLE;
45-
};
33+
SEQUANT_ASSERT(std::set(begin(v0), end(v0)).size() == size(v0));
34+
SEQUANT_ASSERT(std::set(begin(v1), end(v1)).size() == size(v1));
4635

47-
const auto null = make_null();
48-
SEQUANT_ASSERT(ranges::contains(v, null) == false);
49-
SEQUANT_ASSERT(ranges::contains(v1, null) == false);
36+
container::set<decltype(begin(v0))> visited;
37+
visited.reserve(size(v0));
5038

5139
std::size_t n_cycles = 0;
52-
for (auto it = v.begin(); it != v.end(); ++it) {
53-
if (*it == null) {
40+
for (auto it = begin(v0); it != end(v0); ++it) {
41+
if (visited.find(it) != end(visited)) {
5442
continue;
5543
}
5644

5745
n_cycles++;
5846

59-
auto idx = std::distance(v.begin(), it);
47+
auto idx = std::distance(begin(v0), it);
6048
SEQUANT_ASSERT(idx >= 0);
6149

6250
auto it0 = it;
6351

64-
auto it1 = std::find(v1.begin(), v1.end(), *it0);
65-
SEQUANT_ASSERT(it1 != v1.end());
52+
auto it1 = std::find(begin(v1), end(v1), *it0);
53+
SEQUANT_ASSERT(it1 != end(v1));
6654

67-
auto idx1 = std::distance(v1.begin(), it1);
55+
auto idx1 = std::distance(begin(v1), it1);
6856
SEQUANT_ASSERT(idx1 >= 0);
6957

7058
do {
71-
it0 = std::find(v.begin(), v.end(), v[idx1]);
72-
SEQUANT_ASSERT(it0 != v.end());
59+
it0 = std::find(begin(v0), end(v0), *it1);
60+
SEQUANT_ASSERT(it0 != end(v0));
7361

74-
it1 = std::find(v1.begin(), v1.end(), *it0);
75-
SEQUANT_ASSERT(it1 != v1.end());
62+
it1 = std::find(begin(v1), end(v1), *it0);
63+
SEQUANT_ASSERT(it1 != end(v1));
7664

77-
idx1 = std::distance(v1.begin(), it1);
65+
idx1 = std::distance(begin(v1), it1);
7866
SEQUANT_ASSERT(idx1 >= 0);
7967

80-
*it0 = null;
68+
visited.insert(it0);
8169
} while (idx1 != idx);
8270
}
8371
return n_cycles;
@@ -107,7 +95,7 @@ int permutation_parity(std::span<T> p, bool overwrite = false) {
10795
}
10896

10997
if (overwrite) {
110-
ranges::for_each(p, [N](auto& e) { e -= N; });
98+
std::ranges::for_each(p, [N](auto& e) { e -= N; });
11199
}
112100

113101
return parity;

0 commit comments

Comments
 (0)