stdex/include/stdex/interval.hpp
Simon Rozman 18c41ebfdf interval: add += and -= operators
Signed-off-by: Simon Rozman <simon@rozman.si>
2024-01-24 12:25:47 +01:00

235 lines
4.4 KiB
C++

/*
SPDX-License-Identifier: MIT
Copyright © 2023-2024 Amebis
*/
#pragma once
#include "compat.hpp"
#include <vector>
namespace stdex
{
///
/// Numerical interval
///
template <class T>
struct interval
{
T start; ///< interval start
T end; ///< interval end
///
/// Constructs an invalid interval
///
interval() noexcept : start(static_cast<T>(1)), end(static_cast<T>(0)) {}
///
/// Constructs a zero-size interval
///
/// \param[in] x Interval start and end value
///
interval(_In_ T x) noexcept : start(x), end(x) {}
///
/// Constructs an interval
///
/// \param[in] _start Interval start value
/// \param[in] _end Interval end value
///
interval(_In_ T _start, _In_ T _end) noexcept : start(_start), end(_end) {}
///
/// Returns interval size
///
/// \returns Interval size or 0 if interval is invalid
///
T size() const { return start <= end ? end - start : 0; }
///
/// Is interval empty?
///
/// \returns true if interval is empty or false otherwise
///
bool empty() const { return start >= end; }
///
/// Invalidates interval
///
void invalidate()
{
start = static_cast<T>(1);
end = static_cast<T>(0);
}
///
/// Is interval valid?
///
/// \returns true if interval is valid or false otherwise
///
operator bool() const { return start <= end; }
///
/// Is value in interval?
///
/// \param[in] x Value to test
///
/// \returns true if x is in [start, end) or false otherwise
///
bool contains(_In_ T x) const { return start <= x && x < end; }
///
/// Adds two intervals by components
///
/// \param[in] other Second interval
///
/// \returns Resulting interval
///
interval operator+(_In_ const interval& other) const
{
return interval(start + other.start, end + other.end);
}
///
/// Moves interval towards the end by a number
///
/// \param[in] x Amount to move for
///
/// \returns Moved interval
///
interval operator+(_In_ const T x) const
{
return interval(start + x, end + x);
}
///
/// Moves interval towards the end by a number
///
/// \param[in] x Amount to move for
///
/// \returns Resulting interval
///
interval operator+=(_In_ const T x)
{
start += x;
end += x;
return *this;
}
///
/// Moves interval towards the end by one
///
/// \returns Moved interval
///
interval operator++()
{
++start;
++end;
return *this;
}
///
/// Moves interval towards the end by one
///
/// \returns Original interval
///
interval operator++(int) // Postfix increment operator.
{
interval r = *this;
++start;
++end;
return r;
}
///
/// Subtracts two intervals by components
///
/// \param[in] other Second interval
///
/// \returns Resulting interval
///
interval operator-(_In_ const interval& other) const
{
return interval(start - other.start, end - other.end);
}
///
/// Moves interval towards the beginning by a number
///
/// \param[in] x Amount to move for
///
/// \returns Moved interval
///
interval operator-(_In_ const T x) const
{
return interval(start - x, end - x);
}
///
/// Moves interval towards the beginning by a number
///
/// \param[in] x Amount to move for
///
/// \returns Resulting interval
///
interval operator-=(_In_ const T x)
{
start -= x;
end -= x;
return *this;
}
///
/// Moves interval towards the beginning by one
///
/// \returns Moved interval
///
interval operator--()
{
--start;
--end;
return *this;
}
///
/// Moves interval towards the begginning by one
///
/// \returns Original interval
///
interval operator--(int) // Postfix decrement operator.
{
interval r = *this;
--start;
--end;
return r;
}
///
/// Are intervals identical?
///
/// \param[in] other Second interval to compare
///
/// \returns true if intervals are identical or false otherwise
///
bool operator==(_In_ const interval& other) const
{
return start == other.start && end == other.end;
}
///
/// Are intervals different?
///
/// \param[in] other Second interval to compare
///
/// \returns true if intervals are different or false otherwise
///
bool operator!=(_In_ const interval& other) const
{
return !operator ==(other);
}
};
template <class T, class AX = std::allocator<interval<T>>>
using interval_vector = std::vector<interval<T>, AX>;
}