clamp_test.cpp 14 KB

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