range.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. #include "simple/support/range.hpp"
  2. #include <cassert>
  3. #include <random>
  4. #include <iostream>
  5. #include <algorithm>
  6. using namespace simple::support;
  7. void Validity()
  8. {
  9. range valid_range{-13,31};
  10. assert(valid_range.valid());
  11. valid_range.fix();
  12. assert(valid_range.valid());
  13. assert(valid_range.fixed() == valid_range);
  14. assert(valid_range.fixed().valid());
  15. range invalid_range{valid_range.upper(), valid_range.lower()};
  16. const range const_invalid_range = invalid_range;
  17. assert(!invalid_range.valid());
  18. assert(!const_invalid_range.valid());
  19. assert(invalid_range.fixed().valid());
  20. assert(invalid_range.fixed() == valid_range);
  21. assert(!invalid_range.valid());
  22. invalid_range.fix();
  23. const range const_valid_range = const_invalid_range.fix();
  24. assert(invalid_range.valid());
  25. assert(invalid_range == valid_range);
  26. assert(const_valid_range.valid());
  27. assert(const_valid_range == valid_range);
  28. assert(( const_valid_range == range{31,-13}.fix() ));
  29. }
  30. void SetLikePredicates()
  31. {
  32. range r{-13,31};
  33. assert(contains(r, 2));
  34. assert(!contains(r, r.lower()));
  35. assert(!contains(r, 45));
  36. assert(!contains(r, r.upper()));
  37. assert(intersects(r, 12));
  38. assert(!intersects(r, 42));
  39. assert(intersects(r, r.lower()));
  40. assert(intersects(r, r.upper()));
  41. assert(intersects_lower(r, 13));
  42. assert(!intersects_lower(r, 41));
  43. assert(intersects_lower(r, r.lower()));
  44. assert(!intersects_lower(r, r.upper()));
  45. assert(intersects_upper(r, 14));
  46. assert(!intersects_upper(r, 40));
  47. assert(!intersects_upper(r, r.lower()));
  48. assert(intersects_upper(r, r.upper()));
  49. assert(contains(r, {12, 21}));
  50. assert(!contains(r, {-21, 53}));
  51. assert(!contains(r, {r.lower(), 0}));
  52. assert(!contains(r, {0, r.upper()}));
  53. assert(!contains(r, r));
  54. assert(covers(r, {12, 21}));
  55. assert(!covers(r, {-21, 53}));
  56. assert(covers(r, {r.lower(), 0}));
  57. assert(!covers(r, {r.lower(), 53}));
  58. assert(covers(r, {0, r.upper()}));
  59. assert(!covers(r, {-21, r.upper()}));
  60. assert(covers(r, r));
  61. assert(overlaps(r, {12, 21}));
  62. assert(overlaps(r, {-21, 53}));
  63. assert(overlaps(r, {r.lower(), 0}));
  64. assert(overlaps(r, {r.lower(), 53}));
  65. assert(overlaps(r, {0, r.upper()}));
  66. assert(overlaps(r, {-21, r.upper()}));
  67. assert(!overlaps(r, {r.upper(), 102}));
  68. assert(!overlaps(r, {-102, r.lower()}));
  69. assert(overlaps(r, r));
  70. assert(!overlaps(r, {67, 102}));
  71. assert(!overlaps(r, {-67, -102}));
  72. assert(intersects(r, {12, 21}));
  73. assert(intersects(r, {-21, 53}));
  74. assert(intersects(r, {r.lower(), 0}));
  75. assert(intersects(r, {r.lower(), 53}));
  76. assert(intersects(r, {0, r.upper()}));
  77. assert(intersects(r, {-21, r.upper()}));
  78. assert(intersects(r, {r.upper(), 102}));
  79. assert(intersects(r, {-102, r.lower()}));
  80. assert(intersects(r, r));
  81. assert(!intersects(r, {67, 102}));
  82. assert(!intersects(r, {-67, -102}));
  83. assert(( intersection(r, {12,56}) == range{12,31} ));
  84. assert(( r != range{12,31} ));
  85. assert(( intersection(r, {12,22}) == range{12,22} ));
  86. assert(( r != range{12,22} ));
  87. assert(( intersection(r, {-31,13}) == range{-13,13} ));
  88. assert(( r != range{-13,13} ));
  89. assert(( !intersection(r, {-31,-21}).valid() ));
  90. assert(( !intersection(r, {32,52}).valid() ));
  91. r.intersect({12,56});
  92. assert(( r == range{12,31} ));
  93. r.intersect({12,22});
  94. assert(( r == range{12,22} ));
  95. r.intersect({-31,13});
  96. assert(( r == range{12,13} ));
  97. }
  98. void Clamping()
  99. {
  100. assert(13 == clamp(44, {-13, 13}));
  101. assert(-13 == clamp(-44, {-13, 13}));
  102. int a = 44;
  103. clamp_in_place(a, {-13, 13});
  104. assert(13 == a);
  105. assert((clamp(range{-13, 13}, {-3, 3}) == range{-3, 3}));
  106. assert((clamp(range{-13, 2}, {-3, 3}) == range{-3, 2}));
  107. assert((clamp(range{0, 2}, {-3, 3}) == range{0, 2}));
  108. // clang version 7.0.0-svn345923-1~exp1~20181102032948.33 chokes on these without the bool casts
  109. range b{-13, 13};
  110. clamp_in_place(b, {-10, 10});
  111. assert(bool(range{-10, 10} == b));
  112. clamp_in_place(b, {-20, 5});
  113. assert(bool(range{-10, 5} == b));
  114. clamp_in_place(b, {-4, 50});
  115. assert(bool(range{-4, 5} == b));
  116. clamp_in_place(b, {-40, 50});
  117. assert(bool(range{-4, 5} == b));
  118. }
  119. void SubRange()
  120. {
  121. range rng {0, 9};
  122. range sub_rng{3, 8};
  123. range sub_rng_2{5, 9};
  124. range sub_rng_3{0, 5};
  125. assert( sub_rng == rng.sub_range(range{3, 8}) );
  126. assert( sub_rng_2 == rng.sub_range(range{5, 800}) );
  127. assert( sub_rng_3 == rng.sub_range(range{-105, 5}) );
  128. assert( rng == rng.sub_range(range{-105, 105}) );
  129. auto limit = range<int>::limit();
  130. range inc{-1,1};
  131. assert( inc == inc.sub_range(limit) );
  132. range near_limit {limit.upper(), limit.upper()};
  133. near_limit -= 100;
  134. near_limit.upper() += 50;
  135. range overflow {25, 125};
  136. range sub_near_limit = near_limit;
  137. sub_near_limit.lower() += 25;
  138. assert( sub_near_limit == near_limit.sub_range(overflow) );
  139. }
  140. template <typename Larger, typename Smaller>
  141. void limits_check_containment(std::mt19937_64 & generator)
  142. {
  143. std::uniform_int_distribution<Smaller> uid(std::numeric_limits<Smaller>::lowest());
  144. constexpr auto bounds = range<Larger>::limit();
  145. assert( bounds.lower() == std::numeric_limits<Larger>::lowest() &&
  146. bounds.upper() == std::numeric_limits<Larger>::max() );
  147. bool out_of_bounds = false;
  148. for(int i = 0; i < 100'000; ++i)
  149. if( out_of_bounds |= (!bounds.intersects(uid(generator))), out_of_bounds )
  150. break;
  151. assert(!out_of_bounds);
  152. }
  153. template <typename Larger, typename Smaller>
  154. void limits_check_containment_f(std::mt19937_64 & generator)
  155. {
  156. std::uniform_real_distribution<Smaller> uid(
  157. std::numeric_limits<Smaller>::min(),
  158. std::numeric_limits<Smaller>::max());
  159. std::uniform_real_distribution<Smaller> sign(-1,1);
  160. constexpr auto bounds = range<Larger>::limit();
  161. assert( bounds.lower() == std::numeric_limits<Larger>::lowest() &&
  162. bounds.upper() == std::numeric_limits<Larger>::max() );
  163. bool out_of_bounds = false;
  164. for(int i = 0; i < 100'000; ++i)
  165. {
  166. auto value = std::copysign(uid(generator), sign(generator));
  167. if( out_of_bounds |= !bounds.intersects(value), out_of_bounds )
  168. break;
  169. }
  170. assert(!out_of_bounds);
  171. }
  172. void Limit()
  173. {
  174. auto seed = std::random_device{}();
  175. std::cout << "Range limit random test seed: " << std::hex << std::showbase << seed << std::endl;
  176. std::mt19937_64 generator(seed);
  177. limits_check_containment<signed char, signed char>(generator);
  178. limits_check_containment<signed short, signed char>(generator);
  179. limits_check_containment<signed short, signed short>(generator);
  180. limits_check_containment<signed int, signed short>(generator);
  181. limits_check_containment<signed int, signed int>(generator);
  182. limits_check_containment<signed long, signed int>(generator);
  183. limits_check_containment<signed long, signed long>(generator);
  184. limits_check_containment<signed long long, signed long>(generator);
  185. limits_check_containment<signed long long, signed long long>(generator);
  186. limits_check_containment_f<float, float>(generator);
  187. limits_check_containment_f<double, float>(generator);
  188. limits_check_containment_f<double, double>(generator);
  189. limits_check_containment_f<long double, double>(generator);
  190. limits_check_containment_f<long double, long double>(generator);
  191. if(std::numeric_limits<signed long long>::lowest() < std::numeric_limits<signed char>::lowest())
  192. assert( !range<signed char>::limit().contains(std::numeric_limits<signed long long>::lowest()) );
  193. if(std::numeric_limits<signed long long>::max() > std::numeric_limits<signed char>::max())
  194. assert( !range<signed char>::limit().contains(std::numeric_limits<signed long long>::max()) );
  195. }
  196. void Arithmetic()
  197. {
  198. {range<float> r{-1,1};
  199. assert(( r + 0.25 == range<double>{-0.75,1.25} ));
  200. r += 0.25;
  201. assert(( r == range<float>{-0.75,1.25} ));
  202. }
  203. {range<float> r{-1,1};
  204. assert(( r - 0.25 == range<double>{-1.25,0.75} ));
  205. r -= 0.25;
  206. assert(( r == range<float>{-1.25,0.75} ));
  207. }
  208. {range<float> r{-1,1};
  209. assert(( r * 13 == range<float>{-13,13} ));
  210. r *= 13;
  211. assert(( r == range<float>{-13,13} ));
  212. }
  213. {range<float> r{-1,1};
  214. assert(( r / 2 == range<float>{-0.5,0.5} ));
  215. r /= 2;
  216. assert(( r == range<float>{-0.5,0.5} ));
  217. }
  218. }
  219. void Iterator()
  220. {
  221. static_assert(std::is_same_v<int*, range<int*>::iterator>);
  222. static_assert(std::is_same_v<void, range<int>::iterator>);
  223. }
  224. constexpr bool Constexprness()
  225. {
  226. range<int> v{};
  227. if(v == v)
  228. {
  229. v.lower() = 3;
  230. v.upper() = 1;
  231. };
  232. if(!v.valid())
  233. v.fix();
  234. const range<int> cv = v;
  235. v = cv.fix();
  236. v = range<int>{}.fix();
  237. clamp_in_place(v, {12,13});
  238. int i = 1;
  239. clamp_in_place(i, v);
  240. clamp(v,v);
  241. clamp(i,v);
  242. contains(v, i);
  243. contains(v, v);
  244. covers(v, v);
  245. intersects(v, i);
  246. intersects(v, v);
  247. overlaps(v, v);
  248. intersects_lower(v, i);
  249. intersects_upper(v, i);
  250. v.contains(i);
  251. v.contains(v);
  252. v.covers(v);
  253. v.intersects(i);
  254. v.intersects(v);
  255. v.overlaps(v);
  256. v.intersects_lower(i);
  257. v.intersects_upper(i);
  258. (void)v.sub_range(v);
  259. v += 1;
  260. v = v+1;
  261. v -= 1;
  262. v = v-1;
  263. v *= 1;
  264. v = v*1;
  265. v /= 1;
  266. v = v/1;
  267. return true;
  268. }
  269. void UpperRange()
  270. {
  271. auto valid_upper_range = make_range_upper<std::integral_constant<int,-3>>(12);
  272. assert(valid_upper_range.valid());
  273. assert(( valid_upper_range + 3 == range{0,15} ));
  274. struct { int x; } one_int;
  275. static_assert(sizeof(valid_upper_range) == sizeof(one_int));
  276. auto invalid_upper_range = make_range_upper<std::integral_constant<int,13>>(12);
  277. assert(!invalid_upper_range.valid());
  278. assert(( invalid_upper_range.fixed() == range{12,13} ));
  279. // TODO: rest of const stuff should work
  280. }
  281. void ImplicitConversion()
  282. {
  283. {
  284. int i[] = {1,2,3};
  285. range r{i + 0, i + 3};
  286. range<const int*> view = r;
  287. assert( std::equal(view.begin(), view.end(), i+0, i+3) );
  288. assert( view.begin() == i + 0 );
  289. assert( view.begin() + 1 == i + 1 );
  290. assert( view.begin() + 2 == i + 2 );
  291. assert( view.end() == i + 3 );
  292. *(r.begin() + 1) = 99;
  293. assert( *(view.begin() + 1) == 99 );
  294. range r2{i + 1, i + 3};
  295. view = r2;
  296. assert( std::equal(view.begin(), view.end(), i+1, i+3) );
  297. assert( view.begin() == i + 1 );
  298. assert( view.begin() + 1 == i + 2 );
  299. assert( view.end() == i + 3 );
  300. }
  301. }
  302. int main()
  303. {
  304. Validity();
  305. SetLikePredicates();
  306. Clamping();
  307. SubRange();
  308. Limit();
  309. Arithmetic();
  310. static_assert(Constexprness());
  311. UpperRange();
  312. ImplicitConversion();
  313. return 0;
  314. }