Nat192.cs 31 KB

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