/** * Copyright 2013-2020 Software Radio Systems Limited * * This file is part of srsLTE. * * srsLTE is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * srsLTE 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 Affero General Public License for more details. * * A copy of the GNU Affero General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. * */ #ifndef SRSLTE_INTERVAL_H #define SRSLTE_INTERVAL_H #include "adt_utils.h" #include "srslte/srslog/bundled/fmt/format.h" #include #include #include namespace srslte { /// Representation of an interval between two numeric-types in the math representation [start, stop) template class interval { // TODO: older compilers may not have defined this C++11 trait. #if (defined(__clang__) && (__clang_major__ >= 5)) || (defined(__GNUG__) && (__GNUC__ >= 5)) static_assert(std::is_trivially_copyable::value, "Expected to be trivially copyable"); #endif public: interval() : start_(T{}), stop_(T{}) {} interval(T start_point, T stop_point) : start_(start_point), stop_(stop_point) { assert(start_ <= stop_); } T start() const { return start_; } T stop() const { return stop_; } bool empty() const { return stop_ == start_; } auto length() -> decltype(std::declval() - std::declval()) const { return stop_ - start_; } void set(T start_point, T stop_point) { assert(stop_point >= start_point); start_ = start_point; stop_ = stop_point; } void resize_by(T len) { // Detect length overflows assert(std::is_unsigned::value or (len >= 0 or length() >= -len)); stop_ += len; } void resize_to(T len) { assert(std::is_unsigned::value or len >= 0); stop_ = start_ + len; } void displace_by(int offset) { start_ += offset; stop_ += offset; } void displace_to(T start_point) { stop_ = start_point + length(); start_ = start_point; } bool overlaps(interval other) const { return start_ < other.stop_ and other.start_ < stop_; } bool contains(T point) const { return start_ <= point and point < stop_; } std::string to_string() const { return fmt::format("[{},{})", start_, stop_); } private: T start_; T stop_; }; template bool operator==(const interval& lhs, const interval& rhs) { return lhs.start() == rhs.start() and lhs.stop() == rhs.stop(); } template bool operator!=(const interval& lhs, const interval& rhs) { return not(lhs == rhs); } template bool operator<(const interval& lhs, const interval& rhs) { return lhs.start() < rhs.start() or (lhs.start() == rhs.start() and lhs.stop() < rhs.stop()); } //! Union of intervals template interval operator|(const interval& lhs, const interval& rhs) { if (not lhs.overlaps(rhs)) { return interval{}; } return {std::min(lhs.start(), rhs.start()), std::max(lhs.stop(), rhs.stop())}; } template interval make_union(const interval& lhs, const interval& rhs) { return lhs | rhs; } //! Intersection of intervals template interval operator&(const interval& lhs, const interval& rhs) { if (not lhs.overlaps(rhs)) { return interval{}; } return interval{std::max(lhs.start(), rhs.start()), std::min(lhs.stop(), rhs.stop())}; } template interval make_intersection(const interval& lhs, const interval& rhs) { return lhs & rhs; } template std::ostream& operator<<(std::ostream& out, const interval& interv) { out << interv.to_string(); return out; } } // namespace srslte #endif // SRSLTE_INTERVAL_H