big_int.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. #pragma warning(push)
  2. #pragma warning(disable: 4146)
  3. #include "libtommath/tommath.h"
  4. #pragma warning(pop)
  5. #ifndef MAX_BIG_INT_SHIFT
  6. #define MAX_BIG_INT_SHIFT 1024
  7. #endif
  8. typedef mp_int BigInt;
  9. void big_int_from_u64(BigInt *dst, u64 x);
  10. void big_int_from_i64(BigInt *dst, i64 x);
  11. void big_int_init (BigInt *dst, BigInt const *src);
  12. void big_int_from_string(BigInt *dst, String const &s);
  13. void big_int_dealloc(BigInt *dst) {
  14. mp_clear(dst);
  15. }
  16. BigInt big_int_make(BigInt const *b, bool abs=false);
  17. BigInt big_int_make_abs(BigInt const *b);
  18. BigInt big_int_make_u64(u64 x);
  19. BigInt big_int_make_i64(i64 x);
  20. u64 big_int_to_u64 (BigInt const *x);
  21. i64 big_int_to_i64 (BigInt const *x);
  22. f64 big_int_to_f64 (BigInt const *x);
  23. String big_int_to_string(gbAllocator allocator, BigInt const *x, u64 base = 10);
  24. void big_int_add (BigInt *dst, BigInt const *x, BigInt const *y);
  25. void big_int_sub (BigInt *dst, BigInt const *x, BigInt const *y);
  26. void big_int_shl (BigInt *dst, BigInt const *x, BigInt const *y);
  27. void big_int_shr (BigInt *dst, BigInt const *x, BigInt const *y);
  28. void big_int_mul (BigInt *dst, BigInt const *x, BigInt const *y);
  29. void big_int_mul_u64(BigInt *dst, BigInt const *x, u64 y);
  30. void big_int_quo_rem(BigInt const *x, BigInt const *y, BigInt *q, BigInt *r);
  31. void big_int_quo (BigInt *z, BigInt const *x, BigInt const *y);
  32. void big_int_rem (BigInt *z, BigInt const *x, BigInt const *y);
  33. void big_int_and (BigInt *dst, BigInt const *x, BigInt const *y);
  34. void big_int_and_not(BigInt *dst, BigInt const *x, BigInt const *y);
  35. void big_int_xor (BigInt *dst, BigInt const *x, BigInt const *y);
  36. void big_int_or (BigInt *dst, BigInt const *x, BigInt const *y);
  37. void big_int_not (BigInt *dst, BigInt const *x, u64 bit_count, bool is_signed);
  38. void big_int_add_eq(BigInt *dst, BigInt const *x);
  39. void big_int_sub_eq(BigInt *dst, BigInt const *x);
  40. void big_int_shl_eq(BigInt *dst, BigInt const *x);
  41. void big_int_shr_eq(BigInt *dst, BigInt const *x);
  42. void big_int_mul_eq(BigInt *dst, BigInt const *x);
  43. void big_int_quo_eq(BigInt *dst, BigInt const *x);
  44. void big_int_rem_eq(BigInt *dst, BigInt const *x);
  45. bool big_int_is_neg(BigInt const *x);
  46. void big_int_add_eq(BigInt *dst, BigInt const *x) {
  47. BigInt res = {};
  48. big_int_init(&res, dst);
  49. big_int_add(dst, &res, x);
  50. }
  51. void big_int_sub_eq(BigInt *dst, BigInt const *x) {
  52. BigInt res = {};
  53. big_int_init(&res, dst);
  54. big_int_sub(dst, &res, x);
  55. }
  56. void big_int_shl_eq(BigInt *dst, BigInt const *x) {
  57. BigInt res = {};
  58. big_int_init(&res, dst);
  59. big_int_shl(dst, &res, x);
  60. }
  61. void big_int_shr_eq(BigInt *dst, BigInt const *x) {
  62. BigInt res = {};
  63. big_int_init(&res, dst);
  64. big_int_shr(dst, &res, x);
  65. }
  66. void big_int_mul_eq(BigInt *dst, BigInt const *x) {
  67. BigInt res = {};
  68. big_int_init(&res, dst);
  69. big_int_mul(dst, &res, x);
  70. }
  71. void big_int_quo_eq(BigInt *dst, BigInt const *x) {
  72. BigInt res = {};
  73. big_int_init(&res, dst);
  74. big_int_quo(dst, &res, x);
  75. }
  76. void big_int_rem_eq(BigInt *dst, BigInt const *x) {
  77. BigInt res = {};
  78. big_int_init(&res, dst);
  79. big_int_rem(dst, &res, x);
  80. }
  81. i64 big_int_sign(BigInt const *x) {
  82. if (mp_iszero(x)) {
  83. return 0;
  84. }
  85. return x->sign == MP_ZPOS ? +1 : -1;
  86. }
  87. void big_int_from_u64(BigInt *dst, u64 x) {
  88. mp_init_u64(dst, x);
  89. }
  90. void big_int_from_i64(BigInt *dst, i64 x) {
  91. mp_init_i64(dst, x);
  92. }
  93. void big_int_init(BigInt *dst, BigInt const *src) {
  94. if (dst == src) {
  95. return;
  96. }
  97. mp_init_copy(dst, src);
  98. }
  99. BigInt big_int_make(BigInt const *b, bool abs) {
  100. BigInt i = {};
  101. big_int_init(&i, b);
  102. if (abs) mp_abs(&i, &i);
  103. return i;
  104. }
  105. BigInt big_int_make_abs(BigInt const *b) {
  106. return big_int_make(b, true);
  107. }
  108. BigInt big_int_make_u64(u64 x) {
  109. BigInt i = {};
  110. big_int_from_u64(&i, x);
  111. return i;
  112. }
  113. BigInt big_int_make_i64(i64 x) {
  114. BigInt i = {};
  115. big_int_from_i64(&i, x);
  116. return i;
  117. }
  118. void big_int_from_string(BigInt *dst, String const &s) {
  119. u64 base = 10;
  120. bool has_prefix = false;
  121. if (s.len > 2 && s[0] == '0') {
  122. switch (s[1]) {
  123. case 'b': base = 2; has_prefix = true; break;
  124. case 'o': base = 8; has_prefix = true; break;
  125. case 'd': base = 10; has_prefix = true; break;
  126. case 'z': base = 12; has_prefix = true; break;
  127. case 'x': base = 16; has_prefix = true; break;
  128. case 'h': base = 16; has_prefix = true; break;
  129. }
  130. }
  131. u8 *text = s.text;
  132. isize len = s.len;
  133. if (has_prefix) {
  134. text += 2;
  135. len -= 2;
  136. }
  137. BigInt b = {};
  138. big_int_from_u64(&b, base);
  139. mp_zero(dst);
  140. isize i = 0;
  141. for (; i < len; i++) {
  142. Rune r = cast(Rune)text[i];
  143. if (r == '_') {
  144. continue;
  145. }
  146. u64 v = u64_digit_value(r);
  147. if (v >= base) {
  148. break;
  149. }
  150. BigInt val = big_int_make_u64(v);
  151. big_int_mul_eq(dst, &b);
  152. big_int_add_eq(dst, &val);
  153. }
  154. if (i < len && (text[i] == 'e' || text[i] == 'E')) {
  155. i += 1;
  156. GB_ASSERT(base == 10);
  157. GB_ASSERT(text[i] != '-');
  158. if (text[i] == '+') {
  159. i += 1;
  160. }
  161. u64 exp = 0;
  162. for (; i < len; i++) {
  163. char r = cast(char)text[i];
  164. if (r == '_') {
  165. continue;
  166. }
  167. u64 v = 0;
  168. if (gb_char_is_digit(r)) {
  169. v = u64_digit_value(r);
  170. } else {
  171. break;
  172. }
  173. exp *= 10;
  174. exp += v;
  175. }
  176. for (u64 x = 0; x < exp; x++) {
  177. big_int_mul_eq(dst, &b);
  178. }
  179. }
  180. }
  181. u64 big_int_to_u64(BigInt const *x) {
  182. GB_ASSERT(x->sign == 0);
  183. return mp_get_u64(x);
  184. }
  185. i64 big_int_to_i64(BigInt const *x) {
  186. return mp_get_i64(x);
  187. }
  188. f64 big_int_to_f64(BigInt const *x) {
  189. return mp_get_double(x);
  190. }
  191. void big_int_neg(BigInt *dst, BigInt const *x) {
  192. mp_neg(x, dst);
  193. }
  194. int big_int_cmp(BigInt const *x, BigInt const *y) {
  195. return mp_cmp(x, y);
  196. }
  197. int big_int_cmp_zero(BigInt const *x) {
  198. if (mp_iszero(x)) {
  199. return 0;
  200. }
  201. return x->sign ? -1 : +1;
  202. }
  203. bool big_int_is_zero(BigInt const *x) {
  204. return mp_iszero(x);
  205. }
  206. void big_int_add(BigInt *dst, BigInt const *x, BigInt const *y) {
  207. mp_add(x, y, dst);
  208. }
  209. void big_int_sub(BigInt *dst, BigInt const *x, BigInt const *y) {
  210. mp_sub(x, y, dst);
  211. }
  212. void big_int_shl(BigInt *dst, BigInt const *x, BigInt const *y) {
  213. u32 yy = mp_get_u32(y);
  214. mp_mul_2d(x, yy, dst);
  215. }
  216. void big_int_shr(BigInt *dst, BigInt const *x, BigInt const *y) {
  217. u32 yy = mp_get_u32(y);
  218. BigInt d = {};
  219. mp_div_2d(x, yy, dst, &d);
  220. big_int_dealloc(&d);
  221. }
  222. void big_int_mul_u64(BigInt *dst, BigInt const *x, u64 y) {
  223. BigInt d = {};
  224. big_int_from_u64(&d, y);
  225. mp_mul(x, &d, dst);
  226. big_int_dealloc(&d);
  227. }
  228. void big_int_mul(BigInt *dst, BigInt const *x, BigInt const *y) {
  229. mp_mul(x, y, dst);
  230. }
  231. u64 leading_zeros_u64(u64 x) {
  232. #if defined(GB_COMPILER_MSVC)
  233. return __lzcnt64(x);
  234. #else
  235. return cast(u64)__builtin_clzll(cast(unsigned long long)x);
  236. #endif
  237. }
  238. // `big_int_quo_rem` sets z to the quotient x/y and r to the remainder x%y
  239. // and returns the pair (z, r) for y != 0.
  240. // if y == 0, a division-by-zero run-time panic occurs.
  241. //
  242. // q = x/y with the result truncated to zero
  243. // r = x - y*q
  244. void big_int_quo_rem(BigInt const *x, BigInt const *y, BigInt *q_, BigInt *r_) {
  245. mp_div(x, y, q_, r_);
  246. }
  247. void big_int_quo(BigInt *z, BigInt const *x, BigInt const *y) {
  248. BigInt r = {};
  249. big_int_quo_rem(x, y, z, &r);
  250. big_int_dealloc(&r);
  251. }
  252. void big_int_rem(BigInt *z, BigInt const *x, BigInt const *y) {
  253. BigInt q = {};
  254. big_int_quo_rem(x, y, &q, z);
  255. big_int_dealloc(&q);
  256. }
  257. void big_int_euclidean_mod(BigInt *z, BigInt const *x, BigInt const *y) {
  258. BigInt y0 = {};
  259. big_int_init(&y0, y);
  260. BigInt q = {};
  261. big_int_quo_rem(x, y, &q, z);
  262. if (z->sign) {
  263. if (y0.sign) {
  264. big_int_sub(z, z, &y0);
  265. } else {
  266. big_int_add(z, z, &y0);
  267. }
  268. }
  269. }
  270. void big_int_and(BigInt *dst, BigInt const *x, BigInt const *y) {
  271. mp_and(x, y, dst);
  272. }
  273. void big_int_and_not(BigInt *dst, BigInt const *x, BigInt const *y) {
  274. if (mp_iszero(x)) {
  275. big_int_init(dst, y);
  276. return;
  277. }
  278. if (mp_iszero(y)) {
  279. big_int_init(dst, x);
  280. return;
  281. }
  282. if (x->sign == y->sign) {
  283. if (x->sign) {
  284. // (-x) &~ (-y) == ~(x-1) &~ ~(y-1) == ~(x-1) & (y-1) == (y-1) &~ (x-1)
  285. BigInt x1 = big_int_make_abs(x);
  286. BigInt y1 = big_int_make_abs(y);
  287. mp_decr(&x1);
  288. mp_decr(&y1);
  289. BigInt ny1 = {};
  290. mp_complement(&y1, &ny1);
  291. mp_and(&x1, &ny1, dst);
  292. big_int_dealloc(&x1);
  293. big_int_dealloc(&y1);
  294. big_int_dealloc(&ny1);
  295. return;
  296. }
  297. BigInt ny = {};
  298. mp_complement(y, &ny);
  299. mp_and(x, &ny, dst);
  300. big_int_dealloc(&ny);
  301. return;
  302. }
  303. if (x->sign) {
  304. // (-x) &~ y == ~(x-1) &~ y == ~(x-1) & ~y == ~((x-1) | y) == -(((x-1) | y) + 1)
  305. BigInt x1 = big_int_make_abs(x);
  306. BigInt y1 = big_int_make_abs(y);
  307. mp_decr(&x1);
  308. BigInt z1 = {};
  309. big_int_or(&z1, &x1, &y1);
  310. mp_add_d(&z1, 1, dst);
  311. big_int_dealloc(&x1);
  312. big_int_dealloc(&y1);
  313. big_int_dealloc(&z1);
  314. return;
  315. }
  316. // x &~ (-y) == x &~ ~(y-1) == x & (y-1)
  317. BigInt x1 = big_int_make_abs(x);
  318. BigInt y1 = big_int_make_abs(y);
  319. mp_decr(&y1);
  320. big_int_and(dst, &x1, &y1);
  321. big_int_dealloc(&x1);
  322. big_int_dealloc(&y1);
  323. return;
  324. }
  325. void big_int_xor(BigInt *dst, BigInt const *x, BigInt const *y) {
  326. mp_xor(x, y, dst);
  327. }
  328. void big_int_or(BigInt *dst, BigInt const *x, BigInt const *y) {
  329. mp_or(x, y, dst);
  330. }
  331. void debug_print_big_int(BigInt const *x) {
  332. String s = big_int_to_string(temporary_allocator(), x, 10);
  333. gb_printf_err("[DEBUG] %.*s\n", LIT(s));
  334. }
  335. void big_int_not(BigInt *dst, BigInt const *x, i32 bit_count, bool is_signed) {
  336. GB_ASSERT(bit_count >= 0);
  337. if (bit_count == 0) {
  338. big_int_from_u64(dst, 0);
  339. return;
  340. }
  341. BigInt pow2b = {};
  342. mp_2expt(&pow2b, bit_count);
  343. BigInt mask = {};
  344. mp_2expt(&mask, bit_count);
  345. mp_decr(&mask);
  346. BigInt v = {};
  347. mp_init_copy(&v, x);
  348. mp_mod_2d(&v, bit_count, &v);
  349. mp_xor(&v, &mask, dst);
  350. if (is_signed) {
  351. BigInt pmask = {};
  352. BigInt pmask_minus_one = {};
  353. mp_2expt(&pmask, bit_count-1);
  354. mp_sub_d(&pmask, 1, &pmask_minus_one);
  355. BigInt a = {};
  356. BigInt b = {};
  357. big_int_and(&a, dst, &pmask_minus_one);
  358. big_int_and(&b, dst, &pmask);
  359. big_int_sub(dst, &a, &b);
  360. big_int_dealloc(&a);
  361. big_int_dealloc(&b);
  362. }
  363. big_int_dealloc(&pow2b);
  364. big_int_dealloc(&mask);
  365. big_int_dealloc(&v);
  366. }
  367. bool big_int_is_neg(BigInt const *x) {
  368. if (x == nullptr) {
  369. return false;
  370. }
  371. return x->sign != MP_ZPOS;
  372. }
  373. char digit_to_char(u8 digit) {
  374. GB_ASSERT(digit < 16);
  375. if (digit <= 9) {
  376. return digit + '0';
  377. } else if (digit <= 15) {
  378. return digit + 'a';
  379. }
  380. return '0';
  381. }
  382. String big_int_to_string(gbAllocator allocator, BigInt const *x, u64 base) {
  383. GB_ASSERT(base <= 16);
  384. if (mp_iszero(x)) {
  385. u8 *buf = gb_alloc_array(allocator, u8, 1);
  386. buf[0] = '0';
  387. return make_string(buf, 1);
  388. }
  389. Array<char> buf = {};
  390. array_init(&buf, allocator, 0, 32);
  391. BigInt v = {};
  392. mp_init_copy(&v, x);
  393. if (v.sign) {
  394. array_add(&buf, '-');
  395. mp_abs(&v, &v);
  396. }
  397. isize first_word_idx = buf.count;
  398. BigInt r = {};
  399. BigInt b = {};
  400. big_int_from_u64(&b, base);
  401. u8 digit = 0;
  402. while (big_int_cmp(&v, &b) >= 0) {
  403. big_int_quo_rem(&v, &b, &v, &r);
  404. digit = cast(u8)big_int_to_u64(&r);
  405. array_add(&buf, digit_to_char(digit));
  406. }
  407. big_int_rem(&r, &v, &b);
  408. digit = cast(u8)big_int_to_u64(&r);
  409. array_add(&buf, digit_to_char(digit));
  410. big_int_dealloc(&r);
  411. big_int_dealloc(&b);
  412. for (isize i = first_word_idx; i < buf.count/2; i++) {
  413. isize j = buf.count + first_word_idx - i - 1;
  414. char tmp = buf[i];
  415. buf[i] = buf[j];
  416. buf[j] = tmp;
  417. }
  418. return make_string(cast(u8 *)buf.data, buf.count);
  419. }