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
1614namespace 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
2826template <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