main.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. // Copyright Louis Dionne 2013-2017
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  4. #include <boost/hana/and.hpp>
  5. #include <boost/hana/assert.hpp>
  6. #include <boost/hana/comparing.hpp>
  7. #include <boost/hana/div.hpp>
  8. #include <boost/hana/equal.hpp>
  9. #include <boost/hana/eval_if.hpp>
  10. #include <boost/hana/greater.hpp>
  11. #include <boost/hana/greater_equal.hpp>
  12. #include <boost/hana/if.hpp>
  13. #include <boost/hana/less.hpp>
  14. #include <boost/hana/less_equal.hpp>
  15. #include <boost/hana/max.hpp>
  16. #include <boost/hana/min.hpp>
  17. #include <boost/hana/minus.hpp>
  18. #include <boost/hana/mod.hpp>
  19. #include <boost/hana/mult.hpp>
  20. #include <boost/hana/negate.hpp>
  21. #include <boost/hana/not.hpp>
  22. #include <boost/hana/not_equal.hpp>
  23. #include <boost/hana/one.hpp>
  24. #include <boost/hana/or.hpp>
  25. #include <boost/hana/ordering.hpp>
  26. #include <boost/hana/plus.hpp>
  27. #include <boost/hana/power.hpp>
  28. #include <boost/hana/tuple.hpp>
  29. #include <boost/hana/while.hpp>
  30. #include <boost/hana/zero.hpp>
  31. #include <laws/base.hpp>
  32. #include <laws/comparable.hpp>
  33. #include <laws/euclidean_ring.hpp>
  34. #include <laws/group.hpp>
  35. #include <laws/logical.hpp>
  36. #include <laws/monoid.hpp>
  37. #include <laws/orderable.hpp>
  38. #include <support/cnumeric.hpp>
  39. #include <support/numeric.hpp>
  40. #include <cstdlib>
  41. #include <vector>
  42. namespace hana = boost::hana;
  43. struct invalid {
  44. template <typename T>
  45. operator T const() { std::abort(); }
  46. };
  47. int main() {
  48. //////////////////////////////////////////////////////////////////////////
  49. // Comparable
  50. //////////////////////////////////////////////////////////////////////////
  51. {
  52. hana::test::_injection<0> f{};
  53. auto x = numeric(1);
  54. auto y = numeric(2);
  55. // equal
  56. {
  57. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(x, x));
  58. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::equal(x, y)));
  59. }
  60. // not_equal
  61. {
  62. BOOST_HANA_CONSTEXPR_CHECK(hana::not_equal(x, y));
  63. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::not_equal(x, x)));
  64. }
  65. // comparing
  66. {
  67. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  68. hana::comparing(f)(x, x),
  69. hana::equal(f(x), f(x))
  70. ));
  71. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  72. hana::comparing(f)(x, y),
  73. hana::equal(f(x), f(y))
  74. ));
  75. }
  76. }
  77. //////////////////////////////////////////////////////////////////////////
  78. // Orderable
  79. //////////////////////////////////////////////////////////////////////////
  80. {
  81. auto ord = numeric;
  82. // _injection is also monotonic
  83. hana::test::_injection<0> f{};
  84. // less
  85. {
  86. BOOST_HANA_CONSTEXPR_CHECK(hana::less(ord(0), ord(1)));
  87. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::less(ord(0), ord(0))));
  88. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::less(ord(1), ord(0))));
  89. }
  90. // less_equal
  91. {
  92. BOOST_HANA_CONSTEXPR_CHECK(hana::less_equal(ord(0), ord(1)));
  93. BOOST_HANA_CONSTEXPR_CHECK(hana::less_equal(ord(0), ord(0)));
  94. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::less_equal(ord(1), ord(0))));
  95. }
  96. // greater_equal
  97. {
  98. BOOST_HANA_CONSTEXPR_CHECK(hana::greater_equal(ord(1), ord(0)));
  99. BOOST_HANA_CONSTEXPR_CHECK(hana::greater_equal(ord(0), ord(0)));
  100. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::greater_equal(ord(0), ord(1))));
  101. }
  102. // greater
  103. {
  104. BOOST_HANA_CONSTEXPR_CHECK(hana::greater(ord(1), ord(0)));
  105. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::greater(ord(0), ord(0))));
  106. BOOST_HANA_CONSTEXPR_CHECK(hana::not_(hana::greater(ord(0), ord(1))));
  107. }
  108. // max
  109. {
  110. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  111. hana::max(ord(0), ord(0)), ord(0)
  112. ));
  113. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  114. hana::max(ord(1), ord(0)), ord(1)
  115. ));
  116. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  117. hana::max(ord(0), ord(1)), ord(1)
  118. ));
  119. }
  120. // min
  121. {
  122. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  123. hana::min(ord(0), ord(0)),
  124. ord(0)
  125. ));
  126. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  127. hana::min(ord(1), ord(0)),
  128. ord(0)
  129. ));
  130. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  131. hana::min(ord(0), ord(1)),
  132. ord(0)
  133. ));
  134. }
  135. // ordering
  136. {
  137. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  138. hana::ordering(f)(ord(1), ord(0)),
  139. hana::less(f(ord(1)), f(ord(0)))
  140. ));
  141. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  142. hana::ordering(f)(ord(0), ord(1)),
  143. hana::less(f(ord(0)), f(ord(1)))
  144. ));
  145. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  146. hana::ordering(f)(ord(0), ord(0)),
  147. hana::less(f(ord(0)), f(ord(0)))
  148. ));
  149. }
  150. }
  151. //////////////////////////////////////////////////////////////////////////
  152. // Monoid
  153. //////////////////////////////////////////////////////////////////////////
  154. {
  155. constexpr int x = 2, y = 3;
  156. // zero
  157. {
  158. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  159. hana::zero<Numeric>(), numeric(0)
  160. ));
  161. }
  162. // plus
  163. {
  164. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  165. hana::plus(numeric(x), numeric(y)),
  166. numeric(x + y)
  167. ));
  168. }
  169. }
  170. //////////////////////////////////////////////////////////////////////////
  171. // Group
  172. //////////////////////////////////////////////////////////////////////////
  173. {
  174. constexpr int x = 2, y = 3;
  175. // minus
  176. {
  177. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  178. hana::minus(numeric(x), numeric(y)),
  179. numeric(x - y)
  180. ));
  181. }
  182. // negate
  183. {
  184. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  185. hana::negate(numeric(x)),
  186. numeric(-x)
  187. ));
  188. }
  189. }
  190. //////////////////////////////////////////////////////////////////////////
  191. // Ring
  192. //////////////////////////////////////////////////////////////////////////
  193. {
  194. constexpr int x = 2, y = 3;
  195. // one
  196. {
  197. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  198. hana::one<Numeric>(),
  199. numeric(1)
  200. ));
  201. }
  202. // mult
  203. {
  204. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  205. hana::mult(numeric(x), numeric(y)),
  206. numeric(x * y)
  207. ));
  208. }
  209. // power
  210. {
  211. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  212. hana::power(numeric(x), hana::zero<CNumeric<int>>()),
  213. hana::one<Numeric>()
  214. ));
  215. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  216. hana::power(numeric(x), hana::one<CNumeric<int>>()),
  217. numeric(x)
  218. ));
  219. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  220. hana::power(numeric(x), cnumeric<int, 2>),
  221. hana::mult(numeric(x), numeric(x))
  222. ));
  223. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  224. hana::power(numeric(x), cnumeric<int, 3>),
  225. hana::mult(hana::mult(numeric(x), numeric(x)), numeric(x))
  226. ));
  227. }
  228. }
  229. //////////////////////////////////////////////////////////////////////////
  230. // EuclideanRing
  231. //////////////////////////////////////////////////////////////////////////
  232. {
  233. constexpr int x = 6, y = 3, z = 4;
  234. // div
  235. {
  236. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  237. hana::div(numeric(x), numeric(y)),
  238. numeric(x / y)
  239. ));
  240. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  241. hana::div(numeric(x), numeric(z)),
  242. numeric(x/ z)
  243. ));
  244. }
  245. // mod
  246. {
  247. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  248. hana::mod(numeric(x), numeric(y)),
  249. numeric(x % y)
  250. ));
  251. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  252. hana::mod(numeric(x), numeric(z)),
  253. numeric(x % z)
  254. ));
  255. }
  256. }
  257. //////////////////////////////////////////////////////////////////////////
  258. // Logical
  259. //////////////////////////////////////////////////////////////////////////
  260. {
  261. auto logical = numeric;
  262. auto comparable = numeric;
  263. // not_
  264. {
  265. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  266. hana::not_(logical(true)),
  267. logical(false)
  268. ));
  269. }
  270. // and_
  271. {
  272. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  273. hana::and_(logical(true)),
  274. logical(true)
  275. ));
  276. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  277. hana::and_(logical(false)),
  278. logical(false)
  279. ));
  280. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  281. hana::and_(logical(true), logical(true)),
  282. logical(true)
  283. ));
  284. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  285. hana::and_(logical(true), logical(false)),
  286. logical(false)
  287. ));
  288. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  289. hana::and_(logical(false), invalid{}),
  290. logical(false)
  291. ));
  292. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  293. hana::and_(logical(true), logical(true), logical(true)),
  294. logical(true)
  295. ));
  296. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  297. hana::and_(logical(true), logical(true), logical(false)),
  298. logical(false)
  299. ));
  300. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  301. hana::and_(logical(true), logical(false), invalid{}),
  302. logical(false)
  303. ));
  304. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  305. hana::and_(logical(false), invalid{}, invalid{}),
  306. logical(false)
  307. ));
  308. }
  309. // or_
  310. {
  311. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  312. hana::or_(logical(true)),
  313. logical(true)
  314. ));
  315. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  316. hana::or_(logical(false)),
  317. logical(false)
  318. ));
  319. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  320. hana::or_(logical(false), logical(false)),
  321. logical(false)
  322. ));
  323. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  324. hana::or_(logical(false), logical(true)),
  325. logical(true)
  326. ));
  327. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  328. hana::or_(logical(true), invalid{}),
  329. logical(true)
  330. ));
  331. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  332. hana::or_(logical(false), logical(false), logical(false)),
  333. logical(false)
  334. ));
  335. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  336. hana::or_(logical(false), logical(false), logical(true)),
  337. logical(true)
  338. ));
  339. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  340. hana::or_(logical(false), logical(true), invalid{}),
  341. logical(true)
  342. ));
  343. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  344. hana::or_(logical(true), invalid{}, invalid{}),
  345. logical(true)
  346. ));
  347. }
  348. // if_
  349. {
  350. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  351. hana::if_(logical(true), comparable(0), comparable(1)),
  352. comparable(0)
  353. ));
  354. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  355. hana::if_(logical(false), comparable(0), comparable(1)),
  356. comparable(1)
  357. ));
  358. }
  359. // eval_if
  360. {
  361. auto t = [=](auto) { return comparable(0); };
  362. auto e = [=](auto) { return comparable(1); };
  363. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  364. hana::eval_if(logical(true), t, e),
  365. comparable(0)
  366. ));
  367. BOOST_HANA_CONSTEXPR_CHECK(hana::equal(
  368. hana::eval_if(logical(false), t, e),
  369. comparable(1)
  370. ));
  371. }
  372. // while_
  373. {
  374. auto smaller_than = [](auto n) {
  375. return [n](auto v) { return v.size() < n; };
  376. };
  377. auto f = [](auto v) {
  378. v.push_back(v.size());
  379. return v;
  380. };
  381. BOOST_HANA_RUNTIME_CHECK(hana::equal(
  382. hana::while_(smaller_than(0u), std::vector<int>{}, f),
  383. std::vector<int>{}
  384. ));
  385. BOOST_HANA_RUNTIME_CHECK(hana::equal(
  386. hana::while_(smaller_than(1u), std::vector<int>{}, f),
  387. std::vector<int>{0}
  388. ));
  389. BOOST_HANA_RUNTIME_CHECK(hana::equal(
  390. hana::while_(smaller_than(2u), std::vector<int>{}, f),
  391. std::vector<int>{0, 1}
  392. ));
  393. BOOST_HANA_RUNTIME_CHECK(hana::equal(
  394. hana::while_(smaller_than(3u), std::vector<int>{}, f),
  395. std::vector<int>{0, 1, 2}
  396. ));
  397. BOOST_HANA_RUNTIME_CHECK(hana::equal(
  398. hana::while_(smaller_than(4u), std::vector<int>{}, f),
  399. std::vector<int>{0, 1, 2, 3}
  400. ));
  401. // Make sure it can be called with an lvalue state:
  402. std::vector<int> v{};
  403. BOOST_HANA_RUNTIME_CHECK(hana::equal(
  404. hana::while_(smaller_than(4u), v, f),
  405. std::vector<int>{0, 1, 2, 3}
  406. ));
  407. }
  408. // while_
  409. {
  410. auto less_than = [](auto n) {
  411. return [n](auto v) { return v.size() < n; };
  412. };
  413. auto f = [](auto v) {
  414. v.push_back(v.size());
  415. return v;
  416. };
  417. BOOST_HANA_RUNTIME_CHECK(hana::equal(
  418. hana::while_(less_than(0u), std::vector<int>{}, f),
  419. std::vector<int>{}
  420. ));
  421. BOOST_HANA_RUNTIME_CHECK(hana::equal(
  422. hana::while_(less_than(1u), std::vector<int>{}, f),
  423. std::vector<int>{0}
  424. ));
  425. BOOST_HANA_RUNTIME_CHECK(hana::equal(
  426. hana::while_(less_than(2u), std::vector<int>{}, f),
  427. std::vector<int>{0, 1}
  428. ));
  429. BOOST_HANA_RUNTIME_CHECK(hana::equal(
  430. hana::while_(less_than(3u), std::vector<int>{}, f),
  431. std::vector<int>{0, 1, 2}
  432. ));
  433. BOOST_HANA_RUNTIME_CHECK(hana::equal(
  434. hana::while_(less_than(4u), std::vector<int>{}, f),
  435. std::vector<int>{0, 1, 2, 3}
  436. ));
  437. // Make sure it can be called with an lvalue state:
  438. std::vector<int> v{};
  439. BOOST_HANA_RUNTIME_CHECK(hana::equal(
  440. hana::while_(less_than(4u), v, f),
  441. std::vector<int>{0, 1, 2, 3}
  442. ));
  443. }
  444. }
  445. }