• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
intGreater(int lhs,int rhs)17 BOOST_CONSTEXPR bool intGreater    ( int lhs, int rhs )       { return lhs > rhs; }
doubleGreater(double lhs,double rhs)18 BOOST_CONSTEXPR bool doubleGreater ( double lhs, double rhs ) { return lhs > rhs; }
19 
20 class custom {
21 public:
custom(int x)22     custom ( int x )             : v(x)     {}
custom(const custom & rhs)23     custom ( const custom &rhs ) : v(rhs.v) {}
~custom()24     ~custom () {}
operator =(const custom & rhs)25     custom & operator = ( const custom &rhs ) { v = rhs.v; return *this; }
26 
operator <(const custom & rhs) const27     bool operator <  ( const custom &rhs ) const { return v < rhs.v; }
operator ==(const custom & rhs) const28     bool operator == ( const custom &rhs ) const { return v == rhs.v; }     // need this for the test
29 
print(std::ostream & os) const30     std::ostream & print ( std::ostream &os ) const { return os << v; }
31 
32     int v;
33     };
34 
operator <<(std::ostream & os,const custom & x)35 std::ostream & operator << ( std::ostream & os, const custom &x ) { return x.print ( os ); }
36 
customLess(const custom & lhs,const custom & rhs)37 bool customLess ( const custom &lhs, const custom &rhs ) { return lhs.v < rhs.v; }
38 
test_ints()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     BOOST_CXX14_CONSTEXPR bool constexpr_res = (
49         ba::clamp (  3, 1, 10 ) == 3
50     );
51     BOOST_CHECK( constexpr_res );
52 
53     BOOST_CHECK_EQUAL (  3, ba::clamp (  3, 10, 1, intGreater ));
54     BOOST_CHECK_EQUAL (  1, ba::clamp (  1, 10, 1, intGreater ));
55     BOOST_CHECK_EQUAL (  1, ba::clamp (  0, 10, 1, intGreater ));
56     BOOST_CHECK_EQUAL ( 10, ba::clamp ( 10, 10, 1, intGreater ));
57     BOOST_CHECK_EQUAL ( 10, ba::clamp ( 11, 10, 1, intGreater ));
58 
59 //  Negative numbers
60     BOOST_CHECK_EQUAL (  -3, ba::clamp (  -3, -10, -1 ));
61     BOOST_CHECK_EQUAL (  -1, ba::clamp (  -1, -10, -1 ));
62     BOOST_CHECK_EQUAL (  -1, ba::clamp (   0, -10, -1 ));
63     BOOST_CHECK_EQUAL ( -10, ba::clamp ( -10, -10, -1 ));
64     BOOST_CHECK_EQUAL ( -10, ba::clamp ( -11, -10, -1 ));
65 
66 //  Mixed positive and negative numbers
67     BOOST_CHECK_EQUAL (   5, ba::clamp (   5, -10, 10 ));
68     BOOST_CHECK_EQUAL ( -10, ba::clamp ( -10, -10, 10 ));
69     BOOST_CHECK_EQUAL ( -10, ba::clamp ( -15, -10, 10 ));
70     BOOST_CHECK_EQUAL (  10, ba::clamp (  10, -10, 10 ));
71     BOOST_CHECK_EQUAL (  10, ba::clamp (  15, -10, 10 ));
72 
73 //  Unsigned
74     BOOST_CHECK_EQUAL (  5U, ba::clamp (  5U, 1U, 10U ));
75     BOOST_CHECK_EQUAL (  1U, ba::clamp (  1U, 1U, 10U ));
76     BOOST_CHECK_EQUAL (  1U, ba::clamp (  0U, 1U, 10U ));
77     BOOST_CHECK_EQUAL ( 10U, ba::clamp ( 10U, 1U, 10U ));
78     BOOST_CHECK_EQUAL ( 10U, ba::clamp ( 15U, 1U, 10U ));
79 
80 //  Mixed (1)
81     BOOST_CHECK_EQUAL (  5U, ba::clamp (  5U, 1,  10 ));
82     BOOST_CHECK_EQUAL (  1U, ba::clamp (  1U, 1,  10 ));
83     BOOST_CHECK_EQUAL (  1U, ba::clamp (  0U, 1,  10 ));
84     BOOST_CHECK_EQUAL ( 10U, ba::clamp ( 10U, 1,  10 ));
85     BOOST_CHECK_EQUAL ( 10U, ba::clamp ( 15U, 1,  10 ));
86 
87 //  Mixed (3)
88     BOOST_CHECK_EQUAL (  5U, ba::clamp (  5U, 1,  10. ));
89     BOOST_CHECK_EQUAL (  1U, ba::clamp (  1U, 1,  10. ));
90     BOOST_CHECK_EQUAL (  1U, ba::clamp (  0U, 1,  10. ));
91     BOOST_CHECK_EQUAL ( 10U, ba::clamp ( 10U, 1,  10. ));
92     BOOST_CHECK_EQUAL ( 10U, ba::clamp ( 15U, 1,  10. ));
93 
94     short foo = 50;
95     BOOST_CHECK_EQUAL ( 56,     ba::clamp ( foo, 56.9, 129 ));
96     BOOST_CHECK_EQUAL ( 24910,  ba::clamp ( foo, 12345678, 123456999 ));
97     }
98 
99 
test_floats()100 void test_floats()
101 {
102 
103 //  Inside the range, equal to the endpoints, and outside the endpoints.
104     BOOST_CHECK_EQUAL (  3.0, ba::clamp (  3.0, 1.0, 10.0 ));
105     BOOST_CHECK_EQUAL (  1.0, ba::clamp (  1.0, 1.0, 10.0 ));
106     BOOST_CHECK_EQUAL (  1.0, ba::clamp (  0.0, 1.0, 10.0 ));
107     BOOST_CHECK_EQUAL ( 10.0, ba::clamp ( 10.0, 1.0, 10.0 ));
108     BOOST_CHECK_EQUAL ( 10.0, ba::clamp ( 11.0, 1.0, 10.0 ));
109 
110     BOOST_CHECK_EQUAL (  3.0, ba::clamp (  3.0, 10.0, 1.0, doubleGreater ));
111     BOOST_CHECK_EQUAL (  1.0, ba::clamp (  1.0, 10.0, 1.0, doubleGreater ));
112     BOOST_CHECK_EQUAL (  1.0, ba::clamp (  0.0, 10.0, 1.0, doubleGreater ));
113     BOOST_CHECK_EQUAL ( 10.0, ba::clamp ( 10.0, 10.0, 1.0, doubleGreater ));
114     BOOST_CHECK_EQUAL ( 10.0, ba::clamp ( 11.0, 10.0, 1.0, doubleGreater ));
115 
116 //  Negative numbers
117     BOOST_CHECK_EQUAL (  -3.f, ba::clamp (  -3.f, -10.f, -1.f ));
118     BOOST_CHECK_EQUAL (  -1.f, ba::clamp (  -1.f, -10.f, -1.f ));
119     BOOST_CHECK_EQUAL (  -1.f, ba::clamp (   0.f, -10.f, -1.f ));
120     BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -10.f, -10.f, -1.f ));
121     BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -11.f, -10.f, -1.f ));
122 
123 //  Mixed positive and negative numbers
124     BOOST_CHECK_EQUAL (   5.f, ba::clamp (   5.f, -10.f, 10.f ));
125     BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -10.f, -10.f, 10.f ));
126     BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -15.f, -10.f, 10.f ));
127     BOOST_CHECK_EQUAL (  10.f, ba::clamp (  10.f, -10.f, 10.f ));
128     BOOST_CHECK_EQUAL (  10.f, ba::clamp (  15.f, -10.f, 10.f ));
129 
130 //  Mixed (1)
131     BOOST_CHECK_EQUAL (   5.f, ba::clamp (   5.f, -10., 10. ));
132     BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -10.f, -10., 10. ));
133     BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -15.f, -10., 10. ));
134     BOOST_CHECK_EQUAL (  10.f, ba::clamp (  10.f, -10., 10. ));
135     BOOST_CHECK_EQUAL (  10.f, ba::clamp (  15.f, -10., 10. ));
136 
137 //  Mixed (2)
138     BOOST_CHECK_EQUAL (   5.f, ba::clamp (   5.f, -10, 10 ));
139     BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -10.f, -10, 10 ));
140     BOOST_CHECK_EQUAL ( -10.f, ba::clamp ( -15.f, -10, 10 ));
141     BOOST_CHECK_EQUAL (  10.f, ba::clamp (  10.f, -10, 10 ));
142     BOOST_CHECK_EQUAL (  10.f, ba::clamp (  15.f, -10, 10 ));
143 }
144 
test_custom()145 void test_custom()
146 {
147 
148 //  Inside the range, equal to the endpoints, and outside the endpoints.
149     BOOST_CHECK_EQUAL ( custom( 3), ba::clamp ( custom( 3), custom(1), custom(10)));
150     BOOST_CHECK_EQUAL ( custom( 1), ba::clamp ( custom( 1), custom(1), custom(10)));
151     BOOST_CHECK_EQUAL ( custom( 1), ba::clamp ( custom( 0), custom(1), custom(10)));
152     BOOST_CHECK_EQUAL ( custom(10), ba::clamp ( custom(10), custom(1), custom(10)));
153     BOOST_CHECK_EQUAL ( custom(10), ba::clamp ( custom(11), custom(1), custom(10)));
154 
155     BOOST_CHECK_EQUAL ( custom( 3), ba::clamp ( custom( 3), custom(1), custom(10), customLess ));
156     BOOST_CHECK_EQUAL ( custom( 1), ba::clamp ( custom( 1), custom(1), custom(10), customLess ));
157     BOOST_CHECK_EQUAL ( custom( 1), ba::clamp ( custom( 0), custom(1), custom(10), customLess ));
158     BOOST_CHECK_EQUAL ( custom(10), ba::clamp ( custom(10), custom(1), custom(10), customLess ));
159     BOOST_CHECK_EQUAL ( custom(10), ba::clamp ( custom(11), custom(1), custom(10), customLess ));
160 
161 //  Fail!!
162 //  BOOST_CHECK_EQUAL ( custom(1), ba::clamp ( custom(11), custom(1), custom(10)));
163 }
164 
165 #define elementsof(v)   (sizeof (v) / sizeof (v[0]))
166 #define a_begin(v)      (&v[0])
167 #define a_end(v)        (v + elementsof (v))
168 #define a_range(v)      v
169 #define b_e(v)          a_begin(v),a_end(v)
170 
test_int_range()171 void test_int_range ()
172 {
173     int inputs []  = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 19, 99, 999, -1, -3, -99, 234234 };
174     int outputs [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10,  10, -1, -1, -1,  10 };
175     std::vector<int> results;
176     std::vector<int> in_v;
177 
178     std::copy ( a_begin(inputs), a_end(inputs), std::back_inserter ( in_v ));
179 
180     ba::clamp_range ( a_begin(inputs), a_end(inputs), std::back_inserter ( results ), -1, 10 );
181     BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs ));
182     results.clear ();
183     ba::clamp_range ( in_v.begin (), in_v.end (), std::back_inserter ( results ), -1, 10 );
184     BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs ));
185     results.clear ();
186 
187     ba::clamp_range ( a_begin(inputs), a_end(inputs), std::back_inserter ( results ), 10, -1, intGreater );
188     BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs ));
189     results.clear ();
190     ba::clamp_range ( in_v.begin (), in_v.end (), std::back_inserter ( results ), 10, -1, intGreater );
191     BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs ));
192     results.clear ();
193 
194     ba::clamp_range ( a_range(inputs), std::back_inserter ( results ), -1, 10 );
195     BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs ));
196     results.clear ();
197     ba::clamp_range ( in_v, std::back_inserter ( results ), -1, 10 );
198     BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs ));
199     results.clear ();
200 
201     ba::clamp_range ( a_range(inputs), std::back_inserter ( results ), 10, -1, intGreater );
202     BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs ));
203     results.clear ();
204     ba::clamp_range ( in_v, std::back_inserter ( results ), 10, -1, intGreater );
205     BOOST_CHECK ( std::equal ( results.begin(), results.end (), outputs ));
206     results.clear ();
207 
208     int junk[elementsof(inputs)];
209     ba::clamp_range ( inputs, junk, 10, -1, intGreater );
210     BOOST_CHECK ( std::equal ( b_e(junk), outputs ));
211 }
212 
test_constexpr()213 void test_constexpr()
214 {
215 
216 //  Inside the range, equal to the endpoints, and outside the endpoints.
217     {
218         BOOST_CXX14_CONSTEXPR bool check_inside  = (3  == ba::clamp (  3, 1, 10 ));
219         BOOST_CHECK(check_inside);
220         BOOST_CXX14_CONSTEXPR bool check_min     = (1  == ba::clamp (  1, 1, 10 ));
221         BOOST_CHECK(check_min);
222         BOOST_CXX14_CONSTEXPR bool check_min_out = (1  == ba::clamp (  0, 1, 10 ));
223         BOOST_CHECK(check_min_out);
224         BOOST_CXX14_CONSTEXPR bool check_max     = (10 == ba::clamp ( 10, 1, 10 ));
225         BOOST_CHECK(check_max);
226         BOOST_CXX14_CONSTEXPR bool check_max_out = (10 == ba::clamp ( 11, 1, 10 ));
227         BOOST_CHECK(check_max_out);
228     }
229     {
230         BOOST_CXX14_CONSTEXPR bool check_inside  = (3  == ba::clamp (  3, 10, 1, intGreater ));
231         BOOST_CHECK(check_inside);
232         BOOST_CXX14_CONSTEXPR bool check_min     = (1  == ba::clamp (  1, 10, 1, intGreater ));
233         BOOST_CHECK(check_min);
234         BOOST_CXX14_CONSTEXPR bool check_min_out = (1  == ba::clamp (  0, 10, 1, intGreater ));
235         BOOST_CHECK(check_min_out);
236         BOOST_CXX14_CONSTEXPR bool check_max     = (10 == ba::clamp ( 10, 10, 1, intGreater ));
237         BOOST_CHECK(check_max);
238         BOOST_CXX14_CONSTEXPR bool check_max_out = (10 == ba::clamp ( 11, 10, 1, intGreater ));
239         BOOST_CHECK(check_max_out);
240     }
241 
242 //  Negative numbers
243     {
244         BOOST_CXX14_CONSTEXPR bool check_inside  = (-3  == ba::clamp  (  -3, -10, -1 ));
245         BOOST_CHECK(check_inside);
246         BOOST_CXX14_CONSTEXPR bool check_max     = (-1  == ba::clamp  (  -1, -10, -1 ));
247         BOOST_CHECK(check_max);
248         BOOST_CXX14_CONSTEXPR bool check_max_out = (-1  == ba::clamp  (   0, -10, -1 ));
249         BOOST_CHECK(check_max_out);
250         BOOST_CXX14_CONSTEXPR bool check_min     = (-10 == ba::clamp ( -10, -10, -1 ));
251         BOOST_CHECK(check_min);
252         BOOST_CXX14_CONSTEXPR bool check_min_out = (-10 == ba::clamp ( -11, -10, -1 ));
253         BOOST_CHECK(check_min_out);
254     }
255 
256 //  Mixed positive and negative numbers
257     {
258         BOOST_CXX14_CONSTEXPR bool check_inside  = (5   == ba::clamp (   5, -10, 10 ));
259         BOOST_CHECK(check_inside);
260         BOOST_CXX14_CONSTEXPR bool check_min     = (-10 == ba::clamp ( -10, -10, 10 ));
261         BOOST_CHECK(check_min);
262         BOOST_CXX14_CONSTEXPR bool check_min_out = (-10 == ba::clamp ( -15, -10, 10 ));
263         BOOST_CHECK(check_min_out);
264         BOOST_CXX14_CONSTEXPR bool check_max     = (10  == ba::clamp (  10, -10, 10 ));
265         BOOST_CHECK(check_max);
266         BOOST_CXX14_CONSTEXPR bool check_max_out = (10  == ba::clamp (  15, -10, 10 ));
267         BOOST_CHECK(check_max_out);
268     }
269 //  Unsigned
270     {
271         BOOST_CXX14_CONSTEXPR bool check_inside  = (5U  == ba::clamp (  5U, 1U, 10U ));
272         BOOST_CHECK(check_inside);
273         BOOST_CXX14_CONSTEXPR bool check_min     = (1U  == ba::clamp (  1U, 1U, 10U ));
274         BOOST_CHECK(check_min);
275         BOOST_CXX14_CONSTEXPR bool check_min_out = (1U  == ba::clamp (  0U, 1U, 10U ));
276         BOOST_CHECK(check_min_out);
277         BOOST_CXX14_CONSTEXPR bool check_max     = (10U == ba::clamp ( 10U, 1U, 10U ));
278         BOOST_CHECK(check_max);
279         BOOST_CXX14_CONSTEXPR bool check_max_out = (10U == ba::clamp ( 15U, 1U, 10U ));
280         BOOST_CHECK(check_max_out);
281     }
282 //  Mixed (1)
283     {
284         BOOST_CXX14_CONSTEXPR bool check_inside  = (5U  == ba::clamp (  5U, 1,  10 ));
285         BOOST_CHECK(check_inside);
286         BOOST_CXX14_CONSTEXPR bool check_min     = (1U  == ba::clamp (  1U, 1,  10 ));
287         BOOST_CHECK(check_min);
288         BOOST_CXX14_CONSTEXPR bool check_min_out = (1U  == ba::clamp (  0U, 1,  10 ));
289         BOOST_CHECK(check_min_out);
290         BOOST_CXX14_CONSTEXPR bool check_max     = (10U == ba::clamp ( 10U, 1,  10 ));
291         BOOST_CHECK(check_max);
292         BOOST_CXX14_CONSTEXPR bool check_max_out = (10U == ba::clamp ( 15U, 1,  10 ));
293         BOOST_CHECK(check_max_out);
294     }
295 //  Mixed (3)
296     {
297         BOOST_CXX14_CONSTEXPR bool check_inside  = (5U  == ba::clamp (  5U, 1,  10. ));
298         BOOST_CHECK(check_inside);
299         BOOST_CXX14_CONSTEXPR bool check_min     = (1U  == ba::clamp (  1U, 1,  10. ));
300         BOOST_CHECK(check_min);
301         BOOST_CXX14_CONSTEXPR bool check_min_out = (1U  == ba::clamp (  0U, 1,  10. ));
302         BOOST_CHECK(check_min_out);
303         BOOST_CXX14_CONSTEXPR bool check_max     = (10U == ba::clamp ( 10U, 1,  10. ));
304         BOOST_CHECK(check_max);
305         BOOST_CXX14_CONSTEXPR bool check_max_out = (10U == ba::clamp ( 15U, 1,  10. ));
306         BOOST_CHECK(check_max_out);
307     }
308     {
309         BOOST_CXX14_CONSTEXPR short foo = 50;
310         BOOST_CXX14_CONSTEXPR bool check_float   = ( 56    == ba::clamp ( foo, 56.9, 129 ));
311         BOOST_CHECK(check_float);
312         BOOST_CXX14_CONSTEXPR bool check_over    = ( 24910 == ba::clamp ( foo, 12345678, 123456999 ));
313         BOOST_CHECK(check_over);
314     }
315 }
316 
BOOST_AUTO_TEST_CASE(test_main)317 BOOST_AUTO_TEST_CASE( test_main )
318 {
319     test_ints ();
320     test_floats ();
321     test_custom ();
322 
323     test_int_range ();
324 
325     test_constexpr ();
326 //    test_float_range ();
327 //    test_custom_range ();
328 }
329