point.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800
  1. #include "simple/geom/vector.hpp"
  2. #include "simple/geom/bool_algebra.hpp"
  3. #include <cmath>
  4. #include <cassert>
  5. #include <cstdio>
  6. using namespace simple;
  7. using geom::vector;
  8. using float4 = vector<float, 4>;
  9. using int4 = vector<int, 4>;
  10. void ZeroConstruction()
  11. {
  12. float4::array control{};
  13. float4 p{};
  14. float4 p2 = {};
  15. float4 p3 = float4();
  16. assert(control == static_cast<const float4::array>(p));
  17. assert(control == static_cast<const float4::array>(p2));
  18. assert(control == static_cast<const float4::array>(p3));
  19. assert(control == static_cast<const float4::array>(float4::zero()));
  20. // NOTE: can't really test for random garbage since random garbage can be anything, including all zeros
  21. // also UB, great -_-
  22. bool anyGarbage = false;
  23. std::array<float4, 100> garbagePile;
  24. for (auto& garbage : garbagePile)
  25. {
  26. anyGarbage |= (control != static_cast<float4::array>(garbage));
  27. if(anyGarbage) break;
  28. }
  29. assert(anyGarbage);
  30. }
  31. void EqualityComparison()
  32. {
  33. int4 p(1, 2, 3, 4);
  34. int4 p2(1, 2, 3, 4);
  35. int4 p3(4, 3, 2, 1);
  36. assert(p == p2);
  37. assert(p != p3);
  38. assert( vector(1,2,3,4,5) != vector(0,0,0,0,5) ); // at some point this wasn't the case, and no other test caught it -_-
  39. assert( !(vector(1,2,3,4,5) == vector(0,0,0,0,5)) );
  40. assert( ~(vector(1,2,3,4,5) == vector(0,0,0,0,5)) );
  41. }
  42. void OtherConstruction()
  43. {
  44. float4 p(1.0f, 2.0f, 3.0f, 4.0f);
  45. float4 p2{1.0f, 2.0f, 3.0f, 4.0f};
  46. float4 p3{{1.0f, 2.0f, 3.0f, 4.0f}};
  47. float4 p4{float4::array{1.0f, 2.0f, 3.0f, 4.0f}};
  48. float4 p5(float4::array{1.0f, 2.0f, 3.0f, 4.0f});
  49. float4 p6 = float4(int4(1, 2, 3, 4));
  50. float4 p7 {{1, 2, 3, 4}};
  51. float4 p8 (p7);
  52. float4 p9 = {p8};
  53. assert(p == p2);
  54. assert(p2 == p3);
  55. assert(p3 == p4);
  56. assert(p4 == p5);
  57. assert(p5 == p6);
  58. assert(p6 == p7);
  59. assert(p7 == p8);
  60. assert(p8 == p9);
  61. assert(p9 != float4::zero());
  62. static_assert(int4(1,1,1,1) == int4::one(), "");
  63. static_assert(int4(4,4,4,4) == int4::one(4), "");
  64. static_assert(float4(1.0f,1.0f,1.0f,1.0f) == float4::one(), "");
  65. static_assert(int4(1,0,0,0) == int4::i(), "");
  66. static_assert(int4(0,1,0,0) == int4::j(), "");
  67. static_assert(int4(0,0,1,0) == int4::k(), "");
  68. static_assert(int4(0,0,0,1) == int4::l(), "");
  69. static_assert(int4(4,0,0,0) == int4::i(4), "");
  70. static_assert(int4(0,4,0,0) == int4::j(4), "");
  71. static_assert(int4(0,0,4,0) == int4::k(4), "");
  72. static_assert(int4(0,0,0,4) == int4::l(4), "");
  73. static_assert(int4(-1,1,-1,-1) == int4::unit<1>(1,-1), "");
  74. }
  75. bool is_int3(vector<char, 3>) { return false; }
  76. bool is_int3(vector<int, 3>) { return true; }
  77. struct char_constructible
  78. {
  79. char a;
  80. char_constructible() {}
  81. explicit char_constructible(char a): a(a) {}
  82. bool operator==(char o) const { return o == a; };
  83. };
  84. void ImplicitConversion()
  85. {
  86. vector<char,3> c {'a','b','c'};
  87. vector<int,3> i{};
  88. i = c;
  89. assert(( i == vector{int('a'), int('b'), int('c')} ));
  90. assert(( i == vector{'a', 'b', 'c'} ));
  91. assert(( is_int3(i) ));
  92. assert(( not is_int3(c) ));
  93. vector<char_constructible, 3> b{};
  94. // b = c; // TODO: need no-compile tests
  95. b = vector<char_constructible,3>{c};
  96. assert(( b == vector{'a', 'b', 'c'} ));
  97. }
  98. void Transformation()
  99. {
  100. float4 p {1.3f, 1.5f, 2.1f, 4.6f};
  101. int4 p2 {1, 2, 2, 5};
  102. int4 p3 {1, 1, 2, 4};
  103. assert( p2 == p.transformed( [](auto x) -> int { return std::round(x); } ));
  104. assert( p3 == p.transformed( [](auto x) { return int(x); } ));
  105. }
  106. void Mixing()
  107. {
  108. int4 p {1, 2, 3, 4};
  109. assert( (geom::vector<int, 2>{1,2} == p.mix<0,1>()) );
  110. assert( (geom::vector<int, 2>{1,2} == p.mix<2>({0,1})) );
  111. assert( (geom::vector<int, 3>{2,3,4} == p.mix<1,2,3>()) );
  112. assert( (geom::vector<int, 3>{2,3,4} == p.mix<3>({1,2,3})) );
  113. assert( (geom::vector<int, 6>{3,3,3,2,2,1} == p.mix<2,2,2,1,1,0>()) );
  114. assert( (geom::vector<int, 6>{3,3,3,2,2,1} == p.mix<6>({2,2,2,1,1,0})) );
  115. assert( (geom::vector<int, 3>{1,2,0} == p.mix<0,1,4>(0)) );
  116. assert( (geom::vector<int, 3>{1,2,0} == p.mix<3>({0,1,4}, 0)) );
  117. assert( (vector(1,2) == p.first<2>()) );
  118. assert( (vector(2,3,4) == p.last<3>()) );
  119. assert( vector(1,2,3,4,5,6) == p.concat(vector(5,6)) );
  120. assert( vector(-1,0,1,2,3,4) == vector(-1,0).concat(p) );
  121. vector<int, 2, std::index_sequence<1,0>> revector{2,3};
  122. assert(( vector(0,1).concat(revector) == vector<int, 4, std::index_sequence<0,1,3,2>>(0,1,2,3) ));
  123. assert(( revector.concat(vector(4,5,6)) == vector<int, 5, std::index_sequence<1,0,2,3,4>>(2,3,4,5,6) ));
  124. }
  125. void MultidimensionalElementAccess()
  126. {
  127. auto spiral_walk = [](auto room)
  128. {
  129. constexpr auto csize = decltype(room)::meta::template dimensions<int>;
  130. vector <
  131. std::remove_reference_t<decltype(room[csize-1])>,
  132. csize.x()*csize.y()
  133. > ret{};
  134. auto size = csize;
  135. size_t i = 0;
  136. auto direction = 1;
  137. auto begin = vector(-1,0);
  138. while(size > vector(0,0))
  139. {
  140. auto end = begin + direction * (size - vector(0,1)) ;
  141. do
  142. {
  143. begin.x() += direction;
  144. ret[i++] = room[begin];
  145. }
  146. while(begin.x() != end.x());
  147. while(begin.y() != end.y())
  148. {
  149. begin.y() += direction;
  150. ret[i++] = room[begin];
  151. }
  152. //do
  153. --size;
  154. direction = -direction;
  155. }
  156. return ret;
  157. };
  158. assert( spiral_walk(vector(
  159. vector(1,2,3),
  160. vector(4,5,6),
  161. vector(7,8,9)
  162. )) == vector(1,2,3,6,9,8,7,4,5));
  163. assert( spiral_walk(vector(
  164. vector(1),
  165. vector(2)
  166. )) == vector(1,2));
  167. assert( spiral_walk(vector(
  168. vector(1)
  169. )) == vector(1));
  170. assert( spiral_walk(vector(
  171. vector(1,2)
  172. )) == vector(1,2));
  173. // // well clang really doesn't like zero size vectors so...
  174. // assert( spiral_walk(vector(
  175. // vector<int,0>()
  176. // )) == (vector<int,0>{}));
  177. //
  178. // assert( spiral_walk(vector(
  179. // vector<int,0>(),
  180. // vector<int,0>(),
  181. // vector<int,0>(),
  182. // vector<int,0>()
  183. // )) == (vector<int,0>{}));
  184. //
  185. // assert( spiral_walk(vector<vector<int,10>,0>()
  186. // ) == (vector<int,0>{}));
  187. assert( spiral_walk(vector(
  188. vector(1,2),
  189. vector(3,4)
  190. )) == vector(1,2,4,3));
  191. assert( spiral_walk(vector(
  192. vector( 1, 2, 3, 4),
  193. vector( 5, 6, 7, 8),
  194. vector( 9,10,11,12)
  195. )) == vector(1,2,3,4,8,12,11,10,9,5,6,7));
  196. assert( spiral_walk(vector(
  197. vector( 1, 2, 3),
  198. vector( 4, 5, 6),
  199. vector( 7, 8, 9),
  200. vector(10,11,12)
  201. )) == vector(1,2,3,6,9,12,11,10,7,4,5,8));
  202. assert( spiral_walk(vector(
  203. vector( 1, 2, 3, 4),
  204. vector( 5, 6, 7, 8),
  205. vector( 9,10,11,12),
  206. vector(13,14,15,16)
  207. )) == vector(1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10));
  208. }
  209. void RangeBasedLooping()
  210. {
  211. const float4 p{1.0f, 2.0f, 3.0f, 4.0f};
  212. float4 p2;
  213. int num = 1;
  214. for(auto& coord : p2)
  215. {
  216. coord = num;
  217. num += 1;
  218. }
  219. assert(p == p2);
  220. num = 1;
  221. for(auto coord : p)
  222. {
  223. assert(coord == num);
  224. num += 1;
  225. }
  226. }
  227. void Arithmetic()
  228. {
  229. float4 p{{1, 2, 3, 4}};
  230. float4 p2 = p;
  231. float4 sum{{2, 4, 6, 8}};
  232. float4 inc{{2, 3, 4, 5}};
  233. float4 dec{{0, 1, 2, 3}};
  234. assert(p + p2 == sum);
  235. assert(p + 1 == inc);
  236. assert(1 + p == inc);
  237. assert(p - 1 == dec);
  238. assert(p - dec == float4::one());
  239. assert(p - p2 == float4::zero());
  240. assert(-p == float4(int4(-1, -2, -3, -4)));
  241. assert(p2++ == p);
  242. assert(p2 == p+1);
  243. p2 = p;
  244. assert(++p2 == p+1);
  245. assert(p2 == p+1);
  246. p2 = p;
  247. assert(p2-- == p);
  248. assert(p2 == p-1);
  249. p2 = p;
  250. assert(--p2 == p-1);
  251. assert(p2 == p-1);
  252. p2 = p;
  253. p2 += p;
  254. assert(p2 == p+p);
  255. p2 -= p;
  256. assert(p2 == p);
  257. p2 -= p;
  258. assert(p2 == float4::zero());
  259. p2 = p;
  260. p2 += 3;
  261. assert(p2 == p + 3);
  262. p2 -= 1.5f;
  263. assert(p2 == p + 1.5f);
  264. assert( p + p == p * 2);
  265. assert( p * p == float4(1.0f, 4.0f, 9.0f, 16.0f));
  266. assert( (p + p)/2 == p);
  267. assert( p / (float4::one() * 2) == float4(0.5f, 1.0f, 1.5f, 2.0f) );
  268. assert( p / p == float4::one());
  269. p2 = p;
  270. p2 *= 2;
  271. assert(p2 == p*2);
  272. p2 *= p;
  273. assert(p2 == p*p*2);
  274. p2 /= p;
  275. assert(p2 == p*2);
  276. p2 /= 2;
  277. assert(p2 == p);
  278. p = {1.f, 2.f, 3.f, 4.f};
  279. p2 = {1.f, 0.f, 1.f, 0.f};
  280. float4 p3 = {1.f, 2.f, 0.f, 1.f};
  281. assert(p%2.f == p2);
  282. assert(p%float4::one(2.f) == p2);
  283. p %= 3.f;
  284. assert(p == p3);
  285. p = {1.f, 2.f, 3.f, 4.f};
  286. p3 = {4.f, 5.f, 7.f, 9.f};
  287. p2 = {3.f, 3.f, 4.f, 5.f};
  288. assert(p3 % p2 == p);
  289. p3 %= p2;
  290. assert(p3 == p);
  291. }
  292. // discrete? what?
  293. // TODO: used unsigned and if constexpr guard implied sizes
  294. void DiscreteArithmetic()
  295. {
  296. // %
  297. int4 p(1, 2, 3, 4);
  298. int4 p2(1, 0, 1, 0);
  299. int4 p3(1, 2, 0, 1);
  300. assert(p%2 == p2);
  301. p %= 3;
  302. assert(p == p3);
  303. p = {1, 2, 3, 4};
  304. p3 = {4, 5, 7, 9};
  305. p2 = {3, 3, 4, 5};
  306. assert(p3 % p2 == p);
  307. p3 %= p2;
  308. assert(p3 == p);
  309. // <<
  310. p = {0xA, 0xB0, 0xC00, 0xD000};
  311. p2 = {0xA0, 0xB00, 0xC000, 0xD0000};
  312. assert((p << 4) == p2);
  313. p <<= 4;
  314. assert(p == p2);
  315. p = {0xA, 0xB0, 0xC00, 0xD000};
  316. p2 = {0xA, 0xB, 0xC, 0xD};
  317. p3 = {0, 1, 2, 3};
  318. assert((p2 << (p3*4)) == p);
  319. p2 <<= (p3*4);
  320. assert(p2 == p);
  321. // >>
  322. p = {0xA, 0xB0, 0xC00, 0xD000};
  323. p2 = {0xA0, 0xB00, 0xC000, 0xD0000};
  324. assert((p2 >> 4) == p);
  325. p2 >>= 4;
  326. assert(p == p2);
  327. p = {0xA, 0xB0, 0xC00, 0xD000};
  328. p2 = {0xA, 0xB, 0xC, 0xD};
  329. p3 = {0, 1, 2, 3};
  330. assert((p >> (p3*4)) == p2);
  331. p >>= (p3*4);
  332. assert(p == p2);
  333. // &
  334. p = {0b0101, 0b1010, 0b1111, 0b0000};
  335. p2 = {0b0101, 0b0000, 0b0101, 0b0000};
  336. assert((p & 0b101) == p2);
  337. p &= 0b0101;
  338. assert(p == p2);
  339. p = {0b0101, 0b1010, 0b1111, 0b0000};
  340. p2 = {0b0110, 0b0111, 0b1001, 0b1111};
  341. p3 = {0b0100, 0b0010, 0b1001, 0b0000};
  342. assert((p & p2) == p3);
  343. p &= p2;
  344. assert(p == p3);
  345. // |
  346. p = {0b0101, 0b1010, 0b1111, 0b0000};
  347. p2 = {0b0101, 0b1111, 0b1111, 0b0101};
  348. assert((p | 0b0101) == p2);
  349. p |= 0b0101;
  350. assert(p == p2);
  351. p = {0b0101, 0b1010, 0b1111, 0b0000};
  352. p2 = {0b0110, 0b0111, 0b1001, 0b1111};
  353. p3 = {0b0111, 0b1111, 0b1111, 0b1111};
  354. assert((p | p2) == p3);
  355. p |= p2;
  356. assert(p == p3);
  357. // ^
  358. p = {0b0101, 0b1010, 0b1111, 0b0000};
  359. p2 = {0b0000, 0b1111, 0b1010, 0b0101};
  360. assert((p ^ 0b0101) == p2);
  361. p ^= 0b0101;
  362. assert(p == p2);
  363. p = {0b0101, 0b1010, 0b1111, 0b0000};
  364. p2 = {0b0110, 0b0111, 0b1001, 0b1111};
  365. p3 = {0b0011, 0b1101, 0b0110, 0b1111};
  366. assert((p ^ p2) == p3);
  367. p ^= p2;
  368. assert(p == p3);
  369. // ~
  370. p = {0b0101, 0b1010, 0b1111, 0b0000};
  371. assert( (~p & 0b1111) == int4(0b1010, 0b0101, 0b0000, 0b1111));
  372. // ~ for vector<bool>
  373. assert( ~vector(true, false, true, false) == vector(false, true, false, true) );
  374. assert( ~vector(true, true, false, false) == vector(false, false, true, true) );
  375. assert( ~vector(true, true, true, true) == vector(false, false, false, false) );
  376. // ! for vector<bool>
  377. assert( (!vector(true, false, true, false)) == vector(false, true, false, true) );
  378. assert( (!vector(true, true, false, false)) == vector(false, false, true, true) );
  379. assert( (!vector(true, true, true, true)) == vector(false, false, false, false) );
  380. // ~ for vector<vector<bool>>
  381. assert( (~vector(vector(true, false), vector(true, false))) ==
  382. vector(vector(false, true), vector(false, true)) );
  383. assert( (~vector(vector(true, true), vector(false, false))) ==
  384. vector(vector(false, false), vector(true, true)) );
  385. assert( (~vector(vector(true, true), vector(true, true))) ==
  386. vector(vector(false, false), vector(false, false)) );
  387. // ! for vector<vector<bool>>
  388. assert( (!vector(vector(true, false), vector(true, false))) ==
  389. vector(vector(false, true), vector(false, true)) );
  390. assert( (!vector(vector(true, true), vector(false, false))) ==
  391. vector(vector(false, false), vector(true, true)) );
  392. assert( (!vector(vector(true, true), vector(true, true))) ==
  393. vector(vector(false, false), vector(false, false)) );
  394. }
  395. void ComparisonOperators()
  396. {
  397. int4 p(1, 2, 3, 4);
  398. int4 p2(1, -2, 0, 1);
  399. // some random masking logic
  400. assert(p * int4(p2 > int4::zero()) == int4(1, 0, 0, 4));
  401. assert(p * int4(p2 < int4::zero()) == int4(0, 2, 0, 0));
  402. assert(p * int4(p2 == int4::zero()) == int4(0, 0, 3, 0));
  403. assert(p * int4(p2 == int4::zero() | p2 == int4::one()) == int4(1, 0, 3, 4));
  404. assert(p * int4(p2 != int4::zero() | p2 == int4::one()) == int4(1, 2, 0, 4));
  405. assert(p * int4(p2 != int4::zero() & p2 != int4::one(-2)) == int4(1, 0, 0, 4));
  406. }
  407. int PotentiallyAmbigous(geom::vector<int, 2>){ return 2; }
  408. int PotentiallyAmbigous(geom::vector<int, 3>){ return 3; }
  409. void DisabiguateOnConstructorParameterCount()
  410. {
  411. assert( PotentiallyAmbigous({1,2,3}) == 3 );
  412. assert( PotentiallyAmbigous({1,2}) == 2 );
  413. }
  414. void NumericLimits()
  415. {
  416. using limits = std::numeric_limits<int4>;
  417. using coordLimits = std::numeric_limits<int4::coordinate_type>;
  418. static_assert(limits::is_specialized);
  419. static_assert(limits::max() == int4::one(coordLimits::max()));
  420. static_assert(limits::min() == int4::one(coordLimits::min()));
  421. }
  422. void CoordinateOrder()
  423. {
  424. geom::vector<int, 4, std::index_sequence<3,2,1,0>> p_wzyx(1,2,3,4);
  425. assert( p_wzyx.x() == 4 );
  426. assert( p_wzyx.y() == 3 );
  427. assert( p_wzyx.z() == 2 );
  428. assert( p_wzyx.w() == 1 );
  429. assert( p_wzyx.get<0>() == 4 );
  430. assert( p_wzyx.get<1>() == 3 );
  431. assert( p_wzyx.get<2>() == 2 );
  432. assert( p_wzyx.get<3>() == 1 );
  433. assert( p_wzyx[p_wzyx.x_index] == 4 );
  434. assert( p_wzyx[p_wzyx.y_index] == 3 );
  435. assert( p_wzyx[p_wzyx.z_index] == 2 );
  436. assert( p_wzyx[p_wzyx.w_index] == 1 );
  437. assert( p_wzyx[0] == 1 );
  438. assert( p_wzyx[1] == 2 );
  439. assert( p_wzyx[2] == 3 );
  440. assert( p_wzyx[3] == 4 );
  441. assert( int4(p_wzyx) == int4(4,3,2,1) );
  442. auto [x,y,z,w] = p_wzyx;
  443. assert( x == p_wzyx.x() );
  444. assert( y == p_wzyx.y() );
  445. assert( z == p_wzyx.z() );
  446. assert( w == p_wzyx.w() );
  447. }
  448. // not absolutely insane unsigned short
  449. struct naius
  450. {
  451. unsigned short val;
  452. };
  453. bool operator==(naius a, naius b) { return a.val == b.val; }
  454. bool operator!=(naius a, naius b) { return !(a == b); }
  455. naius operator-(naius a)
  456. {
  457. auto promoted = -unsigned(a.val);
  458. return naius{(unsigned short)promoted};
  459. }
  460. naius operator>>(naius a, int shift)
  461. {
  462. auto promoted = unsigned(a.val) << shift;
  463. return naius{(unsigned short)promoted};
  464. }
  465. unsigned operator*(naius a, naius b)
  466. {
  467. return unsigned(a.val) * unsigned(b.val);
  468. }
  469. void DefyPromotion()
  470. {
  471. using puny = unsigned short; // bad
  472. // NOTE: can no longer demonstrate buny of size 1, since it promotes and decays to element type when shifted and initializer list contructor catches the bad implicit cast
  473. using buny = vector<puny,2>; // used to be goodish but now bad
  474. using vuny = vector<naius,1>; // good
  475. if constexpr (sizeof(puny) < sizeof(decltype(-puny{})))
  476. {
  477. // TODO: this test also relies on 2's complement representation and sign extension -_-
  478. puny p{1};
  479. assert( puny( -p >> 1 ) == puny(-p) ); // this does not look equivalent at all!
  480. assert( puny( -p >> 1 ) != -p >> 1 ); // and this does!
  481. // same for vector
  482. buny b{p,p};
  483. assert( buny( -b >> 1 ) == buny(-b) );
  484. assert( buny( -b >> 1 ) != -b >> 1 );
  485. // all fixed by a sane element type
  486. vuny v{naius{1}};
  487. assert( vuny( -v >> 1 ) != vuny(-v) );
  488. assert( vuny( -v >> 1 ) == -v >> 1 );
  489. // bonus multiplication, old goodish vector couldn't do this properly
  490. if constexpr (sizeof(unsigned short)*2 == sizeof(unsigned) && sizeof(int) == sizeof(unsigned))
  491. {
  492. auto biggy = std::numeric_limits<puny>::max();
  493. // assert( biggy * biggy < std::numeric_limits<int>::max() ); // instaUB
  494. naius nicey{biggy};
  495. assert( nicey * nicey > std::numeric_limits<int>::max() ); // all fine and dandy
  496. vuny vicey{nicey};
  497. assert(( vicey * vicey > vector<unsigned, 1>{{std::numeric_limits<int>::max()}} )); // vector respec sanity
  498. [[maybe_unused]] buny buggy{biggy, biggy};
  499. // assert(( buggy * buggy < vector(std::numeric_limits<int>::max(),std::numeric_limits<int>::max()) )); // as well as insanity -_-
  500. }
  501. else
  502. std::puts("what a world we live in~");
  503. }
  504. else
  505. std::puts("Type not puny enough to test promotion defiance!");
  506. };
  507. constexpr bool Constexprness() // TODO: needs better coverage
  508. {
  509. constexpr int4 p = int4(1,2,3,4);
  510. constexpr std::array<int, p[2]> arr = {1,2,3};
  511. constexpr std::array<int, int4::zero()[0]> arr2 = {};
  512. constexpr std::array<int, int4::one()[1]> arr3 = {13};
  513. static_assert(arr[p[1]] == 3, "Some other test should have caught this error.");
  514. static_assert(arr2.size() == 0, "Some other test should have caught this error.");
  515. static_assert(arr3[0] == 13, "Some other test should have caught this error.");
  516. assert(arr[2] == 3); // redundant check;
  517. return true;
  518. }
  519. void ValueCategoryOfGet()
  520. {
  521. using std::get;
  522. vector a(1,2,3);
  523. static_assert(std::is_same_v<decltype(( get<0>(a) )), int&>);
  524. static_assert(std::is_same_v<decltype(( a[0] )), int&>);
  525. static_assert(std::is_same_v<decltype(( a.x() )), int&>);
  526. static_assert(std::is_same_v<decltype(( get<0>(vector(1,2,3)) )), int&&>);
  527. static_assert(std::is_same_v<decltype(( vector(1,2,3)[0] )), int&&>);
  528. // static_assert(std::is_same_v<decltype(( vector(1,2,3).x() )), int&&>); // TODO
  529. vector b(vector(1,2),vector(3,4));
  530. static_assert(std::is_same_v<decltype(( get<0>(b) )), vector<int,2>&>);
  531. static_assert(std::is_same_v<decltype(( get<1>(get<0>(b)) )), int&>);
  532. static_assert(std::is_same_v<decltype(( b[0] )), vector<int,2>&>);
  533. static_assert(std::is_same_v<decltype(( b[0][0] )), int&>);
  534. static_assert(std::is_same_v<decltype(( get<0>(
  535. vector(vector(1,2),vector(3,4))
  536. ) )), vector<int,2>&&>);
  537. static_assert(std::is_same_v<decltype(( get<1>(get<0>(
  538. vector(vector(1,2),vector(3,4))
  539. )) )), int&&>);
  540. static_assert(std::is_same_v<
  541. decltype(( vector(vector(1,2),vector(3,4))[0] )),
  542. vector<int,2>&&>);
  543. static_assert(std::is_same_v<
  544. decltype(( vector(vector(1,2),vector(3,4))[0][1] )),
  545. int&&>);
  546. }
  547. void EmbracePromotion()
  548. {
  549. using short3 = vector<short, 3>;
  550. short3 a {{1,2,3}}, b {{4,5,6}};
  551. auto c = a + b;
  552. assert((c == vector(5,7,9)));
  553. static_assert( std::is_same_v<decltype(c), vector<int,3>> );
  554. auto d = short3(a + b);
  555. assert((d == short3{{5,7,9}}));
  556. static_assert( std::is_same_v<decltype(d), short3> );
  557. auto e = a + a + b;
  558. assert((e == vector(6,9,12)));
  559. static_assert( std::is_same_v<decltype(e), vector<int,3>> );
  560. d += a;
  561. assert((d == short3{{6,9,12}}));
  562. e += d;
  563. assert((e == vector(12,18,24)));
  564. auto cc = a + 1;
  565. static_assert( std::is_same_v<decltype(cc), vector<int,3>> );
  566. }
  567. template <typename E>
  568. class expr
  569. {
  570. public:
  571. operator int() const
  572. {
  573. return static_cast<const E&>(*this);
  574. }
  575. };
  576. class expr_int : public expr<expr_int>
  577. {
  578. int value;
  579. public:
  580. operator int() const { return value; }
  581. expr_int(int value = int{}) : value(value) {}
  582. template <typename E>
  583. expr_int(expr<E> const& expr) : value{expr} {}
  584. };
  585. template <typename E1, typename E2>
  586. class expr_sum : public expr<expr_sum<E1, E2> > {
  587. E1 const* left;
  588. E2 const* right;
  589. public:
  590. expr_sum() : left(), right() {}
  591. expr_sum(E1 const& left, E2 const& right) : left(&left), right(&right) {}
  592. operator int() const { return static_cast<int>(*left) + static_cast<int>(*right); }
  593. };
  594. template <typename E1, typename E2>
  595. expr_sum<E1, E2>
  596. operator+(expr<E1> const& left, expr<E2> const& right) {
  597. return expr_sum<E1, E2>(*static_cast<const E1*>(&left), *static_cast<const E2*>(&right));
  598. }
  599. void ExpressionTemplates()
  600. {
  601. using expr_vec = vector<expr_int, 2>;
  602. expr_vec x{1,2};
  603. expr_vec y{3,4};
  604. vector<int,2> z (x + y + x);
  605. assert(z == vector(5,8));
  606. }
  607. void BoolBitwiseCorrections()
  608. {
  609. // insanity check
  610. static_assert(std::is_same_v<int, decltype(true & true)>);
  611. static_assert(std::is_same_v<int, decltype(true | true)>);
  612. static_assert(std::is_same_v<int, decltype(true ^ true)>);
  613. // static_assert(std::is_same_v<int, decltype(~true)>); // this is kind of sane, but compiler warns so cleary shouldn't be used
  614. // much saner vector -v-
  615. static_assert(std::is_same_v<vector<bool,1>, decltype(vector(true) & vector(true))>);
  616. static_assert(std::is_same_v<vector<bool,1>, decltype(vector(true) | vector(true))>);
  617. static_assert(std::is_same_v<vector<bool,1>, decltype(vector(true) ^ vector(true))>);
  618. static_assert(std::is_same_v<vector<bool,1>, decltype(~vector(true))>); // ok with vector, it's same as !
  619. // note: in conditional expressions ~ is elementwise negation, while ! causes a reduction to plain bool (see bool_algebra.cpp)
  620. // make sure we didn't break other things
  621. // bit operations involving other types still promotes
  622. static_assert(std::is_same_v<vector<int,1>, decltype(vector(true) & vector(1))>);
  623. static_assert(std::is_same_v<vector<int,1>, decltype(vector(1) & vector(1))>);
  624. static_assert(std::is_same_v<vector<int,1>, decltype(vector(true) | vector(1))>);
  625. static_assert(std::is_same_v<vector<int,1>, decltype(vector(1) | vector(true))>);
  626. static_assert(std::is_same_v<vector<int,1>, decltype(vector(true) ^ vector(1))>);
  627. static_assert(std::is_same_v<vector<int,1>, decltype(vector(1) ^ vector(true))>);
  628. // arithmetic still promotes
  629. static_assert(std::is_same_v<vector<int,1>, decltype(vector(true) + vector(true))>);
  630. static_assert(std::is_same_v<vector<int,1>, decltype(vector(true) - vector(true))>);
  631. // TODO: not sure about these... multiplication is basically conjunction so maybe should return bool,
  632. // division makes no sense, can only divide by 1, / is a no-op, % is constant 0, both still stay within bounds of bool though
  633. static_assert(std::is_same_v<vector<int,1>, decltype(vector(true) * vector(true))>);
  634. static_assert(std::is_same_v<vector<int,1>, decltype(vector(true) / vector(true))>);
  635. static_assert(std::is_same_v<vector<int,1>, decltype(vector(true) % vector(true))>);
  636. }
  637. void BoolReductionImplicitConversion()
  638. {
  639. vector x (1,2,3);
  640. assert( x + (x == vector(1,1,1)) == vector(2,2,3) );
  641. assert( (x == vector(1,1,1)) + x == vector(2,2,3) );
  642. x += x == vector(1,1,1);
  643. assert( x == vector(2,2,3) );
  644. x = x == vector(2,2,2);
  645. assert( x == vector(1,1,0) );
  646. }
  647. void OneDimentionalVectorDecays()
  648. {
  649. using puny = short;
  650. assert (vector(puny(1)) + puny(1) == 2);
  651. static_assert( std::is_same_v<decltype(vector(puny(1)) + puny(1)), int> );
  652. }
  653. template <int4 i, int4 j = i> constexpr auto template_plus() { return i + j; }
  654. void NonTypeTemplateParamater()
  655. {
  656. static_assert(template_plus<int4{1,2,3,4}>() == int4{2,4,6,8});
  657. static_assert(template_plus<int4{1,2,3,4}, int4{5,6,7,8}>() == int4{6,8,10,12});
  658. }
  659. int main()
  660. {
  661. ZeroConstruction();
  662. EqualityComparison();
  663. OtherConstruction();
  664. ImplicitConversion();
  665. Transformation();
  666. Mixing();
  667. MultidimensionalElementAccess();
  668. RangeBasedLooping();
  669. Arithmetic();
  670. DiscreteArithmetic();
  671. ComparisonOperators();
  672. DisabiguateOnConstructorParameterCount();
  673. NumericLimits();
  674. CoordinateOrder();
  675. DefyPromotion();
  676. static_assert(Constexprness());
  677. ValueCategoryOfGet();
  678. EmbracePromotion();
  679. ExpressionTemplates();
  680. BoolBitwiseCorrections();
  681. BoolReductionImplicitConversion();
  682. OneDimentionalVectorDecays();
  683. NonTypeTemplateParamater();
  684. return 0;
  685. }