1 package org.bouncycastle.math.raw; 2 3 import java.math.BigInteger; 4 5 import org.bouncycastle.util.Pack; 6 7 public abstract class Nat192 8 { 9 private static final long M = 0xFFFFFFFFL; 10 add(int[] x, int[] y, int[] z)11 public static int add(int[] x, int[] y, int[] z) 12 { 13 long c = 0; 14 c += (x[0] & M) + (y[0] & M); 15 z[0] = (int)c; 16 c >>>= 32; 17 c += (x[1] & M) + (y[1] & M); 18 z[1] = (int)c; 19 c >>>= 32; 20 c += (x[2] & M) + (y[2] & M); 21 z[2] = (int)c; 22 c >>>= 32; 23 c += (x[3] & M) + (y[3] & M); 24 z[3] = (int)c; 25 c >>>= 32; 26 c += (x[4] & M) + (y[4] & M); 27 z[4] = (int)c; 28 c >>>= 32; 29 c += (x[5] & M) + (y[5] & M); 30 z[5] = (int)c; 31 c >>>= 32; 32 return (int)c; 33 } 34 addBothTo(int[] x, int[] y, int[] z)35 public static int addBothTo(int[] x, int[] y, int[] z) 36 { 37 long c = 0; 38 c += (x[0] & M) + (y[0] & M) + (z[0] & M); 39 z[0] = (int)c; 40 c >>>= 32; 41 c += (x[1] & M) + (y[1] & M) + (z[1] & M); 42 z[1] = (int)c; 43 c >>>= 32; 44 c += (x[2] & M) + (y[2] & M) + (z[2] & M); 45 z[2] = (int)c; 46 c >>>= 32; 47 c += (x[3] & M) + (y[3] & M) + (z[3] & M); 48 z[3] = (int)c; 49 c >>>= 32; 50 c += (x[4] & M) + (y[4] & M) + (z[4] & M); 51 z[4] = (int)c; 52 c >>>= 32; 53 c += (x[5] & M) + (y[5] & M) + (z[5] & M); 54 z[5] = (int)c; 55 c >>>= 32; 56 return (int)c; 57 } 58 addTo(int[] x, int[] z)59 public static int addTo(int[] x, int[] z) 60 { 61 long c = 0; 62 c += (x[0] & M) + (z[0] & M); 63 z[0] = (int)c; 64 c >>>= 32; 65 c += (x[1] & M) + (z[1] & M); 66 z[1] = (int)c; 67 c >>>= 32; 68 c += (x[2] & M) + (z[2] & M); 69 z[2] = (int)c; 70 c >>>= 32; 71 c += (x[3] & M) + (z[3] & M); 72 z[3] = (int)c; 73 c >>>= 32; 74 c += (x[4] & M) + (z[4] & M); 75 z[4] = (int)c; 76 c >>>= 32; 77 c += (x[5] & M) + (z[5] & M); 78 z[5] = (int)c; 79 c >>>= 32; 80 return (int)c; 81 } 82 addTo(int[] x, int xOff, int[] z, int zOff, int cIn)83 public static int addTo(int[] x, int xOff, int[] z, int zOff, int cIn) 84 { 85 long c = cIn & M; 86 c += (x[xOff + 0] & M) + (z[zOff + 0] & M); 87 z[zOff + 0] = (int)c; 88 c >>>= 32; 89 c += (x[xOff + 1] & M) + (z[zOff + 1] & M); 90 z[zOff + 1] = (int)c; 91 c >>>= 32; 92 c += (x[xOff + 2] & M) + (z[zOff + 2] & M); 93 z[zOff + 2] = (int)c; 94 c >>>= 32; 95 c += (x[xOff + 3] & M) + (z[zOff + 3] & M); 96 z[zOff + 3] = (int)c; 97 c >>>= 32; 98 c += (x[xOff + 4] & M) + (z[zOff + 4] & M); 99 z[zOff + 4] = (int)c; 100 c >>>= 32; 101 c += (x[xOff + 5] & M) + (z[zOff + 5] & M); 102 z[zOff + 5] = (int)c; 103 c >>>= 32; 104 return (int)c; 105 } 106 addToEachOther(int[] u, int uOff, int[] v, int vOff)107 public static int addToEachOther(int[] u, int uOff, int[] v, int vOff) 108 { 109 long c = 0; 110 c += (u[uOff + 0] & M) + (v[vOff + 0] & M); 111 u[uOff + 0] = (int)c; 112 v[vOff + 0] = (int)c; 113 c >>>= 32; 114 c += (u[uOff + 1] & M) + (v[vOff + 1] & M); 115 u[uOff + 1] = (int)c; 116 v[vOff + 1] = (int)c; 117 c >>>= 32; 118 c += (u[uOff + 2] & M) + (v[vOff + 2] & M); 119 u[uOff + 2] = (int)c; 120 v[vOff + 2] = (int)c; 121 c >>>= 32; 122 c += (u[uOff + 3] & M) + (v[vOff + 3] & M); 123 u[uOff + 3] = (int)c; 124 v[vOff + 3] = (int)c; 125 c >>>= 32; 126 c += (u[uOff + 4] & M) + (v[vOff + 4] & M); 127 u[uOff + 4] = (int)c; 128 v[vOff + 4] = (int)c; 129 c >>>= 32; 130 c += (u[uOff + 5] & M) + (v[vOff + 5] & M); 131 u[uOff + 5] = (int)c; 132 v[vOff + 5] = (int)c; 133 c >>>= 32; 134 return (int)c; 135 } 136 copy(int[] x, int[] z)137 public static void copy(int[] x, int[] z) 138 { 139 z[0] = x[0]; 140 z[1] = x[1]; 141 z[2] = x[2]; 142 z[3] = x[3]; 143 z[4] = x[4]; 144 z[5] = x[5]; 145 } 146 copy64(long[] x, long[] z)147 public static void copy64(long[] x, long[] z) 148 { 149 z[0] = x[0]; 150 z[1] = x[1]; 151 z[2] = x[2]; 152 } 153 create()154 public static int[] create() 155 { 156 return new int[6]; 157 } 158 create64()159 public static long[] create64() 160 { 161 return new long[3]; 162 } 163 createExt()164 public static int[] createExt() 165 { 166 return new int[12]; 167 } 168 createExt64()169 public static long[] createExt64() 170 { 171 return new long[6]; 172 } 173 diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)174 public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) 175 { 176 boolean pos = gte(x, xOff, y, yOff); 177 if (pos) 178 { 179 sub(x, xOff, y, yOff, z, zOff); 180 } 181 else 182 { 183 sub(y, yOff, x, xOff, z, zOff); 184 } 185 return pos; 186 } 187 eq(int[] x, int[] y)188 public static boolean eq(int[] x, int[] y) 189 { 190 for (int i = 5; i >= 0; --i) 191 { 192 if (x[i] != y[i]) 193 { 194 return false; 195 } 196 } 197 return true; 198 } 199 eq64(long[] x, long[] y)200 public static boolean eq64(long[] x, long[] y) 201 { 202 for (int i = 2; i >= 0; --i) 203 { 204 if (x[i] != y[i]) 205 { 206 return false; 207 } 208 } 209 return true; 210 } 211 fromBigInteger(BigInteger x)212 public static int[] fromBigInteger(BigInteger x) 213 { 214 if (x.signum() < 0 || x.bitLength() > 192) 215 { 216 throw new IllegalArgumentException(); 217 } 218 219 int[] z = create(); 220 int i = 0; 221 while (x.signum() != 0) 222 { 223 z[i++] = x.intValue(); 224 x = x.shiftRight(32); 225 } 226 return z; 227 } 228 fromBigInteger64(BigInteger x)229 public static long[] fromBigInteger64(BigInteger x) 230 { 231 if (x.signum() < 0 || x.bitLength() > 192) 232 { 233 throw new IllegalArgumentException(); 234 } 235 236 long[] z = create64(); 237 int i = 0; 238 while (x.signum() != 0) 239 { 240 z[i++] = x.longValue(); 241 x = x.shiftRight(64); 242 } 243 return z; 244 } 245 getBit(int[] x, int bit)246 public static int getBit(int[] x, int bit) 247 { 248 if (bit == 0) 249 { 250 return x[0] & 1; 251 } 252 int w = bit >> 5; 253 if (w < 0 || w >= 6) 254 { 255 return 0; 256 } 257 int b = bit & 31; 258 return (x[w] >>> b) & 1; 259 } 260 gte(int[] x, int[] y)261 public static boolean gte(int[] x, int[] y) 262 { 263 for (int i = 5; i >= 0; --i) 264 { 265 int x_i = x[i] ^ Integer.MIN_VALUE; 266 int y_i = y[i] ^ Integer.MIN_VALUE; 267 if (x_i < y_i) 268 return false; 269 if (x_i > y_i) 270 return true; 271 } 272 return true; 273 } 274 gte(int[] x, int xOff, int[] y, int yOff)275 public static boolean gte(int[] x, int xOff, int[] y, int yOff) 276 { 277 for (int i = 5; i >= 0; --i) 278 { 279 int x_i = x[xOff + i] ^ Integer.MIN_VALUE; 280 int y_i = y[yOff + i] ^ Integer.MIN_VALUE; 281 if (x_i < y_i) 282 return false; 283 if (x_i > y_i) 284 return true; 285 } 286 return true; 287 } 288 isOne(int[] x)289 public static boolean isOne(int[] x) 290 { 291 if (x[0] != 1) 292 { 293 return false; 294 } 295 for (int i = 1; i < 6; ++i) 296 { 297 if (x[i] != 0) 298 { 299 return false; 300 } 301 } 302 return true; 303 } 304 isOne64(long[] x)305 public static boolean isOne64(long[] x) 306 { 307 if (x[0] != 1L) 308 { 309 return false; 310 } 311 for (int i = 1; i < 3; ++i) 312 { 313 if (x[i] != 0L) 314 { 315 return false; 316 } 317 } 318 return true; 319 } 320 isZero(int[] x)321 public static boolean isZero(int[] x) 322 { 323 for (int i = 0; i < 6; ++i) 324 { 325 if (x[i] != 0) 326 { 327 return false; 328 } 329 } 330 return true; 331 } 332 isZero64(long[] x)333 public static boolean isZero64(long[] x) 334 { 335 for (int i = 0; i < 3; ++i) 336 { 337 if (x[i] != 0L) 338 { 339 return false; 340 } 341 } 342 return true; 343 } 344 mul(int[] x, int[] y, int[] zz)345 public static void mul(int[] x, int[] y, int[] zz) 346 { 347 long y_0 = y[0] & M; 348 long y_1 = y[1] & M; 349 long y_2 = y[2] & M; 350 long y_3 = y[3] & M; 351 long y_4 = y[4] & M; 352 long y_5 = y[5] & M; 353 354 { 355 long c = 0, x_0 = x[0] & M; 356 c += x_0 * y_0; 357 zz[0] = (int)c; 358 c >>>= 32; 359 c += x_0 * y_1; 360 zz[1] = (int)c; 361 c >>>= 32; 362 c += x_0 * y_2; 363 zz[2] = (int)c; 364 c >>>= 32; 365 c += x_0 * y_3; 366 zz[3] = (int)c; 367 c >>>= 32; 368 c += x_0 * y_4; 369 zz[4] = (int)c; 370 c >>>= 32; 371 c += x_0 * y_5; 372 zz[5] = (int)c; 373 c >>>= 32; 374 zz[6] = (int)c; 375 } 376 377 for (int i = 1; i < 6; ++i) 378 { 379 long c = 0, x_i = x[i] & M; 380 c += x_i * y_0 + (zz[i + 0] & M); 381 zz[i + 0] = (int)c; 382 c >>>= 32; 383 c += x_i * y_1 + (zz[i + 1] & M); 384 zz[i + 1] = (int)c; 385 c >>>= 32; 386 c += x_i * y_2 + (zz[i + 2] & M); 387 zz[i + 2] = (int)c; 388 c >>>= 32; 389 c += x_i * y_3 + (zz[i + 3] & M); 390 zz[i + 3] = (int)c; 391 c >>>= 32; 392 c += x_i * y_4 + (zz[i + 4] & M); 393 zz[i + 4] = (int)c; 394 c >>>= 32; 395 c += x_i * y_5 + (zz[i + 5] & M); 396 zz[i + 5] = (int)c; 397 c >>>= 32; 398 zz[i + 6] = (int)c; 399 } 400 } 401 mul(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)402 public static void mul(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff) 403 { 404 long y_0 = y[yOff + 0] & M; 405 long y_1 = y[yOff + 1] & M; 406 long y_2 = y[yOff + 2] & M; 407 long y_3 = y[yOff + 3] & M; 408 long y_4 = y[yOff + 4] & M; 409 long y_5 = y[yOff + 5] & M; 410 411 { 412 long c = 0, x_0 = x[xOff + 0] & M; 413 c += x_0 * y_0; 414 zz[zzOff + 0] = (int)c; 415 c >>>= 32; 416 c += x_0 * y_1; 417 zz[zzOff + 1] = (int)c; 418 c >>>= 32; 419 c += x_0 * y_2; 420 zz[zzOff + 2] = (int)c; 421 c >>>= 32; 422 c += x_0 * y_3; 423 zz[zzOff + 3] = (int)c; 424 c >>>= 32; 425 c += x_0 * y_4; 426 zz[zzOff + 4] = (int)c; 427 c >>>= 32; 428 c += x_0 * y_5; 429 zz[zzOff + 5] = (int)c; 430 c >>>= 32; 431 zz[zzOff + 6] = (int)c; 432 } 433 434 for (int i = 1; i < 6; ++i) 435 { 436 ++zzOff; 437 long c = 0, x_i = x[xOff + i] & M; 438 c += x_i * y_0 + (zz[zzOff + 0] & M); 439 zz[zzOff + 0] = (int)c; 440 c >>>= 32; 441 c += x_i * y_1 + (zz[zzOff + 1] & M); 442 zz[zzOff + 1] = (int)c; 443 c >>>= 32; 444 c += x_i * y_2 + (zz[zzOff + 2] & M); 445 zz[zzOff + 2] = (int)c; 446 c >>>= 32; 447 c += x_i * y_3 + (zz[zzOff + 3] & M); 448 zz[zzOff + 3] = (int)c; 449 c >>>= 32; 450 c += x_i * y_4 + (zz[zzOff + 4] & M); 451 zz[zzOff + 4] = (int)c; 452 c >>>= 32; 453 c += x_i * y_5 + (zz[zzOff + 5] & M); 454 zz[zzOff + 5] = (int)c; 455 c >>>= 32; 456 zz[zzOff + 6] = (int)c; 457 } 458 } 459 mulAddTo(int[] x, int[] y, int[] zz)460 public static int mulAddTo(int[] x, int[] y, int[] zz) 461 { 462 long y_0 = y[0] & M; 463 long y_1 = y[1] & M; 464 long y_2 = y[2] & M; 465 long y_3 = y[3] & M; 466 long y_4 = y[4] & M; 467 long y_5 = y[5] & M; 468 469 long zc = 0; 470 for (int i = 0; i < 6; ++i) 471 { 472 long c = 0, x_i = x[i] & M; 473 c += x_i * y_0 + (zz[i + 0] & M); 474 zz[i + 0] = (int)c; 475 c >>>= 32; 476 c += x_i * y_1 + (zz[i + 1] & M); 477 zz[i + 1] = (int)c; 478 c >>>= 32; 479 c += x_i * y_2 + (zz[i + 2] & M); 480 zz[i + 2] = (int)c; 481 c >>>= 32; 482 c += x_i * y_3 + (zz[i + 3] & M); 483 zz[i + 3] = (int)c; 484 c >>>= 32; 485 c += x_i * y_4 + (zz[i + 4] & M); 486 zz[i + 4] = (int)c; 487 c >>>= 32; 488 c += x_i * y_5 + (zz[i + 5] & M); 489 zz[i + 5] = (int)c; 490 c >>>= 32; 491 c += zc + (zz[i + 6] & M); 492 zz[i + 6] = (int)c; 493 zc = c >>> 32; 494 } 495 return (int)zc; 496 } 497 mulAddTo(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff)498 public static int mulAddTo(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff) 499 { 500 long y_0 = y[yOff + 0] & M; 501 long y_1 = y[yOff + 1] & M; 502 long y_2 = y[yOff + 2] & M; 503 long y_3 = y[yOff + 3] & M; 504 long y_4 = y[yOff + 4] & M; 505 long y_5 = y[yOff + 5] & M; 506 507 long zc = 0; 508 for (int i = 0; i < 6; ++i) 509 { 510 long c = 0, x_i = x[xOff + i] & M; 511 c += x_i * y_0 + (zz[zzOff + 0] & M); 512 zz[zzOff + 0] = (int)c; 513 c >>>= 32; 514 c += x_i * y_1 + (zz[zzOff + 1] & M); 515 zz[zzOff + 1] = (int)c; 516 c >>>= 32; 517 c += x_i * y_2 + (zz[zzOff + 2] & M); 518 zz[zzOff + 2] = (int)c; 519 c >>>= 32; 520 c += x_i * y_3 + (zz[zzOff + 3] & M); 521 zz[zzOff + 3] = (int)c; 522 c >>>= 32; 523 c += x_i * y_4 + (zz[zzOff + 4] & M); 524 zz[zzOff + 4] = (int)c; 525 c >>>= 32; 526 c += x_i * y_5 + (zz[zzOff + 5] & M); 527 zz[zzOff + 5] = (int)c; 528 c >>>= 32; 529 c += zc + (zz[zzOff + 6] & M); 530 zz[zzOff + 6] = (int)c; 531 zc = c >>> 32; 532 ++zzOff; 533 } 534 return (int)zc; 535 } 536 mul33Add(int w, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)537 public static long mul33Add(int w, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) 538 { 539 // assert w >>> 31 == 0; 540 541 long c = 0, wVal = w & M; 542 long x0 = x[xOff + 0] & M; 543 c += wVal * x0 + (y[yOff + 0] & M); 544 z[zOff + 0] = (int)c; 545 c >>>= 32; 546 long x1 = x[xOff + 1] & M; 547 c += wVal * x1 + x0 + (y[yOff + 1] & M); 548 z[zOff + 1] = (int)c; 549 c >>>= 32; 550 long x2 = x[xOff + 2] & M; 551 c += wVal * x2 + x1 + (y[yOff + 2] & M); 552 z[zOff + 2] = (int)c; 553 c >>>= 32; 554 long x3 = x[xOff + 3] & M; 555 c += wVal * x3 + x2 + (y[yOff + 3] & M); 556 z[zOff + 3] = (int)c; 557 c >>>= 32; 558 long x4 = x[xOff + 4] & M; 559 c += wVal * x4 + x3 + (y[yOff + 4] & M); 560 z[zOff + 4] = (int)c; 561 c >>>= 32; 562 long x5 = x[xOff + 5] & M; 563 c += wVal * x5 + x4 + (y[yOff + 5] & M); 564 z[zOff + 5] = (int)c; 565 c >>>= 32; 566 c += x5; 567 return c; 568 } 569 mulWordAddExt(int x, int[] yy, int yyOff, int[] zz, int zzOff)570 public static int mulWordAddExt(int x, int[] yy, int yyOff, int[] zz, int zzOff) 571 { 572 // assert yyOff <= 6; 573 // assert zzOff <= 6; 574 long c = 0, xVal = x & M; 575 c += xVal * (yy[yyOff + 0] & M) + (zz[zzOff + 0] & M); 576 zz[zzOff + 0] = (int)c; 577 c >>>= 32; 578 c += xVal * (yy[yyOff + 1] & M) + (zz[zzOff + 1] & M); 579 zz[zzOff + 1] = (int)c; 580 c >>>= 32; 581 c += xVal * (yy[yyOff + 2] & M) + (zz[zzOff + 2] & M); 582 zz[zzOff + 2] = (int)c; 583 c >>>= 32; 584 c += xVal * (yy[yyOff + 3] & M) + (zz[zzOff + 3] & M); 585 zz[zzOff + 3] = (int)c; 586 c >>>= 32; 587 c += xVal * (yy[yyOff + 4] & M) + (zz[zzOff + 4] & M); 588 zz[zzOff + 4] = (int)c; 589 c >>>= 32; 590 c += xVal * (yy[yyOff + 5] & M) + (zz[zzOff + 5] & M); 591 zz[zzOff + 5] = (int)c; 592 c >>>= 32; 593 return (int)c; 594 } 595 mul33DWordAdd(int x, long y, int[] z, int zOff)596 public static int mul33DWordAdd(int x, long y, int[] z, int zOff) 597 { 598 // assert x >>> 31 == 0; 599 // assert zOff <= 2; 600 601 long c = 0, xVal = x & M; 602 long y00 = y & M; 603 c += xVal * y00 + (z[zOff + 0] & M); 604 z[zOff + 0] = (int)c; 605 c >>>= 32; 606 long y01 = y >>> 32; 607 c += xVal * y01 + y00 + (z[zOff + 1] & M); 608 z[zOff + 1] = (int)c; 609 c >>>= 32; 610 c += y01 + (z[zOff + 2] & M); 611 z[zOff + 2] = (int)c; 612 c >>>= 32; 613 c += (z[zOff + 3] & M); 614 z[zOff + 3] = (int)c; 615 c >>>= 32; 616 return c == 0 ? 0 : Nat.incAt(6, z, zOff, 4); 617 } 618 mul33WordAdd(int x, int y, int[] z, int zOff)619 public static int mul33WordAdd(int x, int y, int[] z, int zOff) 620 { 621 // assert x >>> 31 == 0; 622 // assert zOff <= 3; 623 624 long c = 0, xVal = x & M, yVal = y & M; 625 c += yVal * xVal + (z[zOff + 0] & M); 626 z[zOff + 0] = (int)c; 627 c >>>= 32; 628 c += yVal + (z[zOff + 1] & M); 629 z[zOff + 1] = (int)c; 630 c >>>= 32; 631 c += (z[zOff + 2] & M); 632 z[zOff + 2] = (int)c; 633 c >>>= 32; 634 return c == 0 ? 0 : Nat.incAt(6, z, zOff, 3); 635 } 636 mulWordDwordAdd(int x, long y, int[] z, int zOff)637 public static int mulWordDwordAdd(int x, long y, int[] z, int zOff) 638 { 639 // assert zOff <= 3; 640 long c = 0, xVal = x & M; 641 c += xVal * (y & M) + (z[zOff + 0] & M); 642 z[zOff + 0] = (int)c; 643 c >>>= 32; 644 c += xVal * (y >>> 32) + (z[zOff + 1] & M); 645 z[zOff + 1] = (int)c; 646 c >>>= 32; 647 c += (z[zOff + 2] & M); 648 z[zOff + 2] = (int)c; 649 c >>>= 32; 650 return c == 0 ? 0 : Nat.incAt(6, z, zOff, 3); 651 } 652 mulWord(int x, int[] y, int[] z, int zOff)653 public static int mulWord(int x, int[] y, int[] z, int zOff) 654 { 655 long c = 0, xVal = x & M; 656 int i = 0; 657 do 658 { 659 c += xVal * (y[i] & M); 660 z[zOff + i] = (int)c; 661 c >>>= 32; 662 } 663 while (++i < 6); 664 return (int)c; 665 } 666 square(int[] x, int[] zz)667 public static void square(int[] x, int[] zz) 668 { 669 long x_0 = x[0] & M; 670 long zz_1; 671 672 int c = 0, w; 673 { 674 int i = 5, j = 12; 675 do 676 { 677 long xVal = (x[i--] & M); 678 long p = xVal * xVal; 679 zz[--j] = (c << 31) | (int)(p >>> 33); 680 zz[--j] = (int)(p >>> 1); 681 c = (int)p; 682 } 683 while (i > 0); 684 685 { 686 long p = x_0 * x_0; 687 zz_1 = ((c << 31) & M) | (p >>> 33); 688 zz[0] = (int)p; 689 c = (int)(p >>> 32) & 1; 690 } 691 } 692 693 long x_1 = x[1] & M; 694 long zz_2 = zz[2] & M; 695 696 { 697 zz_1 += x_1 * x_0; 698 w = (int)zz_1; 699 zz[1] = (w << 1) | c; 700 c = w >>> 31; 701 zz_2 += zz_1 >>> 32; 702 } 703 704 long x_2 = x[2] & M; 705 long zz_3 = zz[3] & M; 706 long zz_4 = zz[4] & M; 707 { 708 zz_2 += x_2 * x_0; 709 w = (int)zz_2; 710 zz[2] = (w << 1) | c; 711 c = w >>> 31; 712 zz_3 += (zz_2 >>> 32) + x_2 * x_1; 713 zz_4 += zz_3 >>> 32; 714 zz_3 &= M; 715 } 716 717 long x_3 = x[3] & M; 718 long zz_5 = (zz[5] & M) + (zz_4 >>> 32); zz_4 &= M; 719 long zz_6 = (zz[6] & M) + (zz_5 >>> 32); zz_5 &= M; 720 { 721 zz_3 += x_3 * x_0; 722 w = (int)zz_3; 723 zz[3] = (w << 1) | c; 724 c = w >>> 31; 725 zz_4 += (zz_3 >>> 32) + x_3 * x_1; 726 zz_5 += (zz_4 >>> 32) + x_3 * x_2; 727 zz_4 &= M; 728 zz_6 += zz_5 >>> 32; 729 zz_5 &= M; 730 } 731 732 long x_4 = x[4] & M; 733 long zz_7 = (zz[7] & M) + (zz_6 >>> 32); zz_6 &= M; 734 long zz_8 = (zz[8] & M) + (zz_7 >>> 32); zz_7 &= M; 735 { 736 zz_4 += x_4 * x_0; 737 w = (int)zz_4; 738 zz[4] = (w << 1) | c; 739 c = w >>> 31; 740 zz_5 += (zz_4 >>> 32) + x_4 * x_1; 741 zz_6 += (zz_5 >>> 32) + x_4 * x_2; 742 zz_5 &= M; 743 zz_7 += (zz_6 >>> 32) + x_4 * x_3; 744 zz_6 &= M; 745 zz_8 += zz_7 >>> 32; 746 zz_7 &= M; 747 } 748 749 long x_5 = x[5] & M; 750 long zz_9 = (zz[9] & M) + (zz_8 >>> 32); zz_8 &= M; 751 long zz_10 = (zz[10] & M) + (zz_9 >>> 32); zz_9 &= M; 752 { 753 zz_5 += x_5 * x_0; 754 w = (int)zz_5; 755 zz[5] = (w << 1) | c; 756 c = w >>> 31; 757 zz_6 += (zz_5 >>> 32) + x_5 * x_1; 758 zz_7 += (zz_6 >>> 32) + x_5 * x_2; 759 zz_8 += (zz_7 >>> 32) + x_5 * x_3; 760 zz_9 += (zz_8 >>> 32) + x_5 * x_4; 761 zz_10 += zz_9 >>> 32; 762 } 763 764 w = (int)zz_6; 765 zz[6] = (w << 1) | c; 766 c = w >>> 31; 767 w = (int)zz_7; 768 zz[7] = (w << 1) | c; 769 c = w >>> 31; 770 w = (int)zz_8; 771 zz[8] = (w << 1) | c; 772 c = w >>> 31; 773 w = (int)zz_9; 774 zz[9] = (w << 1) | c; 775 c = w >>> 31; 776 w = (int)zz_10; 777 zz[10] = (w << 1) | c; 778 c = w >>> 31; 779 w = zz[11] + (int)(zz_10 >>> 32); 780 zz[11] = (w << 1) | c; 781 } 782 square(int[] x, int xOff, int[] zz, int zzOff)783 public static void square(int[] x, int xOff, int[] zz, int zzOff) 784 { 785 long x_0 = x[xOff + 0] & M; 786 long zz_1; 787 788 int c = 0, w; 789 { 790 int i = 5, j = 12; 791 do 792 { 793 long xVal = (x[xOff + i--] & M); 794 long p = xVal * xVal; 795 zz[zzOff + --j] = (c << 31) | (int)(p >>> 33); 796 zz[zzOff + --j] = (int)(p >>> 1); 797 c = (int)p; 798 } 799 while (i > 0); 800 801 { 802 long p = x_0 * x_0; 803 zz_1 = ((c << 31) & M) | (p >>> 33); 804 zz[zzOff + 0] = (int)p; 805 c = (int)(p >>> 32) & 1; 806 } 807 } 808 809 long x_1 = x[xOff + 1] & M; 810 long zz_2 = zz[zzOff + 2] & M; 811 812 { 813 zz_1 += x_1 * x_0; 814 w = (int)zz_1; 815 zz[zzOff + 1] = (w << 1) | c; 816 c = w >>> 31; 817 zz_2 += zz_1 >>> 32; 818 } 819 820 long x_2 = x[xOff + 2] & M; 821 long zz_3 = zz[zzOff + 3] & M; 822 long zz_4 = zz[zzOff + 4] & M; 823 { 824 zz_2 += x_2 * x_0; 825 w = (int)zz_2; 826 zz[zzOff + 2] = (w << 1) | c; 827 c = w >>> 31; 828 zz_3 += (zz_2 >>> 32) + x_2 * x_1; 829 zz_4 += zz_3 >>> 32; 830 zz_3 &= M; 831 } 832 833 long x_3 = x[xOff + 3] & M; 834 long zz_5 = (zz[zzOff + 5] & M) + (zz_4 >>> 32); zz_4 &= M; 835 long zz_6 = (zz[zzOff + 6] & M) + (zz_5 >>> 32); zz_5 &= M; 836 { 837 zz_3 += x_3 * x_0; 838 w = (int)zz_3; 839 zz[zzOff + 3] = (w << 1) | c; 840 c = w >>> 31; 841 zz_4 += (zz_3 >>> 32) + x_3 * x_1; 842 zz_5 += (zz_4 >>> 32) + x_3 * x_2; 843 zz_4 &= M; 844 zz_6 += zz_5 >>> 32; 845 zz_5 &= M; 846 } 847 848 long x_4 = x[xOff + 4] & M; 849 long zz_7 = (zz[zzOff + 7] & M) + (zz_6 >>> 32); zz_6 &= M; 850 long zz_8 = (zz[zzOff + 8] & M) + (zz_7 >>> 32); zz_7 &= M; 851 { 852 zz_4 += x_4 * x_0; 853 w = (int)zz_4; 854 zz[zzOff + 4] = (w << 1) | c; 855 c = w >>> 31; 856 zz_5 += (zz_4 >>> 32) + x_4 * x_1; 857 zz_6 += (zz_5 >>> 32) + x_4 * x_2; 858 zz_5 &= M; 859 zz_7 += (zz_6 >>> 32) + x_4 * x_3; 860 zz_6 &= M; 861 zz_8 += zz_7 >>> 32; 862 zz_7 &= M; 863 } 864 865 long x_5 = x[xOff + 5] & M; 866 long zz_9 = (zz[zzOff + 9] & M) + (zz_8 >>> 32); zz_8 &= M; 867 long zz_10 = (zz[zzOff + 10] & M) + (zz_9 >>> 32); zz_9 &= M; 868 { 869 zz_5 += x_5 * x_0; 870 w = (int)zz_5; 871 zz[zzOff + 5] = (w << 1) | c; 872 c = w >>> 31; 873 zz_6 += (zz_5 >>> 32) + x_5 * x_1; 874 zz_7 += (zz_6 >>> 32) + x_5 * x_2; 875 zz_8 += (zz_7 >>> 32) + x_5 * x_3; 876 zz_9 += (zz_8 >>> 32) + x_5 * x_4; 877 zz_10 += zz_9 >>> 32; 878 } 879 880 w = (int)zz_6; 881 zz[zzOff + 6] = (w << 1) | c; 882 c = w >>> 31; 883 w = (int)zz_7; 884 zz[zzOff + 7] = (w << 1) | c; 885 c = w >>> 31; 886 w = (int)zz_8; 887 zz[zzOff + 8] = (w << 1) | c; 888 c = w >>> 31; 889 w = (int)zz_9; 890 zz[zzOff + 9] = (w << 1) | c; 891 c = w >>> 31; 892 w = (int)zz_10; 893 zz[zzOff + 10] = (w << 1) | c; 894 c = w >>> 31; 895 w = zz[zzOff + 11] + (int)(zz_10 >>> 32); 896 zz[zzOff + 11] = (w << 1) | c; 897 } 898 sub(int[] x, int[] y, int[] z)899 public static int sub(int[] x, int[] y, int[] z) 900 { 901 long c = 0; 902 c += (x[0] & M) - (y[0] & M); 903 z[0] = (int)c; 904 c >>= 32; 905 c += (x[1] & M) - (y[1] & M); 906 z[1] = (int)c; 907 c >>= 32; 908 c += (x[2] & M) - (y[2] & M); 909 z[2] = (int)c; 910 c >>= 32; 911 c += (x[3] & M) - (y[3] & M); 912 z[3] = (int)c; 913 c >>= 32; 914 c += (x[4] & M) - (y[4] & M); 915 z[4] = (int)c; 916 c >>= 32; 917 c += (x[5] & M) - (y[5] & M); 918 z[5] = (int)c; 919 c >>= 32; 920 return (int)c; 921 } 922 sub(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff)923 public static int sub(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) 924 { 925 long c = 0; 926 c += (x[xOff + 0] & M) - (y[yOff + 0] & M); 927 z[zOff + 0] = (int)c; 928 c >>= 32; 929 c += (x[xOff + 1] & M) - (y[yOff + 1] & M); 930 z[zOff + 1] = (int)c; 931 c >>= 32; 932 c += (x[xOff + 2] & M) - (y[yOff + 2] & M); 933 z[zOff + 2] = (int)c; 934 c >>= 32; 935 c += (x[xOff + 3] & M) - (y[yOff + 3] & M); 936 z[zOff + 3] = (int)c; 937 c >>= 32; 938 c += (x[xOff + 4] & M) - (y[yOff + 4] & M); 939 z[zOff + 4] = (int)c; 940 c >>= 32; 941 c += (x[xOff + 5] & M) - (y[yOff + 5] & M); 942 z[zOff + 5] = (int)c; 943 c >>= 32; 944 return (int)c; 945 } 946 subBothFrom(int[] x, int[] y, int[] z)947 public static int subBothFrom(int[] x, int[] y, int[] z) 948 { 949 long c = 0; 950 c += (z[0] & M) - (x[0] & M) - (y[0] & M); 951 z[0] = (int)c; 952 c >>= 32; 953 c += (z[1] & M) - (x[1] & M) - (y[1] & M); 954 z[1] = (int)c; 955 c >>= 32; 956 c += (z[2] & M) - (x[2] & M) - (y[2] & M); 957 z[2] = (int)c; 958 c >>= 32; 959 c += (z[3] & M) - (x[3] & M) - (y[3] & M); 960 z[3] = (int)c; 961 c >>= 32; 962 c += (z[4] & M) - (x[4] & M) - (y[4] & M); 963 z[4] = (int)c; 964 c >>= 32; 965 c += (z[5] & M) - (x[5] & M) - (y[5] & M); 966 z[5] = (int)c; 967 c >>= 32; 968 return (int)c; 969 } 970 subFrom(int[] x, int[] z)971 public static int subFrom(int[] x, int[] z) 972 { 973 long c = 0; 974 c += (z[0] & M) - (x[0] & M); 975 z[0] = (int)c; 976 c >>= 32; 977 c += (z[1] & M) - (x[1] & M); 978 z[1] = (int)c; 979 c >>= 32; 980 c += (z[2] & M) - (x[2] & M); 981 z[2] = (int)c; 982 c >>= 32; 983 c += (z[3] & M) - (x[3] & M); 984 z[3] = (int)c; 985 c >>= 32; 986 c += (z[4] & M) - (x[4] & M); 987 z[4] = (int)c; 988 c >>= 32; 989 c += (z[5] & M) - (x[5] & M); 990 z[5] = (int)c; 991 c >>= 32; 992 return (int)c; 993 } 994 subFrom(int[] x, int xOff, int[] z, int zOff)995 public static int subFrom(int[] x, int xOff, int[] z, int zOff) 996 { 997 long c = 0; 998 c += (z[zOff + 0] & M) - (x[xOff + 0] & M); 999 z[zOff + 0] = (int)c; 1000 c >>= 32; 1001 c += (z[zOff + 1] & M) - (x[xOff + 1] & M); 1002 z[zOff + 1] = (int)c; 1003 c >>= 32; 1004 c += (z[zOff + 2] & M) - (x[xOff + 2] & M); 1005 z[zOff + 2] = (int)c; 1006 c >>= 32; 1007 c += (z[zOff + 3] & M) - (x[xOff + 3] & M); 1008 z[zOff + 3] = (int)c; 1009 c >>= 32; 1010 c += (z[zOff + 4] & M) - (x[xOff + 4] & M); 1011 z[zOff + 4] = (int)c; 1012 c >>= 32; 1013 c += (z[zOff + 5] & M) - (x[xOff + 5] & M); 1014 z[zOff + 5] = (int)c; 1015 c >>= 32; 1016 return (int)c; 1017 } 1018 toBigInteger(int[] x)1019 public static BigInteger toBigInteger(int[] x) 1020 { 1021 byte[] bs = new byte[24]; 1022 for (int i = 0; i < 6; ++i) 1023 { 1024 int x_i = x[i]; 1025 if (x_i != 0) 1026 { 1027 Pack.intToBigEndian(x_i, bs, (5 - i) << 2); 1028 } 1029 } 1030 return new BigInteger(1, bs); 1031 } 1032 toBigInteger64(long[] x)1033 public static BigInteger toBigInteger64(long[] x) 1034 { 1035 byte[] bs = new byte[24]; 1036 for (int i = 0; i < 3; ++i) 1037 { 1038 long x_i = x[i]; 1039 if (x_i != 0L) 1040 { 1041 Pack.longToBigEndian(x_i, bs, (2 - i) << 3); 1042 } 1043 } 1044 return new BigInteger(1, bs); 1045 } 1046 zero(int[] z)1047 public static void zero(int[] z) 1048 { 1049 z[0] = 0; 1050 z[1] = 0; 1051 z[2] = 0; 1052 z[3] = 0; 1053 z[4] = 0; 1054 z[5] = 0; 1055 } 1056 } 1057