int128.h 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278
  1. #pragma once
  2. #include "int128_util.h"
  3. #include <util/generic/bitops.h>
  4. #include <util/system/compiler.h>
  5. #include <util/system/defaults.h>
  6. #include <util/stream/output.h>
  7. #include <util/string/cast.h>
  8. #include <util/string/builder.h>
  9. #include <util/str_stl.h>
  10. #include <util/ysaveload.h>
  11. #include <cfenv>
  12. #include <climits>
  13. #include <cmath>
  14. #include <limits>
  15. #include <type_traits>
  16. #if !defined(_little_endian_) && !defined(_big_endian_)
  17. static_assert(false, "Platform endianness is not supported");
  18. #endif
  19. template <bool IsSigned>
  20. class TInteger128 {
  21. public:
  22. TInteger128() noexcept = default;
  23. #if defined(_little_endian_)
  24. constexpr TInteger128(const ui64 high, const ui64 low) noexcept
  25. : Low_(low)
  26. , High_(high)
  27. {
  28. }
  29. #elif defined(_big_endian_)
  30. constexpr TInteger128(const ui64 high, const ui64 low) noexcept
  31. : High_(high)
  32. , Low_(low)
  33. {
  34. }
  35. #endif
  36. constexpr TInteger128(const TInteger128<!IsSigned> other) noexcept
  37. : TInteger128{GetHigh(other), GetLow(other)}
  38. {
  39. }
  40. #if defined(_little_endian_)
  41. constexpr TInteger128(const char other) noexcept
  42. : Low_{static_cast<ui64>(other)}
  43. , High_{0}
  44. {
  45. }
  46. constexpr TInteger128(const ui8 other) noexcept
  47. : Low_{other}
  48. , High_{0}
  49. {
  50. }
  51. constexpr TInteger128(const ui16 other) noexcept
  52. : Low_{other}
  53. , High_{0}
  54. {
  55. }
  56. constexpr TInteger128(const ui32 other) noexcept
  57. : Low_{other}
  58. , High_{0}
  59. {
  60. }
  61. constexpr TInteger128(const ui64 other) noexcept
  62. : Low_{other}
  63. , High_{0}
  64. {
  65. }
  66. #if defined(Y_HAVE_INT128)
  67. constexpr TInteger128(const unsigned __int128 other) noexcept
  68. : Low_{static_cast<ui64>(other & ~ui64{0})}
  69. , High_{static_cast<ui64>(other >> 64)}
  70. {
  71. }
  72. #endif
  73. constexpr TInteger128(const i8 other) noexcept
  74. : Low_{static_cast<ui64>(other)}
  75. , High_{other < 0 ? std::numeric_limits<ui64>::max() : 0}
  76. {
  77. }
  78. constexpr TInteger128(const i16 other) noexcept
  79. : Low_{static_cast<ui64>(other)}
  80. , High_{other < 0 ? std::numeric_limits<ui64>::max() : 0}
  81. {
  82. }
  83. constexpr TInteger128(const i32 other) noexcept
  84. : Low_(static_cast<ui64>(other))
  85. , High_{other < 0 ? std::numeric_limits<ui64>::max() : 0}
  86. {
  87. }
  88. constexpr TInteger128(const i64 other) noexcept
  89. : Low_(static_cast<ui64>(other))
  90. , High_{other < 0 ? std::numeric_limits<ui64>::max() : 0}
  91. {
  92. }
  93. #if defined(Y_HAVE_INT128)
  94. template <bool IsSigned2 = IsSigned, std::enable_if_t<!IsSigned2, bool> = false>
  95. constexpr TInteger128(const signed __int128 other) noexcept
  96. : Low_{static_cast<ui64>(other & ~ui64{0})}
  97. , High_{static_cast<ui64>(static_cast<unsigned __int128>(other) >> 64)}
  98. {
  99. }
  100. template <bool IsSigned2 = IsSigned, typename std::enable_if_t<IsSigned2, bool> = false>
  101. constexpr TInteger128(const signed __int128 other) noexcept
  102. : Low_{static_cast<ui64>(other & ~ui64(0))}
  103. , High_{static_cast<ui64>(other >> 64)}
  104. {
  105. }
  106. #endif
  107. #elif defined(_big_endian_)
  108. static_assert(false, "Big-endian will be later");
  109. #endif // _little_endian_ or _big_endian_
  110. constexpr TInteger128& operator=(const char other) noexcept {
  111. *this = TInteger128{other};
  112. return *this;
  113. }
  114. constexpr TInteger128& operator=(const ui8 other) noexcept {
  115. *this = TInteger128{other};
  116. return *this;
  117. }
  118. constexpr TInteger128& operator=(const ui16 other) noexcept {
  119. *this = TInteger128{other};
  120. return *this;
  121. }
  122. constexpr TInteger128& operator=(const ui32 other) noexcept {
  123. *this = TInteger128{other};
  124. return *this;
  125. }
  126. constexpr TInteger128& operator=(const ui64 other) noexcept {
  127. *this = TInteger128{other};
  128. return *this;
  129. }
  130. #if defined(Y_HAVE_INT128)
  131. constexpr TInteger128& operator=(const unsigned __int128 other) noexcept {
  132. *this = TInteger128{other};
  133. return *this;
  134. }
  135. #endif
  136. constexpr TInteger128& operator=(const i8 other) noexcept {
  137. *this = TInteger128{other};
  138. return *this;
  139. }
  140. constexpr TInteger128& operator=(const i16 other) noexcept {
  141. *this = TInteger128{other};
  142. return *this;
  143. }
  144. constexpr TInteger128& operator=(const i32 other) noexcept {
  145. *this = TInteger128{other};
  146. return *this;
  147. }
  148. constexpr TInteger128& operator=(const i64 other) noexcept {
  149. *this = TInteger128{other};
  150. return *this;
  151. }
  152. #if defined(Y_HAVE_INT128)
  153. constexpr TInteger128& operator=(const signed __int128 other) noexcept {
  154. *this = TInteger128{other};
  155. return *this;
  156. }
  157. #endif // Y_HAVE_INT128
  158. constexpr TInteger128& operator+=(const TInteger128 other) noexcept {
  159. return *this = *this + other;
  160. }
  161. constexpr TInteger128& operator-=(const TInteger128 other) noexcept {
  162. return *this = *this - other;
  163. }
  164. constexpr TInteger128& operator*=(const TInteger128 other) noexcept {
  165. return *this = *this * other;
  166. }
  167. constexpr TInteger128& operator&=(const TInteger128 other) noexcept {
  168. return *this = *this & other;
  169. }
  170. constexpr TInteger128& operator^=(const TInteger128 other) noexcept {
  171. return *this = *this ^ other;
  172. }
  173. constexpr TInteger128& operator|=(const TInteger128 other) noexcept {
  174. return *this = *this | other;
  175. }
  176. constexpr TInteger128& operator<<=(int n) noexcept {
  177. *this = *this << n;
  178. return *this;
  179. }
  180. constexpr TInteger128& operator>>=(int n) noexcept {
  181. *this = *this >> n;
  182. return *this;
  183. }
  184. constexpr TInteger128& operator++() noexcept {
  185. *this += 1;
  186. return *this;
  187. }
  188. constexpr TInteger128 operator++(int) noexcept {
  189. const TInteger128 ret{*this};
  190. this->operator++();
  191. return ret;
  192. }
  193. constexpr TInteger128& operator--() noexcept {
  194. *this -= 1;
  195. return *this;
  196. }
  197. constexpr TInteger128 operator--(int) noexcept {
  198. const TInteger128 ret{*this};
  199. this->operator--();
  200. return ret;
  201. }
  202. explicit constexpr operator bool() const noexcept {
  203. return Low_ || High_;
  204. }
  205. explicit constexpr operator char() const noexcept {
  206. return static_cast<char>(Low_);
  207. }
  208. explicit constexpr operator ui8() const noexcept {
  209. return static_cast<ui8>(Low_);
  210. }
  211. explicit constexpr operator i8() const noexcept {
  212. return static_cast<i8>(Low_);
  213. }
  214. explicit constexpr operator ui16() const noexcept {
  215. return static_cast<ui16>(Low_);
  216. }
  217. explicit constexpr operator i16() const noexcept {
  218. return static_cast<i16>(Low_);
  219. }
  220. explicit constexpr operator ui32() const noexcept {
  221. return static_cast<ui32>(Low_);
  222. }
  223. explicit constexpr operator i32() const noexcept {
  224. return static_cast<i32>(Low_);
  225. }
  226. explicit constexpr operator ui64() const noexcept {
  227. return static_cast<ui64>(Low_);
  228. }
  229. explicit constexpr operator i64() const noexcept {
  230. return static_cast<i64>(Low_);
  231. }
  232. #if defined(Y_HAVE_INT128)
  233. explicit constexpr operator unsigned __int128() const noexcept {
  234. return (static_cast<unsigned __int128>(High_) << 64) + Low_;
  235. }
  236. explicit constexpr operator signed __int128() const noexcept {
  237. return (static_cast<__int128>(High_) << 64) + Low_;
  238. }
  239. #endif
  240. private:
  241. #if defined(_little_endian_)
  242. ui64 Low_;
  243. ui64 High_;
  244. #elif defined(_big_endian_)
  245. ui64 High_;
  246. ui64 Low_;
  247. #endif
  248. template <bool IsSigned2>
  249. friend constexpr ui64 GetHigh(TInteger128<IsSigned2> value) noexcept;
  250. template <bool IsSigned2>
  251. friend constexpr ui64 GetLow(TInteger128<IsSigned2> value) noexcept;
  252. friend constexpr bool signbit(TInteger128 arg) noexcept {
  253. if constexpr (IsSigned) {
  254. return GetHigh(arg) & 0x8000000000000000;
  255. } else {
  256. Y_UNUSED(arg);
  257. return false;
  258. }
  259. }
  260. friend constexpr TInteger128 abs(TInteger128 arg) noexcept {
  261. if constexpr (IsSigned) {
  262. return signbit(arg) ? (-arg) : arg;
  263. } else {
  264. return arg;
  265. }
  266. }
  267. friend IOutputStream& operator<<(IOutputStream& out, const TInteger128& other);
  268. }; // class TInteger128
  269. using ui128 = TInteger128<false>;
  270. using i128 = TInteger128<true>;
  271. constexpr ui128 operator+(ui128 lhs, ui128 rhs) noexcept;
  272. constexpr i128 operator+( i128 lhs, i128 rhs) noexcept;
  273. constexpr ui128 operator-(ui128 lhs, ui128 rhs) noexcept;
  274. constexpr i128 operator-( i128 lhs, i128 rhs) noexcept;
  275. constexpr ui128 operator-(ui128 num) noexcept;
  276. constexpr i128 operator-( i128 num) noexcept;
  277. constexpr ui128 operator*(ui128 lhs, ui128 rhs) noexcept;
  278. constexpr i128 operator*( i128 lhs, i128 rhs) noexcept;
  279. constexpr ui128 operator/(ui128 lhs, ui128 rhs) noexcept;
  280. constexpr i128 operator/( i128 lhs, i128 rhs) noexcept;
  281. constexpr ui128 operator%(ui128 lhs, ui128 rhs) noexcept;
  282. constexpr i128 operator%( i128 lhs, i128 rhs) noexcept;
  283. constexpr ui128 operator|(ui128 lhs, ui128 rhs) noexcept;
  284. constexpr i128 operator|( i128 lhs, i128 rhs) noexcept;
  285. constexpr ui128 operator&(ui128 lhs, ui128 rhs) noexcept;
  286. constexpr i128 operator&( i128 lhs, i128 rhs) noexcept;
  287. constexpr ui128 operator^(ui128 lhs, ui128 rhs) noexcept;
  288. constexpr i128 operator^( i128 lhs, i128 rhs) noexcept;
  289. constexpr ui128 operator<<(ui128 lhs, int n) noexcept;
  290. constexpr i128 operator<<( i128 lhs, int n) noexcept;
  291. constexpr ui128 operator>>(ui128 lhs, int n) noexcept;
  292. constexpr i128 operator>>( i128 lhs, int n) noexcept;
  293. template <bool IsSigned>
  294. size_t MostSignificantBit(const TInteger128<IsSigned> v);
  295. namespace std {
  296. //// type traits
  297. template <bool IsSigned>
  298. struct is_integral<TInteger128<IsSigned>> : public std::true_type{};
  299. template <bool IsSigned>
  300. struct is_class<TInteger128<IsSigned>> : public std::false_type{};
  301. template <>
  302. struct is_signed<ui128> : public std::false_type{};
  303. template <>
  304. struct is_signed<i128> : public std::true_type{};
  305. }
  306. template <bool IsSigned>
  307. constexpr ui64 GetHigh(const TInteger128<IsSigned> value) noexcept {
  308. return value.High_;
  309. }
  310. template <bool IsSigned>
  311. constexpr ui64 GetLow(const TInteger128<IsSigned> value) noexcept {
  312. return value.Low_;
  313. }
  314. template <class T, std::enable_if_t<std::is_same_v<std::remove_cv_t<T>, i128>>* = nullptr>
  315. constexpr ui128 operator-(const ui128 lhs, const T rhs) noexcept {
  316. return lhs - static_cast<ui128>(rhs);
  317. }
  318. template <class T, std::enable_if_t<std::is_same_v<std::remove_cv_t<T>, ui128>>* = nullptr>
  319. constexpr ui128 operator-(const i128 lhs, const T rhs) noexcept {
  320. return static_cast<ui128>(lhs) - rhs;
  321. }
  322. // specialize std templates
  323. namespace std {
  324. // numeric limits
  325. // see full list at https://en.cppreference.com/w/cpp/types/numeric_limits
  326. template <bool IsSigned>
  327. struct numeric_limits<TInteger128<IsSigned>> {
  328. static constexpr bool is_specialized = true;
  329. static constexpr bool is_signed = IsSigned;
  330. static constexpr bool is_integer = true;
  331. static constexpr bool is_exact = true;
  332. static constexpr bool has_infinity = false;
  333. static constexpr bool has_quiet_NAN = false;
  334. static constexpr bool has_signaling_NAN = false;
  335. static constexpr float_denorm_style has_denorm = std::denorm_absent;
  336. static constexpr bool has_denorm_loss = false;
  337. static constexpr float_round_style round_style = std::round_toward_zero;
  338. static constexpr bool is_iec559 = false;
  339. static constexpr bool is_bounded = true;
  340. static constexpr bool is_modulo = true;
  341. static constexpr int digits = CHAR_BIT * sizeof(ui128) - (IsSigned ? 1 : 0);
  342. static constexpr int digits10 = 38; // std::numeric_limits<ui128>::digits * std::log10(2);
  343. static constexpr int max_digits10 = 0;
  344. static constexpr int radix = 2;
  345. static constexpr int min_exponent = 0;
  346. static constexpr int min_exponent10 = 0;
  347. static constexpr int max_exponent = 0;
  348. static constexpr int max_exponent10 = 0;
  349. static constexpr bool traps = std::numeric_limits<ui64>::traps; // same as of any other ui*
  350. static constexpr bool tinyness_before = false;
  351. static constexpr TInteger128<IsSigned> min() noexcept {
  352. if constexpr (IsSigned) {
  353. return TInteger128<IsSigned>{
  354. static_cast<ui64>(std::numeric_limits<i64>::min()),
  355. 0
  356. };
  357. }
  358. else {
  359. return 0;
  360. }
  361. }
  362. static constexpr TInteger128<IsSigned> lowest() noexcept {
  363. return min();
  364. }
  365. static constexpr TInteger128<IsSigned> max() noexcept {
  366. if constexpr (IsSigned) {
  367. return TInteger128<IsSigned>{
  368. static_cast<ui64>(std::numeric_limits<i64>::max()),
  369. std::numeric_limits<ui64>::max()
  370. };
  371. }
  372. else {
  373. return TInteger128<IsSigned>{
  374. std::numeric_limits<ui64>::max(),
  375. std::numeric_limits<ui64>::max()
  376. };
  377. }
  378. }
  379. static constexpr TInteger128<IsSigned> epsilon() noexcept {
  380. return 0;
  381. }
  382. static constexpr TInteger128<IsSigned> round_error() noexcept {
  383. return 0;
  384. }
  385. static constexpr TInteger128<IsSigned> infinity() noexcept {
  386. return 0;
  387. }
  388. static constexpr TInteger128<IsSigned> quiet_NAN() noexcept {
  389. return 0;
  390. }
  391. static constexpr TInteger128<IsSigned> signaling_NAN() noexcept {
  392. return 0;
  393. }
  394. static constexpr TInteger128<IsSigned> denorm_min() noexcept {
  395. return 0;
  396. }
  397. };
  398. }
  399. constexpr bool operator==(const ui128 lhs, const ui128 rhs) noexcept {
  400. return GetLow(lhs) == GetLow(rhs) && GetHigh(lhs) == GetHigh(rhs);
  401. }
  402. constexpr bool operator==(const i128 lhs, const i128 rhs) noexcept {
  403. return GetLow(lhs) == GetLow(rhs) && GetHigh(lhs) == GetHigh(rhs);
  404. }
  405. constexpr bool operator!=(const ui128 lhs, const ui128 rhs) noexcept {
  406. return !(lhs == rhs);
  407. }
  408. constexpr bool operator!=(const i128 lhs, const i128 rhs) noexcept {
  409. return !(lhs == rhs);
  410. }
  411. constexpr bool operator<(const ui128 lhs, const ui128 rhs) noexcept {
  412. if (GetHigh(lhs) != GetHigh(rhs)) {
  413. return GetHigh(lhs) < GetHigh(rhs);
  414. }
  415. return GetLow(lhs) < GetLow(rhs);
  416. }
  417. constexpr bool operator<(const i128 lhs, const i128 rhs) noexcept {
  418. if (lhs == 0 && rhs == 0) {
  419. return false;
  420. }
  421. const bool lhsIsNegative = signbit(lhs);
  422. const bool rhsIsNegative = signbit(rhs);
  423. if (lhsIsNegative && !rhsIsNegative) {
  424. return true;
  425. }
  426. if (!lhsIsNegative && rhsIsNegative) {
  427. return false;
  428. }
  429. // both are negative or both are positive
  430. if (GetHigh(lhs) != GetHigh(rhs)) {
  431. return GetHigh(lhs) < GetHigh(rhs);
  432. }
  433. return GetLow(lhs) < GetLow(rhs);
  434. }
  435. constexpr bool operator>(const ui128 lhs, const ui128 rhs) noexcept {
  436. return rhs < lhs;
  437. }
  438. constexpr bool operator>(const i128 lhs, const i128 rhs) noexcept {
  439. return rhs < lhs;
  440. }
  441. constexpr bool operator<=(const ui128 lhs, const ui128 rhs) noexcept {
  442. return !(rhs < lhs);
  443. }
  444. constexpr bool operator<=(const i128 lhs, const i128 rhs) noexcept {
  445. return !(rhs < lhs);
  446. }
  447. constexpr bool operator>=(const ui128 lhs, const ui128 rhs) noexcept {
  448. return !(lhs < rhs);
  449. }
  450. constexpr bool operator>=(const i128 lhs, const i128 rhs) noexcept {
  451. return !(lhs < rhs);
  452. }
  453. constexpr ui128 operator+(const ui128 lhs, const ui128 rhs) noexcept {
  454. const ui128 result{GetHigh(lhs) + GetHigh(rhs), GetLow(lhs) + GetLow(rhs)};
  455. if (GetLow(result) < GetLow(lhs)) {
  456. return ui128{GetHigh(result) + 1, GetLow(result)};
  457. }
  458. return result;
  459. }
  460. constexpr i128 operator+(const i128 lhs, const i128 rhs) noexcept {
  461. const i128 result{GetHigh(lhs) + GetHigh(rhs), GetLow(lhs) + GetLow(rhs)};
  462. if (GetLow(result) < GetLow(lhs)) {
  463. return i128{GetHigh(result) + 1, GetLow(result)};
  464. }
  465. return result;
  466. }
  467. constexpr ui128 operator-(const ui128 lhs, const ui128 rhs) noexcept {
  468. const ui128 result{GetHigh(lhs) - GetHigh(rhs), GetLow(lhs) - GetLow(rhs)};
  469. if (GetLow(result) > GetLow(lhs)) { // underflow
  470. return ui128{GetHigh(result) - 1, GetLow(result)};
  471. }
  472. return result;
  473. }
  474. constexpr i128 operator-(const i128 lhs, const i128 rhs) noexcept {
  475. const i128 result{GetHigh(lhs) - GetHigh(rhs), GetLow(lhs) - GetLow(rhs)};
  476. if (GetLow(result) > GetLow(lhs)) { // underflow
  477. return i128{GetHigh(result) - 1, GetLow(result)};
  478. }
  479. return result;
  480. }
  481. constexpr ui128 operator-(const ui128 num) noexcept {
  482. const ui128 result{~GetHigh(num), ~GetLow(num) + 1};
  483. if (GetLow(result) == 0) {
  484. return ui128{GetHigh(result) + 1, GetLow(result)};
  485. }
  486. return result;
  487. }
  488. constexpr i128 operator-(const i128 num) noexcept {
  489. const i128 result{~GetHigh(num), ~GetLow(num) + 1};
  490. if (GetLow(result) == 0) {
  491. return i128{GetHigh(result) + 1, GetLow(result)};
  492. }
  493. return result;
  494. }
  495. constexpr ui128 operator*(const ui128 lhs, const ui128 rhs) noexcept {
  496. if (rhs == 0) {
  497. return 0;
  498. }
  499. if (rhs == 1) {
  500. return lhs;
  501. }
  502. ui128 result{};
  503. ui128 t = rhs;
  504. for (size_t i = 0; i < 128; ++i) {
  505. if ((t & 1) != 0) {
  506. result += (lhs << i);
  507. }
  508. t = t >> 1;
  509. }
  510. return result;
  511. }
  512. constexpr i128 operator*(const i128 lhs, const i128 rhs) noexcept {
  513. if (rhs == 0) {
  514. return 0;
  515. }
  516. if (rhs == 1) {
  517. return lhs;
  518. }
  519. i128 result{};
  520. i128 t = rhs;
  521. for (size_t i = 0; i < 128; ++i) {
  522. if ((t & 1) != 0) {
  523. result += (lhs << i);
  524. }
  525. t = t >> 1;
  526. }
  527. return result;
  528. }
  529. namespace NPrivateInt128 {
  530. // NOTE: division by zero is UB and can be changed in future
  531. constexpr void DivMod128(const ui128 lhs, const ui128 rhs, ui128* const quo, ui128* const rem) {
  532. if (!quo && !rem) {
  533. return;
  534. }
  535. constexpr size_t n_udword_bits = sizeof(ui64) * CHAR_BIT;
  536. constexpr size_t n_utword_bits = sizeof(ui128) * CHAR_BIT;
  537. ui128 q{};
  538. ui128 r{};
  539. unsigned sr{};
  540. /* special cases, X is unknown, K != 0 */
  541. if (GetHigh(lhs) == 0)
  542. {
  543. if (GetHigh(rhs) == 0)
  544. {
  545. /* 0 X
  546. * ---
  547. * 0 X
  548. */
  549. if (rem) {
  550. *rem = GetLow(lhs) % GetLow(rhs);
  551. }
  552. if (quo) {
  553. *quo = GetLow(lhs) / GetLow(rhs);
  554. }
  555. return;
  556. }
  557. /* 0 X
  558. * ---
  559. * K X
  560. */
  561. if (rem) {
  562. *rem = GetLow(lhs);
  563. }
  564. if (quo) {
  565. *quo = 0;
  566. }
  567. return;
  568. }
  569. /* n.s.high != 0 */
  570. if (GetLow(rhs) == 0)
  571. {
  572. if (GetHigh(rhs) == 0)
  573. {
  574. /* K X
  575. * ---
  576. * 0 0
  577. */
  578. if (rem) {
  579. *rem = GetHigh(lhs) % GetLow(rhs);
  580. }
  581. if (quo) {
  582. *quo = GetHigh(lhs) / GetLow(rhs);
  583. }
  584. return;
  585. }
  586. /* d.s.high != 0 */
  587. if (GetLow(lhs) == 0)
  588. {
  589. /* K 0
  590. * ---
  591. * K 0
  592. */
  593. if (rem) {
  594. *rem = ui128{GetHigh(lhs) % GetHigh(rhs), 0};
  595. }
  596. if (quo) {
  597. *quo = GetHigh(lhs) / GetHigh(rhs);
  598. }
  599. return;
  600. }
  601. /* K K
  602. * ---
  603. * K 0
  604. */
  605. if ((GetHigh(rhs) & (GetHigh(rhs) - 1)) == 0) /* if d is a power of 2 */
  606. {
  607. if (rem) {
  608. *rem = ui128{GetHigh(lhs) & (GetHigh(rhs) - 1), GetLow(lhs)};
  609. }
  610. if (quo) {
  611. *quo = GetHigh(lhs) >> CountLeadingZeroBits(GetHigh(rhs));
  612. }
  613. return;
  614. }
  615. /* K K
  616. * ---
  617. * K 0
  618. */
  619. sr = CountLeadingZeroBits(GetHigh(rhs)) - CountLeadingZeroBits(GetHigh(lhs));
  620. /* 0 <= sr <= n_udword_bits - 2 or sr large */
  621. if (sr > n_udword_bits - 2)
  622. {
  623. if (rem) {
  624. *rem = lhs;
  625. }
  626. if (quo) {
  627. *quo = 0;
  628. }
  629. return;
  630. }
  631. ++sr;
  632. /* 1 <= sr <= n_udword_bits - 1 */
  633. /* q.all = n.all << (n_utword_bits - sr); */
  634. q = ui128{
  635. GetLow(lhs) << (n_udword_bits - sr),
  636. 0
  637. };
  638. r = ui128{
  639. GetHigh(lhs) >> sr,
  640. (GetHigh(lhs) << (n_udword_bits - sr)) | (GetLow(lhs) >> sr)
  641. };
  642. }
  643. else /* d.s.low != 0 */
  644. {
  645. if (GetHigh(rhs) == 0)
  646. {
  647. /* K X
  648. * ---
  649. * 0 K
  650. */
  651. if ((GetLow(rhs) & (GetLow(rhs) - 1)) == 0) /* if d is a power of 2 */
  652. {
  653. if (rem) {
  654. *rem = ui128{0, GetLow(lhs) & (GetLow(rhs) - 1)};
  655. }
  656. if (GetLow(rhs) == 1) {
  657. if (quo) {
  658. *quo = lhs;
  659. }
  660. return;
  661. }
  662. sr = CountTrailingZeroBits(GetLow(rhs));
  663. if (quo) {
  664. *quo = ui128{
  665. GetHigh(lhs) >> sr,
  666. (GetHigh(lhs) << (n_udword_bits - sr)) | (GetLow(lhs) >> sr)
  667. };
  668. return;
  669. }
  670. }
  671. /* K X
  672. * ---
  673. * 0 K
  674. */
  675. sr = 1 + n_udword_bits + CountLeadingZeroBits(GetLow(rhs))
  676. - CountLeadingZeroBits(GetHigh(lhs));
  677. /* 2 <= sr <= n_utword_bits - 1
  678. * q.all = n.all << (n_utword_bits - sr);
  679. * r.all = n.all >> sr;
  680. */
  681. if (sr == n_udword_bits)
  682. {
  683. q = ui128{GetLow(lhs), 0};
  684. r = ui128{0, GetHigh(lhs)};
  685. }
  686. else if (sr < n_udword_bits) // 2 <= sr <= n_udword_bits - 1
  687. {
  688. q = ui128{
  689. GetLow(lhs) << (n_udword_bits - sr),
  690. 0
  691. };
  692. r = ui128{
  693. GetHigh(lhs) >> sr,
  694. (GetHigh(lhs) << (n_udword_bits - sr)) | (GetLow(lhs) >> sr)
  695. };
  696. }
  697. else // n_udword_bits + 1 <= sr <= n_utword_bits - 1
  698. {
  699. q = ui128{
  700. (GetHigh(lhs) << (n_utword_bits - sr)) | (GetLow(lhs) >> (sr - n_udword_bits)),
  701. GetLow(lhs) << (n_utword_bits - sr)
  702. };
  703. r = ui128{
  704. 0,
  705. GetHigh(lhs) >> (sr - n_udword_bits)
  706. };
  707. }
  708. }
  709. else
  710. {
  711. /* K X
  712. * ---
  713. * K K
  714. */
  715. sr = CountLeadingZeroBits(GetHigh(rhs)) - CountLeadingZeroBits(GetHigh(lhs));
  716. /*0 <= sr <= n_udword_bits - 1 or sr large */
  717. if (sr > n_udword_bits - 1)
  718. {
  719. if (rem) {
  720. *rem = lhs;
  721. }
  722. if (quo) {
  723. *quo = 0;
  724. }
  725. return;
  726. }
  727. ++sr;
  728. /* 1 <= sr <= n_udword_bits
  729. * q.all = n.all << (n_utword_bits - sr);
  730. * r.all = n.all >> sr;
  731. */
  732. if (sr == n_udword_bits)
  733. {
  734. q = ui128{
  735. GetLow(lhs),
  736. 0
  737. };
  738. r = ui128{
  739. 0,
  740. GetHigh(lhs)
  741. };
  742. }
  743. else
  744. {
  745. r = ui128{
  746. GetHigh(lhs) >> sr,
  747. (GetHigh(lhs) << (n_udword_bits - sr)) | (GetLow(lhs) >> sr)
  748. };
  749. q = ui128{
  750. GetLow(lhs) << (n_udword_bits - sr),
  751. 0
  752. };
  753. }
  754. }
  755. }
  756. /* Not a special case
  757. * q and r are initialized with:
  758. * q = n << (128 - sr);
  759. * r = n >> sr;
  760. * 1 <= sr <= 128 - 1
  761. */
  762. ui32 carry = 0;
  763. for (; sr > 0; --sr)
  764. {
  765. /* r:q = ((r:q) << 1) | carry */
  766. r = ui128{
  767. (GetHigh(r) << 1) | (GetLow(r) >> (n_udword_bits - 1)),
  768. (GetLow(r) << 1) | (GetHigh(q) >> (n_udword_bits - 1))
  769. };
  770. q = ui128{
  771. (GetHigh(q) << 1) | (GetLow(q) >> (n_udword_bits - 1)),
  772. (GetLow(q) << 1) | carry
  773. };
  774. carry = 0;
  775. if (r >= rhs) {
  776. r -= rhs;
  777. carry = 1;
  778. }
  779. }
  780. q = (q << 1) | carry;
  781. if (rem) {
  782. *rem = r;
  783. }
  784. if (quo) {
  785. *quo = q;
  786. }
  787. }
  788. struct TSignedDivisionResult {
  789. i128 Quotient;
  790. i128 Remainder;
  791. };
  792. constexpr TSignedDivisionResult Divide(i128 lhs, i128 rhs) noexcept;
  793. }
  794. constexpr ui128 operator/(const ui128 lhs, const ui128 rhs) noexcept {
  795. ui128 quotient{};
  796. NPrivateInt128::DivMod128(lhs, rhs, &quotient, nullptr);
  797. return quotient;
  798. }
  799. constexpr i128 operator/(const i128 lhs, const i128 rhs) noexcept {
  800. i128 a = abs(lhs);
  801. i128 b = abs(rhs);
  802. ui128 quotient{};
  803. NPrivateInt128::DivMod128(a, b, &quotient, nullptr);
  804. if (signbit(lhs) ^ signbit(rhs)) {
  805. quotient = -quotient;
  806. }
  807. return quotient;
  808. }
  809. constexpr ui128 operator%(const ui128 lhs, const ui128 rhs) noexcept {
  810. ui128 remainder{};
  811. NPrivateInt128::DivMod128(lhs, rhs, nullptr, &remainder);
  812. return remainder;
  813. }
  814. constexpr i128 operator%(const i128 lhs, const i128 rhs) noexcept {
  815. i128 a = abs(lhs);
  816. i128 b = abs(rhs);
  817. ui128 remainder{};
  818. NPrivateInt128::DivMod128(a, b, nullptr, &remainder);
  819. if (signbit(lhs)) {
  820. remainder = -remainder;
  821. }
  822. return remainder;
  823. }
  824. constexpr ui128 operator<<(const ui128 lhs, int n) noexcept {
  825. if (n < 64) {
  826. if (n != 0) {
  827. return
  828. ui128{
  829. (GetHigh(lhs) << n) | (GetLow(lhs) >> (64 - n)),
  830. GetLow(lhs) << n
  831. };
  832. }
  833. return lhs;
  834. }
  835. return ui128{GetLow(lhs) << (n - 64), 0};
  836. }
  837. constexpr ui128 operator>>(const ui128 lhs, int n) noexcept {
  838. if (n < 64) {
  839. if (n != 0) {
  840. return
  841. ui128{
  842. GetHigh(lhs) >> n,
  843. (GetLow(lhs) >> n) | (GetHigh(lhs) << (64 - n))
  844. };
  845. }
  846. return lhs;
  847. }
  848. return ui128{0, GetHigh(lhs) >> (n - 64)};
  849. }
  850. constexpr bool operator!(const ui128 num) noexcept {
  851. return !GetHigh(num) && !GetLow(num);
  852. }
  853. constexpr ui128 operator~(const ui128 num) noexcept {
  854. return ui128{~GetHigh(num), ~GetLow(num)};
  855. }
  856. constexpr ui128 operator|(const ui128 lhs, const ui128 rhs) noexcept {
  857. return ui128{GetHigh(lhs) | GetHigh(rhs), GetLow(lhs) | GetLow(rhs)};
  858. }
  859. constexpr ui128 operator&(const ui128 lhs, const ui128 rhs) noexcept {
  860. return ui128{GetHigh(lhs) & GetHigh(rhs), GetLow(lhs) & GetLow(rhs)};
  861. }
  862. constexpr ui128 operator^(const ui128 lhs, const ui128 rhs) noexcept {
  863. return ui128{GetHigh(lhs) ^ GetHigh(rhs), GetLow(lhs) ^ GetLow(rhs)};
  864. }
  865. IOutputStream& operator<<(IOutputStream& out, const ui128& other);
  866. // For THashMap
  867. template <>
  868. struct THash<ui128> {
  869. inline size_t operator()(const ui128& num) const {
  870. return THash<ui64>()(GetHigh(num)) + THash<ui64>()(GetLow(num));
  871. }
  872. };
  873. template <>
  874. class TSerializer<ui128> {
  875. public:
  876. static void Save(IOutputStream* out, const ui128& Number);
  877. static void Load(IInputStream* in, ui128& Number);
  878. };
  879. template <>
  880. inline TString ToString<ui128>(const ui128& number) {
  881. return TStringBuilder{} << number;
  882. }
  883. template <>
  884. inline ui128 FromStringImpl<ui128>(const char* data, size_t length) {
  885. if (length < 20) {
  886. return ui128{ FromString<ui64>(data, length) };
  887. } else {
  888. ui128 result = 0;
  889. const TStringBuf string(data, length);
  890. for (auto&& c : string) {
  891. if (!std::isdigit(c)) {
  892. ythrow TFromStringException() << "Unexpected symbol \""sv << c << "\""sv;
  893. }
  894. ui128 x1 = result;
  895. ui128 x2 = x1 + x1;
  896. ui128 x4 = x2 + x2;
  897. ui128 x8 = x4 + x4;
  898. ui128 x10 = x8 + x2;
  899. ui128 s = c - '0';
  900. result = x10 + s;
  901. if (GetHigh(result) < GetHigh(x1)) {
  902. ythrow TFromStringException() << TStringBuf("Integer overflow");
  903. }
  904. }
  905. return result;
  906. }
  907. }
  908. #if defined(Y_HAVE_INT128)
  909. template <>
  910. inline TString ToString<unsigned __int128>(const unsigned __int128& number) {
  911. return ToString(ui128{number});
  912. }
  913. template <>
  914. inline unsigned __int128 FromStringImpl<unsigned __int128>(const char* data, size_t length) {
  915. return static_cast<unsigned __int128>(FromString<ui128>(data, length));
  916. }
  917. #endif
  918. // operators
  919. namespace NPrivateInt128 {
  920. // very naive algorithm of division
  921. // no contract for divide by zero (i.e. it is UB) (may be changed in future)
  922. constexpr TSignedDivisionResult Divide(i128 lhs, i128 rhs) noexcept {
  923. TSignedDivisionResult result {};
  924. // check trivial cases
  925. // X/0 = +/- inf, X%0 = X
  926. if (rhs == 0) {
  927. // UB, let's return: `X / 0 = +inf`, and `X % 0 = X`
  928. result.Quotient = signbit(lhs) ? std::numeric_limits<i128>::min() : std::numeric_limits<i128>::max();
  929. result.Remainder = lhs;
  930. }
  931. // 0/Y = 0, 0%Y = 0
  932. else if (lhs == 0) {
  933. result.Quotient = 0;
  934. result.Remainder = 0;
  935. }
  936. // X/1 = X, X%1 = 0
  937. else if (rhs == 1) {
  938. result.Quotient = lhs;
  939. result.Remainder = 0;
  940. }
  941. // X/-1 = -X, X%(-1) = 0
  942. else if (rhs == -1) {
  943. result.Quotient = -lhs;
  944. result.Remainder = 0;
  945. }
  946. // abs(X)<abs(Y), X/Y = 0, X%Y = X
  947. else if (abs(lhs) < abs(rhs)) {
  948. result.Quotient = 0;
  949. result.Remainder = lhs;
  950. }
  951. else if (lhs == rhs) {
  952. result.Quotient = 1;
  953. result.Remainder = 0;
  954. }
  955. else if (lhs == -rhs) {
  956. result.Quotient = -1;
  957. result.Remainder = 0;
  958. }
  959. else if (abs(lhs) > abs(rhs)) {
  960. const bool quotientMustBeNegative = signbit(lhs) ^ signbit(rhs);
  961. const bool remainderMustBeNegative = signbit(lhs);
  962. lhs = abs(lhs);
  963. rhs = abs(rhs);
  964. // result is division of two ui64
  965. if (GetHigh(lhs) == 0 && GetHigh(rhs) == 0) {
  966. result.Quotient = GetLow(lhs) / GetLow(rhs);
  967. result.Remainder = GetLow(lhs) % GetLow(rhs);
  968. }
  969. // naive shift-and-subtract
  970. // https://stackoverflow.com/questions/5386377/division-without-using
  971. i128 denominator = rhs;
  972. result.Quotient = 0;
  973. result.Remainder = lhs;
  974. const size_t shift = MostSignificantBit(lhs) - MostSignificantBit(denominator);
  975. denominator <<= shift;
  976. for (size_t i = 0; i <= shift; ++i) {
  977. result.Quotient <<= 1;
  978. if (result.Remainder >= denominator) {
  979. result.Remainder -= denominator;
  980. result.Quotient |= 1;
  981. }
  982. denominator >>= 1;
  983. }
  984. if (quotientMustBeNegative) {
  985. result.Quotient = -result.Quotient;
  986. }
  987. if (remainderMustBeNegative) {
  988. result.Remainder = -result.Remainder;
  989. }
  990. }
  991. return result;
  992. }
  993. } // namespace NPrivateInt128
  994. constexpr i128 operator<<(const i128 lhs, int n) noexcept {
  995. if (n < 64) {
  996. if (n != 0) {
  997. return
  998. i128{
  999. (GetHigh(lhs) << n) | (GetLow(lhs) >> (64 - n)),
  1000. GetLow(lhs) << n
  1001. };
  1002. }
  1003. return lhs;
  1004. }
  1005. return i128{GetLow(lhs) << (n - 64), 0};
  1006. }
  1007. constexpr i128 operator>>(const i128 lhs, int n) noexcept {
  1008. if (n < 64) {
  1009. if (n != 0) {
  1010. return
  1011. i128{
  1012. GetHigh(lhs) >> n,
  1013. (GetLow(lhs) >> n) | (GetHigh(lhs) << (64 - n))
  1014. };
  1015. }
  1016. return lhs;
  1017. }
  1018. return i128{0, GetHigh(lhs) >> (n - 64)};
  1019. }
  1020. constexpr bool operator!(const i128 num) noexcept {
  1021. return !GetHigh(num) && !GetLow(num);
  1022. }
  1023. constexpr i128 operator~(const i128 num) noexcept {
  1024. return i128{~GetHigh(num), ~GetLow(num)};
  1025. }
  1026. constexpr i128 operator|(const i128 lhs, const i128 rhs) noexcept {
  1027. return i128{GetHigh(lhs) | GetHigh(rhs), GetLow(lhs) | GetLow(rhs)};
  1028. }
  1029. constexpr i128 operator&(const i128 lhs, const i128 rhs) noexcept {
  1030. return i128{GetHigh(lhs) & GetHigh(rhs), GetLow(lhs) & GetLow(rhs)};
  1031. }
  1032. constexpr i128 operator^(const i128 lhs, const i128 rhs) noexcept {
  1033. return i128{GetHigh(lhs) ^ GetHigh(rhs), GetLow(lhs) ^ GetLow(rhs)};
  1034. }
  1035. IOutputStream& operator<<(IOutputStream& out, const i128& other);
  1036. // For THashMap
  1037. template <>
  1038. struct THash<i128> {
  1039. inline size_t operator()(const i128& num) const {
  1040. return THash<ui64>()(GetHigh(num)) + THash<ui64>()(GetLow(num));
  1041. }
  1042. };
  1043. template <>
  1044. class TSerializer<i128> {
  1045. public:
  1046. static void Save(IOutputStream* out, const i128& Number);
  1047. static void Load(IInputStream* in, i128& Number);
  1048. };
  1049. template <>
  1050. inline TString ToString<i128>(const i128& number) {
  1051. return TStringBuilder{} << number;
  1052. }
  1053. template <>
  1054. inline i128 FromStringImpl<i128>(const char* data, size_t length) {
  1055. if (length < 20) {
  1056. return i128{ FromString<ui64>(data, length) };
  1057. } else {
  1058. i128 result = 0;
  1059. const TStringBuf string(data, length);
  1060. for (auto&& c : string) {
  1061. if (!std::isdigit(c)) {
  1062. ythrow TFromStringException() << "Unexpected symbol \""sv << c << "\""sv;
  1063. }
  1064. i128 x1 = result;
  1065. i128 x2 = x1 + x1;
  1066. i128 x4 = x2 + x2;
  1067. i128 x8 = x4 + x4;
  1068. i128 x10 = x8 + x2;
  1069. i128 s = c - '0';
  1070. result = x10 + s;
  1071. if (GetHigh(result) < GetHigh(x1)) {
  1072. ythrow TFromStringException() << TStringBuf("Integer overflow");
  1073. }
  1074. }
  1075. return result;
  1076. }
  1077. }
  1078. #if defined(Y_HAVE_INT128)
  1079. template <>
  1080. inline TString ToString<signed __int128>(const signed __int128& number) {
  1081. return ToString(i128{number});
  1082. }
  1083. template <>
  1084. inline signed __int128 FromStringImpl<signed __int128>(const char* data, size_t length) {
  1085. return static_cast<signed __int128>(FromString<i128>(data, length));
  1086. }
  1087. #endif
  1088. template <bool IsSigned>
  1089. Y_FORCE_INLINE size_t MostSignificantBit(const TInteger128<IsSigned> v) {
  1090. if (ui64 hi = GetHigh(v)) {
  1091. return MostSignificantBit(hi) + 64;
  1092. }
  1093. return MostSignificantBit(GetLow(v));
  1094. }