Skip to content

Commit e4d0113

Browse files
author
Lukas Thomann
committed
formatted and fixed macro.hpp contains function
now properly checks set and subset
1 parent 5ba9710 commit e4d0113

41 files changed

Lines changed: 560 additions & 741 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CMakeLists.txt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@ cmake_minimum_required(VERSION 4.1.1)
22
project(
33
cth
44
LANGUAGES CXX
5-
VERSION 1.0.0)
5+
VERSION 1.0.0
6+
)
67

78
include(cth_setup_utilities)
89
include(cth_target_utilities)
910
include(cth_install_utilities)
1011

1112
cth_set_compiler_specifics()
1213
cth_set_latest_c_cpp_standard()
14+
set(CMAKE_CXX_SCAN_FOR_MODULES FALSE)
15+
16+
set(CMAKE_C_COMPILER_LAUNCHER "buildcache")
17+
set(CMAKE_CXX_COMPILER_LAUNCHER "buildcache")
1318

1419
# exported
1520
add_subdirectory(cth)
@@ -30,14 +35,13 @@ cth_glob_cpp(
3035
FORMAT_FILES
3136
"cth"
3237
"cth_coro"
33-
"cth_coro_tests"
3438
"cth_cthm"
35-
"cth_tests"
3639
"cth_win"
37-
"cth_win_tests"
3840
"integration_tests"
41+
"playground"
3942
)
4043

41-
cth_add_uncrustify_target(uncrustify-format OPTIONAL ${FORMAT_FILES})
44+
#cth_add_uncrustify_target(uncrustify-format OPTIONAL ${FORMAT_FILES})
45+
4246
# playground
4347
add_subdirectory(playground)

cth/incl/cth/algorithm/combine.hpp

Lines changed: 58 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
#include <unordered_set>
1313
#include <vector>
1414

15-
16-
1715
/**
1816
* @brief creates a vector of unique elements with exactly one element from each given range. order is
1917
* preserved
@@ -97,36 +95,37 @@ template<mta::range2d_over_cpt<CPT(std::equality_comparable)> Rng>
9795

9896
}
9997

100-
101-
10298
namespace cth::alg {
10399

104100
/**
105-
* \brief assigns a's to b's based of every a's options for b's
101+
* \brief assigns a's to b's based of every a's options for b's, prioritizing spread
106102
* \tparam Rng1 rng<rng<std::integral>>
107103
* \tparam Rng2 rng<std::integral>
108104
* \param a_b_options range of b options from a's
109105
* \param b_max max assignments for b's
110106
* \return vector<integral> based on Rng1
111107
*/
112108
template<mta::range2d_over_cpt<CPT(std::integral)> Rng1, mta::range_over_cpt<CPT(std::integral)> Rng2>
113-
[[nodiscard]] auto assign(Rng1 const& a_b_options, Rng2 const& b_max) -> std::vector<mta::range2d_value_t<Rng1>> {
109+
[[nodiscard]] auto assign(
110+
Rng1 const& a_b_options,
111+
Rng2 const& b_max
112+
) -> std::vector<mta::range2d_value_t<Rng1>> {
114113
using T = std::remove_cvref_t<mta::range2d_value_t<Rng1>>;
115114
static constexpr size_t UNASSIGNED = static_cast<size_t>(-1);
116115

117116
CTH_CRITICAL(
118117
!std::ranges::all_of(
119118
a_b_options,
120119
[&b_max](std::span<T const> b_options) {
121-
return std::ranges::all_of(b_options, [&b_max](auto const index) {
120+
return std::ranges::all_of(b_options,
121+
[&b_max](auto const index) {
122122
return 0 <= index && index < std::ranges::size(b_max);
123-
});
123+
}
124+
);
124125
}
125126
),
126127
"0 <= indices < size(b_max) required"
127-
) {
128-
details->add("size(b_max): {}", std::ranges::size(b_max));
129-
}
128+
) { details->add("size(b_max): {}", std::ranges::size(b_max)); }
130129

131130
auto const aCount = std::ranges::size(a_b_options);
132131
auto const bCount = std::ranges::size(b_max);
@@ -146,6 +145,10 @@ template<mta::range2d_over_cpt<CPT(std::integral)> Rng1, mta::range_over_cpt<CPT
146145
std::vector<bool> visitedB(bCount, false);
147146
std::vector<bool> visitedA(aCount, false);
148147

148+
// NEW: State for "Water-filling" spreading
149+
size_t assignedCount = 0;
150+
std::vector<size_t> current_b_max(bCount, 0);
151+
149152
// 2. Isolated BFS Engine
150153
auto find_augmenting_path = [&](size_t startA) -> size_t {
151154
std::ranges::fill(visitedB, false);
@@ -165,55 +168,73 @@ template<mta::range2d_over_cpt<CPT(std::integral)> Rng1, mta::range_over_cpt<CPT
165168
visitedB[b] = true;
166169
parentB[b] = currentA; // Record path
167170

168-
// Path End: Open slot found
169-
if(std::ranges::size(bToA[b]) < static_cast<size_t>(b_max[b]))
171+
// MODIFIED: Compare against the current water level, NOT absolute max
172+
if(std::ranges::size(bToA[b]) < current_b_max[b])
170173
return b;
171174

172175
// Path Continuation: Displace existing residents
173-
for(auto previousA : bToA[b]) {
176+
for(auto previousA : bToA[b])
174177
if(!visitedA[previousA]) {
175178
visitedA[previousA] = true;
176179
parentA[previousA] = b;
177180
q.push(previousA);
178181
}
179-
}
180182
}
181183
}
182184
return UNASSIGNED;
183185
};
184186

185-
// 3. Main Logic
186-
for(size_t i = 0; i < aCount; ++i) {
187-
auto endB = find_augmenting_path(i);
187+
// 3. Main Logic (Water-filling Loop)
188+
bool capacity_increased = true;
188189

189-
if(endB == UNASSIGNED) return std::vector<T>{}; // Dead end
190+
// Loop until all 'a's are assigned or we've exhausted true capacities
191+
while(assignedCount < aCount && capacity_increased) {
192+
capacity_increased = false;
190193

191-
// Backtrack and flip assignments
192-
auto currentB = endB;
193-
while(true) {
194-
auto currentA = parentB[currentB];
194+
// Step 3a: Raise the water level (allow 1 more allocation per family)
195+
for(size_t i = 0; i < bCount; ++i)
196+
if(current_b_max[i] < static_cast<size_t>(b_max[i])) {
197+
current_b_max[i]++;
198+
capacity_increased = true;
199+
}
200+
201+
// Step 3b: Try to assign all unassigned elements at this new capacity level
202+
for(size_t i = 0; i < aCount; ++i) {
203+
if(aToB[i] != static_cast<T>(UNASSIGNED)) continue; // Already assigned
204+
205+
auto endB = find_augmenting_path(i);
206+
207+
if(endB != UNASSIGNED) {
208+
// Backtrack and flip assignments
209+
auto currentB = endB;
210+
while(true) {
211+
auto currentA = parentB[currentB];
195212

196-
if(currentA != i) {
197-
auto previousB = parentA[currentA];
213+
if(currentA != i) {
214+
auto previousB = parentA[currentA];
198215

199-
// O(1) Swap-and-pop
200-
auto it = std::ranges::find(bToA[previousB], currentA);
201-
*it = bToA[previousB].back();
202-
bToA[previousB].pop_back();
216+
// O(1) Swap-and-pop
217+
auto it = std::ranges::find(bToA[previousB], currentA);
218+
*it = bToA[previousB].back();
219+
bToA[previousB].pop_back();
203220

204-
bToA[currentB].push_back(currentA);
205-
aToB[currentA] = static_cast<T>(currentB);
221+
bToA[currentB].push_back(currentA);
222+
aToB[currentA] = static_cast<T>(currentB);
206223

207-
currentB = previousB; // Move up
208-
} else {
209-
bToA[currentB].push_back(currentA);
210-
aToB[currentA] = static_cast<T>(currentB);
211-
break;
224+
currentB = previousB; // Move up
225+
} else {
226+
bToA[currentB].push_back(currentA);
227+
aToB[currentA] = static_cast<T>(currentB);
228+
break;
229+
}
230+
}
231+
assignedCount++; // Successfully placed an 'a'
212232
}
213233
}
214234
}
215235

236+
if(assignedCount < aCount) return std::vector<T>{}; // Dead end
237+
216238
return aToB;
217239
}
218-
219240
}

cth/incl/cth/algorithm/ranges.hpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,2 @@
11
#pragma once
22
#include "cth/algorithm/views.hpp"
3-
4-
5-
6-
7-

cth/incl/cth/algorithm/views.hpp

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
#include <format>
88
#include <ranges>
99

10-
1110
namespace cth::views {
1211
struct to_ptr_range_fn : cth::ranges::piped_fn {
1312
template<std::ranges::viewable_range Rng> requires std::is_lvalue_reference_v<std::ranges::range_reference_t<Rng>>
@@ -18,15 +17,14 @@ struct to_ptr_range_fn : cth::ranges::piped_fn {
1817

1918
inline cxpr to_ptr_range_fn to_ptr_range;
2019

21-
2220
struct split_into_fn {
2321
/**
24-
*
22+
*
2523
* @param rng to chunk
2624
* @param max_chunks count of chunks to split into
2725
* @pre chunks > 0
28-
* @post split into `N` chunks where `N <= chunks`
29-
* @return view of
26+
* @post split into `N` chunks where `N <= chunks`
27+
* @return view of
3028
*/
3129
template<std::ranges::sized_range Rng>
3230
cxpr auto operator()(Rng&& rng, std::ranges::range_difference_t<Rng> const max_chunks) const {
@@ -40,7 +38,9 @@ struct split_into_fn {
4038

4139
template<class Fn, class T> requires std::constructible_from<std::decay_t<T>, T>
4240
cxpr auto operator()(this Fn&&, T&& chunks) {
43-
return ranges::pipe_call_closure<std::remove_cvref_t<Fn>, std::decay_t<T>>{std::forward<T>(chunks)};
41+
return ranges::pipe_call_closure<
42+
std::remove_cvref_t<Fn>, std::decay_t<T>
43+
>{std::forward<T>(chunks)};
4444
}
4545
};
4646

@@ -49,18 +49,16 @@ struct split_into_fn {
4949
*/
5050
inline cxpr split_into_fn split_into;
5151

52-
5352
struct drop_stride_fn {
5453
template<std::ranges::viewable_range Rng>
5554
cxpr auto operator()(
5655
Rng&& rng,
5756
std::ranges::range_difference_t<Rng> const drop,
5857
std::ranges::range_difference_t<Rng> const stride
59-
) const {
60-
return std::views::stride(std::views::drop(std::forward<Rng>(rng), drop), stride);
61-
}
58+
) const { return std::views::stride(std::views::drop(std::forward<Rng>(rng), drop), stride); }
6259

63-
template<class Fn, class T, class U> requires(std::constructible_from<std::decay_t<T>, T> && std::constructible_from<std::decay_t<U>, U>)
60+
template<class Fn, class T, class U> requires(std::constructible_from<std::decay_t<T>, T> && std::constructible_from
61+
<std::decay_t<U>, U>)
6462
cxpr auto operator()(this Fn&&, T&& drop, U&& stride) {
6563
return ranges::pipe_call_closure<std::remove_cvref_t<Fn>, std::decay_t<T>, std::decay_t<U>>{
6664
std::forward<T>(drop),
@@ -71,17 +69,16 @@ struct drop_stride_fn {
7169

7270
inline cxpr drop_stride_fn drop_stride;
7371

74-
7572
struct transform_call_fn {
7673
template<class Rng>
7774
using range_value_t = std::ranges::range_value_t<Rng>;
7875

79-
template<std::ranges::range Rng, class Call, class... Args> requires(
80-
std::invocable<Call, std::ranges::range_value_t<Rng>, Args...>)
76+
template<std::ranges::range Rng, class Call, class... Args> requires(std::invocable<Call, std::ranges::range_value_t
77+
<Rng>, Args...>)
8178
cxpr auto operator()(Rng&& rng, Call&& call, Args&&... args) const {
8279
return std::views::transform(
8380
std::forward<Rng>(rng),
84-
[&call, &args...]<class T>(T&& element) {
81+
[&call, &args...] < class T >(T&& element) {
8582
return std::invoke(
8683
std::forward<Call>(call),
8784
std::forward<T>(element),
@@ -103,7 +100,6 @@ struct transform_call_fn {
103100
inline cxpr transform_call_fn transform_call;
104101
}
105102

106-
107103
namespace cth::views {
108104
template<std::ranges::input_range Rng>
109105
struct format_view {
@@ -129,9 +125,7 @@ struct format_fn {
129125
std::string_view sep,
130126
std::string_view pre = "",
131127
std::string_view post = ""
132-
) const {
133-
return format_view{std::views::all(std::forward<Rng>(rng)), sep, pre, post};
134-
}
128+
) const { return format_view{std::views::all(std::forward<Rng>(rng)), sep, pre, post}; }
135129

136130
template<class Me>
137131
[[nodiscard]] cxpr auto operator()(
@@ -161,17 +155,13 @@ template<class Rng>
161155
struct std::formatter<cth::views::format_view<Rng>> {
162156
using value_type = std::ranges::range_value_t<Rng>;
163157

164-
165-
[[nodiscard]] cxpr auto parse(std::format_parse_context& ctx) {
166-
return _formatter.parse(ctx);
167-
}
158+
[[nodiscard]] cxpr auto parse(std::format_parse_context& ctx) { return _formatter.parse(ctx); }
168159

169160
template<typename FormatContext>
170161
[[nodiscard]] cxpr auto format(
171162
cth::views::format_view<Rng>& obj,
172163
FormatContext& ctx
173164
) const {
174-
175165
auto& [rng, sep, pre, post] = obj;
176166

177167
_formatter.set_separator(sep);

cth/incl/cth/constants.hpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,38 +16,34 @@
1616
#endif
1717
#endif
1818

19-
2019
#ifdef CTH_DEBUG_MODE
2120
#ifdef CTH_RELEASE_MODE
2221
#error "CTH_DEBUG_MODE and CTH_RELEASE_MODE must not be defined at the same time."
2322
#endif
2423
#endif
2524

26-
2725
#ifndef CTH_DEBUG_MODE
2826
#ifndef CTH_RELEASE_MODE
2927
#error "Neither CTH_DEBUG_MODE nor CTH_RELEASE_MODE is defined."
3028
#endif
3129
#endif
3230

33-
3431
#ifdef CTH_DEBUG_MODE
3532
#define CTH_DEBUG_IMPL
36-
#define CTH_DEBUG_INLINE_IMPL(code) {code}
33+
#define CTH_DEBUG_INLINE_IMPL(code) { code }
3734

3835
#define CTH_RELEASE_NOEXCEPT noexcept(false)
3936
#define CTH_RELEASE_CONSTEXPR
4037
#else
4138
#define CTH_DEBUG_IMPL = default;
42-
#define CTH_DEBUG_INLINE_IMPL(code) \
43-
{}
39+
#define CTH_DEBUG_INLINE_IMPL(code) \
40+
{}
4441

4542
#define CTH_RELEASE_NOEXCEPT noexcept(true)
4643
#define CTH_RELEASE_CONSTEXPR constexpr
4744
#endif
4845
#include <cstdint>
4946

50-
5147
namespace cth {
5248
enum class CompilationMode {
5349
DEBUG,

cth/incl/cth/coro/fence.hpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#pragma once
22
#include "cth/coro/utility.hpp"
33

4-
54
#include <atomic>
65
#include <memory>
76

@@ -34,7 +33,6 @@ class fence {
3433
public:
3534
bool signaled() const noexcept { return _state.load(std::memory_order_acquire); }
3635

37-
3836
fence(fence const&) = delete;
3937
fence& operator=(fence const&) = delete;
4038
fence(fence&&) = delete;
@@ -62,7 +60,6 @@ class heap_fence {
6260
_fence->force_signal();
6361
}
6462

65-
6663
void reset() {
6764
if(_fence)
6865
_fence->reset();

0 commit comments

Comments
 (0)