315 lines
7.7 KiB
C++
315 lines
7.7 KiB
C++
// Copyright 2024 The Manifold Authors.
|
|
//
|
|
// 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
|
|
//
|
|
// 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.
|
|
#pragma once
|
|
|
|
#include <iterator>
|
|
#include <type_traits>
|
|
|
|
namespace manifold {
|
|
|
|
template <typename F, typename Iter>
|
|
struct TransformIterator {
|
|
private:
|
|
Iter iter;
|
|
F f;
|
|
|
|
public:
|
|
using pointer = void;
|
|
using reference = std::invoke_result_t<
|
|
F, typename std::iterator_traits<std::remove_const_t<Iter>>::value_type>;
|
|
using difference_type =
|
|
typename std::iterator_traits<std::remove_const_t<Iter>>::difference_type;
|
|
using value_type = reference;
|
|
using iterator_category = typename std::iterator_traits<
|
|
std::remove_const_t<Iter>>::iterator_category;
|
|
|
|
constexpr TransformIterator(Iter iter, F f) : iter(iter), f(f) {}
|
|
|
|
TransformIterator& operator=(const TransformIterator& other) {
|
|
if (this == &other) return *this;
|
|
// don't copy function, should be the same
|
|
iter = other.iter;
|
|
return *this;
|
|
}
|
|
|
|
constexpr reference operator*() const { return f(*iter); }
|
|
|
|
constexpr reference operator[](size_t i) const { return f(iter[i]); }
|
|
|
|
// prefix increment
|
|
TransformIterator& operator++() {
|
|
iter += 1;
|
|
return *this;
|
|
}
|
|
|
|
// postfix
|
|
TransformIterator operator++(int) {
|
|
auto old = *this;
|
|
operator++();
|
|
return old;
|
|
}
|
|
|
|
// prefix increment
|
|
TransformIterator& operator--() {
|
|
iter -= 1;
|
|
return *this;
|
|
}
|
|
|
|
// postfix
|
|
TransformIterator operator--(int) {
|
|
auto old = *this;
|
|
operator--();
|
|
return old;
|
|
}
|
|
|
|
constexpr TransformIterator operator+(size_t n) const {
|
|
return TransformIterator(iter + n, f);
|
|
}
|
|
|
|
TransformIterator& operator+=(size_t n) {
|
|
iter += n;
|
|
return *this;
|
|
}
|
|
|
|
constexpr TransformIterator operator-(size_t n) const {
|
|
return TransformIterator(iter - n, f);
|
|
}
|
|
|
|
TransformIterator& operator-=(size_t n) {
|
|
iter -= n;
|
|
return *this;
|
|
}
|
|
|
|
constexpr bool operator==(TransformIterator other) const {
|
|
return iter == other.iter;
|
|
}
|
|
|
|
constexpr bool operator!=(TransformIterator other) const {
|
|
return !(iter == other.iter);
|
|
}
|
|
|
|
constexpr bool operator<(TransformIterator other) const {
|
|
return iter < other.iter;
|
|
}
|
|
|
|
constexpr difference_type operator-(TransformIterator other) const {
|
|
return iter - other.iter;
|
|
}
|
|
|
|
constexpr operator TransformIterator<F, const Iter>() const {
|
|
return TransformIterator(f, iter);
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
struct CountingIterator {
|
|
private:
|
|
T counter;
|
|
|
|
public:
|
|
using pointer = void;
|
|
using reference = T;
|
|
using difference_type = std::make_signed_t<T>;
|
|
using value_type = T;
|
|
using iterator_category = std::random_access_iterator_tag;
|
|
|
|
constexpr CountingIterator(T counter) : counter(counter) {}
|
|
|
|
constexpr value_type operator*() const { return counter; }
|
|
constexpr value_type operator[](T i) const { return counter + i; }
|
|
|
|
// prefix increment
|
|
CountingIterator& operator++() {
|
|
counter += 1;
|
|
return *this;
|
|
}
|
|
|
|
// postfix
|
|
CountingIterator operator++(int) {
|
|
auto old = *this;
|
|
operator++();
|
|
return old;
|
|
}
|
|
|
|
// prefix increment
|
|
CountingIterator& operator--() {
|
|
counter -= 1;
|
|
return *this;
|
|
}
|
|
|
|
// postfix
|
|
CountingIterator operator--(int) {
|
|
auto old = *this;
|
|
operator--();
|
|
return old;
|
|
}
|
|
|
|
constexpr CountingIterator operator+(T n) const {
|
|
return CountingIterator(counter + n);
|
|
}
|
|
|
|
CountingIterator& operator+=(T n) {
|
|
counter += n;
|
|
return *this;
|
|
}
|
|
|
|
constexpr CountingIterator operator-(T n) const {
|
|
return CountingIterator(counter - n);
|
|
}
|
|
|
|
CountingIterator& operator-=(T n) {
|
|
counter -= n;
|
|
return *this;
|
|
}
|
|
|
|
constexpr friend bool operator==(CountingIterator a, CountingIterator b) {
|
|
return a.counter == b.counter;
|
|
}
|
|
|
|
constexpr friend bool operator!=(CountingIterator a, CountingIterator b) {
|
|
return a.counter != b.counter;
|
|
}
|
|
|
|
constexpr friend bool operator<(CountingIterator a, CountingIterator b) {
|
|
return a.counter < b.counter;
|
|
}
|
|
|
|
constexpr friend difference_type operator-(CountingIterator a,
|
|
CountingIterator b) {
|
|
return a.counter - b.counter;
|
|
}
|
|
|
|
constexpr operator CountingIterator<const T>() const {
|
|
return CountingIterator(counter);
|
|
}
|
|
};
|
|
|
|
constexpr CountingIterator<size_t> countAt(size_t i) {
|
|
return CountingIterator(i);
|
|
}
|
|
|
|
template <typename Iter>
|
|
struct StridedRange {
|
|
private:
|
|
struct StridedRangeIter {
|
|
private:
|
|
Iter iter;
|
|
size_t stride;
|
|
|
|
public:
|
|
using pointer =
|
|
typename std::iterator_traits<std::remove_const_t<Iter>>::pointer;
|
|
using reference =
|
|
typename std::iterator_traits<std::remove_const_t<Iter>>::reference;
|
|
using difference_type = typename std::iterator_traits<
|
|
std::remove_const_t<Iter>>::difference_type;
|
|
using value_type =
|
|
typename std::iterator_traits<std::remove_const_t<Iter>>::value_type;
|
|
using iterator_category = typename std::iterator_traits<
|
|
std::remove_const_t<Iter>>::iterator_category;
|
|
|
|
constexpr StridedRangeIter(Iter iter, int stride)
|
|
: iter(iter), stride(stride) {}
|
|
|
|
constexpr reference operator*() { return *iter; }
|
|
|
|
constexpr std::add_const_t<reference> operator*() const { return *iter; }
|
|
|
|
constexpr reference operator[](size_t i) { return iter[i * stride]; }
|
|
|
|
constexpr std::add_const_t<reference> operator[](size_t i) const {
|
|
return iter[i * stride];
|
|
}
|
|
|
|
// prefix increment
|
|
StridedRangeIter& operator++() {
|
|
iter += stride;
|
|
return *this;
|
|
}
|
|
|
|
// postfix
|
|
StridedRangeIter operator++(int) {
|
|
auto old = *this;
|
|
operator++();
|
|
return old;
|
|
}
|
|
|
|
// prefix increment
|
|
StridedRangeIter& operator--() {
|
|
iter -= stride;
|
|
return *this;
|
|
}
|
|
|
|
// postfix
|
|
StridedRangeIter operator--(int) {
|
|
auto old = *this;
|
|
operator--();
|
|
return old;
|
|
}
|
|
|
|
constexpr StridedRangeIter operator+(size_t n) const {
|
|
return StridedRangeIter(iter + n * stride, stride);
|
|
}
|
|
|
|
StridedRangeIter& operator+=(size_t n) {
|
|
iter += n * stride;
|
|
return *this;
|
|
}
|
|
|
|
constexpr StridedRangeIter operator-(size_t n) const {
|
|
return StridedRangeIter(iter - n * stride, stride);
|
|
}
|
|
|
|
StridedRangeIter& operator-=(size_t n) {
|
|
iter -= n * stride;
|
|
return *this;
|
|
}
|
|
|
|
constexpr friend bool operator==(StridedRangeIter a, StridedRangeIter b) {
|
|
return a.iter == b.iter;
|
|
}
|
|
|
|
constexpr friend bool operator!=(StridedRangeIter a, StridedRangeIter b) {
|
|
return !(a.iter == b.iter);
|
|
}
|
|
|
|
constexpr friend bool operator<(StridedRangeIter a, StridedRangeIter b) {
|
|
return a.iter < b.iter;
|
|
}
|
|
|
|
constexpr friend difference_type operator-(StridedRangeIter a,
|
|
StridedRangeIter b) {
|
|
// note that this is not well-defined if a.stride != b.stride...
|
|
return (a.iter - b.iter) / a.stride;
|
|
}
|
|
};
|
|
Iter _start, _end;
|
|
const size_t stride;
|
|
|
|
public:
|
|
constexpr StridedRange(Iter start, Iter end, size_t stride)
|
|
: _start(start), _end(end), stride(stride) {}
|
|
|
|
constexpr StridedRangeIter begin() const {
|
|
return StridedRangeIter(_start, stride);
|
|
}
|
|
|
|
constexpr StridedRangeIter end() const {
|
|
return StridedRangeIter(_start, stride) +
|
|
((std::distance(_start, _end) + (stride - 1)) / stride);
|
|
}
|
|
};
|
|
|
|
} // namespace manifold
|