1 | // (C) Copyright Jesse Williamson 2009 |
2 | // Use, modification and distribution are subject to the |
3 | // Boost Software License, Version 1.0. (See accompanying file |
4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
5 | |
6 | #include <iostream> |
7 | #include <vector> |
8 | |
9 | #include <boost/config.hpp> |
10 | #include <boost/algorithm/clamp.hpp> |
11 | |
12 | #define BOOST_TEST_MAIN |
13 | #include <boost/test/unit_test.hpp> |
14 | |
15 | namespace ba = boost::algorithm; |
16 | |
17 | bool intGreater ( int lhs, int rhs ) { return lhs > rhs; } |
18 | bool doubleGreater ( double lhs, double rhs ) { return lhs > rhs; } |
19 | |
20 | class custom { |
21 | public: |
22 | custom ( int x ) : v(x) {} |
23 | custom ( const custom &rhs ) : v(rhs.v) {} |
24 | ~custom () {} |
25 | custom & operator = ( const custom &rhs ) { v = rhs.v; return *this; } |
26 | |
27 | bool operator < ( const custom &rhs ) const { return v < rhs.v; } |
28 | bool operator == ( const custom &rhs ) const { return v == rhs.v; } // need this for the test |
29 | |
30 | std::ostream & print ( std::ostream &os ) const { return os << v; } |
31 | |
32 | int v; |
33 | }; |
34 | |
35 | std::ostream & operator << ( std::ostream & os, const custom &x ) { return x.print ( os ); } |
36 | |
37 | bool customLess ( const custom &lhs, const custom &rhs ) { return lhs.v < rhs.v; } |
38 | |
39 | void test_ints() |
40 | { |
41 | |
42 | // Inside the range, equal to the endpoints, and outside the endpoints. |
43 | BOOST_CHECK_EQUAL ( 3, ba::clamp ( 3, 1, 10 )); |
44 | BOOST_CHECK_EQUAL ( 1, ba::clamp ( 1, 1, 10 )); |
45 | BOOST_CHECK_EQUAL ( 1, ba::clamp ( 0, 1, 10 )); |
46 | BOOST_CHECK_EQUAL ( 10, ba::clamp ( 10, 1, 10 )); |
47 | BOOST_CHECK_EQUAL ( 10, ba::clamp ( 11, 1, 10 )); |
48 | |
49 | BOOST_CHECK_EQUAL ( 3, ba::clamp ( 3, 10, 1, intGreater )); |
50 | BOOST_CHECK_EQUAL ( 1, ba::clamp ( 1, 10, 1, intGreater )); |
51 | BOOST_CHECK_EQUAL ( 1, ba::clamp ( 0, 10, 1, intGreater )); |
52 | BOOST_CHECK_EQUAL ( 10, ba::clamp ( 10, 10, 1, intGreater )); |
53 | BOOST_CHECK_EQUAL ( 10, ba::clamp ( 11, 10, 1, intGreater )); |
54 | |
55 | // Negative numbers |
56 | BOOST_CHECK_EQUAL ( -3, ba::clamp ( -3, -10, -1 )); |
57 | BOOST_CHECK_EQUAL ( -1, ba::clamp ( -1, -10, -1 )); |
58 | BOOST_CHECK_EQUAL ( -1, ba::clamp ( 0, -10, -1 )); |
59 | BOOST_CHECK_EQUAL ( -10, ba::clamp ( -10, -10, -1 )); |
60 | BOOST_CHECK_EQUAL ( -10, ba::clamp ( -11, -10, -1 )); |
61 | |
62 | // Mixed positive and negative numbers |
63 | BOOST_CHECK_EQUAL ( 5, ba::clamp ( 5, -10, 10 )); |
64 | BOOST_CHECK_EQUAL ( -10, ba::clamp ( -10, -10, 10 )); |
65 | BOOST_CHECK_EQUAL ( -10, ba::clamp ( -15, -10, 10 )); |
66 | BOOST_CHECK_EQUAL ( 10, ba::clamp ( 10, -10, 10 )); |
67 | BOOST_CHECK_EQUAL ( 10, ba::clamp ( 15, -10, 10 )); |
68 | |
69 | // Unsigned |
70 | BOOST_CHECK_EQUAL ( 5U, ba::clamp ( 5U, 1U, 10U )); |
71 | BOOST_CHECK_EQUAL ( 1U, ba::clamp ( 1U, 1U, 10U )); |
72 | BOOST_CHECK_EQUAL ( 1U, ba::clamp ( 0U, 1U, 10U )); |
73 | BOOST_CHECK_EQUAL ( 10U, ba::clamp ( 10U, 1U, 10U )); |
74 | BOOST_CHECK_EQUAL ( 10U, ba::clamp ( 15U, 1U, 10U )); |
75 | |
76 | // Mixed (1) |
77 | BOOST_CHECK_EQUAL ( 5U, ba::clamp ( 5U, 1, 10 )); |
78 | BOOST_CHECK_EQUAL ( 1U, ba::clamp ( 1U, 1, 10 )); |
79 | BOOST_CHECK_EQUAL ( 1U, ba::clamp ( 0U, 1, 10 )); |
80 | BOOST_CHECK_EQUAL ( 10U, ba::clamp ( 10U, 1, 10 )); |
81 | BOOST_CHECK_EQUAL ( 10U, ba::clamp ( 15U, 1, 10 )); |
82 | |
83 | // Mixed (3) |
84 | BOOST_CHECK_EQUAL ( 5U, ba::clamp ( 5U, 1, 10. )); |
85 | BOOST_CHECK_EQUAL ( 1U, ba::clamp ( 1U, 1, 10. )); |
86 | BOOST_CHECK_EQUAL ( 1U, ba::clamp ( 0U, 1, 10. )); |
87 | BOOST_CHECK_EQUAL ( 10U, ba::clamp ( 10U, 1, 10. )); |
88 | BOOST_CHECK_EQUAL ( 10U, ba::clamp ( 15U, 1, 10. )); |
89 | |
90 | short foo = 50; |
91 | BOOST_CHECK_EQUAL ( 56, ba::clamp ( foo, 56.9, 129 )); |
92 | BOOST_CHECK_EQUAL ( 24910, ba::clamp ( foo, 12345678, 123456999 )); |
93 | } |
94 | |
95 | |
96 | void test_floats() |
97 | { |
98 | |
99 | // Inside the range, equal to the endpoints, and outside the endpoints. |
100 | BOOST_CHECK_EQUAL ( 3.0, ba::clamp ( 3.0, 1.0, 10.0 )); |
101 | BOOST_CHECK_EQUAL ( 1.0, ba::clamp ( 1.0, 1.0, 10.0 )); |
102 | BOOST_CHECK_EQUAL ( 1.0, ba::clamp ( 0.0, 1.0, 10.0 )); |
103 | BOOST_CHECK_EQUAL ( 10.0, ba::clamp ( 10.0, 1.0, 10.0 )); |
104 | BOOST_CHECK_EQUAL ( 10.0, ba::clamp ( 11.0, 1.0, 10.0 )); |
105 | |
106 | BOOST_CHECK_EQUAL ( 3.0, ba::clamp ( 3.0, 10.0, 1.0, doubleGreater )); |
107 | BOOST_CHECK_EQUAL ( 1.0, ba::clamp ( 1.0, 10.0, 1.0, doubleGreater )); |
108 | BOOST_CHECK_EQUAL ( 1.0, ba::clamp ( 0.0, 10.0, 1.0, doubleGreater )); |
109 | BOOST_CHECK_EQUAL ( 10.0, ba::clamp ( 10.0, 10.0, 1.0, doubleGreater )); |
110 | BOOST_CHECK_EQUAL ( 10.0, ba::clamp ( 11.0, 10.0, 1.0, doubleGreater )); |
111 | |
112 | // Negative numbers |
113 | BOOST_CHECK_EQUAL ( -3.f, ba::clamp ( -3.f, -10.f, -1.f )); |
114 | BOOST_CHECK_EQUAL ( -1.f, ba::clamp ( -1.f, -10.f, -1.f )); |
115 | BOOST_CHECK_EQUAL ( -1.f, ba::clamp ( 0.f, -10.f, -1.f )); |
116 | BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -10.f, -10.f, -1.f )); |
117 | BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -11.f, -10.f, -1.f )); |
118 | |
119 | // Mixed positive and negative numbers |
120 | BOOST_CHECK_EQUAL ( 5.f, ba::clamp ( 5.f, -10.f, 10.f )); |
121 | BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -10.f, -10.f, 10.f )); |
122 | BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -15.f, -10.f, 10.f )); |
123 | BOOST_CHECK_EQUAL ( 10.f, ba::clamp ( 10.f, -10.f, 10.f )); |
124 | BOOST_CHECK_EQUAL ( 10.f, ba::clamp ( 15.f, -10.f, 10.f )); |
125 | |
126 | // Mixed (1) |
127 | BOOST_CHECK_EQUAL ( 5.f, ba::clamp ( 5.f, -10., 10. )); |
128 | BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -10.f, -10., 10. )); |
129 | BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -15.f, -10., 10. )); |
130 | BOOST_CHECK_EQUAL ( 10.f, ba::clamp ( 10.f, -10., 10. )); |
131 | BOOST_CHECK_EQUAL ( 10.f, ba::clamp ( 15.f, -10., 10. )); |
132 | |
133 | // Mixed (2) |
134 | BOOST_CHECK_EQUAL ( 5.f, ba::clamp ( 5.f, -10, 10 )); |
135 | BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -10.f, -10, 10 )); |
136 | BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -15.f, -10, 10 )); |
137 | BOOST_CHECK_EQUAL ( 10.f, ba::clamp ( 10.f, -10, 10 )); |
138 | BOOST_CHECK_EQUAL ( 10.f, ba::clamp ( 15.f, -10, 10 )); |
139 | } |
140 | |
141 | void test_custom() |
142 | { |
143 | |
144 | // Inside the range, equal to the endpoints, and outside the endpoints. |
145 | BOOST_CHECK_EQUAL ( custom( 3), ba::clamp ( custom( 3), custom(1), custom(10))); |
146 | BOOST_CHECK_EQUAL ( custom( 1), ba::clamp ( custom( 1), custom(1), custom(10))); |
147 | BOOST_CHECK_EQUAL ( custom( 1), ba::clamp ( custom( 0), custom(1), custom(10))); |
148 | BOOST_CHECK_EQUAL ( custom(10), ba::clamp ( custom(10), custom(1), custom(10))); |
149 | BOOST_CHECK_EQUAL ( custom(10), ba::clamp ( custom(11), custom(1), custom(10))); |
150 | |
151 | BOOST_CHECK_EQUAL ( custom( 3), ba::clamp ( custom( 3), custom(1), custom(10), customLess )); |
152 | BOOST_CHECK_EQUAL ( custom( 1), ba::clamp ( custom( 1), custom(1), custom(10), customLess )); |
153 | BOOST_CHECK_EQUAL ( custom( 1), ba::clamp ( custom( 0), custom(1), custom(10), customLess )); |
154 | BOOST_CHECK_EQUAL ( custom(10), ba::clamp ( custom(10), custom(1), custom(10), customLess )); |
155 | BOOST_CHECK_EQUAL ( custom(10), ba::clamp ( custom(11), custom(1), custom(10), customLess )); |
156 | |
157 | // Fail!! |
158 | // BOOST_CHECK_EQUAL ( custom(1), ba::clamp ( custom(11), custom(1), custom(10))); |
159 | } |
160 | |
161 | #define elementsof(v) (sizeof (v) / sizeof (v[0])) |
162 | #define a_begin(v) (&v[0]) |
163 | #define a_end(v) (v + elementsof (v)) |
164 | #define a_range(v) v |
165 | #define b_e(v) a_begin(v),a_end(v) |
166 | |
167 | void test_int_range () |
168 | { |
169 | int inputs [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 19, 99, 999, -1, -3, -99, 234234 }; |
170 | int outputs [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, -1, -1, -1, 10 }; |
171 | std::vector<int> results; |
172 | std::vector<int> in_v; |
173 | |
174 | std::copy ( a_begin(inputs), a_end(inputs), result: std::back_inserter ( x&: in_v )); |
175 | |
176 | ba::clamp_range ( a_begin(inputs), a_end(inputs), out: std::back_inserter ( x&: results ), lo: -1, hi: 10 ); |
177 | BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs )); |
178 | results.clear (); |
179 | ba::clamp_range ( first: in_v.begin (), last: in_v.end (), out: std::back_inserter ( x&: results ), lo: -1, hi: 10 ); |
180 | BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs )); |
181 | results.clear (); |
182 | |
183 | ba::clamp_range ( a_begin(inputs), a_end(inputs), out: std::back_inserter ( x&: results ), lo: 10, hi: -1, p: intGreater ); |
184 | BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs )); |
185 | results.clear (); |
186 | ba::clamp_range ( first: in_v.begin (), last: in_v.end (), out: std::back_inserter ( x&: results ), lo: 10, hi: -1, p: intGreater ); |
187 | BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs )); |
188 | results.clear (); |
189 | |
190 | ba::clamp_range ( a_range(inputs), out: std::back_inserter ( x&: results ), lo: -1, hi: 10 ); |
191 | BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs )); |
192 | results.clear (); |
193 | ba::clamp_range ( r: in_v, out: std::back_inserter ( x&: results ), lo: -1, hi: 10 ); |
194 | BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs )); |
195 | results.clear (); |
196 | |
197 | ba::clamp_range ( a_range(inputs), out: std::back_inserter ( x&: results ), lo: 10, hi: -1, p: intGreater ); |
198 | BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs )); |
199 | results.clear (); |
200 | ba::clamp_range ( r: in_v, out: std::back_inserter ( x&: results ), lo: 10, hi: -1, p: intGreater ); |
201 | BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs )); |
202 | results.clear (); |
203 | |
204 | int junk[elementsof(inputs)]; |
205 | ba::clamp_range ( r: inputs, out: junk, lo: 10, hi: -1, p: intGreater ); |
206 | BOOST_CHECK ( std::equal ( b_e(junk), outputs )); |
207 | } |
208 | |
209 | BOOST_AUTO_TEST_CASE( test_main ) |
210 | { |
211 | test_ints (); |
212 | test_floats (); |
213 | test_custom (); |
214 | |
215 | test_int_range (); |
216 | // test_float_range (); |
217 | // test_custom_range (); |
218 | } |
219 | |