Nat256.cs 42 KB

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