uint128_t.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. #ifndef _UINT128_H_
  2. #define _UINT128_H_
  3. #ifndef _UINT128_T_CONFIG_
  4. #define _UINT128_T_CONFIG_
  5. #if defined(_MSC_VER)
  6. #if defined(_DLL)
  7. #define _UINT128_T_EXPORT __declspec(dllexport)
  8. #define _UINT128_T_IMPORT __declspec(dllimport)
  9. #else
  10. #define _UINT128_T_EXPORT
  11. #define _UINT128_T_IMPORT
  12. #endif
  13. #else
  14. // All modules on Unix are compiled with -fvisibility=hidden
  15. // All API symbols get visibility default
  16. // whether or not we're static linking or dynamic linking (with -fPIC)
  17. #define _UINT128_T_EXPORT __attribute__((visibility("default")))
  18. #define _UINT128_T_IMPORT __attribute__((visibility("default")))
  19. #endif
  20. #endif
  21. #define UINT128_T_EXTERN _UINT128_T_IMPORT
  22. /*
  23. uint128_t.h
  24. An unsigned 128 bit integer type for C++
  25. Copyright (c) 2013 - 2017 Jason Lee @ calccrypto at gmail.com
  26. Permission is hereby granted, free of charge, to any person obtaining a copy
  27. of this software and associated documentation files (the "Software"), to deal
  28. in the Software without restriction, including without limitation the rights
  29. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  30. copies of the Software, and to permit persons to whom the Software is
  31. furnished to do so, subject to the following conditions:
  32. The above copyright notice and this permission notice shall be included in
  33. all copies or substantial portions of the Software.
  34. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  35. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  36. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  37. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  38. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  39. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  40. THE SOFTWARE.
  41. With much help from Auston Sterling
  42. Thanks to Stefan Deigmüller for finding
  43. a bug in operator*.
  44. Thanks to François Dessenne for convincing me
  45. to do a general rewrite of this class.
  46. */
  47. #ifndef __UINT128_T__
  48. #define __UINT128_T__
  49. #include <cstdint>
  50. #include <ostream>
  51. #include <stdexcept>
  52. #include <string>
  53. #include <type_traits>
  54. #include <utility>
  55. class UINT128_T_EXTERN uint128_t;
  56. // Give uint128_t type traits
  57. namespace std { // This is probably not a good idea
  58. template <> struct is_arithmetic <uint128_t> : std::true_type {};
  59. template <> struct is_integral <uint128_t> : std::true_type {};
  60. template <> struct is_unsigned <uint128_t> : std::true_type {};
  61. }
  62. class uint128_t{
  63. private:
  64. uint64_t UPPER, LOWER;
  65. public:
  66. // Constructors
  67. uint128_t();
  68. uint128_t(const uint128_t & rhs);
  69. uint128_t(uint128_t && rhs);
  70. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  71. uint128_t(const T & rhs)
  72. : UPPER(0), LOWER(rhs)
  73. {}
  74. template <typename S, typename T, typename = typename std::enable_if <std::is_integral<S>::value && std::is_integral<T>::value, void>::type>
  75. uint128_t(const S & upper_rhs, const T & lower_rhs)
  76. : UPPER(upper_rhs), LOWER(lower_rhs)
  77. {}
  78. // RHS input args only
  79. // Assignment Operator
  80. uint128_t & operator=(const uint128_t & rhs);
  81. uint128_t & operator=(uint128_t && rhs);
  82. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  83. uint128_t & operator=(const T & rhs){
  84. UPPER = 0;
  85. LOWER = rhs;
  86. return *this;
  87. }
  88. // Typecast Operators
  89. operator bool() const;
  90. operator uint8_t() const;
  91. operator uint16_t() const;
  92. operator uint32_t() const;
  93. operator uint64_t() const;
  94. // Bitwise Operators
  95. uint128_t operator&(const uint128_t & rhs) const;
  96. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  97. uint128_t operator&(const T & rhs) const{
  98. return uint128_t(0, LOWER & (uint64_t) rhs);
  99. }
  100. uint128_t & operator&=(const uint128_t & rhs);
  101. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  102. uint128_t & operator&=(const T & rhs){
  103. UPPER = 0;
  104. LOWER &= rhs;
  105. return *this;
  106. }
  107. uint128_t operator|(const uint128_t & rhs) const;
  108. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  109. uint128_t operator|(const T & rhs) const{
  110. return uint128_t(UPPER, LOWER | (uint64_t) rhs);
  111. }
  112. uint128_t & operator|=(const uint128_t & rhs);
  113. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  114. uint128_t & operator|=(const T & rhs){
  115. LOWER |= (uint64_t) rhs;
  116. return *this;
  117. }
  118. uint128_t operator^(const uint128_t & rhs) const;
  119. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  120. uint128_t operator^(const T & rhs) const{
  121. return uint128_t(UPPER, LOWER ^ (uint64_t) rhs);
  122. }
  123. uint128_t & operator^=(const uint128_t & rhs);
  124. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  125. uint128_t & operator^=(const T & rhs){
  126. LOWER ^= (uint64_t) rhs;
  127. return *this;
  128. }
  129. uint128_t operator~() const;
  130. // Bit Shift Operators
  131. uint128_t operator<<(const uint128_t & rhs) const;
  132. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  133. uint128_t operator<<(const T & rhs) const{
  134. return *this << uint128_t(rhs);
  135. }
  136. uint128_t & operator<<=(const uint128_t & rhs);
  137. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  138. uint128_t & operator<<=(const T & rhs){
  139. *this = *this << uint128_t(rhs);
  140. return *this;
  141. }
  142. uint128_t operator>>(const uint128_t & rhs) const;
  143. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  144. uint128_t operator>>(const T & rhs) const{
  145. return *this >> uint128_t(rhs);
  146. }
  147. uint128_t & operator>>=(const uint128_t & rhs);
  148. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  149. uint128_t & operator>>=(const T & rhs){
  150. *this = *this >> uint128_t(rhs);
  151. return *this;
  152. }
  153. // Logical Operators
  154. bool operator!() const;
  155. bool operator&&(const uint128_t & rhs) const;
  156. bool operator||(const uint128_t & rhs) const;
  157. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  158. bool operator&&(const T & rhs){
  159. return static_cast <bool> (*this && rhs);
  160. }
  161. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  162. bool operator||(const T & rhs){
  163. return static_cast <bool> (*this || rhs);
  164. }
  165. // Comparison Operators
  166. bool operator==(const uint128_t & rhs) const;
  167. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  168. bool operator==(const T & rhs) const{
  169. return (!UPPER && (LOWER == (uint64_t) rhs));
  170. }
  171. bool operator!=(const uint128_t & rhs) const;
  172. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  173. bool operator!=(const T & rhs) const{
  174. return (UPPER | (LOWER != (uint64_t) rhs));
  175. }
  176. bool operator>(const uint128_t & rhs) const;
  177. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  178. bool operator>(const T & rhs) const{
  179. return (UPPER || (LOWER > (uint64_t) rhs));
  180. }
  181. bool operator<(const uint128_t & rhs) const;
  182. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  183. bool operator<(const T & rhs) const{
  184. return (!UPPER)?(LOWER < (uint64_t) rhs):false;
  185. }
  186. bool operator>=(const uint128_t & rhs) const;
  187. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  188. bool operator>=(const T & rhs) const{
  189. return ((*this > rhs) | (*this == rhs));
  190. }
  191. bool operator<=(const uint128_t & rhs) const;
  192. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  193. bool operator<=(const T & rhs) const{
  194. return ((*this < rhs) | (*this == rhs));
  195. }
  196. // Arithmetic Operators
  197. uint128_t operator+(const uint128_t & rhs) const;
  198. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  199. uint128_t operator+(const T & rhs) const{
  200. return uint128_t(UPPER + ((LOWER + (uint64_t) rhs) < LOWER), LOWER + (uint64_t) rhs);
  201. }
  202. uint128_t & operator+=(const uint128_t & rhs);
  203. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  204. uint128_t & operator+=(const T & rhs){
  205. UPPER = UPPER + ((LOWER + rhs) < LOWER);
  206. LOWER = LOWER + rhs;
  207. return *this;
  208. }
  209. uint128_t operator-(const uint128_t & rhs) const;
  210. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  211. uint128_t operator-(const T & rhs) const{
  212. return uint128_t((uint64_t) (UPPER - ((LOWER - rhs) > LOWER)), (uint64_t) (LOWER - rhs));
  213. }
  214. uint128_t & operator-=(const uint128_t & rhs);
  215. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  216. uint128_t & operator-=(const T & rhs){
  217. *this = *this - rhs;
  218. return *this;
  219. }
  220. uint128_t operator*(const uint128_t & rhs) const;
  221. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  222. uint128_t operator*(const T & rhs) const{
  223. return *this * uint128_t(rhs);
  224. }
  225. uint128_t & operator*=(const uint128_t & rhs);
  226. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  227. uint128_t & operator*=(const T & rhs){
  228. *this = *this * uint128_t(rhs);
  229. return *this;
  230. }
  231. private:
  232. std::pair <uint128_t, uint128_t> divmod(const uint128_t & lhs, const uint128_t & rhs) const;
  233. public:
  234. uint128_t operator/(const uint128_t & rhs) const;
  235. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  236. uint128_t operator/(const T & rhs) const{
  237. return *this / uint128_t(rhs);
  238. }
  239. uint128_t & operator/=(const uint128_t & rhs);
  240. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  241. uint128_t & operator/=(const T & rhs){
  242. *this = *this / uint128_t(rhs);
  243. return *this;
  244. }
  245. uint128_t operator%(const uint128_t & rhs) const;
  246. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  247. uint128_t operator%(const T & rhs) const{
  248. return *this % uint128_t(rhs);
  249. }
  250. uint128_t & operator%=(const uint128_t & rhs);
  251. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  252. uint128_t & operator%=(const T & rhs){
  253. *this = *this % uint128_t(rhs);
  254. return *this;
  255. }
  256. // Increment Operator
  257. uint128_t & operator++();
  258. uint128_t operator++(int);
  259. // Decrement Operator
  260. uint128_t & operator--();
  261. uint128_t operator--(int);
  262. // Nothing done since promotion doesn't work here
  263. uint128_t operator+() const;
  264. // two's complement
  265. uint128_t operator-() const;
  266. // Get private values
  267. const uint64_t & upper() const;
  268. const uint64_t & lower() const;
  269. // Get bitsize of value
  270. uint8_t bits() const;
  271. // Get string representation of value
  272. std::string str(uint8_t base = 10, const unsigned int & len = 0) const;
  273. };
  274. // useful values
  275. UINT128_T_EXTERN extern const uint128_t uint128_0;
  276. UINT128_T_EXTERN extern const uint128_t uint128_1;
  277. // lhs type T as first arguemnt
  278. // If the output is not a bool, casts to type T
  279. // Bitwise Operators
  280. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  281. uint128_t operator&(const T & lhs, const uint128_t & rhs){
  282. return rhs & lhs;
  283. }
  284. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  285. T & operator&=(T & lhs, const uint128_t & rhs){
  286. return lhs = static_cast <T> (rhs & lhs);
  287. }
  288. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  289. uint128_t operator|(const T & lhs, const uint128_t & rhs){
  290. return rhs | lhs;
  291. }
  292. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  293. T & operator|=(T & lhs, const uint128_t & rhs){
  294. return lhs = static_cast <T> (rhs | lhs);
  295. }
  296. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  297. uint128_t operator^(const T & lhs, const uint128_t & rhs){
  298. return rhs ^ lhs;
  299. }
  300. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  301. T & operator^=(T & lhs, const uint128_t & rhs){
  302. return lhs = static_cast <T> (rhs ^ lhs);
  303. }
  304. // Bitshift operators
  305. UINT128_T_EXTERN uint128_t operator<<(const bool & lhs, const uint128_t & rhs);
  306. UINT128_T_EXTERN uint128_t operator<<(const uint8_t & lhs, const uint128_t & rhs);
  307. UINT128_T_EXTERN uint128_t operator<<(const uint16_t & lhs, const uint128_t & rhs);
  308. UINT128_T_EXTERN uint128_t operator<<(const uint32_t & lhs, const uint128_t & rhs);
  309. UINT128_T_EXTERN uint128_t operator<<(const uint64_t & lhs, const uint128_t & rhs);
  310. UINT128_T_EXTERN uint128_t operator<<(const int8_t & lhs, const uint128_t & rhs);
  311. UINT128_T_EXTERN uint128_t operator<<(const int16_t & lhs, const uint128_t & rhs);
  312. UINT128_T_EXTERN uint128_t operator<<(const int32_t & lhs, const uint128_t & rhs);
  313. UINT128_T_EXTERN uint128_t operator<<(const int64_t & lhs, const uint128_t & rhs);
  314. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  315. T & operator<<=(T & lhs, const uint128_t & rhs){
  316. return lhs = static_cast <T> (uint128_t(lhs) << rhs);
  317. }
  318. UINT128_T_EXTERN uint128_t operator>>(const bool & lhs, const uint128_t & rhs);
  319. UINT128_T_EXTERN uint128_t operator>>(const uint8_t & lhs, const uint128_t & rhs);
  320. UINT128_T_EXTERN uint128_t operator>>(const uint16_t & lhs, const uint128_t & rhs);
  321. UINT128_T_EXTERN uint128_t operator>>(const uint32_t & lhs, const uint128_t & rhs);
  322. UINT128_T_EXTERN uint128_t operator>>(const uint64_t & lhs, const uint128_t & rhs);
  323. UINT128_T_EXTERN uint128_t operator>>(const int8_t & lhs, const uint128_t & rhs);
  324. UINT128_T_EXTERN uint128_t operator>>(const int16_t & lhs, const uint128_t & rhs);
  325. UINT128_T_EXTERN uint128_t operator>>(const int32_t & lhs, const uint128_t & rhs);
  326. UINT128_T_EXTERN uint128_t operator>>(const int64_t & lhs, const uint128_t & rhs);
  327. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  328. T & operator>>=(T & lhs, const uint128_t & rhs){
  329. return lhs = static_cast <T> (uint128_t(lhs) >> rhs);
  330. }
  331. // Comparison Operators
  332. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  333. bool operator==(const T & lhs, const uint128_t & rhs){
  334. return (!rhs.upper() && ((uint64_t) lhs == rhs.lower()));
  335. }
  336. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  337. bool operator!=(const T & lhs, const uint128_t & rhs){
  338. return (rhs.upper() | ((uint64_t) lhs != rhs.lower()));
  339. }
  340. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  341. bool operator>(const T & lhs, const uint128_t & rhs){
  342. return (!rhs.upper()) && ((uint64_t) lhs > rhs.lower());
  343. }
  344. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  345. bool operator<(const T & lhs, const uint128_t & rhs){
  346. if (rhs.upper()){
  347. return true;
  348. }
  349. return ((uint64_t) lhs < rhs.lower());
  350. }
  351. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  352. bool operator>=(const T & lhs, const uint128_t & rhs){
  353. if (rhs.upper()){
  354. return false;
  355. }
  356. return ((uint64_t) lhs >= rhs.lower());
  357. }
  358. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  359. bool operator<=(const T & lhs, const uint128_t & rhs){
  360. if (rhs.upper()){
  361. return true;
  362. }
  363. return ((uint64_t) lhs <= rhs.lower());
  364. }
  365. // Arithmetic Operators
  366. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  367. uint128_t operator+(const T & lhs, const uint128_t & rhs){
  368. return rhs + lhs;
  369. }
  370. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  371. T & operator+=(T & lhs, const uint128_t & rhs){
  372. return lhs = static_cast <T> (rhs + lhs);
  373. }
  374. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  375. uint128_t operator-(const T & lhs, const uint128_t & rhs){
  376. return -(rhs - lhs);
  377. }
  378. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  379. T & operator-=(T & lhs, const uint128_t & rhs){
  380. return lhs = static_cast <T> (-(rhs - lhs));
  381. }
  382. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  383. uint128_t operator*(const T & lhs, const uint128_t & rhs){
  384. return rhs * lhs;
  385. }
  386. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  387. T & operator*=(T & lhs, const uint128_t & rhs){
  388. return lhs = static_cast <T> (rhs * lhs);
  389. }
  390. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  391. uint128_t operator/(const T & lhs, const uint128_t & rhs){
  392. return uint128_t(lhs) / rhs;
  393. }
  394. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  395. T & operator/=(T & lhs, const uint128_t & rhs){
  396. return lhs = static_cast <T> (uint128_t(lhs) / rhs);
  397. }
  398. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  399. uint128_t operator%(const T & lhs, const uint128_t & rhs){
  400. return uint128_t(lhs) % rhs;
  401. }
  402. template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type >
  403. T & operator%=(T & lhs, const uint128_t & rhs){
  404. return lhs = static_cast <T> (uint128_t(lhs) % rhs);
  405. }
  406. // IO Operator
  407. UINT128_T_EXTERN std::ostream & operator<<(std::ostream & stream, const uint128_t & rhs);
  408. #endif
  409. #endif