github.com/platonnetwork/platon-go@v0.7.6/cases/tool/win/bls_win/include/mcl/vint.hpp (about) 1 #pragma once 2 /** 3 emulate mpz_class 4 */ 5 #ifndef CYBOZU_DONT_USE_EXCEPTION 6 #include <cybozu/exception.hpp> 7 #endif 8 #include <cybozu/bit_operation.hpp> 9 #include <cybozu/xorshift.hpp> 10 #include <assert.h> 11 #ifndef CYBOZU_DONT_USE_STRING 12 #include <iostream> 13 #endif 14 #include <mcl/array.hpp> 15 #include <mcl/util.hpp> 16 #include <mcl/randgen.hpp> 17 #include <mcl/conversion.hpp> 18 19 #if defined(__EMSCRIPTEN__) || defined(__wasm__) 20 #define MCL_VINT_64BIT_PORTABLE 21 #define MCL_VINT_FIXED_BUFFER 22 #endif 23 #ifndef MCL_MAX_BIT_SIZE 24 #error "define MCL_MAX_BIT_SZIE" 25 #endif 26 27 #ifndef MCL_SIZEOF_UNIT 28 #if defined(CYBOZU_OS_BIT) && (CYBOZU_OS_BIT == 32) 29 #define MCL_SIZEOF_UNIT 4 30 #else 31 #define MCL_SIZEOF_UNIT 8 32 #endif 33 #endif 34 35 namespace mcl { 36 37 namespace vint { 38 39 #if MCL_SIZEOF_UNIT == 8 40 typedef uint64_t Unit; 41 #else 42 typedef uint32_t Unit; 43 #endif 44 45 template<size_t x> 46 struct RoundUp { 47 static const size_t UnitBitSize = sizeof(Unit) * 8; 48 static const size_t N = (x + UnitBitSize - 1) / UnitBitSize; 49 static const size_t bit = N * UnitBitSize; 50 }; 51 52 template<class T> 53 void dump(const T *x, size_t n, const char *msg = "") 54 { 55 const size_t is4byteUnit = sizeof(*x) == 4; 56 if (msg) printf("%s ", msg); 57 for (size_t i = 0; i < n; i++) { 58 if (is4byteUnit) { 59 printf("%08x", (uint32_t)x[n - 1 - i]); 60 } else { 61 printf("%016llx", (unsigned long long)x[n - 1 - i]); 62 } 63 } 64 printf("\n"); 65 } 66 67 inline uint64_t make64(uint32_t H, uint32_t L) 68 { 69 return ((uint64_t)H << 32) | L; 70 } 71 72 inline void split64(uint32_t *H, uint32_t *L, uint64_t x) 73 { 74 *H = uint32_t(x >> 32); 75 *L = uint32_t(x); 76 } 77 78 /* 79 [H:L] <= x * y 80 @return L 81 */ 82 inline uint32_t mulUnit(uint32_t *pH, uint32_t x, uint32_t y) 83 { 84 uint64_t t = uint64_t(x) * y; 85 uint32_t L; 86 split64(pH, &L, t); 87 return L; 88 } 89 #if MCL_SIZEOF_UNIT == 8 90 inline uint64_t mulUnit(uint64_t *pH, uint64_t x, uint64_t y) 91 { 92 #ifdef MCL_VINT_64BIT_PORTABLE 93 uint32_t a = uint32_t(x >> 32); 94 uint32_t b = uint32_t(x); 95 uint32_t c = uint32_t(y >> 32); 96 uint32_t d = uint32_t(y); 97 98 uint64_t ad = uint64_t(d) * a; 99 uint64_t bd = uint64_t(d) * b; 100 uint64_t L = uint32_t(bd); 101 ad += bd >> 32; // [ad:L] 102 103 uint64_t ac = uint64_t(c) * a; 104 uint64_t bc = uint64_t(c) * b; 105 uint64_t H = uint32_t(bc); 106 ac += bc >> 32; // [ac:H] 107 /* 108 adL 109 acH 110 */ 111 uint64_t t = (ac << 32) | H; 112 ac >>= 32; 113 H = t + ad; 114 if (H < t) { 115 ac++; 116 } 117 /* 118 ac:H:L 119 */ 120 L |= H << 32; 121 H = (ac << 32) | uint32_t(H >> 32); 122 *pH = H; 123 return L; 124 #elif defined(_WIN64) && !defined(__INTEL_COMPILER) 125 return _umul128(x, y, pH); 126 #else 127 typedef __attribute__((mode(TI))) unsigned int uint128; 128 uint128 t = uint128(x) * y; 129 *pH = uint64_t(t >> 64); 130 return uint64_t(t); 131 #endif 132 } 133 #endif 134 135 template<class T> 136 void divNM(T *q, size_t qn, T *r, const T *x, size_t xn, const T *y, size_t yn); 137 138 /* 139 q = [H:L] / y 140 r = [H:L] % y 141 return q 142 */ 143 inline uint32_t divUnit(uint32_t *pr, uint32_t H, uint32_t L, uint32_t y) 144 { 145 uint64_t t = make64(H, L); 146 uint32_t q = uint32_t(t / y); 147 *pr = uint32_t(t % y); 148 return q; 149 } 150 #if MCL_SIZEOF_UNIT == 8 151 inline uint64_t divUnit(uint64_t *pr, uint64_t H, uint64_t L, uint64_t y) 152 { 153 #if defined(MCL_VINT_64BIT_PORTABLE) 154 uint32_t px[4] = { uint32_t(L), uint32_t(L >> 32), uint32_t(H), uint32_t(H >> 32) }; 155 uint32_t py[2] = { uint32_t(y), uint32_t(y >> 32) }; 156 size_t xn = 4; 157 size_t yn = 2; 158 uint32_t q[4]; 159 uint32_t r[2]; 160 size_t qn = xn - yn + 1; 161 divNM(q, qn, r, px, xn, py, yn); 162 *pr = make64(r[1], r[0]); 163 return make64(q[1], q[0]); 164 #elif defined(_MSC_VER) 165 #error "divUnit for uint64_t is not supported" 166 #else 167 typedef __attribute__((mode(TI))) unsigned int uint128; 168 uint128 t = (uint128(H) << 64) | L; 169 uint64_t q = uint64_t(t / y); 170 *pr = uint64_t(t % y); 171 return q; 172 #endif 173 } 174 #endif 175 176 /* 177 compare x[] and y[] 178 @retval positive if x > y 179 @retval 0 if x == y 180 @retval negative if x < y 181 */ 182 template<class T> 183 int compareNM(const T *x, size_t xn, const T *y, size_t yn) 184 { 185 assert(xn > 0 && yn > 0); 186 if (xn != yn) return xn > yn ? 1 : -1; 187 for (int i = (int)xn - 1; i >= 0; i--) { 188 if (x[i] != y[i]) return x[i] > y[i] ? 1 : -1; 189 } 190 return 0; 191 } 192 193 template<class T> 194 void clearN(T *x, size_t n) 195 { 196 for (size_t i = 0; i < n; i++) x[i] = 0; 197 } 198 199 template<class T> 200 void copyN(T *y, const T *x, size_t n) 201 { 202 for (size_t i = 0; i < n; i++) y[i] = x[i]; 203 } 204 205 /* 206 z[] = x[n] + y[n] 207 @note return 1 if having carry 208 z may be equal to x or y 209 */ 210 template<class T> 211 T addN(T *z, const T *x, const T *y, size_t n) 212 { 213 T c = 0; 214 for (size_t i = 0; i < n; i++) { 215 T xc = x[i] + c; 216 if (xc < c) { 217 // x[i] = Unit(-1) and c = 1 218 z[i] = y[i]; 219 } else { 220 xc += y[i]; 221 c = y[i] > xc ? 1 : 0; 222 z[i] = xc; 223 } 224 } 225 return c; 226 } 227 228 /* 229 z[] = x[] + y 230 */ 231 template<class T> 232 T addu1(T *z, const T *x, size_t n, T y) 233 { 234 assert(n > 0); 235 T t = x[0] + y; 236 z[0] = t; 237 size_t i = 0; 238 if (t >= y) goto EXIT_0; 239 i = 1; 240 for (; i < n; i++) { 241 t = x[i] + 1; 242 z[i] = t; 243 if (t != 0) goto EXIT_0; 244 } 245 return 1; 246 EXIT_0: 247 i++; 248 for (; i < n; i++) { 249 z[i] = x[i]; 250 } 251 return 0; 252 } 253 254 /* 255 x[] += y 256 */ 257 template<class T> 258 T addu1(T *x, size_t n, T y) 259 { 260 assert(n > 0); 261 T t = x[0] + y; 262 x[0] = t; 263 size_t i = 0; 264 if (t >= y) return 0; 265 i = 1; 266 for (; i < n; i++) { 267 t = x[i] + 1; 268 x[i] = t; 269 if (t != 0) return 0; 270 } 271 return 1; 272 } 273 /* 274 z[zn] = x[xn] + y[yn] 275 @note zn = max(xn, yn) 276 */ 277 template<class T> 278 T addNM(T *z, const T *x, size_t xn, const T *y, size_t yn) 279 { 280 if (yn > xn) { 281 fp::swap_(xn, yn); 282 fp::swap_(x, y); 283 } 284 assert(xn >= yn); 285 size_t max = xn; 286 size_t min = yn; 287 T c = vint::addN(z, x, y, min); 288 if (max > min) { 289 c = vint::addu1(z + min, x + min, max - min, c); 290 } 291 return c; 292 } 293 294 /* 295 z[] = x[n] - y[n] 296 z may be equal to x or y 297 */ 298 template<class T> 299 T subN(T *z, const T *x, const T *y, size_t n) 300 { 301 assert(n > 0); 302 T c = 0; 303 for (size_t i = 0; i < n; i++) { 304 T yc = y[i] + c; 305 if (yc < c) { 306 // y[i] = T(-1) and c = 1 307 z[i] = x[i]; 308 } else { 309 c = x[i] < yc ? 1 : 0; 310 z[i] = x[i] - yc; 311 } 312 } 313 return c; 314 } 315 316 /* 317 out[] = x[n] - y 318 */ 319 template<class T> 320 T subu1(T *z, const T *x, size_t n, T y) 321 { 322 assert(n > 0); 323 #if 0 324 T t = x[0]; 325 z[0] = t - y; 326 size_t i = 0; 327 if (t >= y) goto EXIT_0; 328 i = 1; 329 for (; i < n; i++ ){ 330 t = x[i]; 331 z[i] = t - 1; 332 if (t != 0) goto EXIT_0; 333 } 334 return 1; 335 EXIT_0: 336 i++; 337 for (; i < n; i++) { 338 z[i] = x[i]; 339 } 340 return 0; 341 #else 342 T c = x[0] < y ? 1 : 0; 343 z[0] = x[0] - y; 344 for (size_t i = 1; i < n; i++) { 345 if (x[i] < c) { 346 z[i] = T(-1); 347 } else { 348 z[i] = x[i] - c; 349 c = 0; 350 } 351 } 352 return c; 353 #endif 354 } 355 356 /* 357 z[xn] = x[xn] - y[yn] 358 @note xn >= yn 359 */ 360 template<class T> 361 T subNM(T *z, const T *x, size_t xn, const T *y, size_t yn) 362 { 363 assert(xn >= yn); 364 T c = vint::subN(z, x, y, yn); 365 if (xn > yn) { 366 c = vint::subu1(z + yn, x + yn, xn - yn, c); 367 } 368 return c; 369 } 370 371 /* 372 z[0..n) = x[0..n) * y 373 return z[n] 374 @note accept z == x 375 */ 376 template<class T> 377 T mulu1(T *z, const T *x, size_t n, T y) 378 { 379 assert(n > 0); 380 T H = 0; 381 for (size_t i = 0; i < n; i++) { 382 T t = H; 383 T L = mulUnit(&H, x[i], y); 384 z[i] = t + L; 385 if (z[i] < t) { 386 H++; 387 } 388 } 389 return H; // z[n] 390 } 391 392 /* 393 z[xn * yn] = x[xn] * y[ym] 394 */ 395 template<class T> 396 static inline void mulNM(T *z, const T *x, size_t xn, const T *y, size_t yn) 397 { 398 assert(xn > 0 && yn > 0); 399 if (yn > xn) { 400 fp::swap_(yn, xn); 401 fp::swap_(x, y); 402 } 403 assert(xn >= yn); 404 if (z == x) { 405 T *p = (T*)CYBOZU_ALLOCA(sizeof(T) * xn); 406 copyN(p, x, xn); 407 x = p; 408 } 409 if (z == y) { 410 T *p = (T*)CYBOZU_ALLOCA(sizeof(T) * yn); 411 copyN(p, y, yn); 412 y = p; 413 } 414 z[xn] = vint::mulu1(&z[0], x, xn, y[0]); 415 clearN(z + xn + 1, yn - 1); 416 417 T *t2 = (T*)CYBOZU_ALLOCA(sizeof(T) * (xn + 1)); 418 for (size_t i = 1; i < yn; i++) { 419 t2[xn] = vint::mulu1(&t2[0], x, xn, y[i]); 420 vint::addN(&z[i], &z[i], &t2[0], xn + 1); 421 } 422 } 423 /* 424 out[xn * 2] = x[xn] * x[xn] 425 QQQ : optimize this 426 */ 427 template<class T> 428 static inline void sqrN(T *y, const T *x, size_t xn) 429 { 430 mulNM(y, x, xn, x, xn); 431 } 432 433 /* 434 q[] = x[] / y 435 @retval r = x[] % y 436 accept q == x 437 */ 438 template<class T> 439 T divu1(T *q, const T *x, size_t n, T y) 440 { 441 T r = 0; 442 for (int i = (int)n - 1; i >= 0; i--) { 443 q[i] = divUnit(&r, r, x[i], y); 444 } 445 return r; 446 } 447 /* 448 q[] = x[] / y 449 @retval r = x[] % y 450 */ 451 template<class T> 452 T modu1(const T *x, size_t n, T y) 453 { 454 T r = 0; 455 for (int i = (int)n - 1; i >= 0; i--) { 456 divUnit(&r, r, x[i], y); 457 } 458 return r; 459 } 460 461 /* 462 y[] = x[] << bit 463 0 < bit < sizeof(T) * 8 464 accept y == x 465 */ 466 template<class T> 467 T shlBit(T *y, const T *x, size_t xn, size_t bit) 468 { 469 assert(0 < bit && bit < sizeof(T) * 8); 470 assert(xn > 0); 471 size_t rBit = sizeof(T) * 8 - bit; 472 T keep = x[xn - 1]; 473 T prev = keep; 474 for (size_t i = xn - 1; i > 0; i--) { 475 T t = x[i - 1]; 476 y[i] = (prev << bit) | (t >> rBit); 477 prev = t; 478 } 479 y[0] = prev << bit; 480 return keep >> rBit; 481 } 482 483 /* 484 y[yn] = x[xn] << bit 485 yn = xn + (bit + unitBitBit - 1) / unitBitSize 486 accept y == x 487 */ 488 template<class T> 489 void shlN(T *y, const T *x, size_t xn, size_t bit) 490 { 491 assert(xn > 0); 492 const size_t unitBitSize = sizeof(T) * 8; 493 size_t q = bit / unitBitSize; 494 size_t r = bit % unitBitSize; 495 if (r == 0) { 496 // don't use copyN(y + q, x, xn); if overlaped 497 for (size_t i = 0; i < xn; i++) { 498 y[q + xn - 1 - i] = x[xn - 1 - i]; 499 } 500 } else { 501 y[q + xn] = shlBit(y + q, x, xn, r); 502 } 503 clearN(y, q); 504 } 505 506 /* 507 y[] = x[] >> bit 508 0 < bit < sizeof(T) * 8 509 */ 510 template<class T> 511 void shrBit(T *y, const T *x, size_t xn, size_t bit) 512 { 513 assert(0 < bit && bit < sizeof(T) * 8); 514 assert(xn > 0); 515 size_t rBit = sizeof(T) * 8 - bit; 516 T prev = x[0]; 517 for (size_t i = 1; i < xn; i++) { 518 T t = x[i]; 519 y[i - 1] = (prev >> bit) | (t << rBit); 520 prev = t; 521 } 522 y[xn - 1] = prev >> bit; 523 } 524 /* 525 y[yn] = x[xn] >> bit 526 yn = xn - bit / unitBit 527 */ 528 template<class T> 529 void shrN(T *y, const T *x, size_t xn, size_t bit) 530 { 531 assert(xn > 0); 532 const size_t unitBitSize = sizeof(T) * 8; 533 size_t q = bit / unitBitSize; 534 size_t r = bit % unitBitSize; 535 assert(xn >= q); 536 if (r == 0) { 537 copyN(y, x + q, xn - q); 538 } else { 539 shrBit(y, x + q, xn - q, r); 540 } 541 } 542 543 template<class T> 544 size_t getRealSize(const T *x, size_t xn) 545 { 546 int i = (int)xn - 1; 547 for (; i > 0; i--) { 548 if (x[i]) { 549 return i + 1; 550 } 551 } 552 return 1; 553 } 554 555 template<class T> 556 size_t getBitSize(const T *x, size_t n) 557 { 558 if (n == 1 && x[0] == 0) return 1; 559 T v = x[n - 1]; 560 assert(v); 561 return (n - 1) * sizeof(T) * 8 + 1 + cybozu::bsr<Unit>(v); 562 } 563 564 /* 565 q[qn] = x[xn] / y[yn] ; qn == xn - yn + 1 if xn >= yn if q 566 r[rn] = x[xn] % y[yn] ; rn = yn before getRealSize 567 allow q == 0 568 */ 569 template<class T> 570 void divNM(T *q, size_t qn, T *r, const T *x, size_t xn, const T *y, size_t yn) 571 { 572 assert(xn > 0 && yn > 0); 573 assert(xn < yn || (q == 0 || qn == xn - yn + 1)); 574 assert(q != r); 575 const size_t rn = yn; 576 xn = getRealSize(x, xn); 577 yn = getRealSize(y, yn); 578 if (x == y) { 579 assert(xn == yn); 580 x_is_y: 581 clearN(r, rn); 582 if (q) { 583 q[0] = 1; 584 clearN(q + 1, qn - 1); 585 } 586 return; 587 } 588 if (yn > xn) { 589 /* 590 if y > x then q = 0 and r = x 591 */ 592 q_is_zero: 593 copyN(r, x, xn); 594 clearN(r + xn, rn - xn); 595 if (q) clearN(q, qn); 596 return; 597 } 598 if (yn == 1) { 599 T t; 600 if (q) { 601 if (qn > xn) { 602 clearN(q + xn, qn - xn); 603 } 604 t = divu1(q, x, xn, y[0]); 605 } else { 606 t = modu1(x, xn, y[0]); 607 } 608 r[0] = t; 609 clearN(r + 1, rn - 1); 610 return; 611 } 612 const size_t yTopBit = cybozu::bsr(y[yn - 1]); 613 assert(yn >= 2); 614 if (xn == yn) { 615 const size_t xTopBit = cybozu::bsr(x[xn - 1]); 616 if (xTopBit < yTopBit) goto q_is_zero; 617 if (yTopBit == xTopBit) { 618 int ret = compareNM(x, xn, y, yn); 619 if (ret == 0) goto x_is_y; 620 if (ret < 0) goto q_is_zero; 621 if (r) { 622 subN(r, x, y, yn); 623 } 624 if (q) { 625 q[0] = 1; 626 clearN(q + 1, qn - 1); 627 } 628 return; 629 } 630 assert(xTopBit > yTopBit); 631 // fast reduction for larger than fullbit-3 size p 632 if (yTopBit >= sizeof(T) * 8 - 4) { 633 T *xx = (T*)CYBOZU_ALLOCA(sizeof(T) * xn); 634 T qv = 0; 635 if (yTopBit == sizeof(T) * 8 - 2) { 636 copyN(xx, x, xn); 637 } else { 638 qv = x[xn - 1] >> (yTopBit + 1); 639 mulu1(xx, y, yn, qv); 640 subN(xx, x, xx, xn); 641 xn = getRealSize(xx, xn); 642 } 643 for (;;) { 644 T ret = subN(xx, xx, y, yn); 645 if (ret) { 646 addN(xx, xx, y, yn); 647 break; 648 } 649 qv++; 650 xn = getRealSize(xx, xn); 651 } 652 if (r) { 653 copyN(r, xx, xn); 654 clearN(r + xn, rn - xn); 655 } 656 if (q) { 657 q[0] = qv; 658 clearN(q + 1, qn - 1); 659 } 660 return; 661 } 662 } 663 /* 664 bitwise left shift x and y to adjust MSB of y[yn - 1] = 1 665 */ 666 const size_t shift = sizeof(T) * 8 - 1 - yTopBit; 667 T *xx = (T*)CYBOZU_ALLOCA(sizeof(T) * (xn + 1)); 668 const T *yy; 669 if (shift) { 670 T v = shlBit(xx, x, xn, shift); 671 if (v) { 672 xx[xn] = v; 673 xn++; 674 } 675 T *yBuf = (T*)CYBOZU_ALLOCA(sizeof(T) * yn); 676 shlBit(yBuf, y, yn ,shift); 677 yy = yBuf; 678 } else { 679 copyN(xx, x, xn); 680 yy = y; 681 } 682 if (q) { 683 clearN(q, qn); 684 } 685 assert((yy[yn - 1] >> (sizeof(T) * 8 - 1)) != 0); 686 T *tt = (T*)CYBOZU_ALLOCA(sizeof(T) * (yn + 1)); 687 while (xn > yn) { 688 size_t d = xn - yn; 689 T xTop = xx[xn - 1]; 690 T yTop = yy[yn - 1]; 691 if (xTop > yTop || (compareNM(xx + d, xn - d, yy, yn) >= 0)) { 692 vint::subN(xx + d, xx + d, yy, yn); 693 xn = getRealSize(xx, xn); 694 if (q) vint::addu1<T>(q + d, qn - d, 1); 695 continue; 696 } 697 if (xTop == 1) { 698 vint::subNM(xx + d - 1, xx + d - 1, xn - d + 1, yy, yn); 699 xn = getRealSize(xx, xn); 700 if (q) vint::addu1<T>(q + d - 1, qn - d + 1, 1); 701 continue; 702 } 703 tt[yn] = vint::mulu1(tt, yy, yn, xTop); 704 vint::subN(xx + d - 1, xx + d - 1, tt, yn + 1); 705 xn = getRealSize(xx, xn); 706 if (q) vint::addu1<T>(q + d - 1, qn - d + 1, xTop); 707 } 708 if (xn == yn && compareNM(xx, xn, yy, yn) >= 0) { 709 subN(xx, xx, yy, yn); 710 xn = getRealSize(xx, xn); 711 if (q) vint::addu1<T>(q, qn, 1); 712 } 713 if (shift) { 714 shrBit(r, xx, xn, shift); 715 } else { 716 copyN(r, xx, xn); 717 } 718 clearN(r + xn, rn - xn); 719 } 720 721 #ifndef MCL_VINT_FIXED_BUFFER 722 template<class T> 723 class Buffer { 724 size_t allocSize_; 725 T *ptr_; 726 public: 727 typedef T Unit; 728 Buffer() : allocSize_(0), ptr_(0) {} 729 ~Buffer() 730 { 731 clear(); 732 } 733 Buffer(const Buffer& rhs) 734 : allocSize_(rhs.allocSize_) 735 , ptr_(0) 736 { 737 ptr_ = (T*)malloc(allocSize_ * sizeof(T)); 738 if (ptr_ == 0) throw cybozu::Exception("Buffer:malloc") << rhs.allocSize_; 739 memcpy(ptr_, rhs.ptr_, allocSize_ * sizeof(T)); 740 } 741 Buffer& operator=(const Buffer& rhs) 742 { 743 Buffer t(rhs); 744 swap(t); 745 return *this; 746 } 747 void swap(Buffer& rhs) 748 #if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11 749 noexcept 750 #endif 751 { 752 fp::swap_(allocSize_, rhs.allocSize_); 753 fp::swap_(ptr_, rhs.ptr_); 754 } 755 void clear() 756 { 757 allocSize_ = 0; 758 free(ptr_); 759 ptr_ = 0; 760 } 761 762 /* 763 @note extended buffer may be not cleared 764 */ 765 void alloc(bool *pb, size_t n) 766 { 767 if (n > allocSize_) { 768 T *p = (T*)malloc(n * sizeof(T)); 769 if (p == 0) { 770 *pb = false; 771 return; 772 } 773 copyN(p, ptr_, allocSize_); 774 free(ptr_); 775 ptr_ = p; 776 allocSize_ = n; 777 } 778 *pb = true; 779 } 780 #ifndef CYBOZU_DONT_USE_EXCEPTION 781 void alloc(size_t n) 782 { 783 bool b; 784 alloc(&b, n); 785 if (!b) throw cybozu::Exception("Buffer:alloc"); 786 } 787 #endif 788 /* 789 *this = rhs 790 rhs may be destroyed 791 */ 792 const T& operator[](size_t n) const { return ptr_[n]; } 793 T& operator[](size_t n) { return ptr_[n]; } 794 }; 795 #endif 796 797 template<class T, size_t BitLen> 798 class FixedBuffer { 799 enum { 800 N = (BitLen + sizeof(T) * 8 - 1) / (sizeof(T) * 8) 801 }; 802 size_t size_; 803 T v_[N]; 804 public: 805 typedef T Unit; 806 FixedBuffer() 807 : size_(0) 808 { 809 } 810 FixedBuffer(const FixedBuffer& rhs) 811 { 812 operator=(rhs); 813 } 814 FixedBuffer& operator=(const FixedBuffer& rhs) 815 { 816 size_ = rhs.size_; 817 #if defined(__GNUC__) && !defined(__EMSCRIPTEN__) && !defined(__clang__) 818 #pragma GCC diagnostic push 819 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 820 #endif 821 for (size_t i = 0; i < size_; i++) { 822 v_[i] = rhs.v_[i]; 823 } 824 #if defined(__GNUC__) && !defined(__EMSCRIPTEN__) && !defined(__clang__) 825 #pragma GCC diagnostic pop 826 #endif 827 return *this; 828 } 829 void clear() { size_ = 0; } 830 void alloc(bool *pb, size_t n) 831 { 832 if (n > N) { 833 *pb = false; 834 return; 835 } 836 size_ = n; 837 *pb = true; 838 } 839 #ifndef CYBOZU_DONT_USE_EXCEPTION 840 void alloc(size_t n) 841 { 842 bool b; 843 alloc(&b, n); 844 if (!b) throw cybozu::Exception("FixedBuffer:alloc"); 845 } 846 #endif 847 void swap(FixedBuffer& rhs) 848 { 849 FixedBuffer *p1 = this; 850 FixedBuffer *p2 = &rhs; 851 if (p1->size_ < p2->size_) { 852 fp::swap_(p1, p2); 853 } 854 assert(p1->size_ >= p2->size_); 855 for (size_t i = 0; i < p2->size_; i++) { 856 fp::swap_(p1->v_[i], p2->v_[i]); 857 } 858 for (size_t i = p2->size_; i < p1->size_; i++) { 859 p2->v_[i] = p1->v_[i]; 860 } 861 fp::swap_(p1->size_, p2->size_); 862 } 863 // to avoid warning of gcc 864 void verify(size_t n) const 865 { 866 assert(n <= N); 867 (void)n; 868 } 869 const T& operator[](size_t n) const { verify(n); return v_[n]; } 870 T& operator[](size_t n) { verify(n); return v_[n]; } 871 }; 872 873 #if MCL_SIZEOF_UNIT == 8 874 /* 875 M = 1 << 256 876 a = M mod p = (1 << 32) + 0x3d1 877 [H:L] mod p = H * a + L 878 879 if H = L = M - 1, t = H * a + L = aM + (M - a - 1) 880 H' = a, L' = M - a - 1 881 t' = H' * a + L' = M + (a^2 - a - 1) 882 H'' = 1, L'' = a^2 - a - 1 883 t'' = H'' * a + L'' = a^2 - 1 884 */ 885 inline void mcl_fpDbl_mod_SECP256K1(Unit *z, const Unit *x, const Unit *p) 886 { 887 const Unit a = (uint64_t(1) << 32) + 0x3d1; 888 Unit buf[5]; 889 buf[4] = mulu1(buf, x + 4, 4, a); // H * a 890 buf[4] += addN(buf, buf, x, 4); // t = H * a + L 891 Unit x2[2]; 892 x2[0] = mulUnit(&x2[1], buf[4], a); 893 Unit x3 = addN(buf, buf, x2, 2); 894 if (x3) { 895 x3 = addu1(buf + 2, buf + 2, 2, Unit(1)); // t' = H' * a + L' 896 if (x3) { 897 x3 = addu1(buf, buf, 4, a); 898 assert(x3 == 0); 899 } 900 } 901 if (fp::isGreaterOrEqualArray(buf, p, 4)) { 902 subN(z, buf, p, 4); 903 } else { 904 fp::copyArray(z, buf, 4); 905 } 906 } 907 908 inline void mcl_fp_mul_SECP256K1(Unit *z, const Unit *x, const Unit *y, const Unit *p) 909 { 910 Unit xy[8]; 911 mulNM(xy, x, 4, y, 4); 912 mcl_fpDbl_mod_SECP256K1(z, xy, p); 913 } 914 inline void mcl_fp_sqr_SECP256K1(Unit *y, const Unit *x, const Unit *p) 915 { 916 Unit xx[8]; 917 sqrN(xx, x, 4); 918 mcl_fpDbl_mod_SECP256K1(y, xx, p); 919 } 920 #endif 921 922 } // vint 923 924 /** 925 signed integer with variable length 926 */ 927 template<class _Buffer> 928 class VintT { 929 public: 930 typedef _Buffer Buffer; 931 typedef typename Buffer::Unit Unit; 932 static const size_t unitBitSize = sizeof(Unit) * 8; 933 static const int invalidVar = -2147483647 - 1; // abs(invalidVar) is not defined 934 private: 935 Buffer buf_; 936 size_t size_; 937 bool isNeg_; 938 void trim(size_t n) 939 { 940 assert(n > 0); 941 int i = (int)n - 1; 942 for (; i > 0; i--) { 943 if (buf_[i]) { 944 size_ = i + 1; 945 return; 946 } 947 } 948 size_ = 1; 949 // zero 950 if (buf_[0] == 0) { 951 isNeg_ = false; 952 } 953 } 954 static int ucompare(const Buffer& x, size_t xn, const Buffer& y, size_t yn) 955 { 956 return vint::compareNM(&x[0], xn, &y[0], yn); 957 } 958 static void uadd(VintT& z, const Buffer& x, size_t xn, const Buffer& y, size_t yn) 959 { 960 size_t zn = fp::max_(xn, yn) + 1; 961 bool b; 962 z.buf_.alloc(&b, zn); 963 assert(b); 964 if (!b) { 965 z.clear(); 966 return; 967 } 968 z.buf_[zn - 1] = vint::addNM(&z.buf_[0], &x[0], xn, &y[0], yn); 969 z.trim(zn); 970 } 971 static void uadd1(VintT& z, const Buffer& x, size_t xn, Unit y) 972 { 973 size_t zn = xn + 1; 974 bool b; 975 z.buf_.alloc(&b, zn); 976 assert(b); 977 if (!b) { 978 z.clear(); 979 return; 980 } 981 z.buf_[zn - 1] = vint::addu1(&z.buf_[0], &x[0], xn, y); 982 z.trim(zn); 983 } 984 static void usub1(VintT& z, const Buffer& x, size_t xn, Unit y) 985 { 986 size_t zn = xn; 987 bool b; 988 z.buf_.alloc(&b, zn); 989 assert(b); 990 if (!b) { 991 z.clear(); 992 return; 993 } 994 Unit c = vint::subu1(&z.buf_[0], &x[0], xn, y); 995 (void)c; 996 assert(!c); 997 z.trim(zn); 998 } 999 static void usub(VintT& z, const Buffer& x, size_t xn, const Buffer& y, size_t yn) 1000 { 1001 assert(xn >= yn); 1002 bool b; 1003 z.buf_.alloc(&b, xn); 1004 assert(b); 1005 if (!b) { 1006 z.clear(); 1007 return; 1008 } 1009 Unit c = vint::subN(&z.buf_[0], &x[0], &y[0], yn); 1010 if (xn > yn) { 1011 c = vint::subu1(&z.buf_[yn], &x[yn], xn - yn, c); 1012 } 1013 assert(!c); 1014 z.trim(xn); 1015 } 1016 static void _add(VintT& z, const VintT& x, bool xNeg, const VintT& y, bool yNeg) 1017 { 1018 if ((xNeg ^ yNeg) == 0) { 1019 // same sign 1020 uadd(z, x.buf_, x.size(), y.buf_, y.size()); 1021 z.isNeg_ = xNeg; 1022 return; 1023 } 1024 int r = ucompare(x.buf_, x.size(), y.buf_, y.size()); 1025 if (r >= 0) { 1026 usub(z, x.buf_, x.size(), y.buf_, y.size()); 1027 z.isNeg_ = xNeg; 1028 } else { 1029 usub(z, y.buf_, y.size(), x.buf_, x.size()); 1030 z.isNeg_ = yNeg; 1031 } 1032 } 1033 static void _adds1(VintT& z, const VintT& x, int y, bool yNeg) 1034 { 1035 assert(y >= 0); 1036 if ((x.isNeg_ ^ yNeg) == 0) { 1037 // same sign 1038 uadd1(z, x.buf_, x.size(), y); 1039 z.isNeg_ = yNeg; 1040 return; 1041 } 1042 if (x.size() > 1 || x.buf_[0] >= (Unit)y) { 1043 usub1(z, x.buf_, x.size(), y); 1044 z.isNeg_ = x.isNeg_; 1045 } else { 1046 z = y - x.buf_[0]; 1047 z.isNeg_ = yNeg; 1048 } 1049 } 1050 static void _addu1(VintT& z, const VintT& x, Unit y, bool yNeg) 1051 { 1052 if ((x.isNeg_ ^ yNeg) == 0) { 1053 // same sign 1054 uadd1(z, x.buf_, x.size(), y); 1055 z.isNeg_ = yNeg; 1056 return; 1057 } 1058 if (x.size() > 1 || x.buf_[0] >= y) { 1059 usub1(z, x.buf_, x.size(), y); 1060 z.isNeg_ = x.isNeg_; 1061 } else { 1062 z = y - x.buf_[0]; 1063 z.isNeg_ = yNeg; 1064 } 1065 } 1066 /** 1067 @param q [out] x / y if q != 0 1068 @param r [out] x % y 1069 */ 1070 static void udiv(VintT* q, VintT& r, const Buffer& x, size_t xn, const Buffer& y, size_t yn) 1071 { 1072 assert(q != &r); 1073 if (xn < yn) { 1074 r.buf_ = x; 1075 r.trim(xn); 1076 if (q) q->clear(); 1077 return; 1078 } 1079 size_t qn = xn - yn + 1; 1080 bool b; 1081 if (q) { 1082 q->buf_.alloc(&b, qn); 1083 assert(b); 1084 if (!b) { 1085 q->clear(); 1086 r.clear(); 1087 return; 1088 } 1089 } 1090 r.buf_.alloc(&b, yn); 1091 assert(b); 1092 if (!b) { 1093 r.clear(); 1094 if (q) q->clear(); 1095 return; 1096 } 1097 vint::divNM(q ? &q->buf_[0] : 0, qn, &r.buf_[0], &x[0], xn, &y[0], yn); 1098 if (q) { 1099 q->trim(qn); 1100 } 1101 r.trim(yn); 1102 } 1103 /* 1104 @param x [inout] x <- d 1105 @retval s for x = 2^s d where d is odd 1106 */ 1107 static uint32_t countTrailingZero(VintT& x) 1108 { 1109 uint32_t s = 0; 1110 while (x.isEven()) { 1111 x >>= 1; 1112 s++; 1113 } 1114 return s; 1115 } 1116 struct MulMod { 1117 const VintT *pm; 1118 void operator()(VintT& z, const VintT& x, const VintT& y) const 1119 { 1120 VintT::mul(z, x, y); 1121 z %= *pm; 1122 } 1123 }; 1124 struct SqrMod { 1125 const VintT *pm; 1126 void operator()(VintT& y, const VintT& x) const 1127 { 1128 VintT::sqr(y, x); 1129 y %= *pm; 1130 } 1131 }; 1132 public: 1133 VintT(int x = 0) 1134 : size_(0) 1135 { 1136 *this = x; 1137 } 1138 VintT(Unit x) 1139 : size_(0) 1140 { 1141 *this = x; 1142 } 1143 VintT(const VintT& rhs) 1144 : buf_(rhs.buf_) 1145 , size_(rhs.size_) 1146 , isNeg_(rhs.isNeg_) 1147 { 1148 } 1149 VintT& operator=(int x) 1150 { 1151 assert(x != invalidVar); 1152 isNeg_ = x < 0; 1153 bool b; 1154 buf_.alloc(&b, 1); 1155 assert(b); (void)b; 1156 buf_[0] = fp::abs_(x); 1157 size_ = 1; 1158 return *this; 1159 } 1160 VintT& operator=(Unit x) 1161 { 1162 isNeg_ = false; 1163 bool b; 1164 buf_.alloc(&b, 1); 1165 assert(b); (void)b; 1166 buf_[0] = x; 1167 size_ = 1; 1168 return *this; 1169 } 1170 VintT& operator=(const VintT& rhs) 1171 { 1172 buf_ = rhs.buf_; 1173 size_ = rhs.size_; 1174 isNeg_ = rhs.isNeg_; 1175 return *this; 1176 } 1177 #if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11 1178 VintT(VintT&& rhs) 1179 : buf_(rhs.buf_) 1180 , size_(rhs.size_) 1181 , isNeg_(rhs.isNeg_) 1182 { 1183 } 1184 VintT& operator=(VintT&& rhs) 1185 { 1186 buf_ = std::move(rhs.buf_); 1187 size_ = rhs.size_; 1188 isNeg_ = rhs.isNeg_; 1189 return *this; 1190 } 1191 #endif 1192 void swap(VintT& rhs) 1193 #if CYBOZU_CPP_VERSION >= CYBOZU_CPP_VERSION_CPP11 1194 noexcept 1195 #endif 1196 { 1197 fp::swap_(buf_, rhs.buf_); 1198 fp::swap_(size_, rhs.size_); 1199 fp::swap_(isNeg_, rhs.isNeg_); 1200 } 1201 void dump(const char *msg = "") const 1202 { 1203 vint::dump(&buf_[0], size_, msg); 1204 } 1205 /* 1206 set positive value 1207 @note assume little endian system 1208 */ 1209 template<class S> 1210 void setArray(bool *pb, const S *x, size_t size) 1211 { 1212 isNeg_ = false; 1213 if (size == 0) { 1214 clear(); 1215 *pb = true; 1216 return; 1217 } 1218 size_t unitSize = (sizeof(S) * size + sizeof(Unit) - 1) / sizeof(Unit); 1219 buf_.alloc(pb, unitSize); 1220 if (!*pb) return; 1221 char *dst = (char *)&buf_[0]; 1222 const char *src = (const char *)x; 1223 size_t i = 0; 1224 for (; i < sizeof(S) * size; i++) { 1225 dst[i] = src[i]; 1226 } 1227 for (; i < sizeof(Unit) * unitSize; i++) { 1228 dst[i] = 0; 1229 } 1230 trim(unitSize); 1231 } 1232 /* 1233 set [0, max) randomly 1234 */ 1235 void setRand(bool *pb, const VintT& max, fp::RandGen rg = fp::RandGen()) 1236 { 1237 assert(max > 0); 1238 if (rg.isZero()) rg = fp::RandGen::get(); 1239 size_t n = max.size(); 1240 buf_.alloc(pb, n); 1241 if (!*pb) return; 1242 rg.read(pb, &buf_[0], n * sizeof(buf_[0])); 1243 if (!*pb) return; 1244 trim(n); 1245 *this %= max; 1246 } 1247 /* 1248 get abs value 1249 buf_[0, size) = x 1250 buf_[size, maxSize) with zero 1251 @note assume little endian system 1252 */ 1253 void getArray(bool *pb, Unit *x, size_t maxSize) const 1254 { 1255 size_t n = size(); 1256 if (n > maxSize) { 1257 *pb = false; 1258 return; 1259 } 1260 vint::copyN(x, &buf_[0], n); 1261 vint::clearN(x + n, maxSize - n); 1262 *pb = true; 1263 } 1264 void clear() { *this = 0; } 1265 template<class OutputStream> 1266 void save(bool *pb, OutputStream& os, int base = 10) const 1267 { 1268 if (isNeg_) cybozu::writeChar(pb, os, '-'); 1269 char buf[1024]; 1270 size_t n = mcl::fp::arrayToStr(buf, sizeof(buf), &buf_[0], size_, base, false); 1271 if (n == 0) { 1272 *pb = false; 1273 return; 1274 } 1275 cybozu::write(pb, os, buf + sizeof(buf) - n, n); 1276 } 1277 /* 1278 set buf with string terminated by '\0' 1279 return strlen(buf) if success else 0 1280 */ 1281 size_t getStr(char *buf, size_t bufSize, int base = 10) const 1282 { 1283 cybozu::MemoryOutputStream os(buf, bufSize); 1284 bool b; 1285 save(&b, os, base); 1286 const size_t n = os.getPos(); 1287 if (!b || n == bufSize) return 0; 1288 buf[n] = '\0'; 1289 return n; 1290 } 1291 /* 1292 return bitSize(abs(*this)) 1293 @note return 1 if zero 1294 */ 1295 size_t getBitSize() const 1296 { 1297 if (isZero()) return 1; 1298 size_t n = size(); 1299 Unit v = buf_[n - 1]; 1300 assert(v); 1301 return (n - 1) * sizeof(Unit) * 8 + 1 + cybozu::bsr<Unit>(v); 1302 } 1303 // ignore sign 1304 bool testBit(size_t i) const 1305 { 1306 size_t q = i / unitBitSize; 1307 size_t r = i % unitBitSize; 1308 assert(q <= size()); 1309 Unit mask = Unit(1) << r; 1310 return (buf_[q] & mask) != 0; 1311 } 1312 void setBit(size_t i, bool v = true) 1313 { 1314 size_t q = i / unitBitSize; 1315 size_t r = i % unitBitSize; 1316 assert(q <= size()); 1317 bool b; 1318 buf_.alloc(&b, q + 1); 1319 assert(b); 1320 if (!b) { 1321 clear(); 1322 return; 1323 } 1324 Unit mask = Unit(1) << r; 1325 if (v) { 1326 buf_[q] |= mask; 1327 } else { 1328 buf_[q] &= ~mask; 1329 trim(q + 1); 1330 } 1331 } 1332 /* 1333 @param str [in] number string 1334 @note "0x..." => base = 16 1335 "0b..." => base = 2 1336 otherwise => base = 10 1337 */ 1338 void setStr(bool *pb, const char *str, int base = 0) 1339 { 1340 // allow twice size of MCL_MAX_BIT_SIZE because of multiplication 1341 const size_t maxN = (MCL_MAX_BIT_SIZE * 2 + unitBitSize - 1) / unitBitSize; 1342 buf_.alloc(pb, maxN); 1343 if (!*pb) return; 1344 *pb = false; 1345 isNeg_ = false; 1346 size_t len = strlen(str); 1347 size_t n = fp::strToArray(&isNeg_, &buf_[0], maxN, str, len, base); 1348 if (n == 0) return; 1349 trim(n); 1350 *pb = true; 1351 } 1352 static int compare(const VintT& x, const VintT& y) 1353 { 1354 if (x.isNeg_ ^ y.isNeg_) { 1355 if (x.isZero() && y.isZero()) return 0; 1356 return x.isNeg_ ? -1 : 1; 1357 } else { 1358 // same sign 1359 int c = ucompare(x.buf_, x.size(), y.buf_, y.size()); 1360 if (x.isNeg_) { 1361 return -c; 1362 } 1363 return c; 1364 } 1365 } 1366 static int compares1(const VintT& x, int y) 1367 { 1368 assert(y != invalidVar); 1369 if (x.isNeg_ ^ (y < 0)) { 1370 if (x.isZero() && y == 0) return 0; 1371 return x.isNeg_ ? -1 : 1; 1372 } else { 1373 // same sign 1374 Unit y0 = fp::abs_(y); 1375 int c = vint::compareNM(&x.buf_[0], x.size(), &y0, 1); 1376 if (x.isNeg_) { 1377 return -c; 1378 } 1379 return c; 1380 } 1381 } 1382 static int compareu1(const VintT& x, uint32_t y) 1383 { 1384 if (x.isNeg_) return -1; 1385 if (x.size() > 1) return 1; 1386 Unit x0 = x.buf_[0]; 1387 return x0 > y ? 1 : x0 == y ? 0 : -1; 1388 } 1389 size_t size() const { return size_; } 1390 bool isZero() const { return size() == 1 && buf_[0] == 0; } 1391 bool isNegative() const { return !isZero() && isNeg_; } 1392 uint32_t getLow32bit() const { return (uint32_t)buf_[0]; } 1393 bool isOdd() const { return (buf_[0] & 1) == 1; } 1394 bool isEven() const { return !isOdd(); } 1395 const Unit *getUnit() const { return &buf_[0]; } 1396 size_t getUnitSize() const { return size_; } 1397 static void add(VintT& z, const VintT& x, const VintT& y) 1398 { 1399 _add(z, x, x.isNeg_, y, y.isNeg_); 1400 } 1401 static void sub(VintT& z, const VintT& x, const VintT& y) 1402 { 1403 _add(z, x, x.isNeg_, y, !y.isNeg_); 1404 } 1405 static void mul(VintT& z, const VintT& x, const VintT& y) 1406 { 1407 const size_t xn = x.size(); 1408 const size_t yn = y.size(); 1409 size_t zn = xn + yn; 1410 bool b; 1411 z.buf_.alloc(&b, zn); 1412 assert(b); 1413 if (!b) { 1414 z.clear(); 1415 return; 1416 } 1417 vint::mulNM(&z.buf_[0], &x.buf_[0], xn, &y.buf_[0], yn); 1418 z.isNeg_ = x.isNeg_ ^ y.isNeg_; 1419 z.trim(zn); 1420 } 1421 static void sqr(VintT& y, const VintT& x) 1422 { 1423 mul(y, x, x); 1424 } 1425 static void addu1(VintT& z, const VintT& x, Unit y) 1426 { 1427 _addu1(z, x, y, false); 1428 } 1429 static void subu1(VintT& z, const VintT& x, Unit y) 1430 { 1431 _addu1(z, x, y, true); 1432 } 1433 static void mulu1(VintT& z, const VintT& x, Unit y) 1434 { 1435 size_t xn = x.size(); 1436 size_t zn = xn + 1; 1437 bool b; 1438 z.buf_.alloc(&b, zn); 1439 assert(b); 1440 if (!b) { 1441 z.clear(); 1442 return; 1443 } 1444 z.buf_[zn - 1] = vint::mulu1(&z.buf_[0], &x.buf_[0], xn, y); 1445 z.isNeg_ = x.isNeg_; 1446 z.trim(zn); 1447 } 1448 static void divu1(VintT& q, const VintT& x, Unit y) 1449 { 1450 udivModu1(&q, x, y); 1451 } 1452 static void modu1(VintT& r, const VintT& x, Unit y) 1453 { 1454 bool xNeg = x.isNeg_; 1455 r = divModu1(0, x, y); 1456 r.isNeg_ = xNeg; 1457 } 1458 static void adds1(VintT& z, const VintT& x, int y) 1459 { 1460 assert(y != invalidVar); 1461 _adds1(z, x, fp::abs_(y), y < 0); 1462 } 1463 static void subs1(VintT& z, const VintT& x, int y) 1464 { 1465 assert(y != invalidVar); 1466 _adds1(z, x, fp::abs_(y), !(y < 0)); 1467 } 1468 static void muls1(VintT& z, const VintT& x, int y) 1469 { 1470 assert(y != invalidVar); 1471 mulu1(z, x, fp::abs_(y)); 1472 z.isNeg_ ^= (y < 0); 1473 } 1474 /* 1475 @param q [out] q = x / y if q is not zero 1476 @param x [in] 1477 @param y [in] must be not zero 1478 return x % y 1479 */ 1480 static int divMods1(VintT *q, const VintT& x, int y) 1481 { 1482 assert(y != invalidVar); 1483 bool xNeg = x.isNeg_; 1484 bool yNeg = y < 0; 1485 Unit absY = fp::abs_(y); 1486 size_t xn = x.size(); 1487 int r; 1488 if (q) { 1489 q->isNeg_ = xNeg ^ yNeg; 1490 bool b; 1491 q->buf_.alloc(&b, xn); 1492 assert(b); 1493 if (!b) { 1494 q->clear(); 1495 return 0; 1496 } 1497 r = (int)vint::divu1(&q->buf_[0], &x.buf_[0], xn, absY); 1498 q->trim(xn); 1499 } else { 1500 r = (int)vint::modu1(&x.buf_[0], xn, absY); 1501 } 1502 return xNeg ? -r : r; 1503 } 1504 /* 1505 like C 1506 13 / 5 = 2 ... 3 1507 13 / -5 = -2 ... 3 1508 -13 / 5 = -2 ... -3 1509 -13 / -5 = 2 ... -3 1510 */ 1511 static void divMod(VintT *q, VintT& r, const VintT& x, const VintT& y) 1512 { 1513 bool qsign = x.isNeg_ ^ y.isNeg_; 1514 udiv(q, r, x.buf_, x.size(), y.buf_, y.size()); 1515 r.isNeg_ = x.isNeg_; 1516 if (q) q->isNeg_ = qsign; 1517 } 1518 static void div(VintT& q, const VintT& x, const VintT& y) 1519 { 1520 VintT r; 1521 divMod(&q, r, x, y); 1522 } 1523 static void mod(VintT& r, const VintT& x, const VintT& y) 1524 { 1525 divMod(0, r, x, y); 1526 } 1527 static void divs1(VintT& q, const VintT& x, int y) 1528 { 1529 divMods1(&q, x, y); 1530 } 1531 static void mods1(VintT& r, const VintT& x, int y) 1532 { 1533 bool xNeg = x.isNeg_; 1534 r = divMods1(0, x, y); 1535 r.isNeg_ = xNeg; 1536 } 1537 static Unit udivModu1(VintT *q, const VintT& x, Unit y) 1538 { 1539 assert(!x.isNeg_); 1540 size_t xn = x.size(); 1541 if (q) { 1542 bool b; 1543 q->buf_.alloc(&b, xn); 1544 assert(b); 1545 if (!b) { 1546 q->clear(); 1547 return 0; 1548 } 1549 } 1550 Unit r = vint::divu1(q ? &q->buf_[0] : 0, &x.buf_[0], xn, y); 1551 if (q) { 1552 q->trim(xn); 1553 q->isNeg_ = false; 1554 } 1555 return r; 1556 } 1557 /* 1558 like Python 1559 13 / 5 = 2 ... 3 1560 13 / -5 = -3 ... -2 1561 -13 / 5 = -3 ... 2 1562 -13 / -5 = 2 ... -3 1563 */ 1564 static void quotRem(VintT *q, VintT& r, const VintT& x, const VintT& y) 1565 { 1566 VintT yy = y; 1567 bool qsign = x.isNeg_ ^ y.isNeg_; 1568 udiv(q, r, x.buf_, x.size(), y.buf_, y.size()); 1569 r.isNeg_ = y.isNeg_; 1570 if (q) q->isNeg_ = qsign; 1571 if (!r.isZero() && qsign) { 1572 if (q) { 1573 uadd1(*q, q->buf_, q->size(), 1); 1574 } 1575 usub(r, yy.buf_, yy.size(), r.buf_, r.size()); 1576 } 1577 } 1578 template<class InputStream> 1579 void load(bool *pb, InputStream& is, int ioMode) 1580 { 1581 *pb = false; 1582 char buf[1024]; 1583 size_t n = fp::local::loadWord(buf, sizeof(buf), is); 1584 if (n == 0) return; 1585 const size_t maxN = 384 / (sizeof(MCL_SIZEOF_UNIT) * 8); 1586 buf_.alloc(pb, maxN); 1587 if (!*pb) return; 1588 isNeg_ = false; 1589 n = fp::strToArray(&isNeg_, &buf_[0], maxN, buf, n, ioMode); 1590 if (n == 0) return; 1591 trim(n); 1592 *pb = true; 1593 } 1594 // logical left shift (copy sign) 1595 static void shl(VintT& y, const VintT& x, size_t shiftBit) 1596 { 1597 size_t xn = x.size(); 1598 size_t yn = xn + (shiftBit + unitBitSize - 1) / unitBitSize; 1599 bool b; 1600 y.buf_.alloc(&b, yn); 1601 assert(b); 1602 if (!b) { 1603 y.clear(); 1604 return; 1605 } 1606 vint::shlN(&y.buf_[0], &x.buf_[0], xn, shiftBit); 1607 y.isNeg_ = x.isNeg_; 1608 y.trim(yn); 1609 } 1610 // logical right shift (copy sign) 1611 static void shr(VintT& y, const VintT& x, size_t shiftBit) 1612 { 1613 size_t xn = x.size(); 1614 if (xn * unitBitSize <= shiftBit) { 1615 y.clear(); 1616 return; 1617 } 1618 size_t yn = xn - shiftBit / unitBitSize; 1619 bool b; 1620 y.buf_.alloc(&b, yn); 1621 assert(b); 1622 if (!b) { 1623 y.clear(); 1624 return; 1625 } 1626 vint::shrN(&y.buf_[0], &x.buf_[0], xn, shiftBit); 1627 y.isNeg_ = x.isNeg_; 1628 y.trim(yn); 1629 } 1630 static void neg(VintT& y, const VintT& x) 1631 { 1632 if (&y != &x) { y = x; } 1633 y.isNeg_ = !x.isNeg_; 1634 } 1635 static void abs(VintT& y, const VintT& x) 1636 { 1637 if (&y != &x) { y = x; } 1638 y.isNeg_ = false; 1639 } 1640 static VintT abs(const VintT& x) 1641 { 1642 VintT y = x; 1643 abs(y, x); 1644 return y; 1645 } 1646 // accept only non-negative value 1647 static void orBit(VintT& z, const VintT& x, const VintT& y) 1648 { 1649 assert(!x.isNeg_ && !y.isNeg_); 1650 const VintT *px = &x, *py = &y; 1651 if (x.size() < y.size()) { 1652 fp::swap_(px, py); 1653 } 1654 size_t xn = px->size(); 1655 size_t yn = py->size(); 1656 assert(xn >= yn); 1657 bool b; 1658 z.buf_.alloc(&b, xn); 1659 assert(b); 1660 if (!b) { 1661 z.clear(); 1662 } 1663 for (size_t i = 0; i < yn; i++) { 1664 z.buf_[i] = x.buf_[i] | y.buf_[i]; 1665 } 1666 vint::copyN(&z.buf_[0] + yn, &px->buf_[0] + yn, xn - yn); 1667 z.trim(xn); 1668 } 1669 static void andBit(VintT& z, const VintT& x, const VintT& y) 1670 { 1671 assert(!x.isNeg_ && !y.isNeg_); 1672 const VintT *px = &x, *py = &y; 1673 if (x.size() < y.size()) { 1674 fp::swap_(px, py); 1675 } 1676 size_t yn = py->size(); 1677 assert(px->size() >= yn); 1678 bool b; 1679 z.buf_.alloc(&b, yn); 1680 assert(b); 1681 if (!b) { 1682 z.clear(); 1683 return; 1684 } 1685 for (size_t i = 0; i < yn; i++) { 1686 z.buf_[i] = x.buf_[i] & y.buf_[i]; 1687 } 1688 z.trim(yn); 1689 } 1690 static void orBitu1(VintT& z, const VintT& x, Unit y) 1691 { 1692 assert(!x.isNeg_); 1693 z = x; 1694 z.buf_[0] |= y; 1695 } 1696 static void andBitu1(VintT& z, const VintT& x, Unit y) 1697 { 1698 assert(!x.isNeg_); 1699 bool b; 1700 z.buf_.alloc(&b, 1); 1701 assert(b); (void)b; 1702 z.buf_[0] = x.buf_[0] & y; 1703 z.size_ = 1; 1704 z.isNeg_ = false; 1705 } 1706 /* 1707 REMARK y >= 0; 1708 */ 1709 static void pow(VintT& z, const VintT& x, const VintT& y) 1710 { 1711 assert(!y.isNeg_); 1712 const VintT xx = x; 1713 z = 1; 1714 mcl::fp::powGeneric(z, xx, &y.buf_[0], y.size(), mul, sqr, (void (*)(VintT&, const VintT&))0); 1715 } 1716 /* 1717 REMARK y >= 0; 1718 */ 1719 static void pow(VintT& z, const VintT& x, int64_t y) 1720 { 1721 assert(y >= 0); 1722 const VintT xx = x; 1723 z = 1; 1724 #if MCL_SIZEOF_UNIT == 8 1725 Unit ua = fp::abs_(y); 1726 mcl::fp::powGeneric(z, xx, &ua, 1, mul, sqr, (void (*)(VintT&, const VintT&))0); 1727 #else 1728 uint64_t ua = fp::abs_(y); 1729 Unit u[2] = { uint32_t(ua), uint32_t(ua >> 32) }; 1730 size_t un = u[1] ? 2 : 1; 1731 mcl::fp::powGeneric(z, xx, u, un, mul, sqr, (void (*)(VintT&, const VintT&))0); 1732 #endif 1733 } 1734 /* 1735 z = x ^ y mod m 1736 REMARK y >= 0; 1737 */ 1738 static void powMod(VintT& z, const VintT& x, const VintT& y, const VintT& m) 1739 { 1740 assert(!y.isNeg_); 1741 VintT zz; 1742 MulMod mulMod; 1743 SqrMod sqrMod; 1744 mulMod.pm = &m; 1745 sqrMod.pm = &m; 1746 zz = 1; 1747 mcl::fp::powGeneric(zz, x, &y.buf_[0], y.size(), mulMod, sqrMod, (void (*)(VintT&, const VintT&))0); 1748 z.swap(zz); 1749 } 1750 /* 1751 inverse mod 1752 y = 1/x mod m 1753 REMARK x != 0 and m != 0; 1754 */ 1755 static void invMod(VintT& y, const VintT& x, const VintT& m) 1756 { 1757 assert(!x.isZero() && !m.isZero()); 1758 if (x == 1) { 1759 y = 1; 1760 return; 1761 } 1762 VintT a = 1; 1763 VintT t; 1764 VintT q; 1765 divMod(&q, t, m, x); 1766 VintT s = x; 1767 VintT b = -q; 1768 1769 for (;;) { 1770 divMod(&q, s, s, t); 1771 if (s.isZero()) { 1772 if (b.isNeg_) { 1773 b += m; 1774 } 1775 y = b; 1776 return; 1777 } 1778 a -= b * q; 1779 1780 divMod(&q, t, t, s); 1781 if (t.isZero()) { 1782 if (a.isNeg_) { 1783 a += m; 1784 } 1785 y = a; 1786 return; 1787 } 1788 b -= a * q; 1789 } 1790 } 1791 /* 1792 Miller-Rabin 1793 */ 1794 static bool isPrime(bool *pb, const VintT& n, int tryNum = 32) 1795 { 1796 *pb = true; 1797 if (n <= 1) return false; 1798 if (n == 2 || n == 3) return true; 1799 if (n.isEven()) return false; 1800 cybozu::XorShift rg; 1801 const VintT nm1 = n - 1; 1802 VintT d = nm1; 1803 uint32_t r = countTrailingZero(d); 1804 // n - 1 = 2^r d 1805 VintT a, x; 1806 for (int i = 0; i < tryNum; i++) { 1807 a.setRand(pb, n - 3, rg); 1808 if (!*pb) return false; 1809 a += 2; // a in [2, n - 2] 1810 powMod(x, a, d, n); 1811 if (x == 1 || x == nm1) { 1812 continue; 1813 } 1814 for (uint32_t j = 1; j < r; j++) { 1815 sqr(x, x); 1816 x %= n; 1817 if (x == 1) return false; 1818 if (x == nm1) goto NEXT_LOOP; 1819 } 1820 return false; 1821 NEXT_LOOP:; 1822 } 1823 return true; 1824 } 1825 bool isPrime(bool *pb, int tryNum = 32) const 1826 { 1827 return isPrime(pb, *this, tryNum); 1828 } 1829 static void gcd(VintT& z, VintT x, VintT y) 1830 { 1831 VintT t; 1832 for (;;) { 1833 if (y.isZero()) { 1834 z = x; 1835 return; 1836 } 1837 t = x; 1838 x = y; 1839 mod(y, t, y); 1840 } 1841 } 1842 static VintT gcd(const VintT& x, const VintT& y) 1843 { 1844 VintT z; 1845 gcd(z, x, y); 1846 return z; 1847 } 1848 static void lcm(VintT& z, const VintT& x, const VintT& y) 1849 { 1850 VintT c; 1851 gcd(c, x, y); 1852 div(c, x, c); 1853 mul(z, c, y); 1854 } 1855 static VintT lcm(const VintT& x, const VintT& y) 1856 { 1857 VintT z; 1858 lcm(z, x, y); 1859 return z; 1860 } 1861 /* 1862 1 if m is quadratic residue modulo n (i.e., there exists an x s.t. x^2 = m mod n) 1863 0 if m = 0 mod n 1864 -1 otherwise 1865 @note return legendre_symbol(m, p) for m and odd prime p 1866 */ 1867 static int jacobi(VintT m, VintT n) 1868 { 1869 assert(n.isOdd()); 1870 if (n == 1) return 1; 1871 if (m < 0 || m > n) { 1872 quotRem(0, m, m, n); // m = m mod n 1873 } 1874 if (m.isZero()) return 0; 1875 if (m == 1) return 1; 1876 if (gcd(m, n) != 1) return 0; 1877 1878 int j = 1; 1879 VintT t; 1880 goto START; 1881 while (m != 1) { 1882 if ((m.getLow32bit() % 4) == 3 && (n.getLow32bit() % 4) == 3) { 1883 j = -j; 1884 } 1885 mod(t, n, m); 1886 n = m; 1887 m = t; 1888 START: 1889 int s = countTrailingZero(m); 1890 uint32_t nmod8 = n.getLow32bit() % 8; 1891 if ((s % 2) && (nmod8 == 3 || nmod8 == 5)) { 1892 j = -j; 1893 } 1894 } 1895 return j; 1896 } 1897 #ifndef CYBOZU_DONT_USE_STRING 1898 explicit VintT(const std::string& str) 1899 : size_(0) 1900 { 1901 setStr(str); 1902 } 1903 void getStr(std::string& s, int base = 10) const 1904 { 1905 s.clear(); 1906 cybozu::StringOutputStream os(s); 1907 save(os, base); 1908 } 1909 std::string getStr(int base = 10) const 1910 { 1911 std::string s; 1912 getStr(s, base); 1913 return s; 1914 } 1915 inline friend std::ostream& operator<<(std::ostream& os, const VintT& x) 1916 { 1917 return os << x.getStr(os.flags() & std::ios_base::hex ? 16 : 10); 1918 } 1919 inline friend std::istream& operator>>(std::istream& is, VintT& x) 1920 { 1921 x.load(is); 1922 return is; 1923 } 1924 #endif 1925 #ifndef CYBOZU_DONT_USE_EXCEPTION 1926 void setStr(const std::string& str, int base = 0) 1927 { 1928 bool b; 1929 setStr(&b, str.c_str(), base); 1930 if (!b) throw cybozu::Exception("Vint:setStr") << str; 1931 } 1932 void setRand(const VintT& max, fp::RandGen rg = fp::RandGen()) 1933 { 1934 bool b; 1935 setRand(&b, max, rg); 1936 if (!b) throw cybozu::Exception("Vint:setRand"); 1937 } 1938 void getArray(Unit *x, size_t maxSize) const 1939 { 1940 bool b; 1941 getArray(&b, x, maxSize); 1942 if (!b) throw cybozu::Exception("Vint:getArray"); 1943 } 1944 template<class InputStream> 1945 void load(InputStream& is, int ioMode = 0) 1946 { 1947 bool b; 1948 load(&b, is, ioMode); 1949 if (!b) throw cybozu::Exception("Vint:load"); 1950 } 1951 template<class OutputStream> 1952 void save(OutputStream& os, int base = 10) const 1953 { 1954 bool b; 1955 save(&b, os, base); 1956 if (!b) throw cybozu::Exception("Vint:save"); 1957 } 1958 static bool isPrime(const VintT& n, int tryNum = 32) 1959 { 1960 bool b; 1961 bool ret = isPrime(&b, n, tryNum); 1962 if (!b) throw cybozu::Exception("Vint:isPrime"); 1963 return ret; 1964 } 1965 bool isPrime(int tryNum = 32) const 1966 { 1967 bool b; 1968 bool ret = isPrime(&b, *this, tryNum); 1969 if (!b) throw cybozu::Exception("Vint:isPrime"); 1970 return ret; 1971 } 1972 template<class S> 1973 void setArray(const S *x, size_t size) 1974 { 1975 bool b; 1976 setArray(&b, x, size); 1977 if (!b) throw cybozu::Exception("Vint:setArray"); 1978 } 1979 #endif 1980 VintT& operator++() { adds1(*this, *this, 1); return *this; } 1981 VintT& operator--() { subs1(*this, *this, 1); return *this; } 1982 VintT operator++(int) { VintT c = *this; adds1(*this, *this, 1); return c; } 1983 VintT operator--(int) { VintT c = *this; subs1(*this, *this, 1); return c; } 1984 friend bool operator<(const VintT& x, const VintT& y) { return compare(x, y) < 0; } 1985 friend bool operator>=(const VintT& x, const VintT& y) { return !operator<(x, y); } 1986 friend bool operator>(const VintT& x, const VintT& y) { return compare(x, y) > 0; } 1987 friend bool operator<=(const VintT& x, const VintT& y) { return !operator>(x, y); } 1988 friend bool operator==(const VintT& x, const VintT& y) { return compare(x, y) == 0; } 1989 friend bool operator!=(const VintT& x, const VintT& y) { return !operator==(x, y); } 1990 1991 friend bool operator<(const VintT& x, int y) { return compares1(x, y) < 0; } 1992 friend bool operator>=(const VintT& x, int y) { return !operator<(x, y); } 1993 friend bool operator>(const VintT& x, int y) { return compares1(x, y) > 0; } 1994 friend bool operator<=(const VintT& x, int y) { return !operator>(x, y); } 1995 friend bool operator==(const VintT& x, int y) { return compares1(x, y) == 0; } 1996 friend bool operator!=(const VintT& x, int y) { return !operator==(x, y); } 1997 1998 friend bool operator<(const VintT& x, uint32_t y) { return compareu1(x, y) < 0; } 1999 friend bool operator>=(const VintT& x, uint32_t y) { return !operator<(x, y); } 2000 friend bool operator>(const VintT& x, uint32_t y) { return compareu1(x, y) > 0; } 2001 friend bool operator<=(const VintT& x, uint32_t y) { return !operator>(x, y); } 2002 friend bool operator==(const VintT& x, uint32_t y) { return compareu1(x, y) == 0; } 2003 friend bool operator!=(const VintT& x, uint32_t y) { return !operator==(x, y); } 2004 2005 VintT& operator+=(const VintT& rhs) { add(*this, *this, rhs); return *this; } 2006 VintT& operator-=(const VintT& rhs) { sub(*this, *this, rhs); return *this; } 2007 VintT& operator*=(const VintT& rhs) { mul(*this, *this, rhs); return *this; } 2008 VintT& operator/=(const VintT& rhs) { div(*this, *this, rhs); return *this; } 2009 VintT& operator%=(const VintT& rhs) { mod(*this, *this, rhs); return *this; } 2010 VintT& operator&=(const VintT& rhs) { andBit(*this, *this, rhs); return *this; } 2011 VintT& operator|=(const VintT& rhs) { orBit(*this, *this, rhs); return *this; } 2012 2013 VintT& operator+=(int rhs) { adds1(*this, *this, rhs); return *this; } 2014 VintT& operator-=(int rhs) { subs1(*this, *this, rhs); return *this; } 2015 VintT& operator*=(int rhs) { muls1(*this, *this, rhs); return *this; } 2016 VintT& operator/=(int rhs) { divs1(*this, *this, rhs); return *this; } 2017 VintT& operator%=(int rhs) { mods1(*this, *this, rhs); return *this; } 2018 VintT& operator+=(Unit rhs) { addu1(*this, *this, rhs); return *this; } 2019 VintT& operator-=(Unit rhs) { subu1(*this, *this, rhs); return *this; } 2020 VintT& operator*=(Unit rhs) { mulu1(*this, *this, rhs); return *this; } 2021 VintT& operator/=(Unit rhs) { divu1(*this, *this, rhs); return *this; } 2022 VintT& operator%=(Unit rhs) { modu1(*this, *this, rhs); return *this; } 2023 2024 VintT& operator&=(Unit rhs) { andBitu1(*this, *this, rhs); return *this; } 2025 VintT& operator|=(Unit rhs) { orBitu1(*this, *this, rhs); return *this; } 2026 2027 friend VintT operator+(const VintT& a, const VintT& b) { VintT c; add(c, a, b); return c; } 2028 friend VintT operator-(const VintT& a, const VintT& b) { VintT c; sub(c, a, b); return c; } 2029 friend VintT operator*(const VintT& a, const VintT& b) { VintT c; mul(c, a, b); return c; } 2030 friend VintT operator/(const VintT& a, const VintT& b) { VintT c; div(c, a, b); return c; } 2031 friend VintT operator%(const VintT& a, const VintT& b) { VintT c; mod(c, a, b); return c; } 2032 friend VintT operator&(const VintT& a, const VintT& b) { VintT c; andBit(c, a, b); return c; } 2033 friend VintT operator|(const VintT& a, const VintT& b) { VintT c; orBit(c, a, b); return c; } 2034 2035 friend VintT operator+(const VintT& a, int b) { VintT c; adds1(c, a, b); return c; } 2036 friend VintT operator-(const VintT& a, int b) { VintT c; subs1(c, a, b); return c; } 2037 friend VintT operator*(const VintT& a, int b) { VintT c; muls1(c, a, b); return c; } 2038 friend VintT operator/(const VintT& a, int b) { VintT c; divs1(c, a, b); return c; } 2039 friend VintT operator%(const VintT& a, int b) { VintT c; mods1(c, a, b); return c; } 2040 friend VintT operator+(const VintT& a, Unit b) { VintT c; addu1(c, a, b); return c; } 2041 friend VintT operator-(const VintT& a, Unit b) { VintT c; subu1(c, a, b); return c; } 2042 friend VintT operator*(const VintT& a, Unit b) { VintT c; mulu1(c, a, b); return c; } 2043 friend VintT operator/(const VintT& a, Unit b) { VintT c; divu1(c, a, b); return c; } 2044 friend VintT operator%(const VintT& a, Unit b) { VintT c; modu1(c, a, b); return c; } 2045 2046 friend VintT operator&(const VintT& a, Unit b) { VintT c; andBitu1(c, a, b); return c; } 2047 friend VintT operator|(const VintT& a, Unit b) { VintT c; orBitu1(c, a, b); return c; } 2048 2049 VintT operator-() const { VintT c; neg(c, *this); return c; } 2050 VintT& operator<<=(size_t n) { shl(*this, *this, n); return *this; } 2051 VintT& operator>>=(size_t n) { shr(*this, *this, n); return *this; } 2052 VintT operator<<(size_t n) const { VintT c = *this; c <<= n; return c; } 2053 VintT operator>>(size_t n) const { VintT c = *this; c >>= n; return c; } 2054 }; 2055 2056 #ifdef MCL_VINT_FIXED_BUFFER 2057 typedef VintT<vint::FixedBuffer<mcl::vint::Unit, vint::RoundUp<MCL_MAX_BIT_SIZE>::bit * 2> > Vint; 2058 #else 2059 typedef VintT<vint::Buffer<mcl::vint::Unit> > Vint; 2060 #endif 2061 2062 } // mcl 2063 2064 //typedef mcl::Vint mpz_class;