1 /* Copyright 2017-2018 Fizyr B.V. - https://fizyr.com
2  *
3  * Redistribution and use in source and binary forms, with or without modification,
4  * are permitted provided that the following conditions are met:
5  *
6  * 1. Redistributions of source code must retain the above copyright notice,
7  *    this list of conditions and the following disclaimer.
8  *
9  * 2. Redistributions in binary form must reproduce the above copyright notice,
10  *    this list of conditions and the following disclaimer in the documentation
11  *    and/or other materials provided with the distribution.
12  *
13  * 3. Neither the name of the copyright holder nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software without
15  *    specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
21  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "../static_assert_same.hpp"
30 #include "tuple/fold.hpp"
31 
32 #include <catch2/catch.hpp>
33 
34 namespace estd {
35 
36 TEST_CASE("tuple left fold", "[tuple]") {
__anon44bd59e20102(auto a, auto b) 37 	auto sum = [] (auto a, auto b) { return a + b; };
__anon44bd59e20202(auto a, auto b) 38 	auto mul = [] (auto a, auto b) { return a * b; };
__anon44bd59e20302(auto a, auto) 39 	auto drop_right = [] (auto a, auto) { return a; };
__anon44bd59e20402(auto, auto b) 40 	auto drop_left  = [] (auto, auto b) { return b; };
41 
42 	SECTION("foldl over empty tuple returns initial accumulator") {
43 		REQUIRE(foldl(std::tuple<>(), 5, sum) == 5);
44 	}
45 
46 	SECTION("foldl without accumulator over single element tuple returns first element") {
47 		REQUIRE(foldl(std::tuple(5), mul) == 5);
48 	}
49 
50 	SECTION("foldl without accumulator over non-empty tuple") {
51 		REQUIRE(foldl(std::tuple(1, 2, 3, 4), sum) == 1 + 2 + 3 + 4);
52 		REQUIRE(foldl(std::tuple(1, 2, 3, 4), mul) == 1 * 2 * 3 * 4);
53 	}
54 
55 	SECTION("foldl with accumulator over non-empty tuple") {
56 		REQUIRE(foldl(std::tuple(1, 2, 3, 4), 10, sum) == 10 + 1 + 2 + 3 + 4);
57 		REQUIRE(foldl(std::tuple(1, 2, 3, 4), 10, mul) == 10 * 1 * 2 * 3 * 4);
58 	}
59 
60 	SECTION("foldl over heterogenous tuple") {
61 		REQUIRE(foldl(std::tuple(1, 2.0, 3.f, 4), 10, sum) == 10.0 + 1 + 2 + 3 + 4);
62 		REQUIRE(foldl(std::tuple(1, 2.0, 3.f, 4), 10, mul) == 10.0 * 1 * 2 * 3 * 4);
63 		static_assert_same<decltype(foldl(std::tuple(1, 2.0, 3.f, 4), 10, sum)), double>();
64 		static_assert_same<decltype(foldl(std::tuple(1, 2.0, 3.f, 4), 10, mul)), double>();
65 	}
66 
67 	SECTION("foldl is a left fold") {
68 		REQUIRE(foldl(std::tuple(1.0, 2, 3, 4.0), 10, drop_right) == 10);
69 		REQUIRE(foldl(std::tuple(1  , 2, 3, 4.0),     drop_right) ==  1);
70 		static_assert_same<decltype(foldl(std::tuple(1.0, 2, 3, 4.0), 10, drop_right)), int>();
71 		static_assert_same<decltype(foldl(std::tuple(1  , 2, 3, 4.0),     drop_right)), int>();
72 
73 		REQUIRE(foldl(std::tuple(1, 2, 3, 4.0), 10, drop_left) == 4.0);
74 		REQUIRE(foldl(std::tuple(1, 2, 3, 4.0),     drop_left) == 4.0);
75 		static_assert_same<decltype(foldl(std::tuple(1, 2, 3, 4.0), 10, drop_left)), double>();
76 		static_assert_same<decltype(foldl(std::tuple(1, 2, 3, 4.0),     drop_left)), double>();
77 	}
78 }
79 
80 TEST_CASE("tuple right fold", "[tuple]") {
__anon44bd59e20502(auto a, auto b) 81 	auto sum = [] (auto a, auto b) { return a + b; };
__anon44bd59e20602(auto a, auto b) 82 	auto mul = [] (auto a, auto b) { return a * b; };
__anon44bd59e20702(auto a, auto) 83 	auto drop_right = [] (auto a, auto) { return a; };
__anon44bd59e20802(auto, auto b) 84 	auto drop_left  = [] (auto, auto b) { return b; };
85 
86 	SECTION("foldr over empty tuple returns initial accumulator") {
87 		REQUIRE(foldr(std::tuple<>(), 5, sum) == 5);
88 	}
89 
90 	SECTION("foldr without accumulator over single element tuple returns first element") {
91 		REQUIRE(foldr(std::tuple(5), mul) == 5);
92 	}
93 
94 	SECTION("foldr without accumulator over non-empty tuple") {
95 		REQUIRE(foldr(std::tuple(1, 2, 3, 4), sum) == 1 + 2 + 3 + 4);
96 		REQUIRE(foldr(std::tuple(1, 2, 3, 4), mul) == 1 * 2 * 3 * 4);
97 	}
98 
99 	SECTION("foldr with accumulator over non-empty tuple") {
100 		REQUIRE(foldr(std::tuple(1, 2, 3, 4), 10, sum) == 10 + 1 + 2 + 3 + 4);
101 		REQUIRE(foldr(std::tuple(1, 2, 3, 4), 10, mul) == 10 * 1 * 2 * 3 * 4);
102 	}
103 
104 	SECTION("foldr over heterogenous tuple") {
105 		REQUIRE(foldr(std::tuple(1, 2.0, 3.f, 4), 10, sum) == 10.0 + 1 + 2 + 3 + 4);
106 		REQUIRE(foldr(std::tuple(1, 2.0, 3.f, 4), 10, mul) == 10.0 * 1 * 2 * 3 * 4);
107 		static_assert_same<decltype(foldr(std::tuple(1, 2.0, 3.f, 4), 10, sum)), double>();
108 		static_assert_same<decltype(foldr(std::tuple(1, 2.0, 3.f, 4), 10, mul)), double>();
109 	}
110 
111 	SECTION("foldr is a right fold") {
112 		REQUIRE(foldr(std::tuple(1, 2, 3, 4.0), 10.0, drop_right) == 1);
113 		REQUIRE(foldr(std::tuple(1, 2, 3, 4.0),       drop_right) == 1);
114 		static_assert_same<decltype(foldr(std::tuple(1, 2, 3, 4.0), 10.0, drop_right)), int>();
115 		static_assert_same<decltype(foldr(std::tuple(1, 2, 3, 4.0),       drop_right)), int>();
116 
117 		REQUIRE(foldr(std::tuple(1, 2, 3, 4  ), 10.0, drop_left) == 10.0);
118 		REQUIRE(foldr(std::tuple(1, 2, 3, 4.0),       drop_left) ==  4.0);
119 		static_assert_same<decltype(foldr(std::tuple(1, 2, 3, 4  ), 10.0, drop_left)), double>();
120 		static_assert_same<decltype(foldr(std::tuple(1, 2, 3, 4.0),       drop_left)), double>();
121 	}
122 }
123 
124 }
125