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