├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── bigint.c ├── bigint.h ├── bigint.hpp ├── c_examples.c ├── cpp_examples.cpp └── tests.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # binaries 32 | tests 33 | c_examples 34 | cpp_examples 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | 26 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | FLAGS = -lm -O3 -Wall -Wextra -Wpedantic 2 | 3 | all: tests c_examples cpp_examples bigint.o 4 | rm bigint.o 5 | 6 | bigint.o: 7 | gcc -c bigint.c -o bigint.o $(FLAGS) 8 | 9 | tests: bigint.o 10 | gcc tests.c bigint.o -o tests $(FLAGS) 11 | 12 | c_examples: bigint.o 13 | gcc c_examples.c bigint.o -o c_examples $(FLAGS) 14 | 15 | cpp_examples: bigint.o 16 | g++ cpp_examples.cpp bigint.o -o cpp_examples $(FLAGS) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Discontinued in favour of https://github.com/983/Num 2 | 3 | # bigint 4 | 5 | C usage example: 6 | ```c 7 | #include "bigint.h" 8 | 9 | #include 10 | 11 | int main(){ 12 | char buf[65536]; 13 | 14 | /* neat trick to avoid having to write &a, &b, &c everywhere */ 15 | bigint a[1], b[1], c[1]; 16 | 17 | /* bigints have to be initialized (same as memset'ed to zero) */ 18 | bigint_init(a); 19 | bigint_init(b); 20 | bigint_init(c); 21 | 22 | /* create bigint from string */ 23 | bigint_from_str(a, "123456789"); 24 | bigint_from_str(b, "987654321"); 25 | 26 | /* c = a * b */ 27 | /* first parameter is destination parameter */ 28 | bigint_mul(c, a, b); 29 | 30 | /* write and print */ 31 | puts(bigint_write(buf, sizeof(buf), c)); 32 | 33 | /* bigints have to be free'd */ 34 | bigint_free(a); 35 | bigint_free(b); 36 | bigint_free(c); 37 | 38 | return 0; 39 | } 40 | ``` 41 | 42 | C++ usage example: 43 | ```cpp 44 | #include "bigint.hpp" 45 | 46 | #include 47 | #include 48 | 49 | uint32_t xorshift32() { 50 | static uint32_t x = 314159265; 51 | x ^= x << 13; 52 | x ^= x >> 17; 53 | x ^= x << 5; 54 | return x; 55 | } 56 | 57 | // do not use this as a cryptographically secure random number generator 58 | void not_secure_random(uint8_t *dst, int n){ 59 | for (int i = 0; i < n; i++) dst[i] = xorshift32(); 60 | } 61 | 62 | int main(){ 63 | // BigInts can be created from strings or from integers 64 | BigInt a = "-1137531041259095389425522063651335971086542522289"; 65 | BigInt b = "-9214001518046086468566115579527473139501"; 66 | 67 | // Available operators: 68 | // +, -, *, /, %, <<, >> 69 | // +=, -=, *=, /=, %=, <<=, >>=, ++, -- 70 | // ==, !=, <=, >=, <, > 71 | BigInt c = a / b; 72 | BigInt d = b * c; 73 | assert(c == 123456789); 74 | assert(a == d); 75 | 76 | // write to any output stream 77 | c.write(std::cout) << std::endl; 78 | d.write(std::cout) << std::endl; 79 | 80 | // find the biggest probable prime less than 10^42 81 | BigInt p = BigInt(10).pow(42) - 1; 82 | 83 | for (int i = 0; i < 100; i++){ 84 | if (p.is_probable_prime(10, not_secure_random)){ 85 | p.write(std::cout << "Big prime: ") << std::endl; 86 | break; 87 | } 88 | --p; 89 | } 90 | 91 | return 0; 92 | } 93 | ``` 94 | 95 | Implementation notes: 96 | * BigInts consist of an array of bigint_words which are unsigned ints as defined in bigint.h 97 | * Try adjusting bigint_word in bigint.h for maximum performance 98 | * If there is a highest word, it should always be non-zero, as assured by bigint_raw_truncate 99 | * Multiplication uses [the Karatsuba algorithm](https://en.wikipedia.org/wiki/Karatsuba_algorithm) for large integers 100 | * The C++ interface is easier to use, but the C interface is better at avoiding reallocations 101 | * If you have to calculate both division and modulo, use div_mod 102 | * The bigint_raw_* methods expect the dst parameter to be sufficiently big, so be careful with those! 103 | 104 | Things to do on rainy days: 105 | * Improve performance for reading and writing bigints with 2^n bases 106 | * Extract many digits per division for bigint_write_base 107 | -------------------------------------------------------------------------------- /bigint.c: -------------------------------------------------------------------------------- 1 | #include "bigint.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define BIGINT_ASSERT(a, op, b) assert((a) op (b)); 9 | 10 | /* low bits of a * b */ 11 | bigint_word bigint_word_mul_lo(bigint_word a, bigint_word b){ 12 | return a * b; 13 | } 14 | 15 | /* high bits of a * b */ 16 | bigint_word bigint_word_mul_hi(bigint_word a, bigint_word b){ 17 | bigint_word c0 = BIGINT_WORD_LO(a) * BIGINT_WORD_LO(b); 18 | bigint_word c1 = BIGINT_WORD_LO(a) * BIGINT_WORD_HI(b); 19 | bigint_word c2 = BIGINT_WORD_HI(a) * BIGINT_WORD_LO(b); 20 | bigint_word c3 = BIGINT_WORD_HI(a) * BIGINT_WORD_HI(b); 21 | 22 | bigint_word c4 = BIGINT_WORD_HI(c0) + BIGINT_WORD_LO(c1) + BIGINT_WORD_LO(c2); 23 | return BIGINT_WORD_HI(c4) + BIGINT_WORD_HI(c1) + BIGINT_WORD_HI(c2) + c3; 24 | } 25 | 26 | /* dst = a + b, return carry */ 27 | bigint_word bigint_word_add_get_carry( 28 | bigint_word *dst, 29 | bigint_word a, 30 | bigint_word b 31 | ){ 32 | a += b; 33 | *dst = a; 34 | return a < b; 35 | } 36 | 37 | /* dst = a - b, return carry */ 38 | bigint_word bigint_word_sub_get_carry( 39 | bigint_word *dst, 40 | bigint_word a, 41 | bigint_word b 42 | ){ 43 | b = a - b; 44 | *dst = b; 45 | return b > a; 46 | } 47 | 48 | bigint_word bigint_word_from_char(char c){ 49 | switch (c){ 50 | case '0': return 0; 51 | case '1': return 1; 52 | case '2': return 2; 53 | case '3': return 3; 54 | case '4': return 4; 55 | case '5': return 5; 56 | case '6': return 6; 57 | case '7': return 7; 58 | case '8': return 8; 59 | case '9': return 9; 60 | case 'a': case 'A': return 10; 61 | case 'b': case 'B': return 11; 62 | case 'c': case 'C': return 12; 63 | case 'd': case 'D': return 13; 64 | case 'e': case 'E': return 14; 65 | case 'f': case 'F': return 15; 66 | case 'g': case 'G': return 16; 67 | case 'h': case 'H': return 17; 68 | case 'i': case 'I': return 18; 69 | case 'j': case 'J': return 19; 70 | case 'k': case 'K': return 20; 71 | case 'l': case 'L': return 21; 72 | case 'm': case 'M': return 22; 73 | case 'n': case 'N': return 23; 74 | case 'o': case 'O': return 24; 75 | case 'p': case 'P': return 25; 76 | case 'q': case 'Q': return 26; 77 | case 'r': case 'R': return 27; 78 | case 's': case 'S': return 28; 79 | case 't': case 'T': return 29; 80 | case 'u': case 'U': return 30; 81 | case 'v': case 'V': return 31; 82 | case 'w': case 'W': return 32; 83 | case 'x': case 'X': return 33; 84 | case 'y': case 'Y': return 34; 85 | case 'z': case 'Z': return 35; 86 | default: return BIGINT_WORD_MAX; 87 | } 88 | } 89 | 90 | int bigint_word_bitlength(bigint_word a){ 91 | int i; 92 | for (i = BIGINT_WORD_BITS - 1; i >= 0; i--) if ((a >> i) & 1) return i + 1; 93 | return 0; 94 | } 95 | 96 | int bigint_word_count_trailing_zeros(bigint_word a){ 97 | int i; 98 | for (i = 0; i < (int)BIGINT_WORD_BITS; i++) if ((a >> i) & 1) return i; 99 | return BIGINT_WORD_BITS; 100 | } 101 | 102 | bigint_word bigint_word_gcd(bigint_word a, bigint_word b){ 103 | while (1){ 104 | if (!a) return b; 105 | b %= a; 106 | if (!b) return a; 107 | a %= b; 108 | } 109 | } 110 | 111 | unsigned bigint_uint_gcd(unsigned a, unsigned b){ 112 | while (1){ 113 | if (!a) return b; 114 | b %= a; 115 | if (!b) return a; 116 | a %= b; 117 | } 118 | } 119 | 120 | int bigint_int_gcd(int a, int b){ 121 | return bigint_uint_gcd(BIGINT_INT_ABS(a), BIGINT_INT_ABS(b)); 122 | } 123 | 124 | bigint* bigint_init(bigint *dst){ 125 | dst->words = NULL; 126 | dst->neg = dst->size = dst->capacity = 0; 127 | return dst; 128 | } 129 | 130 | bigint* bigint_reserve(bigint *dst, int capacity){ 131 | if (dst->capacity >= capacity) return dst; 132 | dst->capacity = capacity; 133 | dst->words = (bigint_word*)realloc(dst->words, capacity * sizeof(*dst->words)); 134 | /* out of memory? sorry :( */ 135 | assert(dst->words != NULL); 136 | BIGINT_ASSERT(dst->size, <=, capacity); 137 | return dst; 138 | } 139 | 140 | void bigint_free(bigint *dst){ 141 | free(dst->words); 142 | bigint_init(dst); 143 | } 144 | 145 | int bigint_raw_cmp_abs( 146 | const bigint_word *a, int na, 147 | const bigint_word *b, int nb 148 | ){ 149 | int i; 150 | 151 | if (na > nb) return +1; 152 | if (na < nb) return -1; 153 | 154 | BIGINT_ASSERT(na, ==, nb); 155 | for (i = na - 1; i >= 0; i--){ 156 | if (a[i] < b[i]) return -1; 157 | if (a[i] > b[i]) return +1; 158 | } 159 | 160 | return 0; 161 | } 162 | 163 | int bigint_cmp_abs(const bigint *a, const bigint *b){ 164 | return bigint_raw_cmp_abs(a->words, a->size, b->words, b->size); 165 | } 166 | 167 | int bigint_raw_cmp( 168 | const bigint_word *a, int na, int a_neg, 169 | const bigint_word *b, int nb, int b_neg 170 | ){ 171 | if (na == 0 && nb == 0) return 0; 172 | 173 | if (!a_neg && !b_neg) return bigint_raw_cmp_abs(a, na, b, nb); 174 | if ( a_neg && b_neg) return bigint_raw_cmp_abs(b, na, a, nb); 175 | 176 | return (!a_neg && b_neg) ? +1 : -1; 177 | } 178 | 179 | int bigint_cmp(const bigint *a, const bigint *b){ 180 | return bigint_raw_cmp(a->words, a->size, a->neg, b->words, b->size, b->neg); 181 | } 182 | 183 | int bigint_cmp_abs_word(const bigint *a, bigint_word b){ 184 | if (b == 0){ 185 | if (a->size == 0) return 0; 186 | return a->neg ? -1 : +1; 187 | } 188 | return bigint_raw_cmp_abs(a->words, a->size, &b, 1); 189 | } 190 | 191 | void bigint_raw_zero(bigint_word *dst, int from, int to){ 192 | if (from >= to) return; 193 | memset(dst + from, 0, (to - from) * sizeof(*dst)); 194 | } 195 | 196 | bigint* bigint_set_neg(bigint *dst, int neg){ 197 | dst->neg = neg; 198 | return dst; 199 | } 200 | 201 | bigint* bigint_negate(bigint *dst){ 202 | return bigint_set_neg(dst, !dst->neg); 203 | } 204 | 205 | int bigint_raw_cpy(bigint_word *dst, const bigint_word *src, int n){ 206 | memcpy(dst, src, n * sizeof(*src)); 207 | return n; 208 | } 209 | 210 | bigint* bigint_cpy(bigint *dst, const bigint *src){ 211 | if (src == dst) return dst; 212 | bigint_reserve(dst, src->size); 213 | dst->size = bigint_raw_cpy(dst->words, src->words, src->size); 214 | BIGINT_ASSERT(bigint_cmp_abs(src, dst), ==, 0); 215 | return bigint_set_neg(dst, src->neg); 216 | } 217 | 218 | int bigint_raw_truncate(const bigint_word *a, int n){ 219 | while (n > 0 && a[n - 1] == 0) n--; 220 | return n; 221 | } 222 | 223 | void bigint_raw_clr_bit(bigint_word *dst, unsigned bit_index){ 224 | unsigned word_index = bit_index / BIGINT_WORD_BITS; 225 | bit_index %= BIGINT_WORD_BITS; 226 | dst[word_index] &= BIGINT_WORD_MAX ^ (((bigint_word)1) << bit_index); 227 | } 228 | 229 | bigint* bigint_clr_bit(bigint *dst, unsigned bit_index){ 230 | bigint_raw_clr_bit(dst->words, bit_index); 231 | dst->size = bigint_raw_truncate(dst->words, dst->size); 232 | return dst; 233 | } 234 | 235 | bigint* bigint_set_bit(bigint *dst, unsigned bit_index){ 236 | int word_index = bit_index / BIGINT_WORD_BITS; 237 | int n = word_index + 1; 238 | 239 | bigint_reserve(dst, n); 240 | bigint_raw_zero(dst->words, dst->size, n); 241 | dst->size = BIGINT_MAX(dst->size, n); 242 | dst->words[word_index] |= ((bigint_word)1) << bit_index % BIGINT_WORD_BITS; 243 | 244 | return dst; 245 | } 246 | 247 | bigint_word bigint_get_bit(const bigint *src, unsigned bit_index){ 248 | int i = bit_index / BIGINT_WORD_BITS; 249 | 250 | if (src->size <= i) return 0; 251 | 252 | return (src->words[i] >> bit_index % BIGINT_WORD_BITS) & 1; 253 | } 254 | 255 | int bigint_raw_mul_word_add( 256 | bigint_word *dst, 257 | const bigint_word *src, int n, 258 | bigint_word factor 259 | ){ 260 | int i; 261 | bigint_word carry = 0; 262 | 263 | for (i = 0; i < n; i++){ 264 | bigint_word src_word = src[i]; 265 | bigint_word dst_word = bigint_word_mul_lo(src_word, factor); 266 | carry = bigint_word_add_get_carry(&dst_word, dst_word, carry); 267 | carry += bigint_word_mul_hi(src_word, factor); 268 | carry += bigint_word_add_get_carry(&dst[i], dst[i], dst_word); 269 | } 270 | 271 | for (; carry; i++){ 272 | carry = bigint_word_add_get_carry(&dst[i], dst[i], carry); 273 | } 274 | 275 | return bigint_raw_truncate(dst, i); 276 | } 277 | 278 | int bigint_raw_mul_word( 279 | bigint_word *dst, 280 | const bigint_word *src, int n, 281 | bigint_word factor 282 | ){ 283 | int i; 284 | bigint_word carry = 0; 285 | 286 | for (i = 0; i < n; i++){ 287 | bigint_word src_word = src[i]; 288 | bigint_word dst_word = bigint_word_mul_lo(src_word, factor); 289 | carry = bigint_word_add_get_carry(&dst_word, dst_word, carry); 290 | carry += bigint_word_mul_hi(src_word, factor); 291 | dst[i] = dst_word; 292 | } 293 | 294 | if (carry){ 295 | dst[i++] = carry; 296 | } 297 | 298 | return bigint_raw_truncate(dst, i); 299 | } 300 | 301 | int bigint_raw_mul_add( 302 | bigint_word *dst, 303 | const bigint_word *src_a, int na, 304 | const bigint_word *src_b, int nb 305 | ){ 306 | int i; 307 | 308 | if (na == 0 || nb == 0) return 0; 309 | 310 | assert(dst != src_a); 311 | assert(dst != src_b); 312 | 313 | for (i = 0; i < nb; i++){ 314 | bigint_raw_mul_word_add(dst + i, src_a, na, src_b[i]); 315 | } 316 | 317 | return bigint_raw_truncate(dst, na + nb); 318 | } 319 | 320 | int bigint_raw_add_word( 321 | bigint_word *dst, 322 | const bigint_word *src, int n, 323 | bigint_word b 324 | ){ 325 | int i; 326 | bigint_word carry = b; 327 | 328 | for (i = 0; i < n; i++){ 329 | carry = bigint_word_add_get_carry(&dst[i], src[i], carry); 330 | } 331 | 332 | for (; carry; i++){ 333 | carry = bigint_word_add_get_carry(&dst[i], dst[i], carry); 334 | } 335 | 336 | return bigint_raw_truncate(dst, i); 337 | } 338 | 339 | int bigint_raw_from_str_base(bigint_word *dst, const char *src, int base){ 340 | int n = 0; 341 | 342 | for (; *src; src++){ 343 | bigint_word digit = bigint_word_from_char(*src); 344 | 345 | if (digit == BIGINT_WORD_MAX) continue; 346 | 347 | n = bigint_raw_mul_word(dst, dst, n, base); 348 | n = bigint_raw_add_word(dst, dst, n, digit); 349 | } 350 | 351 | return bigint_raw_truncate(dst, n); 352 | } 353 | 354 | int bigint_count_digits(const char *src){ 355 | int n = 0; 356 | for (; *src; src++) if (bigint_word_from_char(*src) != BIGINT_WORD_MAX) n++; 357 | return n; 358 | } 359 | 360 | int bigint_raw_add( 361 | bigint_word *dst, 362 | const bigint_word *src_a, int na, 363 | const bigint_word *src_b, int nb 364 | ){ 365 | bigint_word sum, carry = 0; 366 | int i, n = BIGINT_MIN(na, nb); 367 | 368 | for (i = 0; i < n; i++){ 369 | carry = bigint_word_add_get_carry(&sum, carry, src_a[i]); 370 | carry += bigint_word_add_get_carry(&sum, sum , src_b[i]); 371 | dst[i] = sum; 372 | } 373 | 374 | for (; i < na; i++){ 375 | carry = bigint_word_add_get_carry(&dst[i], src_a[i], carry); 376 | } 377 | 378 | for (; i < nb; i++){ 379 | carry = bigint_word_add_get_carry(&dst[i], src_b[i], carry); 380 | } 381 | 382 | if (carry) dst[i++] = carry; 383 | 384 | return bigint_raw_truncate(dst, i); 385 | } 386 | 387 | int bigint_raw_sub( 388 | bigint_word *dst, 389 | const bigint_word *src_a, int na, 390 | const bigint_word *src_b, int nb 391 | ){ 392 | bigint_word dif, carry = 0; 393 | int i; 394 | BIGINT_ASSERT(na, >=, nb); 395 | BIGINT_ASSERT(bigint_raw_cmp_abs(src_a, na, src_b, nb), >=, 0); 396 | 397 | for (i = 0; i < nb; i++){ 398 | carry = bigint_word_sub_get_carry(&dif, src_a[i], carry); 399 | carry += bigint_word_sub_get_carry(&dif, dif, src_b[i]); 400 | dst[i] = dif; 401 | } 402 | 403 | for (; i < na; i++){ 404 | carry = bigint_word_sub_get_carry(&dst[i], src_a[i], carry); 405 | } 406 | 407 | BIGINT_ASSERT(carry, ==, 0); 408 | return bigint_raw_truncate(dst, i); 409 | } 410 | 411 | int bigint_raw_mul_karatsuba( 412 | bigint_word *dst, 413 | const bigint_word *a, int na, 414 | const bigint_word *b, int nb, 415 | bigint_word *tmp 416 | ){ 417 | /* so many */ 418 | int n, k, m, m2; 419 | const bigint_word *lo1, *hi1, *lo2, *hi2; 420 | int nlo1, nhi1, nlo2, nhi2; 421 | bigint_word *lo1hi1, *lo2hi2, *z0, *z1, *z2; 422 | int nlo1hi1, nlo2hi2, nz0, nz1, nz2; 423 | 424 | if ( 425 | na < BIGINT_KARATSUBA_WORD_THRESHOLD && 426 | nb < BIGINT_KARATSUBA_WORD_THRESHOLD 427 | ){ 428 | bigint_raw_zero(dst, 0, na + nb); 429 | return bigint_raw_mul_add(dst, a, na, b, nb); 430 | } 431 | 432 | m = BIGINT_MAX(na, nb); 433 | m2 = m / 2; 434 | k = m2 + 2; 435 | 436 | lo1 = a; 437 | lo2 = b; 438 | hi1 = a + m2; 439 | hi2 = b + m2; 440 | 441 | nlo1 = bigint_raw_truncate(lo1, BIGINT_MIN(m2, na)); 442 | nlo2 = bigint_raw_truncate(lo2, BIGINT_MIN(m2, nb)); 443 | nhi1 = bigint_raw_truncate(hi1, BIGINT_MAX(na - m2, 0)); 444 | nhi2 = bigint_raw_truncate(hi2, BIGINT_MAX(nb - m2, 0)); 445 | 446 | lo1hi1 = tmp; tmp += k; 447 | lo2hi2 = tmp; tmp += k; 448 | z0 = tmp; tmp += k*2; 449 | z1 = tmp; tmp += k*2; 450 | z2 = tmp; tmp += k*2; 451 | 452 | nlo1hi1 = bigint_raw_add(lo1hi1, lo1, nlo1, hi1, nhi1); 453 | nlo2hi2 = bigint_raw_add(lo2hi2, lo2, nlo2, hi2, nhi2); 454 | 455 | nz0 = bigint_raw_mul_karatsuba(z0, lo1 , nlo1 , lo2 , nlo2 , tmp); 456 | nz1 = bigint_raw_mul_karatsuba(z1, lo1hi1, nlo1hi1, lo2hi2, nlo2hi2, tmp); 457 | nz2 = bigint_raw_mul_karatsuba(z2, hi1, nhi1 , hi2, nhi2, tmp); 458 | 459 | nz1 = bigint_raw_sub(z1, z1, nz1, z0, nz0); 460 | nz1 = bigint_raw_sub(z1, z1, nz1, z2, nz2); 461 | 462 | n = nz0; 463 | 464 | bigint_raw_cpy(dst, z0, n); 465 | bigint_raw_zero(dst, n, na + nb); 466 | 467 | n = bigint_raw_add(dst + m2*1, dst + m2*1, BIGINT_MAX(n - m2, 0), z1, nz1); 468 | n = bigint_raw_add(dst + m2*2, dst + m2*2, BIGINT_MAX(n - m2, 0), z2, nz2); 469 | 470 | return bigint_raw_truncate(dst, n + m2*2); 471 | } 472 | 473 | bigint* bigint_mul(bigint *dst, const bigint *a, const bigint *b){ 474 | int na = a->size; 475 | int nb = b->size; 476 | int n = na + nb; 477 | bigint_word *tmp; 478 | 479 | bigint_reserve(dst, n); 480 | 481 | /* bigint_raw_mul_karatsuba already has this fastpath */ 482 | /* but this way we avoid allocating tmp */ 483 | if ( 484 | dst != a && 485 | dst != b && 486 | na < BIGINT_KARATSUBA_WORD_THRESHOLD && 487 | nb < BIGINT_KARATSUBA_WORD_THRESHOLD 488 | ){ 489 | bigint_raw_zero(dst->words, 0, na + nb); 490 | dst->size = bigint_raw_mul_add(dst->words, a->words, na, b->words, nb); 491 | }else{ 492 | int magical_upper_bound = BIGINT_MAX(na, nb) * 11 + 180 + n; 493 | tmp = (bigint_word*)malloc(magical_upper_bound * sizeof(*tmp)); 494 | 495 | dst->size = bigint_raw_mul_karatsuba(tmp, a->words, na, b->words, nb, tmp + n); 496 | bigint_raw_cpy(dst->words, tmp, dst->size); 497 | free(tmp); 498 | } 499 | 500 | return bigint_set_neg(dst, a->neg ^ b->neg); 501 | } 502 | 503 | int bigint_digits_bound(int n_digits_src, double src_base, double dst_base){ 504 | /* +1 for rounding errors, just in case */ 505 | return ceil(n_digits_src * log(src_base) / log(dst_base)) + 1; 506 | } 507 | 508 | int bigint_write_size(const bigint *a, double dst_base){ 509 | double src_base = pow(2, BIGINT_WORD_BITS); 510 | return bigint_digits_bound(a->size, src_base, dst_base) 511 | + sizeof('-') + sizeof('\0'); 512 | } 513 | 514 | bigint* bigint_from_str_base(bigint *dst, const char *src, int src_base){ 515 | int n_digits_src, n_digits_dst; 516 | double dst_base = pow(2.0, BIGINT_WORD_BITS); 517 | 518 | n_digits_src = bigint_count_digits(src); 519 | n_digits_dst = bigint_digits_bound(n_digits_src, src_base, dst_base); 520 | 521 | bigint_reserve(dst, n_digits_dst); 522 | dst->size = n_digits_dst; 523 | bigint_raw_zero(dst->words, 0, n_digits_dst); 524 | 525 | dst->size = bigint_raw_from_str_base(dst->words, src, src_base); 526 | return bigint_set_neg(dst, *src == '-'); 527 | } 528 | 529 | bigint* bigint_from_str(bigint *dst, const char *src){ 530 | return bigint_from_str_base(dst, src, 10); 531 | } 532 | 533 | bigint* bigint_from_int(bigint *dst, int src){ 534 | unsigned int x = BIGINT_INT_ABS(src); 535 | int n = BIGINT_MAX(1, sizeof(x)/sizeof(bigint_word)); 536 | bigint_reserve(dst, n); 537 | bigint_raw_zero(dst->words, 0, n); 538 | memcpy(dst->words, &x, sizeof(x)); 539 | dst->size = bigint_raw_truncate(dst->words, n); 540 | return bigint_set_neg(dst, src < 0); 541 | } 542 | 543 | bigint* bigint_from_word(bigint *dst, bigint_word a){ 544 | bigint_reserve(dst, 1); 545 | dst->words[0] = a; 546 | dst->size = bigint_raw_truncate(dst->words, 1); 547 | return bigint_set_neg(dst, 0); 548 | } 549 | 550 | int bigint_raw_add_signed( 551 | bigint_word *dst, int *dst_neg, 552 | const bigint_word *a, int na, int a_neg, 553 | const bigint_word *b, int nb, int b_neg 554 | ){ 555 | if (a_neg){ 556 | if (b_neg){ 557 | if (na >= nb){ 558 | *dst_neg = 1; 559 | return bigint_raw_add(dst, a, na, b, nb); 560 | }else{ 561 | *dst_neg = 1; 562 | return bigint_raw_add(dst, b, nb, a, na); 563 | } 564 | }else{ 565 | if (bigint_raw_cmp_abs(a, na, b, nb) >= 0){ 566 | *dst_neg = 1; 567 | return bigint_raw_sub(dst, a, na, b, nb); 568 | }else{ 569 | *dst_neg = 0; 570 | return bigint_raw_sub(dst, b, nb, a, na); 571 | } 572 | } 573 | }else{ 574 | if (b_neg){ 575 | if (bigint_raw_cmp_abs(a, na, b, nb) >= 0){ 576 | *dst_neg = 0; 577 | return bigint_raw_sub(dst, a, na, b, nb); 578 | }else{ 579 | *dst_neg = 1; 580 | return bigint_raw_sub(dst, b, nb, a, na); 581 | } 582 | }else{ 583 | if (na >= nb){ 584 | *dst_neg = 0; 585 | return bigint_raw_add(dst, a, na, b, nb); 586 | }else{ 587 | *dst_neg = 0; 588 | return bigint_raw_add(dst, b, nb, a, na); 589 | } 590 | } 591 | } 592 | } 593 | 594 | bigint* bigint_add_signed( 595 | bigint *dst, 596 | const bigint *a, int a_neg, 597 | const bigint *b, int b_neg 598 | ){ 599 | int na = a->size; 600 | int nb = b->size; 601 | int n = BIGINT_MAX(na, nb) + 1; 602 | 603 | bigint_reserve(dst, n); 604 | 605 | dst->size = bigint_raw_add_signed( 606 | dst->words, &dst->neg, 607 | a->words, na, a_neg, 608 | b->words, nb, b_neg 609 | ); 610 | 611 | return dst; 612 | } 613 | 614 | bigint* bigint_add(bigint *dst, const bigint *a, const bigint *b){ 615 | return bigint_add_signed(dst, a, a->neg, b, b->neg); 616 | } 617 | 618 | bigint* bigint_sub(bigint *dst, const bigint *a, const bigint *b){ 619 | return bigint_add_signed(dst, a, a->neg, b, !b->neg); 620 | } 621 | 622 | bigint* bigint_add_word_signed( 623 | bigint *dst, 624 | const bigint *src_a, 625 | bigint_word b, int b_neg 626 | ){ 627 | int na = src_a->size; 628 | 629 | bigint_reserve(dst, na + 1); 630 | 631 | dst->size = bigint_raw_add_signed( 632 | dst->words, &dst->neg, 633 | src_a->words, na, src_a->neg, 634 | &b, 1, b_neg 635 | ); 636 | 637 | return dst; 638 | } 639 | 640 | bigint* bigint_add_word(bigint *dst, const bigint *src_a, bigint_word b){ 641 | return bigint_add_word_signed(dst, src_a, b, 0); 642 | } 643 | 644 | bigint* bigint_sub_word(bigint *dst, const bigint *src_a, bigint_word b){ 645 | return bigint_add_word_signed(dst, src_a, b, 1); 646 | } 647 | 648 | int bigint_raw_shift_left( 649 | bigint_word *dst, int n_dst, 650 | const bigint_word *src, int n_src, 651 | unsigned shift 652 | ){ 653 | int i; 654 | int word_shift = shift / BIGINT_WORD_BITS; 655 | int bits_shift = shift % BIGINT_WORD_BITS; 656 | 657 | if (bits_shift){ 658 | bigint_word lo, hi = 0; 659 | 660 | for (i = n_src + word_shift; i > word_shift; i--){ 661 | lo = src[i - word_shift - 1]; 662 | BIGINT_ASSERT(i, >=, 0); 663 | BIGINT_ASSERT(i, <, n_dst); 664 | dst[i] = (hi << bits_shift) | (lo >> (BIGINT_WORD_BITS - bits_shift)); 665 | hi = lo; 666 | } 667 | 668 | for (i = word_shift; i >= 0; i--){ 669 | BIGINT_ASSERT(i, >=, 0); 670 | BIGINT_ASSERT(i, <, n_dst); 671 | dst[i] = hi << bits_shift; 672 | hi = 0; 673 | } 674 | 675 | i = n_src + word_shift + 1; 676 | BIGINT_ASSERT(i, <=, n_dst); 677 | return bigint_raw_truncate(dst, i); 678 | }else{ 679 | /* this case is not only separate because of performance */ 680 | /* but (lo >> (BIGINT_WORD_BITS - 0)) is also undefined behaviour */ 681 | for (i = n_src + word_shift - 1; i >= word_shift; i--){ 682 | BIGINT_ASSERT(i, >=, 0); 683 | BIGINT_ASSERT(i, <, n_dst); 684 | dst[i] = src[i - word_shift]; 685 | } 686 | 687 | for (i = word_shift - 1; i >= 0; i--){ 688 | BIGINT_ASSERT(i, >=, 0); 689 | BIGINT_ASSERT(i, <, n_dst); 690 | dst[i] = 0; 691 | } 692 | 693 | i = n_src + word_shift; 694 | BIGINT_ASSERT(i, <=, n_dst); 695 | return bigint_raw_truncate(dst, i); 696 | } 697 | } 698 | 699 | int bigint_raw_shift_right( 700 | bigint_word *dst, int n_dst, 701 | const bigint_word *src, int n_src, 702 | int shift 703 | ){ 704 | int i; 705 | int word_shift = shift / BIGINT_WORD_BITS; 706 | int bits_shift = shift % BIGINT_WORD_BITS; 707 | 708 | if (bits_shift){ 709 | bigint_word hi, lo = src[word_shift]; 710 | 711 | for (i = 0; i < n_src - word_shift - 1; i++){ 712 | hi = src[i + word_shift + 1]; 713 | BIGINT_ASSERT(i, <, n_dst); 714 | dst[i] = (hi << (BIGINT_WORD_BITS - bits_shift)) | (lo >> bits_shift); 715 | lo = hi; 716 | } 717 | 718 | BIGINT_ASSERT(i, <, n_dst); 719 | dst[i++] = lo >> bits_shift; 720 | 721 | BIGINT_ASSERT(i, <=, n_dst); 722 | return bigint_raw_truncate(dst, i); 723 | }else{ 724 | /* this case is not only separate because of performance */ 725 | /* but (hi << (BIGINT_WORD_BITS - 0)) is also undefined behaviour */ 726 | for (i = 0; i < n_src - word_shift; i++){ 727 | BIGINT_ASSERT(i, <, n_dst); 728 | dst[i] = src[i + word_shift]; 729 | } 730 | 731 | BIGINT_ASSERT(i, <=, n_dst); 732 | return bigint_raw_truncate(dst, i); 733 | } 734 | } 735 | 736 | bigint* bigint_shift_left(bigint *dst, const bigint *src, unsigned shift){ 737 | unsigned n = src->size + shift / BIGINT_WORD_BITS + (shift % BIGINT_WORD_BITS != 0); 738 | bigint_reserve(dst, n); 739 | dst->size = bigint_raw_shift_left(dst->words, dst->capacity, src->words, src->size, shift); 740 | return bigint_set_neg(dst, src->neg); 741 | } 742 | 743 | bigint* bigint_shift_right(bigint *dst, const bigint *src, unsigned shift){ 744 | bigint_reserve(dst, src->size); 745 | dst->size = bigint_raw_shift_right(dst->words, dst->capacity, src->words, src->size, shift); 746 | return bigint_set_neg(dst, src->neg); 747 | } 748 | 749 | int bigint_raw_bitlength(const bigint_word *src_a, int na){ 750 | int last = na - 1; 751 | if (last < 0) return 0; 752 | return bigint_word_bitlength(src_a[last]) + last*BIGINT_WORD_BITS; 753 | } 754 | 755 | int bigint_bitlength(const bigint *a){ 756 | return bigint_raw_bitlength(a->words, a->size); 757 | } 758 | 759 | int bigint_count_trailing_zeros(const bigint *a){ 760 | int i; 761 | for (i = 0; i < a->size; i++){ 762 | bigint_word w = a->words[i]; 763 | if (w) return bigint_word_count_trailing_zeros(w) + i*BIGINT_WORD_BITS; 764 | } 765 | return a->size * BIGINT_WORD_BITS; 766 | } 767 | 768 | bigint* bigint_div_mod( 769 | bigint *dst_quotient, 770 | bigint *dst_remainder, 771 | const bigint *src_numerator, 772 | const bigint *src_denominator 773 | ){ 774 | int shift; 775 | int src_numerator_neg = src_numerator->neg; 776 | int src_denominator_neg = src_denominator->neg; 777 | bigint denominator[1], *remainder = dst_remainder, *quotient = dst_quotient; 778 | 779 | if (src_denominator->size == 0) return NULL; 780 | 781 | /* fast path for native word size */ 782 | if (src_numerator->size == 1 && src_denominator->size == 1){ 783 | /* make sure this is not overwritten */ 784 | bigint_word a = src_numerator->words[0]; 785 | bigint_word b = src_denominator->words[0]; 786 | bigint_from_word(quotient, a / b); 787 | bigint_from_word(remainder, a % b); 788 | quotient->neg = src_numerator_neg ^ src_denominator_neg; 789 | remainder->neg = src_numerator_neg; 790 | return dst_quotient; 791 | } 792 | 793 | /* fast path for half word size */ 794 | if (src_denominator->size == 1 && 795 | src_denominator->words[0] <= BIGINT_HALF_WORD_MAX 796 | ){ 797 | bigint_word rem; 798 | bigint_cpy(quotient, src_numerator); 799 | bigint_div_mod_half_word(quotient, &rem, src_denominator->words[0]); 800 | bigint_from_word(remainder, rem); 801 | quotient->neg = src_numerator_neg ^ src_denominator_neg; 802 | remainder->neg = src_numerator_neg; 803 | return dst_quotient; 804 | } 805 | 806 | bigint_cpy(remainder, src_numerator); 807 | remainder->neg = 0; 808 | quotient->size = 0; 809 | 810 | if (bigint_cmp_abs(remainder, src_denominator) >= 0){ 811 | shift = bigint_bitlength(remainder) - bigint_bitlength(src_denominator); 812 | 813 | bigint_init(denominator); 814 | bigint_shift_left(denominator, src_denominator, shift); 815 | denominator->neg = 0; 816 | 817 | /* divide bit by bit */ 818 | for (; shift >= 0; shift--) { 819 | if (bigint_cmp_abs(remainder, denominator) >= 0) { 820 | bigint_sub(remainder, remainder, denominator); 821 | bigint_set_bit(quotient, shift); 822 | } 823 | bigint_shift_right(denominator, denominator, 1); 824 | } 825 | 826 | bigint_free(denominator); 827 | } 828 | 829 | quotient->neg = src_numerator_neg ^ src_denominator_neg; 830 | remainder->neg = src_numerator_neg; 831 | return dst_quotient; 832 | } 833 | 834 | bigint* bigint_div( 835 | bigint *dst, 836 | const bigint *numerator, 837 | const bigint *denominator 838 | ){ 839 | bigint unused[1]; 840 | bigint_init(unused); 841 | 842 | bigint_div_mod(dst, unused, numerator, denominator); 843 | 844 | bigint_free(unused); 845 | return dst; 846 | } 847 | 848 | bigint* bigint_mod( 849 | bigint *dst, 850 | const bigint *numerator, 851 | const bigint *denominator 852 | ){ 853 | bigint unused[1]; 854 | bigint_init(unused); 855 | 856 | bigint_div_mod(unused, dst, numerator, denominator); 857 | 858 | bigint_free(unused); 859 | return dst; 860 | } 861 | 862 | bigint* bigint_div_mod_half_word( 863 | bigint *dst, 864 | bigint_word *dst_remainder, 865 | bigint_word denominator 866 | ){ 867 | int i, j; 868 | bigint_word parts[2], div_word, mod_word, remainder = 0; 869 | 870 | BIGINT_ASSERT(denominator, !=, 0); 871 | BIGINT_ASSERT(denominator, <=, BIGINT_HALF_WORD_MAX); 872 | 873 | for (i = dst->size - 1; i >= 0; i--){ 874 | bigint_word dst_word = 0; 875 | bigint_word src_word = dst->words[i]; 876 | parts[1] = BIGINT_WORD_LO(src_word); 877 | parts[0] = BIGINT_WORD_HI(src_word); 878 | 879 | /* divide by denominator twice, keeping remainder in mind */ 880 | for (j = 0; j < 2; j++){ 881 | remainder <<= BIGINT_WORD_BITS / 2; 882 | remainder |= parts[j]; 883 | 884 | div_word = remainder / denominator; 885 | mod_word = remainder % denominator; 886 | remainder = mod_word; 887 | 888 | dst_word <<= BIGINT_WORD_BITS / 2; 889 | dst_word |= div_word; 890 | } 891 | 892 | dst->words[i] = dst_word; 893 | } 894 | 895 | *dst_remainder = remainder; 896 | dst->size = bigint_raw_truncate(dst->words, dst->size); 897 | return dst; 898 | } 899 | 900 | bigint* bigint_gcd(bigint *dst, const bigint *src_a, const bigint *src_b){ 901 | int shift, shift_a, shift_b; 902 | bigint a[1], b[1]; 903 | 904 | if (src_a->size == 0) return bigint_set_neg(bigint_cpy(dst, src_b), 0); 905 | if (src_b->size == 0) return bigint_set_neg(bigint_cpy(dst, src_a), 0); 906 | 907 | if (src_a->size == 1 && src_b->size == 1){ 908 | bigint_word word = bigint_word_gcd(src_a->words[0], src_b->words[0]); 909 | return bigint_from_word(dst, word); 910 | } 911 | 912 | bigint_init(a); 913 | bigint_init(b); 914 | 915 | shift_a = bigint_count_trailing_zeros(src_a); 916 | shift_b = bigint_count_trailing_zeros(src_b); 917 | shift = BIGINT_MIN(shift_a, shift_b); 918 | 919 | bigint_shift_right(a, src_a, shift_a); 920 | bigint_shift_right(b, src_b, shift); 921 | a->neg = 0; 922 | b->neg = 0; 923 | 924 | do { 925 | bigint_shift_right(b, b, bigint_count_trailing_zeros(b)); 926 | 927 | if (bigint_cmp_abs(a, b) > 0) BIGINT_SWAP(bigint, *a, *b); 928 | 929 | bigint_sub(b, b, a); 930 | } while (b->size != 0); 931 | 932 | bigint_shift_left(dst, a, shift); 933 | 934 | bigint_free(a); 935 | bigint_free(b); 936 | return dst; 937 | } 938 | 939 | bigint* bigint_sqrt(bigint *dst, const bigint *src){ 940 | int bit; 941 | bigint sum[1], tmp[1]; 942 | const double MAX_INT_THAT_FITS_IN_DOUBLE = pow(2.0, 52.0); 943 | 944 | dst->neg = 0; 945 | dst->size = 0; 946 | 947 | if (src->size == 0) return dst; 948 | 949 | if (src->size == 1 && src->words[0] < MAX_INT_THAT_FITS_IN_DOUBLE){ 950 | bigint_from_word(dst, sqrt(src->words[0])); 951 | return dst; 952 | } 953 | 954 | bigint_init(sum); 955 | bigint_init(tmp); 956 | 957 | bigint_cpy(tmp, src); 958 | tmp->neg = 0; 959 | 960 | /* index of highest 1 bit rounded down */ 961 | bit = bigint_bitlength(src); 962 | if (bit & 1) bit ^= 1; 963 | 964 | for (; bit >= 0; bit -= 2){ 965 | bigint_cpy(sum, dst); 966 | bigint_set_bit(sum, bit); 967 | 968 | if (bigint_cmp_abs(tmp, sum) >= 0){ 969 | bigint_sub(tmp, tmp, sum); 970 | bigint_set_bit(dst, bit + 1); 971 | } 972 | 973 | bigint_shift_right(dst, dst, 1); 974 | } 975 | 976 | bigint_free(tmp); 977 | bigint_free(sum); 978 | return dst; 979 | } 980 | 981 | char* bigint_write_base( 982 | char *dst, 983 | int *n_dst, 984 | const bigint *a, 985 | bigint_word base, 986 | int zero_terminate 987 | ){ 988 | int i = 0, n = *n_dst; 989 | static const char *table = "0123456789abcdefghijklmnopqrstuvwxyz"; 990 | BIGINT_ASSERT(base, >=, 2); 991 | BIGINT_ASSERT(base, <=, 36); 992 | 993 | if (zero_terminate) if (i < n) dst[i++] = '\0'; 994 | 995 | if (a->size == 0){ 996 | if (i < n) dst[i++] = '0'; 997 | }else{ 998 | bigint tmp[1]; 999 | bigint_init(tmp); 1000 | bigint_cpy(tmp, a); 1001 | 1002 | while (tmp->size > 0){ 1003 | bigint_word remainder; 1004 | /* TODO extract as many digits as fit into bigint_word at once */ 1005 | /* tricky with leading zeros */ 1006 | bigint_div_mod_half_word(tmp, &remainder, base); 1007 | if (i < n) dst[i++] = table[remainder]; 1008 | } 1009 | 1010 | bigint_free(tmp); 1011 | } 1012 | 1013 | if (a->neg) if (i < n) dst[i++] = '-'; 1014 | BIGINT_REVERSE(char, dst, i); 1015 | *n_dst = i; 1016 | 1017 | return dst; 1018 | } 1019 | 1020 | char* bigint_write(char *dst, int n_dst, const bigint *a){ 1021 | return bigint_write_base(dst, &n_dst, a, 10, 1); 1022 | } 1023 | 1024 | bigint* bigint_rand_bits(bigint *dst, int n_bits, bigint_rand_func rand_func){ 1025 | int n_word_bits = n_bits % BIGINT_WORD_BITS; 1026 | int n_words = n_bits / BIGINT_WORD_BITS + (n_word_bits != 0); 1027 | 1028 | bigint_reserve(dst, n_words); 1029 | 1030 | rand_func((uint8_t*)dst->words, sizeof(*dst->words) * n_words); 1031 | 1032 | if (n_word_bits){ 1033 | dst->words[n_words - 1] >>= BIGINT_WORD_BITS - n_word_bits; 1034 | } 1035 | 1036 | dst->size = bigint_raw_truncate(dst->words, n_words); 1037 | return dst; 1038 | } 1039 | 1040 | bigint* bigint_rand_inclusive( 1041 | bigint *dst, 1042 | const bigint *n, 1043 | bigint_rand_func rand_func 1044 | ){ 1045 | int n_bits = bigint_bitlength(n); 1046 | 1047 | do { 1048 | bigint_rand_bits(dst, n_bits, rand_func); 1049 | } while (bigint_cmp(dst, n) > 0); 1050 | 1051 | return dst; 1052 | } 1053 | 1054 | bigint* bigint_rand_exclusive( 1055 | bigint *dst, 1056 | const bigint *n, 1057 | bigint_rand_func rand_func 1058 | ){ 1059 | int n_bits = bigint_bitlength(n); 1060 | 1061 | do { 1062 | bigint_rand_bits(dst, n_bits, rand_func); 1063 | } while (bigint_cmp(dst, n) >= 0); 1064 | 1065 | return dst; 1066 | } 1067 | 1068 | bigint* bigint_pow_mod( 1069 | bigint *dst, 1070 | const bigint *src_base, 1071 | const bigint *src_exponent, 1072 | const bigint *src_modulus 1073 | ){ 1074 | bigint base[1], exponent[1], tmp[1], unused[1], modulus[1]; 1075 | 1076 | bigint_init(base); 1077 | bigint_init(exponent); 1078 | bigint_init(tmp); 1079 | bigint_init(unused); 1080 | bigint_init(modulus); 1081 | 1082 | bigint_cpy(exponent, src_exponent); 1083 | bigint_cpy(modulus, src_modulus); 1084 | bigint_div_mod(unused, base, src_base, modulus); 1085 | bigint_from_word(dst, 1); 1086 | 1087 | for (; exponent->size; bigint_shift_right(exponent, exponent, 1)){ 1088 | if (bigint_get_bit(exponent, 0)){ 1089 | bigint_mul(tmp, dst, base); 1090 | bigint_div_mod(unused, dst, tmp, modulus); 1091 | } 1092 | bigint_mul(tmp, base, base); 1093 | bigint_div_mod(unused, base, tmp, modulus); 1094 | } 1095 | 1096 | bigint_free(base); 1097 | bigint_free(exponent); 1098 | bigint_free(tmp); 1099 | bigint_free(unused); 1100 | bigint_free(modulus); 1101 | return dst; 1102 | } 1103 | 1104 | int bigint_is_probable_prime( 1105 | const bigint *n, 1106 | int n_tests, 1107 | bigint_rand_func rand_func 1108 | ){ 1109 | bigint a[1], d[1], x[1], two[1], n_minus_one[1], n_minus_three[1]; 1110 | int i, shift; 1111 | 1112 | /* divisible by 2, not prime */ 1113 | if (bigint_get_bit(n, 0) == 0) return 0; 1114 | 1115 | /* 1 is not prime */ 1116 | if (bigint_cmp_abs_word(n, 1) <= 0) return 0; 1117 | /* 3 is prime */ 1118 | if (bigint_cmp_abs_word(n, 3) <= 0) return 1; 1119 | 1120 | bigint_init(a); 1121 | bigint_init(d); 1122 | bigint_init(x); 1123 | bigint_init(two); 1124 | bigint_init(n_minus_one); 1125 | bigint_init(n_minus_three); 1126 | 1127 | bigint_from_word(two, 2); 1128 | 1129 | bigint_sub_word(n_minus_one, n, 1); 1130 | bigint_sub_word(n_minus_three, n, 3); 1131 | 1132 | shift = bigint_count_trailing_zeros(n_minus_one); 1133 | bigint_shift_right(d, n_minus_one, shift); 1134 | 1135 | do { 1136 | bigint_rand_inclusive(a, n_minus_three, rand_func); 1137 | bigint_add_word(a, a, 2); 1138 | bigint_pow_mod(x, a, d, n); 1139 | 1140 | if (bigint_cmp_abs_word(x, 1) == 0) continue; 1141 | if (bigint_cmp(x, n_minus_one) == 0) continue; 1142 | 1143 | for (i = 1; i < shift; i++){ 1144 | bigint_pow_mod(x, x, two, n); 1145 | if (bigint_cmp_abs_word(x, 1) == 0) return 0; 1146 | if (bigint_cmp(x, n_minus_one) == 0) break; 1147 | } 1148 | 1149 | if (i == shift) return 0; 1150 | } while (--n_tests); 1151 | 1152 | bigint_free(a); 1153 | bigint_free(d); 1154 | bigint_free(x); 1155 | bigint_free(two); 1156 | bigint_free(n_minus_one); 1157 | bigint_free(n_minus_three); 1158 | return 1; 1159 | } 1160 | 1161 | bigint* bigint_pow_word(bigint *dst, const bigint *base, bigint_word exponent){ 1162 | bigint result[1], p[1]; 1163 | 1164 | bigint_init(p); 1165 | bigint_init(result); 1166 | 1167 | bigint_cpy(p, base); 1168 | bigint_from_word(result, 1); 1169 | 1170 | for (; exponent; exponent >>= 1){ 1171 | if (exponent & 1){ 1172 | bigint_mul(result, result, p); 1173 | exponent--; 1174 | } 1175 | bigint_mul(p, p, p); 1176 | } 1177 | 1178 | bigint_cpy(dst, result); 1179 | bigint_free(p); 1180 | bigint_free(result); 1181 | return dst; 1182 | } 1183 | 1184 | void bigint_raw_get_high_bits( 1185 | bigint_word *dst, int n_dst, 1186 | const bigint_word *src_a, int na, 1187 | int n_bits, 1188 | int *n_bitlength 1189 | ){ 1190 | int shift; 1191 | *n_bitlength = bigint_raw_bitlength(src_a, na); 1192 | shift = n_bits - *n_bitlength + 1; 1193 | 1194 | if (shift < 0) bigint_raw_shift_right(dst, n_dst, src_a, na, -shift); 1195 | else bigint_raw_shift_left (dst, n_dst, src_a, na, +shift); 1196 | } 1197 | 1198 | double bigint_double(const bigint *src){ 1199 | /* assumes IEEE 754 floating point standard */ 1200 | int n, n_mant_bits = 52; 1201 | uint64_t x = 0, exponent = 1023; 1202 | double d; 1203 | bigint_word tmp[20]; 1204 | 1205 | if (src->size == 0) return 0.0; 1206 | 1207 | bigint_raw_get_high_bits(tmp, 20, src->words, src->size, n_mant_bits, &n); 1208 | /* this bit is stored implicitely */ 1209 | bigint_raw_clr_bit(tmp, n_mant_bits); 1210 | exponent--; 1211 | exponent += n; 1212 | memcpy(&x, tmp, sizeof(x)); 1213 | x |= exponent << n_mant_bits; 1214 | 1215 | memcpy(&d, &x, sizeof(d)); 1216 | return src->neg ? -d : d; 1217 | } 1218 | -------------------------------------------------------------------------------- /bigint.h: -------------------------------------------------------------------------------- 1 | #ifndef BIGINT_H_INCLUDED 2 | #define BIGINT_H_INCLUDED 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | #include 10 | 11 | /* any unsigned integer type */ 12 | typedef uint32_t bigint_word; 13 | 14 | #define BIGINT_KARATSUBA_WORD_THRESHOLD 20 15 | 16 | #define BIGINT_WORD_BITS ((sizeof(bigint_word) * CHAR_BIT)) 17 | #define BIGINT_WORD_MAX ((bigint_word)-1) 18 | #define BIGINT_HALF_WORD_MAX (BIGINT_WORD_MAX >> BIGINT_WORD_BITS / 2) 19 | 20 | #define BIGINT_WORD_LO(a) ((a) & BIGINT_HALF_WORD_MAX) 21 | #define BIGINT_WORD_HI(a) ((a) >> sizeof(a) * CHAR_BIT / 2) 22 | 23 | #define BIGINT_MIN(a, b) ((a) < (b) ? (a) : (b)) 24 | #define BIGINT_MAX(a, b) ((a) > (b) ? (a) : (b)) 25 | #define BIGINT_INT_ABS(a) ((a) < 0 ? -(unsigned int)(a) : (unsigned int)(a)) 26 | 27 | #define BIGINT_SWAP(type, a, b) do { type _tmp = a; a = b; b = _tmp; } while (0) 28 | 29 | #define BIGINT_REVERSE(type, data, n) do {\ 30 | int _i;\ 31 | for (_i = 0; _i < (n)/2; _i++) BIGINT_SWAP(type, data[_i], data[n - 1 - _i]);\ 32 | } while (0) 33 | 34 | typedef struct bigint { 35 | bigint_word *words; 36 | int neg, size, capacity; 37 | } bigint; 38 | 39 | typedef void (*bigint_rand_func)(uint8_t *dst, int n); 40 | 41 | bigint_word bigint_word_mul_lo(bigint_word a, bigint_word b); 42 | bigint_word bigint_word_mul_hi(bigint_word a, bigint_word b); 43 | 44 | bigint_word bigint_word_add_get_carry(bigint_word *dst, bigint_word a, bigint_word b); 45 | bigint_word bigint_word_sub_get_carry(bigint_word *dst, bigint_word a, bigint_word b); 46 | 47 | bigint_word bigint_word_from_char(char c); 48 | 49 | int bigint_word_bitlength(bigint_word a); 50 | int bigint_word_count_trailing_zeros(bigint_word a); 51 | 52 | bigint_word bigint_word_gcd(bigint_word a, bigint_word b); 53 | unsigned bigint_uint_gcd(unsigned a, unsigned b); 54 | int bigint_int_gcd(int a, int b); 55 | 56 | bigint* bigint_init(bigint *a); 57 | bigint* bigint_reserve(bigint *a, int capacity); 58 | void bigint_free(bigint *a); 59 | 60 | int bigint_cmp_abs(const bigint *a, const bigint *b); 61 | int bigint_cmp(const bigint *a, const bigint *b); 62 | int bigint_cmp_abs_word(const bigint *a, bigint_word b); 63 | 64 | bigint* bigint_set_neg(bigint *dst, int neg); 65 | bigint* bigint_negate(bigint *dst); 66 | 67 | bigint* bigint_cpy(bigint *dst, const bigint *src); 68 | 69 | bigint* bigint_clr_bit(bigint *dst, unsigned bit_index); 70 | bigint* bigint_set_bit(bigint *dst, unsigned bit_index); 71 | bigint_word bigint_get_bit(const bigint *src, unsigned bit_index); 72 | 73 | bigint* bigint_mul(bigint *dst, const bigint *a, const bigint *b); 74 | 75 | int bigint_count_digits(const char *src); 76 | int bigint_digits_bound(int n_digits_src, double src_base, double dst_base); 77 | int bigint_write_size(const bigint *a, double dst_base); 78 | bigint* bigint_from_str_base(bigint *dst, const char *src, int src_base); 79 | bigint* bigint_from_str(bigint *dst, const char *src); 80 | bigint* bigint_from_int(bigint *dst, int src); 81 | bigint* bigint_from_word(bigint *dst, bigint_word a); 82 | 83 | bigint* bigint_add_signed(bigint *dst, const bigint *a, int a_neg, const bigint *b, int b_neg); 84 | bigint* bigint_add(bigint *dst, const bigint *a, const bigint *b); 85 | bigint* bigint_sub(bigint *dst, const bigint *a, const bigint *b); 86 | bigint* bigint_add_word_signed(bigint *dst, const bigint *src_a, bigint_word b, int b_neg); 87 | bigint* bigint_add_word(bigint *dst, const bigint *src_a, bigint_word b); 88 | bigint* bigint_sub_word(bigint *dst, const bigint *src_a, bigint_word b); 89 | 90 | char* bigint_write_base( 91 | char *dst, 92 | int *n_dst, 93 | const bigint *a, 94 | bigint_word base, 95 | int zero_terminate 96 | ); 97 | 98 | /* convenience function defaults to base 10 and zero terminates */ 99 | char* bigint_write(char *dst, int n_dst, const bigint *a); 100 | 101 | bigint* bigint_shift_left (bigint *dst, const bigint *src, unsigned shift); 102 | bigint* bigint_shift_right(bigint *dst, const bigint *src, unsigned shift); 103 | 104 | int bigint_bitlength(const bigint *a); 105 | int bigint_count_trailing_zeros(const bigint *a); 106 | 107 | bigint* bigint_div_mod( 108 | bigint *dst_quotient, 109 | bigint *dst_remainder, 110 | const bigint *src_biginterator, 111 | const bigint *src_denominator 112 | ); 113 | 114 | bigint* bigint_div( 115 | bigint *dst, 116 | const bigint *numerator, 117 | const bigint *denominator 118 | ); 119 | 120 | bigint* bigint_mod( 121 | bigint *dst, 122 | const bigint *numerator, 123 | const bigint *denominator 124 | ); 125 | 126 | bigint* bigint_div_mod_half_word( 127 | bigint *dst, 128 | bigint_word *dst_remainder, 129 | bigint_word denominator 130 | ); 131 | 132 | bigint* bigint_gcd(bigint *dst, const bigint *src_a, const bigint *src_b); 133 | bigint* bigint_sqrt(bigint *dst, const bigint *src); 134 | 135 | bigint* bigint_rand_bits(bigint *dst, int n_bits, bigint_rand_func rand_func); 136 | bigint* bigint_rand_inclusive(bigint *dst, const bigint *n, bigint_rand_func rand_func); 137 | bigint* bigint_rand_exclusive(bigint *dst, const bigint *n, bigint_rand_func rand_func); 138 | 139 | bigint* bigint_pow_mod( 140 | bigint *dst, 141 | const bigint *src_base, 142 | const bigint *src_exponent, 143 | const bigint *src_modulus 144 | ); 145 | 146 | /* probability for wrong positives is approximately 1/4^n_tests */ 147 | int bigint_is_probable_prime(const bigint *n, int n_tests, bigint_rand_func rand_func); 148 | 149 | bigint* bigint_pow_word(bigint *dst, const bigint *src, bigint_word exponent); 150 | 151 | double bigint_double(const bigint *src); 152 | 153 | #ifdef __cplusplus 154 | } 155 | #endif 156 | 157 | #endif 158 | -------------------------------------------------------------------------------- /bigint.hpp: -------------------------------------------------------------------------------- 1 | #ifndef NUM_HPP_INCLUDED 2 | #define NUM_HPP_INCLUDED 3 | 4 | #include "bigint.h" 5 | 6 | #include 7 | 8 | struct BigInt { 9 | bigint data[1]; 10 | 11 | BigInt(){ 12 | bigint_init(data); 13 | } 14 | 15 | BigInt(int b){ 16 | bigint_init(data); 17 | bigint_from_int(data, b); 18 | } 19 | 20 | BigInt(const char *s, int base = 10){ 21 | bigint_init(data); 22 | bigint_from_str_base(data, s, base); 23 | } 24 | 25 | BigInt(const BigInt &b){ 26 | bigint_init(data); 27 | bigint_cpy(data, b.data); 28 | } 29 | 30 | BigInt& operator = (const BigInt &b){ 31 | bigint_cpy(data, b.data); 32 | return *this; 33 | } 34 | 35 | ~BigInt(){ 36 | bigint_free(data); 37 | } 38 | 39 | static void div_mod( 40 | BigInt "ient, BigInt &remainder, 41 | const BigInt &biginterator, 42 | const BigInt &denominator 43 | ){ 44 | bigint_div_mod(quotient.data, remainder.data, 45 | biginterator.data, denominator.data); 46 | } 47 | 48 | void write( 49 | char *dst, 50 | int *n_dst, 51 | int dst_base = 10, 52 | int zero_terminate = 1 53 | ) const { 54 | bigint_write_base(dst, n_dst, data, dst_base, zero_terminate); 55 | } 56 | 57 | template 58 | STREAM& write(STREAM &s, int dst_base = 10) const { 59 | int n = bigint_write_size(data, dst_base); 60 | char *buf = (char*)malloc(n); 61 | write(buf, &n, dst_base); 62 | s << buf; 63 | free(buf); 64 | return s; 65 | } 66 | 67 | BigInt& operator <<= (int shift){ 68 | bigint_shift_left(data, data, shift); 69 | return *this; 70 | } 71 | 72 | BigInt& operator >>= (int shift){ 73 | bigint_shift_right(data, data, shift); 74 | return *this; 75 | } 76 | 77 | BigInt& operator += (const BigInt &b){ 78 | bigint_add(data, data, b.data); 79 | return *this; 80 | } 81 | 82 | BigInt& operator -= (const BigInt &b){ 83 | bigint_sub(data, data, b.data); 84 | return *this; 85 | } 86 | 87 | BigInt& operator *= (const BigInt &b){ 88 | bigint_mul(data, data, b.data); 89 | return *this; 90 | } 91 | 92 | BigInt& operator /= (const BigInt &b){ 93 | bigint_div(data, data, b.data); 94 | return *this; 95 | } 96 | 97 | BigInt& operator %= (const BigInt &b){ 98 | bigint_mod(data, data, b.data); 99 | return *this; 100 | } 101 | 102 | BigInt& operator ++ (){ 103 | bigint_add_word(data, data, 1); 104 | return *this; 105 | } 106 | 107 | BigInt& operator -- (){ 108 | bigint_sub_word(data, data, 1); 109 | return *this; 110 | } 111 | 112 | BigInt& set_bit(int bit_index){ 113 | bigint_set_bit(data, bit_index); 114 | return *this; 115 | } 116 | 117 | BigInt& clr_bit(int bit_index){ 118 | bigint_clr_bit(data, bit_index); 119 | return *this; 120 | } 121 | 122 | bigint_word get_bit(int bit_index) const { 123 | return bigint_get_bit(data, bit_index); 124 | } 125 | 126 | int bitlength() const { 127 | return bigint_bitlength(data); 128 | } 129 | 130 | int count_trailing_zeros() const { 131 | return bigint_count_trailing_zeros(data); 132 | } 133 | 134 | bool is_probable_prime(int n_tests, bigint_rand_func rand_func) const { 135 | return bigint_is_probable_prime(data, n_tests, rand_func); 136 | } 137 | 138 | BigInt sqrt() const { 139 | BigInt b; 140 | bigint_sqrt(b.data, data); 141 | return b; 142 | } 143 | 144 | BigInt pow(bigint_word exponent){ 145 | BigInt b; 146 | bigint_pow_word(b.data, data, exponent); 147 | return b; 148 | } 149 | 150 | static BigInt gcd(const BigInt &a, const BigInt &b){ 151 | BigInt c; 152 | bigint_gcd(c.data, a.data, b.data); 153 | return c; 154 | } 155 | 156 | static BigInt rand_bits(int n_bits, bigint_rand_func rand_func){ 157 | BigInt b; 158 | bigint_rand_bits(b.data, n_bits, rand_func); 159 | return b; 160 | } 161 | 162 | static BigInt rand_inclusive(const BigInt &n, bigint_rand_func rand_func){ 163 | BigInt b; 164 | bigint_rand_inclusive(b.data, n.data, rand_func); 165 | return b; 166 | } 167 | 168 | static BigInt rand_exclusive(const BigInt &n, bigint_rand_func rand_func){ 169 | BigInt b; 170 | bigint_rand_exclusive(b.data, n.data, rand_func); 171 | return b; 172 | } 173 | }; 174 | 175 | inline BigInt operator -(const BigInt &a){ 176 | BigInt b(a); 177 | b.data->neg = !b.data->neg; 178 | return b; 179 | } 180 | 181 | inline BigInt operator + (const BigInt &a, const BigInt &b){ 182 | return BigInt(a) += b; 183 | } 184 | 185 | inline BigInt operator - (const BigInt &a, const BigInt &b){ 186 | return BigInt(a) -= b; 187 | } 188 | 189 | inline BigInt operator * (const BigInt &a, const BigInt &b){ 190 | return BigInt(a) *= b; 191 | } 192 | 193 | inline BigInt operator / (const BigInt &a, const BigInt &b){ 194 | return BigInt(a) /= b; 195 | } 196 | 197 | inline BigInt operator % (const BigInt &a, const BigInt &b){ 198 | return BigInt(a) %= b; 199 | } 200 | 201 | inline BigInt operator << (const BigInt &a, int shift){ 202 | return BigInt(a) <<= shift; 203 | } 204 | 205 | inline BigInt operator >> (const BigInt &a, int shift){ 206 | return BigInt(a) >>= shift; 207 | } 208 | 209 | inline bool operator == (const BigInt &a, const BigInt &b){ return bigint_cmp(a.data, b.data) == 0; } 210 | inline bool operator != (const BigInt &a, const BigInt &b){ return bigint_cmp(a.data, b.data) != 0; } 211 | inline bool operator <= (const BigInt &a, const BigInt &b){ return bigint_cmp(a.data, b.data) <= 0; } 212 | inline bool operator >= (const BigInt &a, const BigInt &b){ return bigint_cmp(a.data, b.data) >= 0; } 213 | inline bool operator < (const BigInt &a, const BigInt &b){ return bigint_cmp(a.data, b.data) < 0; } 214 | inline bool operator > (const BigInt &a, const BigInt &b){ return bigint_cmp(a.data, b.data) > 0; } 215 | 216 | #endif 217 | -------------------------------------------------------------------------------- /c_examples.c: -------------------------------------------------------------------------------- 1 | #include "bigint.h" 2 | 3 | #include 4 | 5 | int main(){ 6 | char buf[65536]; 7 | 8 | /* neat trick to avoid having to write &a, &b, &c everywhere */ 9 | bigint a[1], b[1], c[1]; 10 | 11 | /* bigints have to be initialized (same as memset'ed to zero) */ 12 | bigint_init(a); 13 | bigint_init(b); 14 | bigint_init(c); 15 | 16 | /* create bigint from string */ 17 | bigint_from_str(a, "123456789"); 18 | bigint_from_str(b, "987654321"); 19 | 20 | /* c = a * b */ 21 | /* first parameter is destination parameter */ 22 | bigint_mul(c, a, b); 23 | 24 | /* write and print */ 25 | puts(bigint_write(buf, sizeof(buf), c)); 26 | 27 | /* bigints have to be free'd */ 28 | bigint_free(a); 29 | bigint_free(b); 30 | bigint_free(c); 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /cpp_examples.cpp: -------------------------------------------------------------------------------- 1 | #include "bigint.hpp" 2 | 3 | #include 4 | #include 5 | 6 | uint32_t xorshift32() { 7 | static uint32_t x = 314159265; 8 | x ^= x << 13; 9 | x ^= x >> 17; 10 | x ^= x << 5; 11 | return x; 12 | } 13 | 14 | // do not use this as a cryptographically secure random number generator 15 | void not_secure_random(uint8_t *dst, int n){ 16 | for (int i = 0; i < n; i++) dst[i] = xorshift32(); 17 | } 18 | 19 | int main(){ 20 | // BigInts can be created from strings or from integers 21 | BigInt a = "-1137531041259095389425522063651335971086542522289"; 22 | BigInt b = "-9214001518046086468566115579527473139501"; 23 | 24 | // Available operators: 25 | // +, -, *, /, %, <<, >> 26 | // +=, -=, *=, /=, %=, <<=, >>=, ++, -- 27 | // ==, !=, <=, >=, <, > 28 | BigInt c = a / b; 29 | BigInt d = b * c; 30 | assert(c == 123456789); 31 | assert(a == d); 32 | 33 | // write to any output stream 34 | c.write(std::cout) << std::endl; 35 | d.write(std::cout) << std::endl; 36 | 37 | // find the biggest probable prime less than 10^42 38 | BigInt p = BigInt(10).pow(42) - 1; 39 | 40 | for (int i = 0; i < 100; i++){ 41 | if (p.is_probable_prime(10, not_secure_random)){ 42 | p.write(std::cout << "Big prime: ") << std::endl; 43 | break; 44 | } 45 | --p; 46 | } 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /tests.c: -------------------------------------------------------------------------------- 1 | #include "bigint.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main(){ 10 | int i, j; 11 | char buf[65536]; 12 | bigint a[1], b[1], c[1], d[1], e[20]; 13 | const char *text = "123456790123456790120987654320987654321"; 14 | 15 | bigint_init(a); 16 | bigint_init(b); 17 | bigint_init(c); 18 | bigint_init(d); 19 | 20 | for (i = 0; i < 20; i++) bigint_init(e + i); 21 | 22 | bigint_from_str(a, text); 23 | bigint_from_str(b, "11111111111111111111"); 24 | bigint_sqrt(c, a); 25 | assert(bigint_cmp(b, c) == 0); 26 | 27 | bigint_from_str(a, "1"); 28 | bigint_from_word(b, 1); 29 | bigint_shift_left(a, a, 1 << 10); 30 | 31 | bigint_mul(c, a, a); 32 | bigint_sub(c, c, a); 33 | bigint_sub(c, c, a); 34 | bigint_add(c, c, b); 35 | 36 | bigint_sub(a, a, b); 37 | bigint_mul(d, a, a); 38 | 39 | assert(bigint_cmp(c, d) == 0); 40 | 41 | bigint_from_str_base(a, text, 10); 42 | 43 | i = strcmp(text, bigint_write(buf, sizeof(buf), a)); 44 | assert(i == 0); 45 | 46 | bigint_from_int(a, INT_MIN); 47 | assert(bigint_double(a) == INT_MIN); 48 | 49 | /* max integer value that fits into double without loss of precision */ 50 | /* pow(2, 53) = 9007199254740992 */ 51 | bigint_from_str(a, "-9007199254740992"); 52 | assert(bigint_double(a) == -9007199254740992.0); 53 | 54 | bigint_from_int(a, 0); 55 | assert(bigint_double(a) == 0.0); 56 | bigint_from_int(a, +1); 57 | assert(bigint_double(a) == +1); 58 | bigint_from_int(a, -1); 59 | assert(bigint_double(a) == -1); 60 | 61 | bigint_from_str(a, ""); 62 | bigint_from_str(b, "0"); 63 | bigint_from_str(c, "-0"); 64 | assert(bigint_cmp(a, b) == 0); 65 | assert(bigint_cmp(a, c) == 0); 66 | 67 | for (i = 0; i < 12345; i++){ 68 | int x = rand() % 12345; 69 | int y = rand() % 12345; 70 | int shift = rand() % 1234; 71 | if (rand() & 1) x = -x; 72 | if (rand() & 1) y = -y; 73 | 74 | bigint_from_int(a, x); 75 | bigint_from_int(b, y); 76 | bigint_from_int(e + 0, x + y); 77 | bigint_from_int(e + 1, x - y); 78 | bigint_from_int(e + 2, x * y); 79 | 80 | if (y != 0){ 81 | bigint_from_int(e + 3, x / y); 82 | bigint_from_int(e + 4, x % y); 83 | } 84 | 85 | bigint_from_int(e + 5, sqrt(x > 0 ? x : -x)); 86 | bigint_from_int(e + 6, bigint_int_gcd(x, y)); 87 | 88 | bigint_cpy(c, a); 89 | bigint_shift_left(a, a, shift); 90 | bigint_shift_right(a, a, shift); 91 | 92 | assert(bigint_cmp(a, c) == 0); 93 | 94 | bigint_add(e + 10, a, b); 95 | bigint_sub(e + 11, a, b); 96 | bigint_mul(e + 12, a, b); 97 | bigint_div(e + 13, a, b); 98 | bigint_mod(e + 14, a, b); 99 | bigint_sqrt(e + 15, a); 100 | bigint_gcd(e + 16, a, b); 101 | 102 | for (j = 0; j < 7; j++){ 103 | if (y == 0 && (j == 3 || j == 4)) continue; 104 | if (bigint_cmp(e + j, e + j + 10) != 0){ 105 | printf("i %i, j %i failed for bigints %i, %i\n", i, j, x, y); 106 | } 107 | assert(bigint_cmp(e + j, e + j + 10) == 0); 108 | } 109 | } 110 | 111 | bigint_free(a); 112 | bigint_free(b); 113 | bigint_free(c); 114 | bigint_free(d); 115 | 116 | for (i = 0; i < 20; i++) bigint_free(e + i); 117 | 118 | puts("tests passed"); 119 | 120 | return 0; 121 | } 122 | 123 | --------------------------------------------------------------------------------