Skip to content

Commit bf5fd5f

Browse files
committed
util docs
1 parent fa3a68e commit bf5fd5f

2 files changed

Lines changed: 117 additions & 16 deletions

File tree

include/gl/util/math.hpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
// This file is part of the CPP-GL project (https://github.com/SpectraL519/cpp-gl).
33
// Licensed under the MIT License. See the LICENSE file in the project root for full license information.
44

5+
/// @file gl/util/math.hpp
6+
/// @brief Defines utility mathematical functions.
7+
58
#pragma once
69

710
#include "gl/types/core.hpp"
@@ -11,7 +14,15 @@
1114

1215
namespace gl::util {
1316

14-
// exponentation function for u64 integral type
17+
/// @ingroup GL GL-Util
18+
/// @brief Computes the value of `base` raised to the power of `exp` using exponentiation by squaring.
19+
/// @param base The base value to be raised to a power.
20+
/// @param exp The exponent to which the base is raised.
21+
/// @return The result of `base` raised to the power of `exp`.
22+
///
23+
/// > [!INFO] Time complexity
24+
/// >
25+
/// > $O(\log(\text{exp}))$ due to halving the exponent at each step.
1526
[[nodiscard]] inline constexpr size_type upow(size_type base, size_type exp) {
1627
size_type result = 1uz;
1728
while (exp) {
@@ -24,8 +35,19 @@ namespace gl::util {
2435
return result;
2536
}
2637

27-
// sum of exponents: base ^ i_begin + base ^ (i_begin + 1) + ... + base ^ (i_end)
28-
[[nodiscard]] inline size_type upow_sum(const size_type base, size_type i_begin, size_type i_end) {
38+
/// @ingroup GL GL-Util
39+
/// @brief Computes the sum of powers of `base` from `base^i_begin` to `base^i_end` inclusive.
40+
/// @param base The base value for the powers.
41+
/// @param i_begin The starting exponent (inclusive).
42+
/// @param i_end The ending exponent (inclusive).
43+
/// @return The sum of `base^i` for all `i` in the range `[i_begin, i_end]`.
44+
///
45+
/// > [!INFO] Time complexity
46+
/// >
47+
/// > $O(\log(\text{max}(\text{i\_begin}, \text{i\_end})))$ due to the use of the closed-form formula for geometric series.
48+
[[nodiscard]] inline constexpr size_type upow_sum(
49+
const size_type base, size_type i_begin, size_type i_end
50+
) {
2951
std::tie(i_begin, i_end) = std::minmax(i_begin, i_end);
3052

3153
if (base == 0uz)

include/gl/util/ranges.hpp

Lines changed: 92 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,32 @@
22
// This file is part of the CPP-GL project (https://github.com/SpectraL519/cpp-gl).
33
// Licensed under the MIT License. See the LICENSE file in the project root for full license information.
44

5+
/// @file gl/util/ranges.hpp
6+
/// @brief Defines utility functions and views for working with C++20 ranges.
7+
58
#pragma once
69

710
#include <algorithm>
811
#include <ranges>
912

1013
namespace gl::util {
1114

15+
/// @ingroup GL GL-Util
16+
/// @brief Returns the size of a range.
17+
///
18+
/// This function returns the size of a range if it is a sized range, otherwise it computes the
19+
/// distance between the beginning and end of the range. Note that computing the distance for
20+
/// non-sized ranges may be expensive.
21+
///
22+
/// > [!WARNING] This function will consume input ranges that are not sized, as it needs to iterate through them to count the elements.
23+
///
24+
/// @tparam R The type of the range.
25+
/// @param r The range to measure.
26+
/// @return The size of the range if it is a sized range, otherwise the distance between the beginning and end of the range.
27+
///
28+
/// > [!INFO] Time complexity
29+
/// >
30+
/// > $O(1)$ if the range is a sized range, otherwise $O(N)$ where $N$ is the number of elements in the range.
1231
template <std::ranges::range R>
1332
constexpr auto range_size(R&& r) {
1433
if constexpr (std::ranges::sized_range<R>)
@@ -18,6 +37,15 @@ constexpr auto range_size(R&& r) {
1837
return std::ranges::distance(std::begin(r), std::end(r));
1938
}
2039

40+
/// @ingroup GL GL-Util
41+
/// @brief Checks if all elements in a range are equal.
42+
/// @tparam R The type of the range.
43+
/// @param range The range to check.
44+
/// @return `true` if all elements in the range are equal or the range is empty, otherwise `false`.
45+
///
46+
/// > [!INFO] Time complexity
47+
/// >
48+
/// > $O(N)$ where $N$ is the number of elements in the range.
2149
template <std::ranges::forward_range R>
2250
[[nodiscard]] constexpr bool is_constant(R&& range) noexcept {
2351
if (std::ranges::empty(range))
@@ -28,31 +56,55 @@ template <std::ranges::forward_range R>
2856
});
2957
}
3058

59+
/// @ingroup GL GL-Util
60+
/// @brief Checks if all elements in a range are equal to a given value.
61+
/// @tparam R The type of the range.
62+
/// @param range The range to check.
63+
/// @param value The value to compare against.
64+
/// @return `true` if all elements in the range are equal to the given value or the range is empty, otherwise `false`.
65+
///
66+
/// > [!INFO] Time complexity
67+
/// >
68+
/// > $O(N)$ where $N$ is the number of elements in the range.
3169
template <std::ranges::forward_range R>
32-
[[nodiscard]] constexpr bool all_equal(R&& range, const std::ranges::range_value_t<R>& k) noexcept {
70+
[[nodiscard]] constexpr bool all_equal(
71+
R&& range, const std::ranges::range_value_t<R>& value
72+
) noexcept {
3373
if (std::ranges::empty(range))
3474
return true;
3575

36-
return std::ranges::all_of(range, [&k](const auto& val) { return val == k; });
76+
return std::ranges::all_of(range, [&value](const auto& val) { return val == value; });
3777
}
3878

79+
/// @ingroup GL GL-Util
3980
/// @brief A view concatenating two ranges sequentially (C++20 polyfill for C++26 `std::views::concat`).
4081
///
41-
/// @warning **GCC 13/14 Bug:** Using branching views (like this or `std::ranges::filter_view`)
42-
/// inside complex algorithms (e.g., `std::ranges::is_permutation`) may trigger false-positive
43-
/// `-Wmaybe-uninitialized` warnings. To work around this, suppress the warning at the call site
44-
/// or materialize the view into a contiguous container like `std::vector`.
82+
/// > [!WARNING] GCC 13/14 Bug
83+
/// >
84+
/// > Using branching views (like this or `std::ranges::filter_view`) inside complex algorithms
85+
/// > (e.g., `std::ranges::is_permutation`) may trigger false-positive `-Wmaybe-uninitialized`
86+
/// > warnings. To work around this, suppress the warning at the call site or materialize the
87+
/// > view into a contiguous container like `std::vector`.
4588
///
4689
/// @tparam V1 First view type.
4790
/// @tparam V2 Second view type.
4891
/// @todo Replace with `std::views::concat` (C++26).
92+
/// ### See also
93+
/// - @ref gl::util::concat_fn "concat_fn": A helper compile-time constant function object for creating `concat_view` instances.
94+
/// - @ref gl::util::concat "concat": A compile-time constant instantiation of this function object for convenient use.
4995
template <std::ranges::view V1, std::ranges::view V2>
5096
class concat_view : public std::ranges::view_interface<concat_view<V1, V2>> {
5197
public:
98+
/// @brief Default constructor creates an empty concatenated view.
5299
concat_view() = default;
53100

101+
/// @brief Constructs a `concat_view` from two viewable ranges.
102+
/// @param v1 The first range to concatenate.
103+
/// @param v2 The second range to concatenate.
54104
constexpr concat_view(V1 v1, V2 v2) : _v1(std::move(v1)), _v2(std::move(v2)) {}
55105

106+
/// @brief Returns an iterator to the beginning of the concatenated view.
107+
/// @return An iterator that traverses the first range followed by the second range.
56108
constexpr auto begin() {
57109
return iterator<false>(
58110
std::ranges::begin(this->_v1),
@@ -61,8 +113,10 @@ class concat_view : public std::ranges::view_interface<concat_view<V1, V2>> {
61113
);
62114
}
63115

116+
/// @brief Returns a const iterator to the beginning of the concatenated view.
117+
/// @return A const iterator that traverses the first range followed by the second range.
64118
constexpr auto begin() const
65-
requires std::ranges::range<const V1> and std::ranges::range<const V2>
119+
requires(std::ranges::range<const V1> and std::ranges::range<const V2>)
66120
{
67121
return iterator<true>(
68122
std::ranges::begin(this->_v1),
@@ -71,12 +125,16 @@ class concat_view : public std::ranges::view_interface<concat_view<V1, V2>> {
71125
);
72126
}
73127

128+
/// @brief Returns a sentinel representing the end of the concatenated view.
129+
/// @return A sentinel that compares equal to an iterator when it reaches the end of the second range.
74130
constexpr auto end() {
75131
return sentinel<false>(std::ranges::end(this->_v2));
76132
}
77133

134+
/// @brief Returns a const sentinel representing the end of the concatenated view.
135+
/// @return A const sentinel that compares equal to a const iterator when it reaches the end
78136
constexpr auto end() const
79-
requires std::ranges::range<const V1> and std::ranges::range<const V2>
137+
requires(std::ranges::range<const V1> and std::ranges::range<const V2>)
80138
{
81139
return sentinel<true>(std::ranges::end(this->_v2));
82140
}
@@ -172,9 +230,18 @@ class concat_view : public std::ranges::view_interface<concat_view<V1, V2>> {
172230
};
173231
};
174232

175-
namespace detail {
176-
233+
/// @ingroup GL GL-Util
234+
/// @brief A function object for concatenating two viewable ranges into a `concat_view`.
235+
/// ### See also
236+
/// - @ref gl::util::concat_view "concat_view": The view type that represents the concatenation of two ranges.
237+
/// - @ref gl::util::concat "concat": A compile-time constant instantiation of this function object for convenient use.
177238
struct concat_fn {
239+
/// @brief Concatenates two viewable ranges into a `concat_view`.
240+
/// @tparam R1 The type of the first range.
241+
/// @tparam R2 The type of the second range.
242+
/// @param r1 The first range to concatenate.
243+
/// @param r2 The second range to concatenate.
244+
/// @return A `concat_view` that represents the concatenation of the two ranges.
178245
template <std::ranges::viewable_range R1, std::ranges::viewable_range R2>
179246
constexpr auto operator()(R1&& r1, R2&& r2) const {
180247
return concat_view<std::views::all_t<R1>, std::views::all_t<R2>>(
@@ -183,12 +250,24 @@ struct concat_fn {
183250
}
184251
};
185252

186-
} // namespace detail
187-
253+
/// @ingroup GL GL-Util
188254
/// @brief Concatenates two viewable ranges into a `concat_view`.
255+
///
256+
/// ### Example usage
257+
/// ```cpp
258+
/// std::vector<int> v1 = {1, 2, 3};
259+
/// std::vector<int> v2 = {4, 5, 6};
260+
/// auto concatenated = gl::util::concat(v1, v2);
261+
/// for (int x : concatenated)
262+
/// std::cout << x << " "; // Output: 1 2 3 4 5 6
263+
/// ```
264+
///
189265
/// @param r1 First range to concatenate.
190266
/// @param r2 Second range to concatenate.
191267
/// @todo Replace with `std::views::concat` (C++26).
192-
inline constexpr detail::concat_fn concat{};
268+
/// ### See also
269+
/// - @ref gl::util::concat_view "concat_view": The view type that represents the concatenation of two ranges.
270+
/// - @ref gl::util::concat_fn "concat_fn": A helper compile-time constant function object for creating `concat_view` instances.
271+
inline constexpr concat_fn concat{};
193272

194273
} // namespace gl::util

0 commit comments

Comments
 (0)