limit.h 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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. namespace math {
  11. struct {} assert_bounds;
  12. using AssertBounds = decltype(assert_bounds);
  13. template <typename T, T MINIMUM_VALUE, T MAXIMUM_VALUE>
  14. class Bound final {
  15. private:
  16. public:
  17. static_assert(MINIMUM_VALUE <= MAXIMUM_VALUE,
  18. "The minimum value must be less than or equal to the maximum");
  19. typedef Tp value_type;
  20. static constexpr const value_type min = MINIMUM_VALUE;
  21. static constexpr const value_type max = MAXIMUM_VALUE;
  22. constexpr Bound() = default;
  23. constexpr Bound(value_type const & val) noexcept
  24. : value(std::max(min, std::min(max, val))) {}
  25. Bound(AssertBounds, value_type val) : value(val) {
  26. if (val < min || max < val) {
  27. throw std::out_of_range{"Must construct a value within range"};
  28. }
  29. }
  30. Bound& operator-=(value_type v) { return *this = Bound(value - v); }
  31. Bound& operator+=(value_type v) { return *this = Bound(value + v); }
  32. Bound& operator--() { return *this -= 1; }
  33. Bound& operator++() { return *this += 1; }
  34. Bound operator--(int) {
  35. Bound tmp = *this;
  36. operator--();
  37. return tmp;
  38. }
  39. Bound operator++(int) {
  40. Bound tmp = *this;
  41. operator++();
  42. return tmp;
  43. }
  44. operator value_type() const { return value; }
  45. private:
  46. value_type value{};
  47. };
  48. template <typename T, T MINMAX> using SymBound = Bound<T, -MINMAX, +MINMAX>;
  49. template <typename T, T VAL>
  50. using UniBound = std::conditional_t<0 <= VAL, Bound<T, 0, VAL>, Bound<T, VAL, 0>>;
  51. template <typename L, L l1, L h1, typename R, R l2, R h2>
  52. auto operator+(Bound<L, l1, h1> lhs, Bound<R, l2, h2> rhs) {
  53. return L(lhs) + R(rhs);
  54. }
  55. template <typename L, L l1, L h1, typename R, R l2, R h2>
  56. auto operator-(Bound<L, l1, h1> lhs, Bound<R, l2, h2> rhs) {
  57. return L(lhs) - R(rhs);
  58. }
  59. template <typename L, L l1, L h1, typename R, R l2, R h2>
  60. auto operator*(Bound<L, l1, h1> lhs, Bound<R, l2, h2> rhs) {
  61. return L(lhs) * R(rhs);
  62. }
  63. template <typename L, L l1, L h1, typename R, R l2, R h2>
  64. auto operator/(Bound<L, l1, h1> lhs, Bound<R, l2, h2> rhs) {
  65. return L(lhs) / R(rhs);
  66. }
  67. }