natural.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. #define ConcatenateType(Size) uint##Size##_t
  2. #define DeclareType(Size) ConcatenateType(Size)
  3. #define Pair DeclareType(PairBits)
  4. #define Type DeclareType(TypeBits)
  5. #define Half DeclareType(HalfBits)
  6. //pick the larger of two types to prevent unnecessary data clamping
  7. #define Cast (typename conditional<sizeof(Pair) >= sizeof(T), Pair, T>::type)
  8. namespace nall {
  9. //namespace Arithmetic {
  10. struct Pair {
  11. Pair() = default;
  12. explicit constexpr Pair(const Pair& source) : hi(source.hi), lo(source.lo) {}
  13. template<typename Hi, typename Lo> constexpr Pair(const Hi& hi, const Lo& lo) : hi(hi), lo(lo) {}
  14. template<typename T> Pair(const T& source) { _set(*this, source); }
  15. explicit operator bool() const { return hi | lo; }
  16. template<typename T> operator T() const { T value; _get(*this, value); return value; }
  17. auto operator+() const -> Pair { return *this; }
  18. auto operator-() const -> Pair { return Pair(0) - *this; }
  19. auto operator~() const -> Pair { return {~hi, ~lo}; }
  20. auto operator!() const -> bool { return !(hi || lo); }
  21. auto operator++() -> Pair& { lo++; hi += lo == 0; return *this; }
  22. auto operator--() -> Pair& { hi -= lo == 0; lo--; return *this; }
  23. auto operator++(int) -> Pair { Pair r = *this; lo++; hi += lo == 0; return r; }
  24. auto operator--(int) -> Pair { Pair r = *this; hi -= lo == 0; lo--; return r; }
  25. auto operator* (const Pair& rhs) const -> Pair { return mul(*this, rhs); }
  26. auto operator/ (const Pair& rhs) const -> Pair { Pair q, r; div(*this, rhs, q, r); return q; }
  27. auto operator% (const Pair& rhs) const -> Pair { Pair q, r; div(*this, rhs, q, r); return r; }
  28. auto operator+ (const Pair& rhs) const -> Pair { return {hi + rhs.hi + (lo + rhs.lo < lo), lo + rhs.lo}; }
  29. auto operator- (const Pair& rhs) const -> Pair { return {hi - rhs.hi - (lo - rhs.lo > lo), lo - rhs.lo}; }
  30. auto operator<<(const Pair& rhs) const -> Pair { return shl(*this, rhs); }
  31. auto operator>>(const Pair& rhs) const -> Pair { return shr(*this, rhs); }
  32. auto operator& (const Pair& rhs) const -> Pair { return {hi & rhs.hi, lo & rhs.lo}; }
  33. auto operator| (const Pair& rhs) const -> Pair { return {hi | rhs.hi, lo | rhs.lo}; }
  34. auto operator^ (const Pair& rhs) const -> Pair { return {hi ^ rhs.hi, lo ^ rhs.lo}; }
  35. auto operator==(const Pair& rhs) const -> bool { return hi == rhs.hi && lo == rhs.lo; }
  36. auto operator!=(const Pair& rhs) const -> bool { return hi != rhs.hi || lo != rhs.lo; }
  37. auto operator>=(const Pair& rhs) const -> bool { return hi > rhs.hi || (hi == rhs.hi && lo >= rhs.lo); }
  38. auto operator<=(const Pair& rhs) const -> bool { return hi < rhs.hi || (hi == rhs.hi && lo <= rhs.lo); }
  39. auto operator> (const Pair& rhs) const -> bool { return hi > rhs.hi || (hi == rhs.hi && lo > rhs.lo); }
  40. auto operator< (const Pair& rhs) const -> bool { return hi < rhs.hi || (hi == rhs.hi && lo < rhs.lo); }
  41. template<typename T> auto& operator*= (const T& rhs) { return *this = *this * Pair(rhs); }
  42. template<typename T> auto& operator/= (const T& rhs) { return *this = *this / Pair(rhs); }
  43. template<typename T> auto& operator%= (const T& rhs) { return *this = *this % Pair(rhs); }
  44. template<typename T> auto& operator+= (const T& rhs) { return *this = *this + Pair(rhs); }
  45. template<typename T> auto& operator-= (const T& rhs) { return *this = *this - Pair(rhs); }
  46. template<typename T> auto& operator<<=(const T& rhs) { return *this = *this << Pair(rhs); }
  47. template<typename T> auto& operator>>=(const T& rhs) { return *this = *this >> Pair(rhs); }
  48. template<typename T> auto& operator&= (const T& rhs) { return *this = *this & Pair(rhs); }
  49. template<typename T> auto& operator|= (const T& rhs) { return *this = *this | Pair(rhs); }
  50. template<typename T> auto& operator^= (const T& rhs) { return *this = *this ^ Pair(rhs); }
  51. template<typename T> auto operator* (const T& rhs) const { return Cast(*this) * Cast(rhs); }
  52. template<typename T> auto operator/ (const T& rhs) const { return Cast(*this) / Cast(rhs); }
  53. template<typename T> auto operator% (const T& rhs) const { return Cast(*this) % Cast(rhs); }
  54. template<typename T> auto operator+ (const T& rhs) const { return Cast(*this) + Cast(rhs); }
  55. template<typename T> auto operator- (const T& rhs) const { return Cast(*this) - Cast(rhs); }
  56. template<typename T> auto operator<<(const T& rhs) const { return Cast(*this) << Cast(rhs); }
  57. template<typename T> auto operator>>(const T& rhs) const { return Cast(*this) >> Cast(rhs); }
  58. template<typename T> auto operator& (const T& rhs) const { return Cast(*this) & Cast(rhs); }
  59. template<typename T> auto operator| (const T& rhs) const { return Cast(*this) | Cast(rhs); }
  60. template<typename T> auto operator^ (const T& rhs) const { return Cast(*this) ^ Cast(rhs); }
  61. template<typename T> auto operator==(const T& rhs) const -> bool { return Cast(*this) == Cast(rhs); }
  62. template<typename T> auto operator!=(const T& rhs) const -> bool { return Cast(*this) != Cast(rhs); }
  63. template<typename T> auto operator>=(const T& rhs) const -> bool { return Cast(*this) >= Cast(rhs); }
  64. template<typename T> auto operator<=(const T& rhs) const -> bool { return Cast(*this) <= Cast(rhs); }
  65. template<typename T> auto operator> (const T& rhs) const -> bool { return Cast(*this) > Cast(rhs); }
  66. template<typename T> auto operator< (const T& rhs) const -> bool { return Cast(*this) < Cast(rhs); }
  67. private:
  68. Type lo;
  69. Type hi;
  70. friend auto upper(const Pair&) -> Type;
  71. friend auto lower(const Pair&) -> Type;
  72. friend auto bits(Pair) -> uint;
  73. friend auto square(const Pair&) -> Pair;
  74. friend auto square(const Pair&, Pair&, Pair&) -> void;
  75. friend auto mul(const Pair&, const Pair&) -> Pair;
  76. friend auto mul(const Pair&, const Pair&, Pair&, Pair&) -> void;
  77. friend auto div(const Pair&, const Pair&, Pair&, Pair&) -> void;
  78. template<typename T> friend auto shl(const Pair&, const T&) -> Pair;
  79. template<typename T> friend auto shr(const Pair&, const T&) -> Pair;
  80. };
  81. template<> struct ArithmeticNatural<PairBits> {
  82. using type = Pair;
  83. };
  84. #define ConcatenateUDL(Size) _u##Size
  85. #define DeclareUDL(Size) ConcatenateUDL(Size)
  86. alwaysinline auto operator"" DeclareUDL(PairBits)(const char* s) -> Pair {
  87. Pair p = 0;
  88. if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
  89. s += 2;
  90. while(*s) {
  91. auto c = *s++;
  92. if(c == '\'');
  93. else if(c >= '0' && c <= '9') p = (p << 4) + (c - '0');
  94. else if(c >= 'a' && c <= 'f') p = (p << 4) + (c - 'a' + 10);
  95. else if(c >= 'A' && c <= 'F') p = (p << 4) + (c - 'A' + 10);
  96. else break;
  97. }
  98. } else {
  99. while(*s) {
  100. auto c = *s++;
  101. if(c == '\'');
  102. else if(c >= '0' && c <= '9') p = (p << 3) + (p << 1) + (c - '0');
  103. else break;
  104. }
  105. }
  106. return p;
  107. }
  108. #undef ConcatenateUDL
  109. #undef DeclareUDL
  110. template<typename T> alwaysinline auto _set(Pair& lhs, const T& rhs) -> enable_if_t<(sizeof(Pair) == sizeof(T))> {
  111. lhs = rhs;
  112. }
  113. template<typename T> alwaysinline auto _set(Pair& lhs, const T& rhs) -> enable_if_t<(sizeof(Pair) > sizeof(T))> {
  114. lhs = {0, rhs};
  115. }
  116. template<typename T> alwaysinline auto _set(Pair& lhs, const T& rhs) -> enable_if_t<(sizeof(Pair) < sizeof(T))> {
  117. lhs = {lower(rhs) >> TypeBits, lower(rhs)};
  118. }
  119. template<typename T> alwaysinline auto _get(const Pair& lhs, T& rhs) -> enable_if_t<(sizeof(T) == sizeof(Pair))> {
  120. rhs = lhs;
  121. }
  122. template<typename T> alwaysinline auto _get(const Pair& lhs, T& rhs) -> enable_if_t<(sizeof(T) > sizeof(Pair))> {
  123. rhs = {0, lhs};
  124. }
  125. template<typename T> alwaysinline auto _get(const Pair& lhs, T& rhs) -> enable_if_t<(sizeof(T) < sizeof(Pair))> {
  126. rhs = lower(lhs);
  127. }
  128. alwaysinline auto upper(const Pair& value) -> Type { return value.hi; }
  129. alwaysinline auto lower(const Pair& value) -> Type { return value.lo; }
  130. alwaysinline auto bits(Pair value) -> uint {
  131. if(value.hi) {
  132. uint bits = TypeBits;
  133. while(value.hi) value.hi >>= 1, bits++;
  134. return bits;
  135. } else {
  136. uint bits = 0;
  137. while(value.lo) value.lo >>= 1, bits++;
  138. return bits;
  139. }
  140. }
  141. //Bits * Bits => Bits
  142. inline auto square(const Pair& lhs) -> Pair {
  143. static const Type Mask = (Type(0) - 1) >> HalfBits;
  144. Type a = lhs.hi >> HalfBits, b = lhs.hi & Mask, c = lhs.lo >> HalfBits, d = lhs.lo & Mask;
  145. Type dd = square(d), dc = d * c, db = d * b, da = d * a;
  146. Type cc = square(c), cb = c * b;
  147. Pair r0 = Pair(dd);
  148. Pair r1 = Pair(dc) + Pair(dc) + Pair(r0 >> HalfBits);
  149. Pair r2 = Pair(db) + Pair(cc) + Pair(db) + Pair(r1 >> HalfBits);
  150. Pair r3 = Pair(da) + Pair(cb) + Pair(cb) + Pair(da) + Pair(r2 >> HalfBits);
  151. return {(r3.lo & Mask) << HalfBits | (r2.lo & Mask), (r1.lo & Mask) << HalfBits | (r0.lo & Mask)};
  152. }
  153. //Bits * Bits => 2 * Bits
  154. inline auto square(const Pair& lhs, Pair& hi, Pair& lo) -> void {
  155. static const Type Mask = (Type(0) - 1) >> HalfBits;
  156. Type a = lhs.hi >> HalfBits, b = lhs.hi & Mask, c = lhs.lo >> HalfBits, d = lhs.lo & Mask;
  157. Type dd = square(d), dc = d * c, db = d * b, da = d * a;
  158. Type cc = square(c), cb = c * b, ca = c * a;
  159. Type bb = square(b), ba = b * a;
  160. Type aa = square(a);
  161. Pair r0 = Pair(dd);
  162. Pair r1 = Pair(dc) + Pair(dc) + Pair(r0 >> HalfBits);
  163. Pair r2 = Pair(db) + Pair(cc) + Pair(db) + Pair(r1 >> HalfBits);
  164. Pair r3 = Pair(da) + Pair(cb) + Pair(cb) + Pair(da) + Pair(r2 >> HalfBits);
  165. Pair r4 = Pair(ca) + Pair(bb) + Pair(ca) + Pair(r3 >> HalfBits);
  166. Pair r5 = Pair(ba) + Pair(ba) + Pair(r4 >> HalfBits);
  167. Pair r6 = Pair(aa) + Pair(r5 >> HalfBits);
  168. Pair r7 = Pair(r6 >> HalfBits);
  169. hi = {(r7.lo & Mask) << HalfBits | (r6.lo & Mask), (r5.lo & Mask) << HalfBits | (r4.lo & Mask)};
  170. lo = {(r3.lo & Mask) << HalfBits | (r2.lo & Mask), (r1.lo & Mask) << HalfBits | (r0.lo & Mask)};
  171. }
  172. //Bits * Bits => Bits
  173. alwaysinline auto mul(const Pair& lhs, const Pair& rhs) -> Pair {
  174. static const Type Mask = (Type(0) - 1) >> HalfBits;
  175. Type a = lhs.hi >> HalfBits, b = lhs.hi & Mask, c = lhs.lo >> HalfBits, d = lhs.lo & Mask;
  176. Type e = rhs.hi >> HalfBits, f = rhs.hi & Mask, g = rhs.lo >> HalfBits, h = rhs.lo & Mask;
  177. Pair r0 = Pair(d * h);
  178. Pair r1 = Pair(c * h) + Pair(d * g) + Pair(r0 >> HalfBits);
  179. Pair r2 = Pair(b * h) + Pair(c * g) + Pair(d * f) + Pair(r1 >> HalfBits);
  180. Pair r3 = Pair(a * h) + Pair(b * g) + Pair(c * f) + Pair(d * e) + Pair(r2 >> HalfBits);
  181. return {(r3.lo & Mask) << HalfBits | (r2.lo & Mask), (r1.lo & Mask) << HalfBits | (r0.lo & Mask)};
  182. }
  183. //Bits * Bits => 2 * Bits
  184. alwaysinline auto mul(const Pair& lhs, const Pair& rhs, Pair& hi, Pair& lo) -> void {
  185. static const Type Mask = (Type(0) - 1) >> HalfBits;
  186. Type a = lhs.hi >> HalfBits, b = lhs.hi & Mask, c = lhs.lo >> HalfBits, d = lhs.lo & Mask;
  187. Type e = rhs.hi >> HalfBits, f = rhs.hi & Mask, g = rhs.lo >> HalfBits, h = rhs.lo & Mask;
  188. Pair r0 = Pair(d * h);
  189. Pair r1 = Pair(c * h) + Pair(d * g) + Pair(r0 >> HalfBits);
  190. Pair r2 = Pair(b * h) + Pair(c * g) + Pair(d * f) + Pair(r1 >> HalfBits);
  191. Pair r3 = Pair(a * h) + Pair(b * g) + Pair(c * f) + Pair(d * e) + Pair(r2 >> HalfBits);
  192. Pair r4 = Pair(a * g) + Pair(b * f) + Pair(c * e) + Pair(r3 >> HalfBits);
  193. Pair r5 = Pair(a * f) + Pair(b * e) + Pair(r4 >> HalfBits);
  194. Pair r6 = Pair(a * e) + Pair(r5 >> HalfBits);
  195. Pair r7 = Pair(r6 >> HalfBits);
  196. hi = {(r7.lo & Mask) << HalfBits | (r6.lo & Mask), (r5.lo & Mask) << HalfBits | (r4.lo & Mask)};
  197. lo = {(r3.lo & Mask) << HalfBits | (r2.lo & Mask), (r1.lo & Mask) << HalfBits | (r0.lo & Mask)};
  198. }
  199. alwaysinline auto div(const Pair& lhs, const Pair& rhs, Pair& quotient, Pair& remainder) -> void {
  200. if(!rhs) throw std::runtime_error("division by zero");
  201. quotient = 0, remainder = lhs;
  202. if(!lhs || lhs < rhs) return;
  203. auto count = bits(lhs) - bits(rhs);
  204. Pair x = rhs << count;
  205. Pair y = Pair(1) << count;
  206. if(x > remainder) x >>= 1, y >>= 1;
  207. while(remainder >= rhs) {
  208. if(remainder >= x) remainder -= x, quotient |= y;
  209. x >>= 1, y >>= 1;
  210. }
  211. }
  212. template<typename T> alwaysinline auto shl(const Pair& lhs, const T& rhs) -> Pair {
  213. if(!rhs) return lhs;
  214. auto shift = (uint)rhs;
  215. if(shift < TypeBits) {
  216. return {lhs.hi << shift | lhs.lo >> (TypeBits - shift), lhs.lo << shift};
  217. } else {
  218. return {lhs.lo << (shift - TypeBits), 0};
  219. }
  220. }
  221. template<typename T> alwaysinline auto shr(const Pair& lhs, const T& rhs) -> Pair {
  222. if(!rhs) return lhs;
  223. auto shift = (uint)rhs;
  224. if(shift < TypeBits) {
  225. return {lhs.hi >> shift, lhs.hi << (TypeBits - shift) | lhs.lo >> shift};
  226. } else {
  227. return {0, lhs.hi >> (shift - TypeBits)};
  228. }
  229. }
  230. template<typename T> alwaysinline auto rol(const Pair& lhs, const T& rhs) -> Pair {
  231. return lhs << rhs | lhs >> (PairBits - rhs);
  232. }
  233. template<typename T> alwaysinline auto ror(const Pair& lhs, const T& rhs) -> Pair {
  234. return lhs >> rhs | lhs << (PairBits - rhs);
  235. }
  236. #define EI enable_if_t<is_integral<T>::value>
  237. template<typename T, EI> auto& operator*= (T& lhs, const Pair& rhs) { return lhs = lhs * T(rhs); }
  238. template<typename T, EI> auto& operator/= (T& lhs, const Pair& rhs) { return lhs = lhs / T(rhs); }
  239. template<typename T, EI> auto& operator%= (T& lhs, const Pair& rhs) { return lhs = lhs % T(rhs); }
  240. template<typename T, EI> auto& operator+= (T& lhs, const Pair& rhs) { return lhs = lhs + T(rhs); }
  241. template<typename T, EI> auto& operator-= (T& lhs, const Pair& rhs) { return lhs = lhs - T(rhs); }
  242. template<typename T, EI> auto& operator<<=(T& lhs, const Pair& rhs) { return lhs = lhs << T(rhs); }
  243. template<typename T, EI> auto& operator>>=(T& lhs, const Pair& rhs) { return lhs = lhs >> T(rhs); }
  244. template<typename T, EI> auto& operator&= (T& lhs, const Pair& rhs) { return lhs = lhs & T(rhs); }
  245. template<typename T, EI> auto& operator|= (T& lhs, const Pair& rhs) { return lhs = lhs | T(rhs); }
  246. template<typename T, EI> auto& operator^= (T& lhs, const Pair& rhs) { return lhs = lhs ^ T(rhs); }
  247. template<typename T, EI> auto operator* (const T& lhs, const Pair& rhs) { return Cast(lhs) * Cast(rhs); }
  248. template<typename T, EI> auto operator/ (const T& lhs, const Pair& rhs) { return Cast(lhs) / Cast(rhs); }
  249. template<typename T, EI> auto operator% (const T& lhs, const Pair& rhs) { return Cast(lhs) % Cast(rhs); }
  250. template<typename T, EI> auto operator+ (const T& lhs, const Pair& rhs) { return Cast(lhs) + Cast(rhs); }
  251. template<typename T, EI> auto operator- (const T& lhs, const Pair& rhs) { return Cast(lhs) - Cast(rhs); }
  252. template<typename T, EI> auto operator<<(const T& lhs, const Pair& rhs) { return Cast(lhs) << Cast(rhs); }
  253. template<typename T, EI> auto operator>>(const T& lhs, const Pair& rhs) { return Cast(lhs) >> Cast(rhs); }
  254. template<typename T, EI> auto operator& (const T& lhs, const Pair& rhs) { return Cast(lhs) & Cast(rhs); }
  255. template<typename T, EI> auto operator| (const T& lhs, const Pair& rhs) { return Cast(lhs) | Cast(rhs); }
  256. template<typename T, EI> auto operator^ (const T& lhs, const Pair& rhs) { return Cast(lhs) ^ Cast(rhs); }
  257. template<typename T, EI> auto operator==(const T& lhs, const Pair& rhs) { return Cast(lhs) == Cast(rhs); }
  258. template<typename T, EI> auto operator!=(const T& lhs, const Pair& rhs) { return Cast(lhs) != Cast(rhs); }
  259. template<typename T, EI> auto operator>=(const T& lhs, const Pair& rhs) { return Cast(lhs) >= Cast(rhs); }
  260. template<typename T, EI> auto operator<=(const T& lhs, const Pair& rhs) { return Cast(lhs) <= Cast(rhs); }
  261. template<typename T, EI> auto operator> (const T& lhs, const Pair& rhs) { return Cast(lhs) > Cast(rhs); }
  262. template<typename T, EI> auto operator< (const T& lhs, const Pair& rhs) { return Cast(lhs) < Cast(rhs); }
  263. #undef EI
  264. template<> struct stringify<Pair> {
  265. stringify(Pair source) {
  266. char _output[1 + sizeof(Pair) * 3];
  267. auto p = (char*)&_output;
  268. do {
  269. Pair quotient, remainder;
  270. div(source, 10, quotient, remainder);
  271. *p++ = remainder + '0';
  272. source = quotient;
  273. } while(source);
  274. _size = p - _output;
  275. *p = 0;
  276. for(int x = _size - 1, y = 0; x >= 0 && y < _size; x--, y++) _data[x] = _output[y];
  277. }
  278. auto data() const -> const char* { return _data; }
  279. auto size() const -> uint { return _size; }
  280. char _data[1 + sizeof(Pair) * 3];
  281. uint _size;
  282. };
  283. }
  284. #undef ConcatenateType
  285. #undef DeclareType
  286. #undef Pair
  287. #undef Type
  288. #undef Half
  289. #undef Cast