linear_distribute.hpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Casey Carter 2017
  5. // Copyright Gonzalo Brito Gadeschi 2017
  6. //
  7. // Use, modification and distribution is subject to the
  8. // Boost Software License, Version 1.0. (See accompanying
  9. // file LICENSE_1_0.txt or copy at
  10. // http://www.boost.org/LICENSE_1_0.txt)
  11. //
  12. // Project home: https://github.com/ericniebler/range-v3
  13. //
  14. #ifndef RANGES_V3_VIEW_LINEAR_DISTRIBUTE_HPP
  15. #define RANGES_V3_VIEW_LINEAR_DISTRIBUTE_HPP
  16. #include <type_traits>
  17. #include <meta/meta.hpp>
  18. #include <range/v3/range_fwd.hpp>
  19. #include <range/v3/iterator/default_sentinel.hpp>
  20. #include <range/v3/utility/static_const.hpp>
  21. #include <range/v3/view/facade.hpp>
  22. #include <range/v3/detail/prologue.hpp>
  23. namespace ranges
  24. {
  25. namespace views
  26. {
  27. /// \addtogroup group-views
  28. /// @{
  29. template<typename T>
  30. struct linear_distribute_view : view_facade<linear_distribute_view<T>, finite>
  31. {
  32. CPP_assert(std::is_arithmetic<T>());
  33. private:
  34. friend range_access;
  35. using Calc = meta::conditional_t<std::is_floating_point<T>::value, T, double>;
  36. T from_, to_;
  37. Calc delta_;
  38. std::ptrdiff_t n_;
  39. constexpr T read() const noexcept
  40. {
  41. return from_;
  42. }
  43. constexpr bool equal(default_sentinel_t) const noexcept
  44. {
  45. return n_ == 0;
  46. }
  47. constexpr bool equal(linear_distribute_view const & other) const noexcept
  48. {
  49. bool const eq = n_ == other.n_;
  50. RANGES_DIAGNOSTIC_PUSH
  51. RANGES_DIAGNOSTIC_IGNORE_FLOAT_EQUAL
  52. RANGES_EXPECT(to_ == other.to_);
  53. RANGES_EXPECT(!eq || from_ == other.from_);
  54. RANGES_DIAGNOSTIC_POP
  55. return eq;
  56. }
  57. constexpr void next() noexcept
  58. {
  59. RANGES_EXPECT(n_ > 0);
  60. --n_;
  61. if(n_ == 0)
  62. {
  63. from_ = to_;
  64. }
  65. else
  66. {
  67. from_ = T(to_ - (delta_ * Calc(n_ - 1)));
  68. }
  69. }
  70. public:
  71. constexpr linear_distribute_view() = default;
  72. constexpr linear_distribute_view(T from, T to, std::ptrdiff_t n) noexcept
  73. : from_(from)
  74. , to_(to)
  75. , delta_(n > 1 ? (to - from) / Calc(n - 1) : 0)
  76. , n_(n)
  77. {
  78. RANGES_EXPECT(n_ > 0);
  79. RANGES_EXPECT(to_ >= from_);
  80. }
  81. constexpr std::size_t size() const noexcept
  82. {
  83. return static_cast<std::size_t>(n_);
  84. }
  85. };
  86. /// Distributes `n` values linearly in the closed interval [`from`, `to`].
  87. ///
  88. /// \pre `from <= to && n > 0`
  89. ///
  90. /// If `from == to`, returns n-times `to`.
  91. /// If `n == 1` returns `to`.
  92. struct linear_distribute_fn
  93. {
  94. template(typename T)(
  95. requires std::is_arithmetic<T>::value)
  96. constexpr auto operator()(T from, T to, std::ptrdiff_t n) const
  97. {
  98. return linear_distribute_view<T>{from, to, n};
  99. }
  100. };
  101. /// \relates linear_distribute_fn
  102. /// \ingroup group-views
  103. RANGES_INLINE_VARIABLE(linear_distribute_fn, linear_distribute)
  104. } // namespace views
  105. } // namespace ranges
  106. #include <range/v3/detail/epilogue.hpp>
  107. #endif