Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation, clean up, actions, etc. #8

Merged
merged 7 commits into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
@@ -1,2 +1,15 @@
Checks: '-*,modernize-*,cppcoreguidelines-*,bugprone-*,-modernize-use-trailing-return-type,-cppcoreguidelines-special-member-functions,-cppcoreguidelines-macro-usage,-cppcoreguidelines-no-malloc,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-avoid-magic-numbers, -cppcoreguidelines-non-private-member-variables-in-classes, -bugprone-easily-swappable-parameters'
Checks:
- -*
- modernize-*
- cppcoreguidelines-*
- bugprone-*
- -modernize-use-trailing-return-type
- -cppcoreguidelines-special-member-functions
- -cppcoreguidelines-macro-usage
- -cppcoreguidelines-no-malloc
- -cppcoreguidelines-pro-bounds-pointer-arithmetic
- -cppcoreguidelines-pro-bounds-constant-array-index
- -cppcoreguidelines-avoid-magic-numbers
- -cppcoreguidelines-non-private-member-variables-in-classes
- -bugprone-easily-swappable-parameters
HeaderFilterRegex: 'itertools'
35 changes: 30 additions & 5 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ jobs:
fail-fast: false
matrix:
include:
- {os: ubuntu-22.04, cc: gcc-12, cxx: g++-12}
- {os: ubuntu-22.04, cc: clang-15, cxx: clang++-15}
- {os: macos-12, cc: gcc-12, cxx: g++-12}
- {os: macos-12, cc: clang, cxx: clang++}
- {os: ubuntu-22.04, cc: gcc-12, cxx: g++-12, doc: OFF}
- {os: ubuntu-22.04, cc: clang-15, cxx: clang++-15, doc: ON}
- {os: macos-12, cc: gcc-12, cxx: g++-12, doc: OFF}
- {os: macos-12, cc: clang, cxx: clang++, doc: OFF}

runs-on: ${{ matrix.os }}

Expand Down Expand Up @@ -91,6 +91,23 @@ jobs:
echo "VIRTUAL_ENV=$VIRTUAL_ENV" >> $GITHUB_ENV
echo "PATH=$PATH" >> $GITHUB_ENV

- name: Build doxygen
if: matrix.doc == 'ON'
env:
CC: ${{ matrix.cc }}
CXX: ${{ matrix.cxx }}
LIBRARY_PATH: /usr/local/opt/llvm/lib
run: |
cd $HOME
git clone https://github.com/doxygen/doxygen.git
cd doxygen
git checkout Release_1_10_0
Wentzell marked this conversation as resolved.
Show resolved Hide resolved
mkdir build
cd build
cmake .. -Duse_libclang=ON -Dstatic_libclang=ON -Duse_libc++=OFF -DLLVM_ROOT=/usr/lib/llvm-15/lib/cmake/llvm -DClang_ROOT=/usr/lib/llvm-15/lib/cmake/clang
make -j 2 VERBOSE=1
make install

- name: add clang cxxflags
if: ${{ contains(matrix.cxx, 'clang') }}
run: |
Expand All @@ -103,7 +120,7 @@ jobs:
CXX: ${{ matrix.cxx }}
LIBRARY_PATH: /usr/local/opt/llvm/lib
run: |
mkdir build && cd build && cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/install
mkdir build && cd build && cmake .. -DCMAKE_INSTALL_PREFIX=$HOME/install -DBuild_Documentation=${{ matrix.doc }}
make -j2 || make -j1 VERBOSE=1

- name: Test itertools
Expand All @@ -123,3 +140,11 @@ jobs:
with:
path: ${{ env.CCACHE_DIR }}
key: ccache-${{ matrix.os }}-${{ matrix.cc }}-${{ github.run_id }}

- name: Deploy documentation
if: matrix.doc == 'ON' && github.ref == 'refs/heads/unstable'
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: build/doc/html
branch: github.io
target-folder: docs/unstable
176 changes: 176 additions & 0 deletions c++/itertools/enumerate.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
// Copyright (c) 2019-2022 Simons Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Authors: Olivier Parcollet, Nils Wentzell, chuffa

/**
* @file
* @brief Provides a range adapting function for enumerating a given range/view.
*/

#ifndef _ITERTOOLS_ENUMERATE_HPP
#define _ITERTOOLS_ENUMERATE_HPP

#include "./iterator_facade.hpp"
#include "./sentinel.hpp"

#include <iterator>
#include <tuple>
#include <utility>

namespace itertools {

namespace detail {

/**
* @ingroup range_iterators
* @brief Iterator for a detail::enumerated range.
*
* @details It stores an iterator of the original range and an index. Incrementing advances the iterator
* and the index by 1. Dereferencing returns a std::pair consisting of the current index and the current
* dereferenced value of the original iterator.
*
* See itertools::enumerate(R &&) for more details.
*
* @tparam Iter Iterator type.
*/
template <typename Iter> struct enum_iter : iterator_facade<enum_iter<Iter>, std::pair<long, typename std::iterator_traits<Iter>::value_type>> {
/// Iterator of the original range.
Iter it;

/// Index for enumerating.
long i = 0;

/// Default constructor sets the index to zero and default constructs the original iterator.
enum_iter() = default;

/**
* @brief Construct an enumerated iterator from a given iterator and set the index to zero.
* @param it Iterator of the original range.
*/
enum_iter(Iter it) : it(std::move(it)) {}

/// Increment the iterator by incrementing the original iterator and the index.
void increment() {
++it;
++i;
}

/**
* @brief Equal-to operator for two detail::enum_iter objects.
*
* @param other detail::enum_iter to compare with.
* @return True, if the original iterators are equal.
*/
[[nodiscard]] bool operator==(enum_iter const &other) const { return it == other.it; }

/**
* @brief Equal-to operator for a detail::enum_iter and an itertools::sentinel_t.
*
* @tparam SentinelIter Iterator type of the sentinel.
* @param s itertools::sentinel_t to compare with.
* @return True, if the original iterator is equal to the iterator stored in the sentinel.
*/
template <typename SentinelIter> [[nodiscard]] bool operator==(sentinel_t<SentinelIter> const &s) const { return it == s.it; }

/**
* @brief Dereference the iterator.
* @return Tuple consisting of the current index and the current dereferenced value of the original iterator.
*/
[[nodiscard]] decltype(auto) dereference() const { return std::tuple<long, decltype(*it)>{i, *it}; }
};

/**
* @ingroup adapted_ranges
* @brief Represents an enumerated range.
*
* @details See itertools::enumerate(R &&) for more details.
*
* @tparam R Range type.
*/
template <typename R> struct enumerated {
/// Original range.
R rg;

/// Iterator type of the enumerated range.
using iterator = enum_iter<decltype(std::begin(rg))>;

/// Const iterator type of the enumerated range.
using const_iterator = enum_iter<decltype(std::cbegin(rg))>;

/// Default equal-to operator.
[[nodiscard]] bool operator==(enumerated const &) const = default;

/**
* @brief Beginning of the enumerated range.
* @return detail::enum_iter constructed from the beginning of the original range with the index set to zero.
*/
[[nodiscard]] iterator begin() noexcept { return std::begin(rg); }

/// Const version of begin().
[[nodiscard]] const_iterator cbegin() const noexcept { return std::cbegin(rg); }

/// Const overload of begin().
[[nodiscard]] const_iterator begin() const noexcept { return cbegin(); }

/**
* @brief End of the enumerated range.
* @return itertools::sentinel_t containing the end iterator of the original range.
*/
[[nodiscard]] auto end() noexcept { return make_sentinel(std::end(rg)); }

/// Const version of end().
[[nodiscard]] auto cend() const noexcept { return make_sentinel(std::cend(rg)); }

/// Const overload of end().
[[nodiscard]] auto end() const noexcept { return cend(); }
};

} // namespace detail

/**
* @ingroup range_adapting_functions
* @brief Lazy-enumerate a given range (similar to Python's enumerate).
*
* @details Each element in the original range is assigned an index, starting from zero. This function
* returns an iterable lazy object (a detail::enumerated range), which iterates over tuples consisting of the
* index and the value of the dereferenced iterator of the original range:
*
* @code{.cpp}
* std::vector<char> vec { 'a', 'b', 'c' };
*
* for (auto [idx, val] : enumerate(vec)) {
* std::cout << "(" << idx << ", " << val << ")\n";
* }
* @endcode
*
* Output:
*
* ```
* (0, a)
* (1, b)
* (2, c)
* ```
*
* See also <a href="https://en.cppreference.com/w/cpp/ranges/enumerate_view">std::ranges::views::enumerate</a>.
*
* @tparam R Range type.
* @param rg Range to enumerate.
* @return A detail::enumerated range.
*/
template <typename R> [[nodiscard]] detail::enumerated<R> enumerate(R &&rg) { return {std::forward<R>(rg)}; }

} // namespace itertools

#endif // _ITERTOOLS_ENUMERATE_HPP
119 changes: 119 additions & 0 deletions c++/itertools/iterator_facade.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Copyright (c) 2019-2022 Simons Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Authors: Olivier Parcollet, Nils Wentzell, chuffa

/**
* @file
* @brief Provides a CRTP base class for various iterator types in itertools.
*/

#ifndef _ITERTOOLS_ITERATOR_FACADE_HPP
#define _ITERTOOLS_ITERATOR_FACADE_HPP

#include <cstddef>
#include <iterator>

namespace itertools {

/// @cond
// Forward declaration.
template <typename Iter, typename Value, typename Tag = std::forward_iterator_tag, typename Reference = Value &,
typename Difference = std::ptrdiff_t>
struct iterator_facade;
/// @endcond

/**
* @ingroup utilities
* @brief CRTP base class for various iterator types in itertools.
*
* @details All iterator types defined in itertools are derived from this class. It uses the
* <a href="https://en.cppreference.com/w/cpp/iterator/forward_iterator">forward iterator</a>
* category. Derived classes are required to implement the following member functions:
*
* @code{.cpp}
* // used by operator++() and operator++(int)
* void increment();
*
* // used by operator*() and operator->()
* value_type [const] [&] dereference() [const];
* @endcode
*
* The `[..]` are optional and depend on the actual iterator type.
*
* @tparam Iter Derived iterator type.
* @tparam Value Value type of the iterator.
* @tparam Reference Reference type of the iterator.
* @tparam Difference Difference type of the iterator.
*/
template <typename Iter, typename Value, typename Reference, typename Difference>
struct iterator_facade<Iter, Value, std::forward_iterator_tag, Reference, Difference> {
private:
// Get a reference to the derived iterator.
[[nodiscard]] Iter &self() { return static_cast<Iter &>(*this); }

// Get a const reference to the derived iterator.
[[nodiscard]] Iter const &self() const { return static_cast<const Iter &>(*this); }

public:
/// Value type of the derived iterator.
using value_type = Value;

/// Reference type of the derived iterator.
using reference = Reference;

/// Pointer type of the derived iterator.
using pointer = Value *;

/// Difference type of the derived iterator.
using difference_type = Difference;

/// Iterator category of the derived iterator.
using iterator_category = std::forward_iterator_tag;

/**
* @brief Pre-increment operator.
* @return Reference to the derived iterator after calling the derived iterator's `increment()` function.
*/
Iter &operator++() {
self().increment();
return self();
}

/**
* @brief Post-increment operator.
* @return Copy of the derived iterator before calling the derived iterator's `increment()` function.
*/
Iter operator++(int) {
Iter c = self();
self().increment();
return c;
}

/**
* @brief Dereference operator.
* @return Result of the derived iterator's `dereference()` function.
*/
[[nodiscard]] decltype(auto) operator*() const { return self().dereference(); }

/**
* @brief Member access operator.
* @return Result of the derived iterator's `dereference()` function.
*/
[[nodiscard]] decltype(auto) operator->() const { return operator*(); }
};

} // namespace itertools

#endif // _ITERTOOLS_ITERATOR_FACADE_HPP
Loading
Loading