diff --git a/.clang-format b/.clang-format index 1f706e5..395bbee 100644 --- a/.clang-format +++ b/.clang-format @@ -5,6 +5,7 @@ ColumnLimit: 120 AllowShortBlocksOnASingleLine: Always AllowShortFunctionsOnASingleLine: All AlwaysBreakTemplateDeclarations: MultiLine +#RequiresClausePositionStyle: SingleLine # requires Clang 15 :( #AlignConsecutiveDeclarations: true --- diff --git a/quicktex/Matrix.h b/quicktex/Matrix.h index 8c5cefa..ad2720d 100644 --- a/quicktex/Matrix.h +++ b/quicktex/Matrix.h @@ -24,6 +24,7 @@ #include #include +#include "util/iterator.h" #include "util/map.h" #include "util/math.h" #include "util/ranges.h" @@ -417,10 +418,10 @@ class Matrix : public VecBase>, T } protected: - class column_iterator : public index_iterator_base { + class column_iterator : public index_iterator_base { public: using value_type = column_type; - using base = index_iterator_base; + using base = index_iterator_base; column_iterator(const Matrix *matrix = nullptr, int index = 0) : base(index), _matrix(matrix){}; @@ -435,10 +436,10 @@ class Matrix : public VecBase>, T const Matrix *_matrix; }; - template class linear_iterator : public index_iterator_base> { + template class linear_iterator : public index_iterator_base, T> { public: - using value_type = column_type; - using base = index_iterator_base>; + using value_type = T; + using base = index_iterator_base, T>; linear_iterator(V *matrix = nullptr, int index = 0) : base(index), _matrix(matrix){}; diff --git a/quicktex/util/bitbash.h b/quicktex/util/bitbash.h index 44d32b3..dc3a6a7 100644 --- a/quicktex/util/bitbash.h +++ b/quicktex/util/bitbash.h @@ -26,6 +26,7 @@ #include #include +#include "iterator.h" #include "util/math.h" #include "util/ranges.h" @@ -125,7 +126,7 @@ size_t unpack_into(P packed, OI begin, OI end, WI widths, bool little_endian = t template requires std::unsigned_integral

&& range && range size_t unpack_into(P packed, OR &dest, const WR &widths, bool little_endian = true) { - assert(distance(widths) == distance(dest)); + assert(size(widths) == size(dest)); return unpack_into(packed, dest.begin(), dest.end(), widths.begin(), little_endian); } @@ -201,7 +202,7 @@ std::array unpack(P packed, const std::array &widths, bool litt template requires std::unsigned_integral

&& range std::array unpack(P packed, const WR &widths, bool little_endian = true) { - assert(distance(widths) == N); + assert(size(widths) == N); return unpack(packed, widths.begin(), little_endian); } @@ -273,7 +274,7 @@ inline constexpr P pack(II start, II end, WI widths, bool little_endian = true) template requires std::unsigned_integral

&& range && range inline constexpr P pack(IR r, WR widths, bool little_endian = true) { - assert(distance(widths) == distance(r)); + assert(size(widths) == size(r)); return pack

(r.begin(), r.end(), widths.start(), little_endian); } diff --git a/quicktex/util/bitwiseEnums.h b/quicktex/util/bitwiseEnums.h index 4f74a97..605de1b 100644 --- a/quicktex/util/bitwiseEnums.h +++ b/quicktex/util/bitwiseEnums.h @@ -65,4 +65,4 @@ constexpr inline auto operator^=(E& a, E b) noexcept -> E& { a = a ^ b; return a; } -} // namespace quicktex::util \ No newline at end of file +} // namespace quicktex \ No newline at end of file diff --git a/quicktex/util/iterator.h b/quicktex/util/iterator.h new file mode 100644 index 0000000..c79bb70 --- /dev/null +++ b/quicktex/util/iterator.h @@ -0,0 +1,146 @@ +/* Quicktex Texture Compression Library + Copyright (C) 2021 Andrew Cassidy + Partially derived from rgbcx.h written by Richard Geldreich + and licenced under the public domain + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . + */ + +#pragma once + +namespace quicktex { + +namespace detail { +template using subs_value_t = std::remove_reference_t()[0])>; +} + +template class index_iterator_base { + public: + using value_type = T; + using size_type = int; + using difference_type = int; + + D &operator++() { + _index++; + return static_cast(*this); + } + D operator++(int) { + D old = static_cast(*this); + _index++; + return old; + } + D &operator--() { + _index--; + return static_cast(*this); + } + D operator--(int) { + D old = static_cast(*this); + _index--; + return old; + } + + D operator+(difference_type rhs) const { + D d = static_cast(*this); + d._index += rhs; + return d; + } + + D operator-(difference_type rhs) const { + D d = static_cast(*this); + d._index -= rhs; + return d; + } + + D &operator+=(difference_type rhs) { + *this = *this + rhs; + return *this; + } + + D &operator-=(difference_type rhs) { + *this = *this - rhs; + return *this; + } + + difference_type operator-(const D &rhs) const { return (difference_type)_index - rhs._index; } + + friend D operator+(difference_type lhs, const D &rhs) { return rhs + lhs; } + + friend auto operator<=>(const D &lhs, const D &rhs) { return lhs._index <=> rhs._index; } + + T &operator[](difference_type i) { return *(static_cast(*this) + i); } + T &operator[](difference_type i) const { return *(static_cast(*this) + i); } + + protected: + int _index; + + private: + friend D; + index_iterator_base(size_t index = 0) : _index(index) {} +}; + +template + requires requires(const R &r) { r[0]; } +class index_iterator : public index_iterator_base, detail::subs_value_t> { + public: + using base = index_iterator_base, detail::subs_value_t>; + using typename base::difference_type; + using typename base::size_type; + using typename base::value_type; + + index_iterator() : base(0), _range(nullptr) {} + index_iterator(R &range, int index) : base(index), _range(&range) {} + + value_type &operator*() const { + assert(_range != nullptr); + assert(this->_index >= 0); + assert(this->_index < (size_type)_range->size()); + return (*_range)[this->_index]; + } + value_type *operator->() const { return &(this->operator*()); } + + friend bool operator==(const index_iterator &lhs, const index_iterator &rhs) { + return (lhs._range == rhs._range) && (lhs._index == rhs._index); + } + + private: + R *_range; +}; + +template class const_iterator : public index_iterator_base, const T> { + public: + using base = index_iterator_base, const T>; + using typename base::difference_type; + using typename base::size_type; + using typename base::value_type; + + const_iterator() : base(0), _value(T{}) {} + const_iterator(T value, int index = 0) : base(index), _value(value) {} + + value_type &operator*() const { return _value; } + value_type *operator->() const { return &_value; } + + friend bool operator==(const const_iterator &lhs, const const_iterator &rhs) { + return (lhs._value == rhs._value) && (lhs._index == rhs._index); + } + + private: + T _value; +}; + +// const_iterator is guaranteed to be a random access iterator. it is not writable for obvious reasons +static_assert(std::random_access_iterator>); + +// index_iterator satisfied forward_iterator +static_assert(std::random_access_iterator>>); +} // namespace quicktex \ No newline at end of file diff --git a/quicktex/util/map.h b/quicktex/util/map.h index c0bf127..b9a8436 100644 --- a/quicktex/util/map.h +++ b/quicktex/util/map.h @@ -30,7 +30,7 @@ namespace quicktex { namespace detail { template -concept simdable = subscriptable_range && std::contiguous_iterator().begin())> && +concept simdable = random_access_range && std::contiguous_iterator().begin())> && std::is_arithmetic_v>; template struct chunker_impl {}; @@ -74,7 +74,7 @@ struct chunker_impl { }; template - requires subscriptable_range && (!simdable || serial) + requires random_access_range && (!simdable || serial) struct chunker_impl { // range with data that cant be SIMDed static constexpr size_t steps = 1; diff --git a/quicktex/util/ranges.h b/quicktex/util/ranges.h index 84f1cd2..1a46937 100644 --- a/quicktex/util/ranges.h +++ b/quicktex/util/ranges.h @@ -29,171 +29,46 @@ #include #include #include -#include namespace quicktex { -// std::ranges::range is not usable by default in libc++ 13 +// std::ranges is not usable by default in libc++ 13 template concept range = requires(T &t) { t.begin(); t.end(); }; -template -concept sized = requires(T &t) { std::size(t); }; +using std::size; +template constexpr auto size(const T &range) { return std::distance(range.begin(), range.end()); } template -concept sized_range = range && sized; +concept sized_range = range && requires(T &t) { size(t); }; -template -concept const_subscriptable = requires(T &t) { - t[0]; - std::size(t); - }; +template using iterator_t = decltype(std::declval().begin()); +template using sentinel_t = decltype(std::declval().end()); +template using range_size_t = decltype(size(std::declval())); +template using range_difference_t = std::iter_difference_t>; +template using range_value_t = std::iter_value_t>; +template using range_reference_t = std::iter_reference_t>; +template using range_rvalue_reference_t = std::iter_rvalue_reference_t>; -template -concept subscriptable = const_subscriptable && requires(T &t) { - t[0] = std::declval(); // subscript is assignable - }; +template +concept input_range = range && std::input_iterator>; -template -concept subscriptable_range = sized_range && subscriptable; +template +concept output_range = range && (std::output_iterator, T>); -template struct range_value { using type = void; }; +template +concept forward_range = range && std::forward_iterator>; -template - requires requires(T &t) { std::begin(t); } -struct range_value { - using type = std::iter_value_t()).begin())>; -}; +template +concept bidirectional_range = range && std::bidirectional_iterator>; -template using range_value_t = typename range_value::type; +template +concept random_access_range = range && std::random_access_iterator>; -// some quick inline checks -static_assert(const_subscriptable>); // const array can be subscripted -static_assert(!subscriptable>); // const array cannot be assigned to -static_assert(subscriptable_range>); // array is subscriptable, sized, and has begin() and end() -static_assert(sized_range>); // initializer list is a range and has size() -static_assert(std::same_as, void>); +template +concept contiguous_range = range && std::contiguous_iterator>; -template - requires range -size_t distance(T range) { - return std::distance(range.begin(), range.end()); -} - -template class index_iterator_base { - public: - typedef long long difference_type; - - D &operator++() { - _index++; - return static_cast(*this); - } - D operator++(int) { - D old = static_cast(*this); - _index++; - return old; - } - D &operator--() { - _index--; - return static_cast(*this); - } - D operator--(int) { - D old = static_cast(*this); - _index--; - return old; - } - - D operator+(difference_type rhs) const { - D d = static_cast(*this); - d._index += rhs; - return d; - } - - D operator-(difference_type rhs) const { - D d = static_cast(*this); - d._index -= rhs; - return d; - } - - D &operator+=(difference_type rhs) { - *this = *this + rhs; - return *this; - } - - D &operator-=(difference_type rhs) { - *this = *this - rhs; - return *this; - } - - difference_type operator-(const D &rhs) const { return (difference_type)_index - rhs._index; } - - friend D operator+(difference_type lhs, const D &rhs) { return rhs + lhs; } - - friend auto operator<=>(const D &lhs, const D &rhs) { return lhs._index <=> rhs._index; } - - auto &operator[](difference_type i) { return *(static_cast(*this) + i); } - auto operator[](difference_type i) const { return *(static_cast(*this) + i); } - - protected: - size_t _index; - - private: - friend D; - index_iterator_base(size_t index = 0) : _index(index) {} -}; - -template class const_iterator : public index_iterator_base> { - public: - typedef index_iterator_base> base; - typedef long long difference_type; - typedef T value_type; - - const_iterator() : base(0), _value(T{}) {} - const_iterator(T value, size_t index = 0) : base(index), _value(value) {} - - T operator*() const { return _value; } - const T *operator->() const { return &_value; } - - friend bool operator==(const const_iterator &lhs, const const_iterator &rhs) { - return (lhs._value == rhs._value) && (lhs._index == rhs._index); - } - - private: - T _value; -}; - -// const_iterator is guaranteed to be a random access iterator. it is not writable for obvious reasons -static_assert(std::random_access_iterator>); - -template - requires subscriptable -class index_iterator : public index_iterator_base> { - public: - using base = index_iterator_base>; - using difference_type = long long; - using value_type = range_value_t; - - index_iterator() : base(0), _range(nullptr) {} - index_iterator(R &range, size_t index) : base(index), _range(&range) {} - - auto operator*() const { - // if we have the information, do a bounds check - if constexpr (sized) { assert(this->_index < std::size(*_range)); } - return (*_range)[this->_index]; - } - auto *operator->() const { return &((*_range)[this->_index]); } - - friend bool operator==(const index_iterator &lhs, const index_iterator &rhs) { - return (lhs._range == rhs._range) && (lhs._index == rhs._index); - } - - private: - R *_range; -}; - -// index_iterator satisfied forward_iterator -static_assert(std::random_access_iterator>>); } // namespace quicktex \ No newline at end of file