1package org.bouncycastle.math.raw; 2 3import java.math.BigInteger; 4 5import org.bouncycastle.util.Pack; 6 7public abstract class Nat256 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 c += (x[6] & M) + (y[6] & M); 33 z[6] = (int)c; 34 c >>>= 32; 35 c += (x[7] & M) + (y[7] & M); 36 z[7] = (int)c; 37 c >>>= 32; 38 return (int)c; 39 } 40 41 public static int add(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) 42 { 43 long c = 0; 44 c += (x[xOff + 0] & M) + (y[yOff + 0] & M); 45 z[zOff + 0] = (int)c; 46 c >>>= 32; 47 c += (x[xOff + 1] & M) + (y[yOff + 1] & M); 48 z[zOff + 1] = (int)c; 49 c >>>= 32; 50 c += (x[xOff + 2] & M) + (y[yOff + 2] & M); 51 z[zOff + 2] = (int)c; 52 c >>>= 32; 53 c += (x[xOff + 3] & M) + (y[yOff + 3] & M); 54 z[zOff + 3] = (int)c; 55 c >>>= 32; 56 c += (x[xOff + 4] & M) + (y[yOff + 4] & M); 57 z[zOff + 4] = (int)c; 58 c >>>= 32; 59 c += (x[xOff + 5] & M) + (y[yOff + 5] & M); 60 z[zOff + 5] = (int)c; 61 c >>>= 32; 62 c += (x[xOff + 6] & M) + (y[yOff + 6] & M); 63 z[zOff + 6] = (int)c; 64 c >>>= 32; 65 c += (x[xOff + 7] & M) + (y[yOff + 7] & M); 66 z[zOff + 7] = (int)c; 67 c >>>= 32; 68 return (int)c; 69 } 70 71 public static int addBothTo(int[] x, int[] y, int[] z) 72 { 73 long c = 0; 74 c += (x[0] & M) + (y[0] & M) + (z[0] & M); 75 z[0] = (int)c; 76 c >>>= 32; 77 c += (x[1] & M) + (y[1] & M) + (z[1] & M); 78 z[1] = (int)c; 79 c >>>= 32; 80 c += (x[2] & M) + (y[2] & M) + (z[2] & M); 81 z[2] = (int)c; 82 c >>>= 32; 83 c += (x[3] & M) + (y[3] & M) + (z[3] & M); 84 z[3] = (int)c; 85 c >>>= 32; 86 c += (x[4] & M) + (y[4] & M) + (z[4] & M); 87 z[4] = (int)c; 88 c >>>= 32; 89 c += (x[5] & M) + (y[5] & M) + (z[5] & M); 90 z[5] = (int)c; 91 c >>>= 32; 92 c += (x[6] & M) + (y[6] & M) + (z[6] & M); 93 z[6] = (int)c; 94 c >>>= 32; 95 c += (x[7] & M) + (y[7] & M) + (z[7] & M); 96 z[7] = (int)c; 97 c >>>= 32; 98 return (int)c; 99 } 100 101 public static int addBothTo(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) 102 { 103 long c = 0; 104 c += (x[xOff + 0] & M) + (y[yOff + 0] & M) + (z[zOff + 0] & M); 105 z[zOff + 0] = (int)c; 106 c >>>= 32; 107 c += (x[xOff + 1] & M) + (y[yOff + 1] & M) + (z[zOff + 1] & M); 108 z[zOff + 1] = (int)c; 109 c >>>= 32; 110 c += (x[xOff + 2] & M) + (y[yOff + 2] & M) + (z[zOff + 2] & M); 111 z[zOff + 2] = (int)c; 112 c >>>= 32; 113 c += (x[xOff + 3] & M) + (y[yOff + 3] & M) + (z[zOff + 3] & M); 114 z[zOff + 3] = (int)c; 115 c >>>= 32; 116 c += (x[xOff + 4] & M) + (y[yOff + 4] & M) + (z[zOff + 4] & M); 117 z[zOff + 4] = (int)c; 118 c >>>= 32; 119 c += (x[xOff + 5] & M) + (y[yOff + 5] & M) + (z[zOff + 5] & M); 120 z[zOff + 5] = (int)c; 121 c >>>= 32; 122 c += (x[xOff + 6] & M) + (y[yOff + 6] & M) + (z[zOff + 6] & M); 123 z[zOff + 6] = (int)c; 124 c >>>= 32; 125 c += (x[xOff + 7] & M) + (y[yOff + 7] & M) + (z[zOff + 7] & M); 126 z[zOff + 7] = (int)c; 127 c >>>= 32; 128 return (int)c; 129 } 130 131 public static int addTo(int[] x, int[] z) 132 { 133 long c = 0; 134 c += (x[0] & M) + (z[0] & M); 135 z[0] = (int)c; 136 c >>>= 32; 137 c += (x[1] & M) + (z[1] & M); 138 z[1] = (int)c; 139 c >>>= 32; 140 c += (x[2] & M) + (z[2] & M); 141 z[2] = (int)c; 142 c >>>= 32; 143 c += (x[3] & M) + (z[3] & M); 144 z[3] = (int)c; 145 c >>>= 32; 146 c += (x[4] & M) + (z[4] & M); 147 z[4] = (int)c; 148 c >>>= 32; 149 c += (x[5] & M) + (z[5] & M); 150 z[5] = (int)c; 151 c >>>= 32; 152 c += (x[6] & M) + (z[6] & M); 153 z[6] = (int)c; 154 c >>>= 32; 155 c += (x[7] & M) + (z[7] & M); 156 z[7] = (int)c; 157 c >>>= 32; 158 return (int)c; 159 } 160 161 public static int addTo(int[] x, int xOff, int[] z, int zOff, int cIn) 162 { 163 long c = cIn & M; 164 c += (x[xOff + 0] & M) + (z[zOff + 0] & M); 165 z[zOff + 0] = (int)c; 166 c >>>= 32; 167 c += (x[xOff + 1] & M) + (z[zOff + 1] & M); 168 z[zOff + 1] = (int)c; 169 c >>>= 32; 170 c += (x[xOff + 2] & M) + (z[zOff + 2] & M); 171 z[zOff + 2] = (int)c; 172 c >>>= 32; 173 c += (x[xOff + 3] & M) + (z[zOff + 3] & M); 174 z[zOff + 3] = (int)c; 175 c >>>= 32; 176 c += (x[xOff + 4] & M) + (z[zOff + 4] & M); 177 z[zOff + 4] = (int)c; 178 c >>>= 32; 179 c += (x[xOff + 5] & M) + (z[zOff + 5] & M); 180 z[zOff + 5] = (int)c; 181 c >>>= 32; 182 c += (x[xOff + 6] & M) + (z[zOff + 6] & M); 183 z[zOff + 6] = (int)c; 184 c >>>= 32; 185 c += (x[xOff + 7] & M) + (z[zOff + 7] & M); 186 z[zOff + 7] = (int)c; 187 c >>>= 32; 188 return (int)c; 189 } 190 191 public static int addToEachOther(int[] u, int uOff, int[] v, int vOff) 192 { 193 long c = 0; 194 c += (u[uOff + 0] & M) + (v[vOff + 0] & M); 195 u[uOff + 0] = (int)c; 196 v[vOff + 0] = (int)c; 197 c >>>= 32; 198 c += (u[uOff + 1] & M) + (v[vOff + 1] & M); 199 u[uOff + 1] = (int)c; 200 v[vOff + 1] = (int)c; 201 c >>>= 32; 202 c += (u[uOff + 2] & M) + (v[vOff + 2] & M); 203 u[uOff + 2] = (int)c; 204 v[vOff + 2] = (int)c; 205 c >>>= 32; 206 c += (u[uOff + 3] & M) + (v[vOff + 3] & M); 207 u[uOff + 3] = (int)c; 208 v[vOff + 3] = (int)c; 209 c >>>= 32; 210 c += (u[uOff + 4] & M) + (v[vOff + 4] & M); 211 u[uOff + 4] = (int)c; 212 v[vOff + 4] = (int)c; 213 c >>>= 32; 214 c += (u[uOff + 5] & M) + (v[vOff + 5] & M); 215 u[uOff + 5] = (int)c; 216 v[vOff + 5] = (int)c; 217 c >>>= 32; 218 c += (u[uOff + 6] & M) + (v[vOff + 6] & M); 219 u[uOff + 6] = (int)c; 220 v[vOff + 6] = (int)c; 221 c >>>= 32; 222 c += (u[uOff + 7] & M) + (v[vOff + 7] & M); 223 u[uOff + 7] = (int)c; 224 v[vOff + 7] = (int)c; 225 c >>>= 32; 226 return (int)c; 227 } 228 229 public static void copy(int[] x, int[] z) 230 { 231 z[0] = x[0]; 232 z[1] = x[1]; 233 z[2] = x[2]; 234 z[3] = x[3]; 235 z[4] = x[4]; 236 z[5] = x[5]; 237 z[6] = x[6]; 238 z[7] = x[7]; 239 } 240 241 public static int[] create() 242 { 243 return new int[8]; 244 } 245 246 public static int[] createExt() 247 { 248 return new int[16]; 249 } 250 251 public static boolean diff(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) 252 { 253 boolean pos = gte(x, xOff, y, yOff); 254 if (pos) 255 { 256 sub(x, xOff, y, yOff, z, zOff); 257 } 258 else 259 { 260 sub(y, yOff, x, xOff, z, zOff); 261 } 262 return pos; 263 } 264 265 public static boolean eq(int[] x, int[] y) 266 { 267 for (int i = 7; i >= 0; --i) 268 { 269 if (x[i] != y[i]) 270 { 271 return false; 272 } 273 } 274 return true; 275 } 276 277 public static int[] fromBigInteger(BigInteger x) 278 { 279 if (x.signum() < 0 || x.bitLength() > 256) 280 { 281 throw new IllegalArgumentException(); 282 } 283 284 int[] z = create(); 285 int i = 0; 286 while (x.signum() != 0) 287 { 288 z[i++] = x.intValue(); 289 x = x.shiftRight(32); 290 } 291 return z; 292 } 293 294 public static int getBit(int[] x, int bit) 295 { 296 if (bit == 0) 297 { 298 return x[0] & 1; 299 } 300 if ((bit & 255) != bit) 301 { 302 return 0; 303 } 304 int w = bit >>> 5; 305 int b = bit & 31; 306 return (x[w] >>> b) & 1; 307 } 308 309 public static boolean gte(int[] x, int[] y) 310 { 311 for (int i = 7; i >= 0; --i) 312 { 313 int x_i = x[i] ^ Integer.MIN_VALUE; 314 int y_i = y[i] ^ Integer.MIN_VALUE; 315 if (x_i < y_i) 316 return false; 317 if (x_i > y_i) 318 return true; 319 } 320 return true; 321 } 322 323 public static boolean gte(int[] x, int xOff, int[] y, int yOff) 324 { 325 for (int i = 7; i >= 0; --i) 326 { 327 int x_i = x[xOff + i] ^ Integer.MIN_VALUE; 328 int y_i = y[yOff + i] ^ Integer.MIN_VALUE; 329 if (x_i < y_i) 330 return false; 331 if (x_i > y_i) 332 return true; 333 } 334 return true; 335 } 336 337 public static boolean isOne(int[] x) 338 { 339 if (x[0] != 1) 340 { 341 return false; 342 } 343 for (int i = 1; i < 8; ++i) 344 { 345 if (x[i] != 0) 346 { 347 return false; 348 } 349 } 350 return true; 351 } 352 353 public static boolean isZero(int[] x) 354 { 355 for (int i = 0; i < 8; ++i) 356 { 357 if (x[i] != 0) 358 { 359 return false; 360 } 361 } 362 return true; 363 } 364 365 public static void mul(int[] x, int[] y, int[] zz) 366 { 367 long y_0 = y[0] & M; 368 long y_1 = y[1] & M; 369 long y_2 = y[2] & M; 370 long y_3 = y[3] & M; 371 long y_4 = y[4] & M; 372 long y_5 = y[5] & M; 373 long y_6 = y[6] & M; 374 long y_7 = y[7] & M; 375 376 { 377 long c = 0, x_0 = x[0] & M; 378 c += x_0 * y_0; 379 zz[0] = (int)c; 380 c >>>= 32; 381 c += x_0 * y_1; 382 zz[1] = (int)c; 383 c >>>= 32; 384 c += x_0 * y_2; 385 zz[2] = (int)c; 386 c >>>= 32; 387 c += x_0 * y_3; 388 zz[3] = (int)c; 389 c >>>= 32; 390 c += x_0 * y_4; 391 zz[4] = (int)c; 392 c >>>= 32; 393 c += x_0 * y_5; 394 zz[5] = (int)c; 395 c >>>= 32; 396 c += x_0 * y_6; 397 zz[6] = (int)c; 398 c >>>= 32; 399 c += x_0 * y_7; 400 zz[7] = (int)c; 401 c >>>= 32; 402 zz[8] = (int)c; 403 } 404 405 for (int i = 1; i < 8; ++i) 406 { 407 long c = 0, x_i = x[i] & M; 408 c += x_i * y_0 + (zz[i + 0] & M); 409 zz[i + 0] = (int)c; 410 c >>>= 32; 411 c += x_i * y_1 + (zz[i + 1] & M); 412 zz[i + 1] = (int)c; 413 c >>>= 32; 414 c += x_i * y_2 + (zz[i + 2] & M); 415 zz[i + 2] = (int)c; 416 c >>>= 32; 417 c += x_i * y_3 + (zz[i + 3] & M); 418 zz[i + 3] = (int)c; 419 c >>>= 32; 420 c += x_i * y_4 + (zz[i + 4] & M); 421 zz[i + 4] = (int)c; 422 c >>>= 32; 423 c += x_i * y_5 + (zz[i + 5] & M); 424 zz[i + 5] = (int)c; 425 c >>>= 32; 426 c += x_i * y_6 + (zz[i + 6] & M); 427 zz[i + 6] = (int)c; 428 c >>>= 32; 429 c += x_i * y_7 + (zz[i + 7] & M); 430 zz[i + 7] = (int)c; 431 c >>>= 32; 432 zz[i + 8] = (int)c; 433 } 434 } 435 436 public static void mul(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff) 437 { 438 long y_0 = y[yOff + 0] & M; 439 long y_1 = y[yOff + 1] & M; 440 long y_2 = y[yOff + 2] & M; 441 long y_3 = y[yOff + 3] & M; 442 long y_4 = y[yOff + 4] & M; 443 long y_5 = y[yOff + 5] & M; 444 long y_6 = y[yOff + 6] & M; 445 long y_7 = y[yOff + 7] & M; 446 447 { 448 long c = 0, x_0 = x[xOff + 0] & M; 449 c += x_0 * y_0; 450 zz[zzOff + 0] = (int)c; 451 c >>>= 32; 452 c += x_0 * y_1; 453 zz[zzOff + 1] = (int)c; 454 c >>>= 32; 455 c += x_0 * y_2; 456 zz[zzOff + 2] = (int)c; 457 c >>>= 32; 458 c += x_0 * y_3; 459 zz[zzOff + 3] = (int)c; 460 c >>>= 32; 461 c += x_0 * y_4; 462 zz[zzOff + 4] = (int)c; 463 c >>>= 32; 464 c += x_0 * y_5; 465 zz[zzOff + 5] = (int)c; 466 c >>>= 32; 467 c += x_0 * y_6; 468 zz[zzOff + 6] = (int)c; 469 c >>>= 32; 470 c += x_0 * y_7; 471 zz[zzOff + 7] = (int)c; 472 c >>>= 32; 473 zz[zzOff + 8] = (int)c; 474 } 475 476 for (int i = 1; i < 8; ++i) 477 { 478 ++zzOff; 479 long c = 0, x_i = x[xOff + i] & M; 480 c += x_i * y_0 + (zz[zzOff + 0] & M); 481 zz[zzOff + 0] = (int)c; 482 c >>>= 32; 483 c += x_i * y_1 + (zz[zzOff + 1] & M); 484 zz[zzOff + 1] = (int)c; 485 c >>>= 32; 486 c += x_i * y_2 + (zz[zzOff + 2] & M); 487 zz[zzOff + 2] = (int)c; 488 c >>>= 32; 489 c += x_i * y_3 + (zz[zzOff + 3] & M); 490 zz[zzOff + 3] = (int)c; 491 c >>>= 32; 492 c += x_i * y_4 + (zz[zzOff + 4] & M); 493 zz[zzOff + 4] = (int)c; 494 c >>>= 32; 495 c += x_i * y_5 + (zz[zzOff + 5] & M); 496 zz[zzOff + 5] = (int)c; 497 c >>>= 32; 498 c += x_i * y_6 + (zz[zzOff + 6] & M); 499 zz[zzOff + 6] = (int)c; 500 c >>>= 32; 501 c += x_i * y_7 + (zz[zzOff + 7] & M); 502 zz[zzOff + 7] = (int)c; 503 c >>>= 32; 504 zz[zzOff + 8] = (int)c; 505 } 506 } 507 508 public static int mulAddTo(int[] x, int[] y, int[] zz) 509 { 510 long y_0 = y[0] & M; 511 long y_1 = y[1] & M; 512 long y_2 = y[2] & M; 513 long y_3 = y[3] & M; 514 long y_4 = y[4] & M; 515 long y_5 = y[5] & M; 516 long y_6 = y[6] & M; 517 long y_7 = y[7] & M; 518 519 long zc = 0; 520 for (int i = 0; i < 8; ++i) 521 { 522 long c = 0, x_i = x[i] & M; 523 c += x_i * y_0 + (zz[i + 0] & M); 524 zz[i + 0] = (int)c; 525 c >>>= 32; 526 c += x_i * y_1 + (zz[i + 1] & M); 527 zz[i + 1] = (int)c; 528 c >>>= 32; 529 c += x_i * y_2 + (zz[i + 2] & M); 530 zz[i + 2] = (int)c; 531 c >>>= 32; 532 c += x_i * y_3 + (zz[i + 3] & M); 533 zz[i + 3] = (int)c; 534 c >>>= 32; 535 c += x_i * y_4 + (zz[i + 4] & M); 536 zz[i + 4] = (int)c; 537 c >>>= 32; 538 c += x_i * y_5 + (zz[i + 5] & M); 539 zz[i + 5] = (int)c; 540 c >>>= 32; 541 c += x_i * y_6 + (zz[i + 6] & M); 542 zz[i + 6] = (int)c; 543 c >>>= 32; 544 c += x_i * y_7 + (zz[i + 7] & M); 545 zz[i + 7] = (int)c; 546 c >>>= 32; 547 c += zc + (zz[i + 8] & M); 548 zz[i + 8] = (int)c; 549 zc = c >>> 32; 550 } 551 return (int)zc; 552 } 553 554 public static int mulAddTo(int[] x, int xOff, int[] y, int yOff, int[] zz, int zzOff) 555 { 556 long y_0 = y[yOff + 0] & M; 557 long y_1 = y[yOff + 1] & M; 558 long y_2 = y[yOff + 2] & M; 559 long y_3 = y[yOff + 3] & M; 560 long y_4 = y[yOff + 4] & M; 561 long y_5 = y[yOff + 5] & M; 562 long y_6 = y[yOff + 6] & M; 563 long y_7 = y[yOff + 7] & M; 564 565 long zc = 0; 566 for (int i = 0; i < 8; ++i) 567 { 568 long c = 0, x_i = x[xOff + i] & M; 569 c += x_i * y_0 + (zz[zzOff + 0] & M); 570 zz[zzOff + 0] = (int)c; 571 c >>>= 32; 572 c += x_i * y_1 + (zz[zzOff + 1] & M); 573 zz[zzOff + 1] = (int)c; 574 c >>>= 32; 575 c += x_i * y_2 + (zz[zzOff + 2] & M); 576 zz[zzOff + 2] = (int)c; 577 c >>>= 32; 578 c += x_i * y_3 + (zz[zzOff + 3] & M); 579 zz[zzOff + 3] = (int)c; 580 c >>>= 32; 581 c += x_i * y_4 + (zz[zzOff + 4] & M); 582 zz[zzOff + 4] = (int)c; 583 c >>>= 32; 584 c += x_i * y_5 + (zz[zzOff + 5] & M); 585 zz[zzOff + 5] = (int)c; 586 c >>>= 32; 587 c += x_i * y_6 + (zz[zzOff + 6] & M); 588 zz[zzOff + 6] = (int)c; 589 c >>>= 32; 590 c += x_i * y_7 + (zz[zzOff + 7] & M); 591 zz[zzOff + 7] = (int)c; 592 c >>>= 32; 593 c += zc + (zz[zzOff + 8] & M); 594 zz[zzOff + 8] = (int)c; 595 zc = c >>> 32; 596 ++zzOff; 597 } 598 return (int)zc; 599 } 600 601 public static long mul33Add(int w, int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) 602 { 603 // assert w >>> 31 == 0; 604 605 long c = 0, wVal = w & M; 606 long x0 = x[xOff + 0] & M; 607 c += wVal * x0 + (y[yOff + 0] & M); 608 z[zOff + 0] = (int)c; 609 c >>>= 32; 610 long x1 = x[xOff + 1] & M; 611 c += wVal * x1 + x0 + (y[yOff + 1] & M); 612 z[zOff + 1] = (int)c; 613 c >>>= 32; 614 long x2 = x[xOff + 2] & M; 615 c += wVal * x2 + x1 + (y[yOff + 2] & M); 616 z[zOff + 2] = (int)c; 617 c >>>= 32; 618 long x3 = x[xOff + 3] & M; 619 c += wVal * x3 + x2 + (y[yOff + 3] & M); 620 z[zOff + 3] = (int)c; 621 c >>>= 32; 622 long x4 = x[xOff + 4] & M; 623 c += wVal * x4 + x3 + (y[yOff + 4] & M); 624 z[zOff + 4] = (int)c; 625 c >>>= 32; 626 long x5 = x[xOff + 5] & M; 627 c += wVal * x5 + x4 + (y[yOff + 5] & M); 628 z[zOff + 5] = (int)c; 629 c >>>= 32; 630 long x6 = x[xOff + 6] & M; 631 c += wVal * x6 + x5 + (y[yOff + 6] & M); 632 z[zOff + 6] = (int)c; 633 c >>>= 32; 634 long x7 = x[xOff + 7] & M; 635 c += wVal * x7 + x6 + (y[yOff + 7] & M); 636 z[zOff + 7] = (int)c; 637 c >>>= 32; 638 c += x7; 639 return c; 640 } 641 642 public static int mulByWord(int x, int[] z) 643 { 644 long c = 0, xVal = x & M; 645 c += xVal * (z[0] & M); 646 z[0] = (int)c; 647 c >>>= 32; 648 c += xVal * (z[1] & M); 649 z[1] = (int)c; 650 c >>>= 32; 651 c += xVal * (z[2] & M); 652 z[2] = (int)c; 653 c >>>= 32; 654 c += xVal * (z[3] & M); 655 z[3] = (int)c; 656 c >>>= 32; 657 c += xVal * (z[4] & M); 658 z[4] = (int)c; 659 c >>>= 32; 660 c += xVal * (z[5] & M); 661 z[5] = (int)c; 662 c >>>= 32; 663 c += xVal * (z[6] & M); 664 z[6] = (int)c; 665 c >>>= 32; 666 c += xVal * (z[7] & M); 667 z[7] = (int)c; 668 c >>>= 32; 669 return (int)c; 670 } 671 672 public static int mulByWordAddTo(int x, int[] y, int[] z) 673 { 674 long c = 0, xVal = x & M; 675 c += xVal * (z[0] & M) + (y[0] & M); 676 z[0] = (int)c; 677 c >>>= 32; 678 c += xVal * (z[1] & M) + (y[1] & M); 679 z[1] = (int)c; 680 c >>>= 32; 681 c += xVal * (z[2] & M) + (y[2] & M); 682 z[2] = (int)c; 683 c >>>= 32; 684 c += xVal * (z[3] & M) + (y[3] & M); 685 z[3] = (int)c; 686 c >>>= 32; 687 c += xVal * (z[4] & M) + (y[4] & M); 688 z[4] = (int)c; 689 c >>>= 32; 690 c += xVal * (z[5] & M) + (y[5] & M); 691 z[5] = (int)c; 692 c >>>= 32; 693 c += xVal * (z[6] & M) + (y[6] & M); 694 z[6] = (int)c; 695 c >>>= 32; 696 c += xVal * (z[7] & M) + (y[7] & M); 697 z[7] = (int)c; 698 c >>>= 32; 699 return (int)c; 700 } 701 702 public static int mulWordAddTo(int x, int[] y, int yOff, int[] z, int zOff) 703 { 704 long c = 0, xVal = x & M; 705 c += xVal * (y[yOff + 0] & M) + (z[zOff + 0] & M); 706 z[zOff + 0] = (int)c; 707 c >>>= 32; 708 c += xVal * (y[yOff + 1] & M) + (z[zOff + 1] & M); 709 z[zOff + 1] = (int)c; 710 c >>>= 32; 711 c += xVal * (y[yOff + 2] & M) + (z[zOff + 2] & M); 712 z[zOff + 2] = (int)c; 713 c >>>= 32; 714 c += xVal * (y[yOff + 3] & M) + (z[zOff + 3] & M); 715 z[zOff + 3] = (int)c; 716 c >>>= 32; 717 c += xVal * (y[yOff + 4] & M) + (z[zOff + 4] & M); 718 z[zOff + 4] = (int)c; 719 c >>>= 32; 720 c += xVal * (y[yOff + 5] & M) + (z[zOff + 5] & M); 721 z[zOff + 5] = (int)c; 722 c >>>= 32; 723 c += xVal * (y[yOff + 6] & M) + (z[zOff + 6] & M); 724 z[zOff + 6] = (int)c; 725 c >>>= 32; 726 c += xVal * (y[yOff + 7] & M) + (z[zOff + 7] & M); 727 z[zOff + 7] = (int)c; 728 c >>>= 32; 729 return (int)c; 730 } 731 732 public static int mul33DWordAdd(int x, long y, int[] z, int zOff) 733 { 734 // assert x >>> 31 == 0; 735 // assert zOff <= 4; 736 737 long c = 0, xVal = x & M; 738 long y00 = y & M; 739 c += xVal * y00 + (z[zOff + 0] & M); 740 z[zOff + 0] = (int)c; 741 c >>>= 32; 742 long y01 = y >>> 32; 743 c += xVal * y01 + y00 + (z[zOff + 1] & M); 744 z[zOff + 1] = (int)c; 745 c >>>= 32; 746 c += y01 + (z[zOff + 2] & M); 747 z[zOff + 2] = (int)c; 748 c >>>= 32; 749 c += (z[zOff + 3] & M); 750 z[zOff + 3] = (int)c; 751 c >>>= 32; 752 return c == 0 ? 0 : Nat.incAt(8, z, zOff, 4); 753 } 754 755 public static int mul33WordAdd(int x, int y, int[] z, int zOff) 756 { 757 // assert x >>> 31 == 0; 758 // assert zOff <= 5; 759 760 long c = 0, xVal = x & M, yVal = y & M; 761 c += yVal * xVal + (z[zOff + 0] & M); 762 z[zOff + 0] = (int)c; 763 c >>>= 32; 764 c += yVal + (z[zOff + 1] & M); 765 z[zOff + 1] = (int)c; 766 c >>>= 32; 767 c += (z[zOff + 2] & M); 768 z[zOff + 2] = (int)c; 769 c >>>= 32; 770 return c == 0 ? 0 : Nat.incAt(8, z, zOff, 3); 771 } 772 773 public static int mulWordDwordAdd(int x, long y, int[] z, int zOff) 774 { 775 // assert zOff <= 5; 776 long c = 0, xVal = x & M; 777 c += xVal * (y & M) + (z[zOff + 0] & M); 778 z[zOff + 0] = (int)c; 779 c >>>= 32; 780 c += xVal * (y >>> 32) + (z[zOff + 1] & M); 781 z[zOff + 1] = (int)c; 782 c >>>= 32; 783 c += (z[zOff + 2] & M); 784 z[zOff + 2] = (int)c; 785 c >>>= 32; 786 return c == 0 ? 0 : Nat.incAt(8, z, zOff, 3); 787 } 788 789 public static int mulWord(int x, int[] y, int[] z, int zOff) 790 { 791 long c = 0, xVal = x & M; 792 int i = 0; 793 do 794 { 795 c += xVal * (y[i] & M); 796 z[zOff + i] = (int)c; 797 c >>>= 32; 798 } 799 while (++i < 8); 800 return (int)c; 801 } 802 803 public static void square(int[] x, int[] zz) 804 { 805 long x_0 = x[0] & M; 806 long zz_1; 807 808 int c = 0, w; 809 { 810 int i = 7, j = 16; 811 do 812 { 813 long xVal = (x[i--] & M); 814 long p = xVal * xVal; 815 zz[--j] = (c << 31) | (int)(p >>> 33); 816 zz[--j] = (int)(p >>> 1); 817 c = (int)p; 818 } 819 while (i > 0); 820 821 { 822 long p = x_0 * x_0; 823 zz_1 = ((c << 31) & M) | (p >>> 33); 824 zz[0] = (int)p; 825 c = (int)(p >>> 32) & 1; 826 } 827 } 828 829 long x_1 = x[1] & M; 830 long zz_2 = zz[2] & M; 831 832 { 833 zz_1 += x_1 * x_0; 834 w = (int)zz_1; 835 zz[1] = (w << 1) | c; 836 c = w >>> 31; 837 zz_2 += zz_1 >>> 32; 838 } 839 840 long x_2 = x[2] & M; 841 long zz_3 = zz[3] & M; 842 long zz_4 = zz[4] & M; 843 { 844 zz_2 += x_2 * x_0; 845 w = (int)zz_2; 846 zz[2] = (w << 1) | c; 847 c = w >>> 31; 848 zz_3 += (zz_2 >>> 32) + x_2 * x_1; 849 zz_4 += zz_3 >>> 32; 850 zz_3 &= M; 851 } 852 853 long x_3 = x[3] & M; 854 long zz_5 = zz[5] & M; 855 long zz_6 = zz[6] & M; 856 { 857 zz_3 += x_3 * x_0; 858 w = (int)zz_3; 859 zz[3] = (w << 1) | c; 860 c = w >>> 31; 861 zz_4 += (zz_3 >>> 32) + x_3 * x_1; 862 zz_5 += (zz_4 >>> 32) + x_3 * x_2; 863 zz_4 &= M; 864 zz_6 += zz_5 >>> 32; 865 zz_5 &= M; 866 } 867 868 long x_4 = x[4] & M; 869 long zz_7 = zz[7] & M; 870 long zz_8 = zz[8] & M; 871 { 872 zz_4 += x_4 * x_0; 873 w = (int)zz_4; 874 zz[4] = (w << 1) | c; 875 c = w >>> 31; 876 zz_5 += (zz_4 >>> 32) + x_4 * x_1; 877 zz_6 += (zz_5 >>> 32) + x_4 * x_2; 878 zz_5 &= M; 879 zz_7 += (zz_6 >>> 32) + x_4 * x_3; 880 zz_6 &= M; 881 zz_8 += zz_7 >>> 32; 882 zz_7 &= M; 883 } 884 885 long x_5 = x[5] & M; 886 long zz_9 = zz[9] & M; 887 long zz_10 = zz[10] & M; 888 { 889 zz_5 += x_5 * x_0; 890 w = (int)zz_5; 891 zz[5] = (w << 1) | c; 892 c = w >>> 31; 893 zz_6 += (zz_5 >>> 32) + x_5 * x_1; 894 zz_7 += (zz_6 >>> 32) + x_5 * x_2; 895 zz_6 &= M; 896 zz_8 += (zz_7 >>> 32) + x_5 * x_3; 897 zz_7 &= M; 898 zz_9 += (zz_8 >>> 32) + x_5 * x_4; 899 zz_8 &= M; 900 zz_10 += zz_9 >>> 32; 901 zz_9 &= M; 902 } 903 904 long x_6 = x[6] & M; 905 long zz_11 = zz[11] & M; 906 long zz_12 = zz[12] & M; 907 { 908 zz_6 += x_6 * x_0; 909 w = (int)zz_6; 910 zz[6] = (w << 1) | c; 911 c = w >>> 31; 912 zz_7 += (zz_6 >>> 32) + x_6 * x_1; 913 zz_8 += (zz_7 >>> 32) + x_6 * x_2; 914 zz_7 &= M; 915 zz_9 += (zz_8 >>> 32) + x_6 * x_3; 916 zz_8 &= M; 917 zz_10 += (zz_9 >>> 32) + x_6 * x_4; 918 zz_9 &= M; 919 zz_11 += (zz_10 >>> 32) + x_6 * x_5; 920 zz_10 &= M; 921 zz_12 += zz_11 >>> 32; 922 zz_11 &= M; 923 } 924 925 long x_7 = x[7] & M; 926 long zz_13 = zz[13] & M; 927 long zz_14 = zz[14] & M; 928 { 929 zz_7 += x_7 * x_0; 930 w = (int)zz_7; 931 zz[7] = (w << 1) | c; 932 c = w >>> 31; 933 zz_8 += (zz_7 >>> 32) + x_7 * x_1; 934 zz_9 += (zz_8 >>> 32) + x_7 * x_2; 935 zz_10 += (zz_9 >>> 32) + x_7 * x_3; 936 zz_11 += (zz_10 >>> 32) + x_7 * x_4; 937 zz_12 += (zz_11 >>> 32) + x_7 * x_5; 938 zz_13 += (zz_12 >>> 32) + x_7 * x_6; 939 zz_14 += zz_13 >>> 32; 940 } 941 942 w = (int)zz_8; 943 zz[8] = (w << 1) | c; 944 c = w >>> 31; 945 w = (int)zz_9; 946 zz[9] = (w << 1) | c; 947 c = w >>> 31; 948 w = (int)zz_10; 949 zz[10] = (w << 1) | c; 950 c = w >>> 31; 951 w = (int)zz_11; 952 zz[11] = (w << 1) | c; 953 c = w >>> 31; 954 w = (int)zz_12; 955 zz[12] = (w << 1) | c; 956 c = w >>> 31; 957 w = (int)zz_13; 958 zz[13] = (w << 1) | c; 959 c = w >>> 31; 960 w = (int)zz_14; 961 zz[14] = (w << 1) | c; 962 c = w >>> 31; 963 w = zz[15] + (int)(zz_14 >> 32); 964 zz[15] = (w << 1) | c; 965 } 966 967 public static void square(int[] x, int xOff, int[] zz, int zzOff) 968 { 969 long x_0 = x[xOff + 0] & M; 970 long zz_1; 971 972 int c = 0, w; 973 { 974 int i = 7, j = 16; 975 do 976 { 977 long xVal = (x[xOff + i--] & M); 978 long p = xVal * xVal; 979 zz[zzOff + --j] = (c << 31) | (int)(p >>> 33); 980 zz[zzOff + --j] = (int)(p >>> 1); 981 c = (int)p; 982 } 983 while (i > 0); 984 985 { 986 long p = x_0 * x_0; 987 zz_1 = ((c << 31) & M) | (p >>> 33); 988 zz[zzOff + 0] = (int)p; 989 c = (int)(p >>> 32) & 1; 990 } 991 } 992 993 long x_1 = x[xOff + 1] & M; 994 long zz_2 = zz[zzOff + 2] & M; 995 996 { 997 zz_1 += x_1 * x_0; 998 w = (int)zz_1; 999 zz[zzOff + 1] = (w << 1) | c; 1000 c = w >>> 31; 1001 zz_2 += zz_1 >>> 32; 1002 } 1003 1004 long x_2 = x[xOff + 2] & M; 1005 long zz_3 = zz[zzOff + 3] & M; 1006 long zz_4 = zz[zzOff + 4] & M; 1007 { 1008 zz_2 += x_2 * x_0; 1009 w = (int)zz_2; 1010 zz[zzOff + 2] = (w << 1) | c; 1011 c = w >>> 31; 1012 zz_3 += (zz_2 >>> 32) + x_2 * x_1; 1013 zz_4 += zz_3 >>> 32; 1014 zz_3 &= M; 1015 } 1016 1017 long x_3 = x[xOff + 3] & M; 1018 long zz_5 = zz[zzOff + 5] & M; 1019 long zz_6 = zz[zzOff + 6] & M; 1020 { 1021 zz_3 += x_3 * x_0; 1022 w = (int)zz_3; 1023 zz[zzOff + 3] = (w << 1) | c; 1024 c = w >>> 31; 1025 zz_4 += (zz_3 >>> 32) + x_3 * x_1; 1026 zz_5 += (zz_4 >>> 32) + x_3 * x_2; 1027 zz_4 &= M; 1028 zz_6 += zz_5 >>> 32; 1029 zz_5 &= M; 1030 } 1031 1032 long x_4 = x[xOff + 4] & M; 1033 long zz_7 = zz[zzOff + 7] & M; 1034 long zz_8 = zz[zzOff + 8] & M; 1035 { 1036 zz_4 += x_4 * x_0; 1037 w = (int)zz_4; 1038 zz[zzOff + 4] = (w << 1) | c; 1039 c = w >>> 31; 1040 zz_5 += (zz_4 >>> 32) + x_4 * x_1; 1041 zz_6 += (zz_5 >>> 32) + x_4 * x_2; 1042 zz_5 &= M; 1043 zz_7 += (zz_6 >>> 32) + x_4 * x_3; 1044 zz_6 &= M; 1045 zz_8 += zz_7 >>> 32; 1046 zz_7 &= M; 1047 } 1048 1049 long x_5 = x[xOff + 5] & M; 1050 long zz_9 = zz[zzOff + 9] & M; 1051 long zz_10 = zz[zzOff + 10] & M; 1052 { 1053 zz_5 += x_5 * x_0; 1054 w = (int)zz_5; 1055 zz[zzOff + 5] = (w << 1) | c; 1056 c = w >>> 31; 1057 zz_6 += (zz_5 >>> 32) + x_5 * x_1; 1058 zz_7 += (zz_6 >>> 32) + x_5 * x_2; 1059 zz_6 &= M; 1060 zz_8 += (zz_7 >>> 32) + x_5 * x_3; 1061 zz_7 &= M; 1062 zz_9 += (zz_8 >>> 32) + x_5 * x_4; 1063 zz_8 &= M; 1064 zz_10 += zz_9 >>> 32; 1065 zz_9 &= M; 1066 } 1067 1068 long x_6 = x[xOff + 6] & M; 1069 long zz_11 = zz[zzOff + 11] & M; 1070 long zz_12 = zz[zzOff + 12] & M; 1071 { 1072 zz_6 += x_6 * x_0; 1073 w = (int)zz_6; 1074 zz[zzOff + 6] = (w << 1) | c; 1075 c = w >>> 31; 1076 zz_7 += (zz_6 >>> 32) + x_6 * x_1; 1077 zz_8 += (zz_7 >>> 32) + x_6 * x_2; 1078 zz_7 &= M; 1079 zz_9 += (zz_8 >>> 32) + x_6 * x_3; 1080 zz_8 &= M; 1081 zz_10 += (zz_9 >>> 32) + x_6 * x_4; 1082 zz_9 &= M; 1083 zz_11 += (zz_10 >>> 32) + x_6 * x_5; 1084 zz_10 &= M; 1085 zz_12 += zz_11 >>> 32; 1086 zz_11 &= M; 1087 } 1088 1089 long x_7 = x[xOff + 7] & M; 1090 long zz_13 = zz[zzOff + 13] & M; 1091 long zz_14 = zz[zzOff + 14] & M; 1092 { 1093 zz_7 += x_7 * x_0; 1094 w = (int)zz_7; 1095 zz[zzOff + 7] = (w << 1) | c; 1096 c = w >>> 31; 1097 zz_8 += (zz_7 >>> 32) + x_7 * x_1; 1098 zz_9 += (zz_8 >>> 32) + x_7 * x_2; 1099 zz_10 += (zz_9 >>> 32) + x_7 * x_3; 1100 zz_11 += (zz_10 >>> 32) + x_7 * x_4; 1101 zz_12 += (zz_11 >>> 32) + x_7 * x_5; 1102 zz_13 += (zz_12 >>> 32) + x_7 * x_6; 1103 zz_14 += zz_13 >>> 32; 1104 } 1105 1106 w = (int)zz_8; 1107 zz[zzOff + 8] = (w << 1) | c; 1108 c = w >>> 31; 1109 w = (int)zz_9; 1110 zz[zzOff + 9] = (w << 1) | c; 1111 c = w >>> 31; 1112 w = (int)zz_10; 1113 zz[zzOff + 10] = (w << 1) | c; 1114 c = w >>> 31; 1115 w = (int)zz_11; 1116 zz[zzOff + 11] = (w << 1) | c; 1117 c = w >>> 31; 1118 w = (int)zz_12; 1119 zz[zzOff + 12] = (w << 1) | c; 1120 c = w >>> 31; 1121 w = (int)zz_13; 1122 zz[zzOff + 13] = (w << 1) | c; 1123 c = w >>> 31; 1124 w = (int)zz_14; 1125 zz[zzOff + 14] = (w << 1) | c; 1126 c = w >>> 31; 1127 w = zz[zzOff + 15] + (int)(zz_14 >> 32); 1128 zz[zzOff + 15] = (w << 1) | c; 1129 } 1130 1131 public static int sub(int[] x, int[] y, int[] z) 1132 { 1133 long c = 0; 1134 c += (x[0] & M) - (y[0] & M); 1135 z[0] = (int)c; 1136 c >>= 32; 1137 c += (x[1] & M) - (y[1] & M); 1138 z[1] = (int)c; 1139 c >>= 32; 1140 c += (x[2] & M) - (y[2] & M); 1141 z[2] = (int)c; 1142 c >>= 32; 1143 c += (x[3] & M) - (y[3] & M); 1144 z[3] = (int)c; 1145 c >>= 32; 1146 c += (x[4] & M) - (y[4] & M); 1147 z[4] = (int)c; 1148 c >>= 32; 1149 c += (x[5] & M) - (y[5] & M); 1150 z[5] = (int)c; 1151 c >>= 32; 1152 c += (x[6] & M) - (y[6] & M); 1153 z[6] = (int)c; 1154 c >>= 32; 1155 c += (x[7] & M) - (y[7] & M); 1156 z[7] = (int)c; 1157 c >>= 32; 1158 return (int)c; 1159 } 1160 1161 public static int sub(int[] x, int xOff, int[] y, int yOff, int[] z, int zOff) 1162 { 1163 long c = 0; 1164 c += (x[xOff + 0] & M) - (y[yOff + 0] & M); 1165 z[zOff + 0] = (int)c; 1166 c >>= 32; 1167 c += (x[xOff + 1] & M) - (y[yOff + 1] & M); 1168 z[zOff + 1] = (int)c; 1169 c >>= 32; 1170 c += (x[xOff + 2] & M) - (y[yOff + 2] & M); 1171 z[zOff + 2] = (int)c; 1172 c >>= 32; 1173 c += (x[xOff + 3] & M) - (y[yOff + 3] & M); 1174 z[zOff + 3] = (int)c; 1175 c >>= 32; 1176 c += (x[xOff + 4] & M) - (y[yOff + 4] & M); 1177 z[zOff + 4] = (int)c; 1178 c >>= 32; 1179 c += (x[xOff + 5] & M) - (y[yOff + 5] & M); 1180 z[zOff + 5] = (int)c; 1181 c >>= 32; 1182 c += (x[xOff + 6] & M) - (y[yOff + 6] & M); 1183 z[zOff + 6] = (int)c; 1184 c >>= 32; 1185 c += (x[xOff + 7] & M) - (y[yOff + 7] & M); 1186 z[zOff + 7] = (int)c; 1187 c >>= 32; 1188 return (int)c; 1189 } 1190 1191 public static int subBothFrom(int[] x, int[] y, int[] z) 1192 { 1193 long c = 0; 1194 c += (z[0] & M) - (x[0] & M) - (y[0] & M); 1195 z[0] = (int)c; 1196 c >>= 32; 1197 c += (z[1] & M) - (x[1] & M) - (y[1] & M); 1198 z[1] = (int)c; 1199 c >>= 32; 1200 c += (z[2] & M) - (x[2] & M) - (y[2] & M); 1201 z[2] = (int)c; 1202 c >>= 32; 1203 c += (z[3] & M) - (x[3] & M) - (y[3] & M); 1204 z[3] = (int)c; 1205 c >>= 32; 1206 c += (z[4] & M) - (x[4] & M) - (y[4] & M); 1207 z[4] = (int)c; 1208 c >>= 32; 1209 c += (z[5] & M) - (x[5] & M) - (y[5] & M); 1210 z[5] = (int)c; 1211 c >>= 32; 1212 c += (z[6] & M) - (x[6] & M) - (y[6] & M); 1213 z[6] = (int)c; 1214 c >>= 32; 1215 c += (z[7] & M) - (x[7] & M) - (y[7] & M); 1216 z[7] = (int)c; 1217 c >>= 32; 1218 return (int)c; 1219 } 1220 1221 public static int subFrom(int[] x, int[] z) 1222 { 1223 long c = 0; 1224 c += (z[0] & M) - (x[0] & M); 1225 z[0] = (int)c; 1226 c >>= 32; 1227 c += (z[1] & M) - (x[1] & M); 1228 z[1] = (int)c; 1229 c >>= 32; 1230 c += (z[2] & M) - (x[2] & M); 1231 z[2] = (int)c; 1232 c >>= 32; 1233 c += (z[3] & M) - (x[3] & M); 1234 z[3] = (int)c; 1235 c >>= 32; 1236 c += (z[4] & M) - (x[4] & M); 1237 z[4] = (int)c; 1238 c >>= 32; 1239 c += (z[5] & M) - (x[5] & M); 1240 z[5] = (int)c; 1241 c >>= 32; 1242 c += (z[6] & M) - (x[6] & M); 1243 z[6] = (int)c; 1244 c >>= 32; 1245 c += (z[7] & M) - (x[7] & M); 1246 z[7] = (int)c; 1247 c >>= 32; 1248 return (int)c; 1249 } 1250 1251 public static int subFrom(int[] x, int xOff, int[] z, int zOff) 1252 { 1253 long c = 0; 1254 c += (z[zOff + 0] & M) - (x[xOff + 0] & M); 1255 z[zOff + 0] = (int)c; 1256 c >>= 32; 1257 c += (z[zOff + 1] & M) - (x[xOff + 1] & M); 1258 z[zOff + 1] = (int)c; 1259 c >>= 32; 1260 c += (z[zOff + 2] & M) - (x[xOff + 2] & M); 1261 z[zOff + 2] = (int)c; 1262 c >>= 32; 1263 c += (z[zOff + 3] & M) - (x[xOff + 3] & M); 1264 z[zOff + 3] = (int)c; 1265 c >>= 32; 1266 c += (z[zOff + 4] & M) - (x[xOff + 4] & M); 1267 z[zOff + 4] = (int)c; 1268 c >>= 32; 1269 c += (z[zOff + 5] & M) - (x[xOff + 5] & M); 1270 z[zOff + 5] = (int)c; 1271 c >>= 32; 1272 c += (z[zOff + 6] & M) - (x[xOff + 6] & M); 1273 z[zOff + 6] = (int)c; 1274 c >>= 32; 1275 c += (z[zOff + 7] & M) - (x[xOff + 7] & M); 1276 z[zOff + 7] = (int)c; 1277 c >>= 32; 1278 return (int)c; 1279 } 1280 1281 public static BigInteger toBigInteger(int[] x) 1282 { 1283 byte[] bs = new byte[32]; 1284 for (int i = 0; i < 8; ++i) 1285 { 1286 int x_i = x[i]; 1287 if (x_i != 0) 1288 { 1289 Pack.intToBigEndian(x_i, bs, (7 - i) << 2); 1290 } 1291 } 1292 return new BigInteger(1, bs); 1293 } 1294 1295 public static void zero(int[] z) 1296 { 1297 z[0] = 0; 1298 z[1] = 0; 1299 z[2] = 0; 1300 z[3] = 0; 1301 z[4] = 0; 1302 z[5] = 0; 1303 z[6] = 0; 1304 z[7] = 0; 1305 } 1306} 1307