fold.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // Range v3 library
  2. //
  3. // Copyright Eric Niebler 2014-present
  4. //
  5. // Use, modification and distribution is subject to the
  6. // Boost Software License, Version 1.0. (See accompanying
  7. // file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. // Project home: https://github.com/ericniebler/range-v3
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // The LLVM Compiler Infrastructure
  15. //
  16. // This file is dual licensed under the MIT and the University of Illinois Open
  17. // Source Licenses. See LICENSE.TXT for details.
  18. //
  19. //===----------------------------------------------------------------------===//
  20. #include <cmath>
  21. #include <functional>
  22. #include <range/v3/algorithm/fold.hpp>
  23. #include <range/v3/algorithm/min.hpp>
  24. #include <range/v3/core.hpp>
  25. #include "../simple_test.hpp"
  26. #include "../test_iterators.hpp"
  27. struct Approx
  28. {
  29. double value;
  30. Approx(double v)
  31. : value(v)
  32. {}
  33. friend bool operator==(Approx a, double d)
  34. {
  35. return std::fabs(a.value - d) < 0.001;
  36. }
  37. friend bool operator==(double d, Approx a)
  38. {
  39. return a == d;
  40. }
  41. };
  42. template<class Iter, class Sent = Iter>
  43. void test_left()
  44. {
  45. double da[] = {0.25, 0.75};
  46. CHECK(ranges::fold_left(Iter(da), Sent(da), 1, std::plus<>()) == Approx{1.0});
  47. CHECK(ranges::fold_left(Iter(da), Sent(da + 2), 1, std::plus<>()) == Approx{2.0});
  48. CHECK(ranges::fold_left_first(Iter(da), Sent(da), ranges::min) == ranges::nullopt);
  49. CHECK(ranges::fold_left_first(Iter(da), Sent(da + 2), ranges::min) ==
  50. ranges::optional<Approx>(0.25));
  51. using ranges::make_subrange;
  52. CHECK(ranges::fold_left(make_subrange(Iter(da), Sent(da)), 1, std::plus<>()) ==
  53. Approx{1.0});
  54. CHECK(ranges::fold_left(make_subrange(Iter(da), Sent(da + 2)), 1, std::plus<>()) ==
  55. Approx{2.0});
  56. CHECK(ranges::fold_left_first(make_subrange(Iter(da), Sent(da)), ranges::min) ==
  57. ranges::nullopt);
  58. CHECK(ranges::fold_left_first(make_subrange(Iter(da), Sent(da + 2)), ranges::min) ==
  59. ranges::optional<Approx>(0.25));
  60. }
  61. void test_right()
  62. {
  63. double da[] = {0.25, 0.75};
  64. CHECK(ranges::fold_right(da, da + 2, 1, std::plus<>()) == Approx{2.0});
  65. CHECK(ranges::fold_right(da, 1, std::plus<>()) == Approx{2.0});
  66. // f(0.25, f(0.75, 1))
  67. CHECK(ranges::fold_right(da, da + 2, 1, std::minus<>()) == Approx{0.5});
  68. CHECK(ranges::fold_right(da, 1, std::minus<>()) == Approx{0.5});
  69. int xs[] = {1, 2, 3};
  70. auto concat = [](int i, std::string s) { return s + std::to_string(i); };
  71. CHECK(ranges::fold_right(xs, xs + 2, std::string(), concat) == "21");
  72. CHECK(ranges::fold_right(xs, std::string(), concat) == "321");
  73. }
  74. int main()
  75. {
  76. test_left<InputIterator<const double *>>();
  77. test_left<ForwardIterator<const double *>>();
  78. test_left<BidirectionalIterator<const double *>>();
  79. test_left<RandomAccessIterator<const double *>>();
  80. test_left<const double *>();
  81. test_left<InputIterator<const double *>, Sentinel<const double *>>();
  82. test_left<ForwardIterator<const double *>, Sentinel<const double *>>();
  83. test_left<BidirectionalIterator<const double *>, Sentinel<const double *>>();
  84. test_left<RandomAccessIterator<const double *>, Sentinel<const double *>>();
  85. test_right();
  86. return ::test_result();
  87. }