7
7
#include " flux/core/concepts.hpp"
8
8
#include " flux/core/inline_sequence_base.hpp"
9
9
#include " flux/adaptor/permutations_base.hpp"
10
+ #include " flux/adaptor/cartesian_base.hpp" // tuple_repeated_t
10
11
#include < cstddef>
11
12
#include < flux/core.hpp>
12
13
#include < numeric>
@@ -16,63 +17,12 @@ namespace flux {
16
17
namespace detail {
17
18
18
19
template <flux::sequence Base, flux::distance_t SubsequenceSize>
19
- requires flux::bounded_sequence<Base> && (SubsequenceSize > 0 )
20
+ requires (SubsequenceSize > 0 ) && flux::bounded_sequence<Base> && flux::multipass_sequence<Base>
20
21
struct permutations_adaptor
21
22
: public flux::inline_sequence_base<permutations_adaptor<Base, SubsequenceSize>> {
22
23
private:
23
24
Base base_;
24
25
25
- // Uninitialized: Input sequence is not cached, output can't be generated
26
- // Cached: Input sequence is cached (copied) into the cache_ member variable
27
- enum class state_t { Uninitialized, Cached };
28
- state_t state_ {state_t ::Uninitialized};
29
-
30
- using inner_value_t = flux::value_t <Base>;
31
- std::vector<inner_value_t > cache_;
32
- std::size_t size_;
33
-
34
- [[nodiscard]] constexpr std::size_t count_permutations ()
35
- {
36
- if (not is_cached ()) {
37
- cache_base ();
38
- }
39
-
40
- return size_;
41
- }
42
-
43
- [[nodiscard]] constexpr bool is_cached () const noexcept { return state_ == state_t ::Cached; }
44
-
45
- constexpr auto cache_base () -> void
46
- {
47
- for (const auto elem : base_) {
48
- cache_.emplace_back (elem);
49
- }
50
-
51
- if (SubsequenceSize <= cache_.size ()) {
52
- size_ = factorial (cache_.size ()) / factorial (cache_.size () - SubsequenceSize);
53
- } else {
54
- size_ = 0 ;
55
- }
56
-
57
- state_ = state_t ::Cached;
58
- }
59
-
60
- constexpr auto cache_base () -> void
61
- requires flux::sized_sequence<Base>
62
- {
63
- const auto size = static_cast <std::size_t >(flux::size (base_));
64
- cache_.resize (size);
65
- std::ranges::copy (base_, cache_.begin ());
66
-
67
- if (SubsequenceSize <= size) {
68
- size_ = factorial (cache_.size ()) / factorial (cache_.size () - SubsequenceSize);
69
- } else {
70
- size_ = 0 ;
71
- }
72
-
73
- state_ = state_t ::Cached;
74
- }
75
-
76
26
public:
77
27
constexpr permutations_adaptor (Base&& base) : base_(std::move(base)) { }
78
28
@@ -81,9 +31,6 @@ struct permutations_adaptor
81
31
using self_t = permutations_adaptor;
82
32
83
33
struct cursor_type {
84
- // TODO: remove vector type
85
- std::vector<std::size_t > indices_;
86
- std::vector<std::size_t > cycles_;
87
34
std::size_t permutation_index_;
88
35
89
36
[[nodiscard]] constexpr auto operator <=>(const cursor_type& other) const
@@ -98,58 +45,23 @@ struct permutations_adaptor
98
45
99
46
public:
100
47
// TODO: remove vector type
101
- using value_type = std::vector< inner_value_t >;
48
+ using value_type = tuple_repeated_t < value_t <Base>, SubsequenceSize >;
102
49
103
50
inline static constexpr bool is_infinite = false ;
104
51
105
52
static constexpr auto first (self_t & self) -> cursor_type
106
53
{
107
- if (not self.is_cached ()) {
108
- self.cache_base ();
109
- }
110
-
111
- // variable alias for readability
112
- const auto base_length = self.cache_ .size ();
113
-
114
- // Set indices to range [0, 1, ..., size-1]
115
- std::vector<std::size_t > indices (base_length);
116
- std::iota (indices.begin (), indices.end (), 0 );
117
-
118
- // Set cycles to [i, i+1, ..., size] where i = size - subsequence_size
119
- std::vector<std::size_t > cycles (SubsequenceSize);
120
- std::iota (cycles.rbegin (), cycles.rend (), base_length - SubsequenceSize);
121
-
122
- // return the cursor
123
- return {.indices_ = indices, .cycles_ = cycles, .permutation_index_ = 0 };
124
- }
125
-
126
- static constexpr auto last (self_t & self) -> cursor_type
127
- {
128
- if (not self.is_cached ()) {
129
- self.cache_base ();
130
- }
131
-
132
- // variable aliases for readability
133
- const auto base_length = self.cache_ .size ();
134
-
135
- // fill up the indices from 0 to size-1 in reverse because it's the end
136
- std::vector<std::size_t > indices (base_length);
137
- std::iota (indices.rbegin (), indices.rend (), 0 );
138
-
139
- // fill up the cycles with 0s because it's the end
140
- std::vector<std::size_t > cycles (SubsequenceSize, 0 );
141
-
142
- // return the cursor
143
- return {.indices_ = indices, .cycles_ = cycles, .permutation_index_ = self.count_permutations ()};
54
+ return {.permutation_index_ = 0 };
144
55
}
145
56
146
57
static constexpr auto is_last (self_t & self, const cursor_type& cursor) -> bool
147
58
{
148
- return cursor. permutation_index_ >= self. count_permutations () ;
59
+ return false ;
149
60
}
150
61
151
62
static constexpr auto inc (self_t & self, cursor_type& cursor) -> void
152
63
{
64
+ /*
153
65
const auto k = SubsequenceSize;
154
66
const auto n = self.cache_.size();
155
67
@@ -167,26 +79,12 @@ struct permutations_adaptor
167
79
return;
168
80
}
169
81
}
82
+ */
170
83
}
171
84
172
85
static constexpr auto read_at (self_t & self, const cursor_type& cursor) -> value_type
173
86
{
174
- if (not self.is_cached ()) {
175
- self.cache_base ();
176
- }
177
- return reindex_vec<inner_value_t >(self.cache_ , cursor.indices_ , SubsequenceSize);
178
- }
179
-
180
- static constexpr auto read_at_unchecked (self_t & self, const cursor_type& cursor)
181
- -> value_type
182
- {
183
- return reindex_vec<inner_value_t >(self.cache_ , cursor.indices_ , SubsequenceSize);
184
- }
185
-
186
- static constexpr auto size (self_t & self) -> flux::distance_t
187
- requires flux::sized_sequence<Base>
188
- {
189
- return self.count_permutations ();
87
+ return {};
190
88
}
191
89
};
192
90
};
@@ -197,7 +95,7 @@ struct permutations_fn {
197
95
template <sequence Seq>
198
96
requires (not infinite_sequence<Seq>)
199
97
[[nodiscard]]
200
- constexpr auto operator ()(Seq&& seq) const -> sized_sequence auto
98
+ constexpr auto operator ()(Seq&& seq) const -> auto
201
99
{
202
100
return permutations_adaptor<std::decay_t <Seq>, SubsequenceSize>(FLUX_FWD (seq));
203
101
}
0 commit comments