| //===-- include/flang/Common/interval.h -------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef FORTRAN_COMMON_INTERVAL_H_ |
| #define FORTRAN_COMMON_INTERVAL_H_ |
| |
| // Defines a generalized template class Interval<A> to represent |
| // the half-open interval [x .. x+n). |
| |
| #include "idioms.h" |
| #include <algorithm> |
| #include <cstddef> |
| #include <utility> |
| |
| namespace Fortran::common { |
| |
| template <typename A> class Interval { |
| public: |
| using type = A; |
| constexpr Interval() {} |
| constexpr Interval(const A &s, std::size_t n = 1) : start_{s}, size_{n} {} |
| constexpr Interval(A &&s, std::size_t n = 1) |
| : start_{std::move(s)}, size_{n} {} |
| constexpr Interval(const Interval &) = default; |
| constexpr Interval(Interval &&) = default; |
| constexpr Interval &operator=(const Interval &) = default; |
| constexpr Interval &operator=(Interval &&) = default; |
| |
| constexpr bool operator<(const Interval &that) const { |
| return start_ < that.start_ || |
| (start_ == that.start_ && size_ < that.size_); |
| } |
| constexpr bool operator<=(const Interval &that) const { |
| return start_ < that.start_ || |
| (start_ == that.start_ && size_ <= that.size_); |
| } |
| constexpr bool operator==(const Interval &that) const { |
| return start_ == that.start_ && size_ == that.size_; |
| } |
| constexpr bool operator!=(const Interval &that) const { |
| return !(*this == that); |
| } |
| constexpr bool operator>=(const Interval &that) const { |
| return !(*this < that); |
| } |
| constexpr bool operator>(const Interval &that) const { |
| return !(*this <= that); |
| } |
| |
| constexpr const A &start() const { return start_; } |
| constexpr std::size_t size() const { return size_; } |
| constexpr bool empty() const { return size_ == 0; } |
| |
| constexpr bool Contains(const A &x) const { |
| return start_ <= x && x < start_ + size_; |
| } |
| constexpr bool Contains(const Interval &that) const { |
| return Contains(that.start_) && Contains(that.start_ + (that.size_ - 1)); |
| } |
| constexpr bool IsDisjointWith(const Interval &that) const { |
| return that.NextAfter() <= start_ || NextAfter() <= that.start_; |
| } |
| constexpr bool ImmediatelyPrecedes(const Interval &that) const { |
| return NextAfter() == that.start_; |
| } |
| void Annex(const Interval &that) { |
| size_ = (that.start_ + that.size_) - start_; |
| } |
| bool AnnexIfPredecessor(const Interval &that) { |
| if (ImmediatelyPrecedes(that)) { |
| size_ += that.size_; |
| return true; |
| } |
| return false; |
| } |
| void ExtendToCover(const Interval &that) { |
| if (size_ == 0) { |
| *this = that; |
| } else if (that.size_ != 0) { |
| const auto end{std::max(NextAfter(), that.NextAfter())}; |
| start_ = std::min(start_, that.start_); |
| size_ = end - start_; |
| } |
| } |
| |
| std::size_t MemberOffset(const A &x) const { |
| CHECK(Contains(x)); |
| return x - start_; |
| } |
| A OffsetMember(std::size_t n) const { |
| CHECK(n <= size_); |
| return start_ + n; |
| } |
| |
| constexpr A Last() const { return start_ + (size_ - 1); } |
| constexpr A NextAfter() const { return start_ + size_; } |
| constexpr Interval Prefix(std::size_t n) const { |
| return {start_, std::min(size_, n)}; |
| } |
| Interval Suffix(std::size_t n) const { |
| CHECK(n <= size_); |
| return {start_ + n, size_ - n}; |
| } |
| |
| constexpr Interval Intersection(const Interval &that) const { |
| if (that.NextAfter() <= start_) { |
| return {}; |
| } else if (that.start_ <= start_) { |
| auto skip{start_ - that.start_}; |
| return {start_, std::min(size_, that.size_ - skip)}; |
| } else if (NextAfter() <= that.start_) { |
| return {}; |
| } else { |
| auto skip{that.start_ - start_}; |
| return {that.start_, std::min(that.size_, size_ - skip)}; |
| } |
| } |
| |
| private: |
| A start_; |
| std::size_t size_{0}; |
| }; |
| } // namespace Fortran::common |
| #endif // FORTRAN_COMMON_INTERVAL_H_ |