limit.h 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. //
  2. // limit.h
  3. // utilities
  4. //
  5. // Created by Sam Jaffe on 10/22/13.
  6. // Copyright (c) 2013 Sam Jaffe. All rights reserved.
  7. //
  8. #pragma once
  9. #include <stdexcept>
  10. #include <math/clamp.h>
  11. namespace math {
  12. struct {
  13. } assert_bounds;
  14. using AssertBounds = decltype(assert_bounds);
  15. template <typename T, T MINIMUM_VALUE, T MAXIMUM_VALUE> class Bound final {
  16. public:
  17. static_assert(MINIMUM_VALUE <= MAXIMUM_VALUE,
  18. "The minimum value must be less than or equal to the maximum");
  19. using value_type = T;
  20. using underlying_type = value_type;
  21. static constexpr const value_type min = MINIMUM_VALUE;
  22. static constexpr const value_type max = MAXIMUM_VALUE;
  23. private:
  24. value_type value{min};
  25. public:
  26. constexpr Bound() = default;
  27. constexpr Bound(value_type const & val) noexcept
  28. : value(clamp(val, min, max)) {}
  29. Bound(AssertBounds, value_type val) : value(val) {
  30. if (val < min || max < val) {
  31. throw std::out_of_range{"Must construct a value within range"};
  32. }
  33. }
  34. Bound & operator-=(value_type by) { return *this = Bound(value - by); }
  35. Bound & operator+=(value_type by) { return *this = Bound(value + by); }
  36. Bound operator+(value_type by) const { return Bound{*this} += by; }
  37. Bound operator-(value_type by) const { return Bound{*this} -= by; }
  38. Bound & operator--() { return *this -= 1; }
  39. Bound & operator++() { return *this += 1; }
  40. Bound operator--(int) {
  41. Bound tmp = *this;
  42. operator--();
  43. return tmp;
  44. }
  45. Bound operator++(int) {
  46. Bound tmp = *this;
  47. operator++();
  48. return tmp;
  49. }
  50. operator value_type() const { return value; }
  51. };
  52. template <typename T, T MINMAX> using SymBound = Bound<T, -MINMAX, +MINMAX>;
  53. template <typename T, T VAL>
  54. using UniBound =
  55. std::conditional_t<0 <= VAL, Bound<T, 0, VAL>, Bound<T, VAL, 0>>;
  56. template <typename L, L l1, L h1, typename R, R l2, R h2>
  57. auto operator+(Bound<L, l1, h1> lhs, Bound<R, l2, h2> rhs) {
  58. return L(lhs) + R(rhs);
  59. }
  60. template <typename L, L l1, L h1, typename R, R l2, R h2>
  61. auto operator-(Bound<L, l1, h1> lhs, Bound<R, l2, h2> rhs) {
  62. return L(lhs) - R(rhs);
  63. }
  64. template <typename L, L l1, L h1, typename R, R l2, R h2>
  65. auto operator*(Bound<L, l1, h1> lhs, Bound<R, l2, h2> rhs) {
  66. return L(lhs) * R(rhs);
  67. }
  68. template <typename L, L l1, L h1, typename R, R l2, R h2>
  69. auto operator/(Bound<L, l1, h1> lhs, Bound<R, l2, h2> rhs) {
  70. return L(lhs) / R(rhs);
  71. }
  72. }