| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- //
- // limit.h
- // utilities
- //
- // Created by Sam Jaffe on 10/22/13.
- // Copyright (c) 2013 Sam Jaffe. All rights reserved.
- //
- #pragma once
- #include <stdexcept>
- #include <math/clamp.h>
- namespace math {
- struct {
- } assert_bounds;
- using AssertBounds = decltype(assert_bounds);
- template <typename T, T MINIMUM_VALUE, T MAXIMUM_VALUE> class Bound final {
- public:
- static_assert(MINIMUM_VALUE <= MAXIMUM_VALUE,
- "The minimum value must be less than or equal to the maximum");
- using value_type = T;
- using underlying_type = value_type;
- static constexpr const value_type min = MINIMUM_VALUE;
- static constexpr const value_type max = MAXIMUM_VALUE;
- private:
- value_type value{min};
- public:
- constexpr Bound() = default;
- constexpr Bound(value_type const & val) noexcept
- : value(clamp(val, min, max)) {}
- Bound(AssertBounds, value_type val) : value(val) {
- if (val < min || max < val) {
- throw std::out_of_range{"Must construct a value within range"};
- }
- }
- Bound & operator-=(value_type by) { return *this = Bound(value - by); }
- Bound & operator+=(value_type by) { return *this = Bound(value + by); }
- Bound operator+(value_type by) const { return Bound{*this} += by; }
- Bound operator-(value_type by) const { return Bound{*this} -= by; }
- Bound & operator--() { return *this -= 1; }
- Bound & operator++() { return *this += 1; }
- Bound operator--(int) {
- Bound tmp = *this;
- operator--();
- return tmp;
- }
- Bound operator++(int) {
- Bound tmp = *this;
- operator++();
- return tmp;
- }
- operator value_type() const { return value; }
- };
- template <typename T, T MINMAX> using SymBound = Bound<T, -MINMAX, +MINMAX>;
- template <typename T, T VAL>
- using UniBound =
- std::conditional_t<0 <= VAL, Bound<T, 0, VAL>, Bound<T, VAL, 0>>;
- template <typename L, L l1, L h1, typename R, R l2, R h2>
- auto operator+(Bound<L, l1, h1> lhs, Bound<R, l2, h2> rhs) {
- return L(lhs) + R(rhs);
- }
- template <typename L, L l1, L h1, typename R, R l2, R h2>
- auto operator-(Bound<L, l1, h1> lhs, Bound<R, l2, h2> rhs) {
- return L(lhs) - R(rhs);
- }
- template <typename L, L l1, L h1, typename R, R l2, R h2>
- auto operator*(Bound<L, l1, h1> lhs, Bound<R, l2, h2> rhs) {
- return L(lhs) * R(rhs);
- }
- template <typename L, L l1, L h1, typename R, R l2, R h2>
- auto operator/(Bound<L, l1, h1> lhs, Bound<R, l2, h2> rhs) {
- return L(lhs) / R(rhs);
- }
- }
|